N'utilisez pas « test » comme nom d'exécutable pour un fichier de
test. test
est une commande du shell.
Références :
/usr/share/doc/packages
Unix / Programming
Information
Beaucoup de longs documents informatifs peuvent être obtenus sur papier par
GNU
.
Les quatres sections suivantes contiennent quelques scripts d'exemple dans
différents langages pour créer un fichier texte d'information sur les comptes
utilisateur qui peut être ajouté à /etc/passwd
, avec par exemple
le programme newusers
. Chaque script prend en entrée un fichier
contenant des lignes de la forme prénom nom mot_de_passe. (Les
répertoires « home » des utilisateurs ne seront pas créés avec ces
scripts.)
Lire des scripts shell est le meilleur moyen de comprendre comment un système Unix fonctionne. Ici, je donne quelques pointeurs et rappels sur la programmation du shell.
Références pour Bash :
bash(1)
BASH
Programming - Introduction HOWTO
du LDP comme information pour
commencer
(Installez le paquet bash-doc
pour avoir les exemples.)
Court exemple de programme (crée des entrées de compte pour
newusers
à partir de l'entrée standard) :
#!/bin/bash # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain pid=1000; while read n1 n2 n3 ; do if [ ${n1:0:1} != "#" ]; then let pid=$pid+1 echo ${n1}_${n2}:password:${pid}:${pid}:,,,/home/${n1}_${n2}:/bin/bash fi done
Plusieurs paquets fournissent un shell POSIX dans Debian :
dash
(Sarge)
ash
(Woody)
bash
pdksh
Si vous écrivez des scripts shell portables, il vaut mieux les écrire comme
scripts shell POSIX. Utilisez /bin/sh
lié vers ash
ou (dash
) pour tester sa conformité POSIX. Évitez d'écrire des
scripts avec des bashismes.
Plusieurs paramètres spéciaux à se rappeler :
$0 = nom du shell ou du script shell $1 = premier argument ... $9 = neuvième argument $# = nombre de paramètres "$*" = "$1 $2 $3 $4 ... $n" "$@" = "$1" "$2" "$3" "$4" ... "$n" $? = état de sortie de la commande la plus récente $$ = PID du script shell $! = PID du processus en arrière-plan le plus récent
Expansions des paramètres de base à se rappeler :
Forme Si var est positionné(*) Si var n'est pas positionné(*) ${var:-string} $var string ${var:+string} string null ${var:=string} $var string (et lance var=string) ${var:?string} $var (affiche string et sort)
Ici, les deux points « : » dans tous ces opérateurs est optionnel.
Substitutions de paramètres de base à se rappeler :
Forme Résultat ${var%suffix} Supprime le plus petit motif suffix ${var%%suffix} Supprime le plus grand motif suffix ${var#prefix} Supprime le plus petit motif prefix ${var##prefix} Supprime le plus grand motif prefix
Redirection de base à se rappeler (ici le [n] est un nombre optionnel) :
[n]> file Redirige la sortie standard (ou n) vers file. [n]>> file Ajoute la sortie standard (ou n) à file. [n]< file Redirige l'entrée standard (ou n) depuis file. [n1]>&n2 Redirige la sortie standard (ou n1) vers n2 > file >&2 Redirige l'entrée et l'erreur standards vers file. | command Crée un tuyau (pipe) de l'entrée standard (ou n) vers command. >&2 | command Crée un tuyau (pipe) de l'entrée et l'erreur standards vers command.
Toutes les commandes retournent un état de sortie qui peut être utilisé par les expressions conditionnelles :
Notez que l'utilisation de la valeur 0 signifie « vrai »
contrairement à d'autres domaines de l'informatique. De même, `[' est
l'équivalent de la commande test
, qui évalue ses arguments jusqu'à
`]' comme expression conditionnelle.
Expressions conditionnelles de base à se rappeler :
command && si_succès_lance_cette_commande_aussi command || si_échec_lance_cette_commande_aussi if [ expression_conditionnelle ]; then si_succès_lance_cette_commande else si_échec_lance_cette_commande fi
Les opérateurs de comparaison de fichiers dans les expressions conditionnelles sont :
-e file Vrai si file existe. -d file Vrai si file existe et est un répertoire. -f file Vrai si file existe et est un fichier normal. -w file Vrai si file existe et est en écriture. -x file Vrai si file existe et est exécutable. file1 -nt file2 Vrai si file1 est plus récent que file2. (modification) file1 -ot file2 Vrai si file1 est plus vieux que file2. (modification) file1 -ef file2 Vrai si ce sont les numéros de périphérique et d'inode.
Les opérateurs de comparaison de chaînes dans les expressions conditionnelles sont :
-z str Vrai si la longueur de str est zéro. -n str Vrai si la longueur de str est différente de zéro. str1 == str2 Vrai si les chaînes sont égales. str1 = str2 Vrai si les chaînes sont égales. ( = peut être utilisé à la place de == ) str1 != str2 Vrai si les chaînes ne sont pas égales. str1 < str2 Vrai si str1 est classée avant str2 (dépend de la locale). str1 > str2 Vrai si str1 est classée après str2 (dépend de la locale).
Les opérateurs de comparaison arithmétique entière dans les expressions conditionnelles sont -eq, -ne, -lt, -le, -gt, ou -ge.
Le shell traite un script de la façon suivante :
Des guillemets simples dans des guillemets doubles n'ont pas d'effet.
Références pour Awk :
mawk(1)
et gawk(1)
Court exemple de programme (crée des entrées de compte pour
newusers
) :
#!/usr/bin/awk -f # Script pour créer un fichier utilisable avec la commande 'newusers' # à partir d'un fichier contenant des IDs utilisateur et des mots de # passe sous la forme : # Prénom Nom Mot_de_passe # Copyright (c) KMSelf Sat Aug 25 20:47:38 PDT 2001 # Distributed under GNU GPL v 2, or at your option, any later version. # This program is distributed WITHOUT ANY WARRANTY. BEGIN { # Assign starting UID, GID if ( ARGC > 2 ) { startuid = ARGV[1] delete ARGV[1] } else { printf( "Usage: newusers startUID file\n" \ "...where startUID is the starting userid " \ "to add, and file is \n" \ "an input file in form firstname last name password\n" \ ) exit } infile = ARGV[1] printf( "Starting UID: %s\n\n", startuid ) } /^#/ { next } { ++record first = $1 last = $2 passwd = $3 user= substr( tolower( first ), 1, 1 ) tolower( last ) uid = startuid + record - 1 gid = uid printf( "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n", \ user, passwd, uid, gid, first, last, user \ ) }
Deux paquets fournissent un awk
POSIX dans Debian :
mawk
gawk
C'est l'interpréteur sur un système Unix.
Références pour Perl :
perl(1)
Court exemple de programme (crée une entrée newusers
) :
#!/usr/bin/perl # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain $pid=1000; while (<STDIN>) { if (/^#/) { next;} chop; $pid++; ($n1, $n2, $n3) = split / /; print $n1,"_",$n2,":", $n3, ":",$pid, ":",$pid,",,,/home/",$n1,"_",$n2,":/bin/bash\n" }
Installer le module Perl modulename :
# perl -MCPAN -e 'install modulename'
C'est un interpréteur orienté objet sympa.
Références pour Python :
python(1)
Court exemple de programme (crée une entrée newusers
) :
#! /usr/bin/env python import sys, string # (C) Osamu Aoki Sun Aug 26 16:53:55 UTC 2001 Public Domain # Ported from awk script by KMSelf Sat Aug 25 20:47:38 PDT 2001 # This program is distributed WITHOUT ANY WARRANTY. def usages(): print \ "Usage: ", sys.argv[0], " start_UID [filename]\n" \ "\tstartUID is the starting userid to add.\n" \ "\tfilename is input file name. If not specified, standard input.\n\n" \ "Input file format:\n"\ "\tfirstname lastname password\n" return 1 def parsefile(startuid): # # main filtering # uid = startuid while 1: line = infile.readline() if not line: break if line[0] == '#': continue (first, last, passwd) = string.split(string.lower(line)) # crashe si le nombre de paramètres est mauvais :-) user = first[0] + last gid = uid lineout = "%s:%s:%d:%d:%s %s,,/home/%s:/bin/bash\n" % \ (user, passwd, uid, gid, first, last, user) sys.stdout.write(lineout) +uid if __name__ == '__main__': if len(sys.argv) == 1: usages() else: uid = int(sys.argv[1]) #print "# UID start from: %d\n" % uid if len(sys.argv) > 1: infilename = string.join(sys.argv[2:]) infile = open(infilename, 'r') #print "# Read file from: %s\n\n" % infilename else: infile = sys.stdin parsefile(uid)
Références pour Make :
make(1)
Variables automatiques simples :
Syntaxe des règles :
Target: [ Prerequisite ... ] [TAB] command1 [TAB] -command2 # ignore les erreurs [TAB] @command3 # supprime l'écho
Ici, [TAB] est un code TAB. Chaque ligne est interprétée par le shell après la substitution des variables par make. Utiliser \ à la fin d'une ligne pour continuer le script. Utiliser $$ pour entrer $ pour les variables d'environnement du script shell.
Equivalents des règles implicites :
.c: header.h == % : %.c header.h .o.c: header.h == %.c: %.o header.h
Variables automatiques pour les règles ci-dessus :
foo.o: new1.c new2.c.c old1.c new3.c $@ == foo.o (cible) $< == new1.c (premier) $? == new1.c new2.c new3.c (plus récent) $^ == new1.c new2.c.c old1.c new3.c (tout) $* == `%' motif correspondant dans le motif cible.
Référence des variables :
foo1 := bar # expansion unique foo2 = bar # expansion récursive foo3 += bar # ajoute SRCS := $(wildcard *.c) OBJS := $(foo:c=o) OBJS := $(foo:%.c=%.o) OBJS := $(patsubst %.c,%.o,$(foo)) DIRS = $(dir directory/filename.ext) # Extrait "directory" $(notdir NAMES...), $(basename NAMES...), $(suffix NAMES...) ...
Exécuter make -p -f/dev/null pour voir les règles automatiques internes.
Préparation :
# apt-get install glibc6-doc manpages-dev
Références pour le C :
gcc(1)
nom_de_la_fonction_de_la_bibliothèque_C(3)
gcc
)
Un exemple simple pour compiler example.c
avec la bibliothèque
libm
dans l'exécutable run_example
:
$ cat > example.c << EOF #include <stdio.h> #include <math.h> #include <string.h> int main(int argc, char **argv, char **envp){ double x; char y[11]; x=sqrt(argc+7.5); strncpy(y, argv[0], 10); /* empêche un dépassement de tampon */ y[10] = '\0'; /* remplissage pour être sûr que la chaîne finit par '\0' */ printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]); return 0; } EOF $ gcc -Wall -g -o run_example exmple.c -lm $ ./run_example 1, 2.915, ./run_exam, (null) $ ./run_example 1234567890qwerty 2, 3.082, ./run_exam, 1234567890qwerty
Ici, -lm est nécessaire pour lier la bibliothèque
libm, pour utiliser sqrt(). La bibliothèque est
en fait dans /lib
sous le nom libm.so.6
qui est un
lien symbolique vers libm-2.1.3.so
.
Regardez le dernier paramètre dans le texte affiché. Il y a plus de 10 caractères affichés alors que %10s est spécifié.
L'utilisation de fonctions effectuant des opérations sur des pointeurs sans
vérifier la limite, comme sprintf
et strcpy
, est
dépréciée pour prévenir les exploits de dépassement de tampon, annulant les
effets ci-dessus. Utilisez snprintf
et strncpy
à la
place.
gdb
Préparation :
# apt-get install gdb
Références pour gdb
:
gdb(1)
http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html
Utilisez gdb
pour déboguer des programmes compilés avec l'option
-g. Beaucoup de commandes peuvent être abbréviées. L'expansion
par tab marche comme avec le shell.
$ gdb program (gdb) b 1 # positionne un point d'arrêt à la ligne 1 (gdb) run arg1 arg2 arg3 # exécute le programme (gdb) next # ligne suivante ... (gdb) step # pas en avant ... (gdb) p parm # affiche parm ... (gdb) p parm=12 # met la valeur de parm à 12
Pour déboguer depuis Emacs, référez-vous à Résumé des commandes de l'éditeur (Emacs, Vim), Section 11.3.4.
Utilisez ldd
pour trouver les dépendances d'un programme sur des
bibliothèques :
$ ldd /bin/ls librt.so.1 => /lib/librt.so.1 (0x4001e000) libc.so.6 => /lib/libc.so.6 (0x40030000) libpthread.so.0 => /lib/libpthread.so.0 (0x40153000) /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
Pour que ls
marche dans un environnement chroot
é, les
bibliothèques suivantes doivent être disponibles dans votre environnement
chroot
é.
Les commandes suivantes sont aussi utiles :
strace
: trace les appels et signaux système
ltrace
: trace les appels aux bibliothèques
Il y a plusieurs outils de détection des fuites de mémoire disponibles dans Debian.
njamd
valgrind
dmalloc
electric-fence
memprof
memwatch
mpatrol
leaktracer
libgc6
Parasoft
. (non-libre, commercial
gratuit)
Consultez aussi Debugging
Tools for Dynamic Storage Allocation and Memory Management
.
flex
est un générateur rapide d'analyseur lexical.
Références pour flex
:
flex(1)
Vous devez fournir vos propres main()
et yywrap()
, ou
votre program.l
devrait ressembler à ce qui suit pour compiler
sans bibliothèque. (yywrap
est une macro ; %option
mainactive %option noyywrap implicitement) :
%option main %% .|\n ECHO ; %%
Autrement, vous pouvez compiler avec l'option de l'éditeur de liens
-lfl à la fin de la ligne de commande de cc
(comme
ATT-Lex avec -ll). %option n'est pas nécessaire dans
ce cas.
Quelques paquets fournissent un générateur d'analyseur LALR compatible avec Yacc dans Debian :
bison
: générateur d'analyseur LALR GNU
byyacc
: générateur d'analyseur avec retour arrière basé sur
byacc
Références pour bison
:
bison(1)
Vous devez fournir vos propres main()
et yyerror()
.
main()
appelle yyparse()
qui appelle
yylex()
, habituellement créé avec Flex.
%% %%
autoconf
est un otil pour produire des scripts shell qui
configurent automatiquement les paquets de code source pour s'adapter aux
nombreux systèmes Unix qui utilisent le système de compilation GNU entier.
autoconf
produit le script de configuration
configure
. configure
crée automatiquement un
Makefile
personnalisé et Makefile.am
.
Debian ne touche pas aux fichiers de /usr/local
(voir Support de la diversité, Section 2.5).
Donc si vous compilez un programme depuis le source, installez le dans
/usr/local
pour qu'il n'interfère pas avec Debian.
$ cd src $ ./configure --prefix=/usr/loca $ make $ make install # cela met les fichiers dans le système
SI vous avez toujours les sources et si elles utilisent
autoconf
/automake
et si vous vous souvenez comment
vous avez configuré la compilation :
$ ./configure les-options-de-configuration # make uninstall
Autrement, si vous êtes absolument sûr que le processus d'installation n'a mis
des fichiers que sous /usr/local
et qu'il n'y a rien d'important
là, vous pouvez supprimer tout son contenu avec :
# find /usr/local -type f -print0 | xargs -0 rm -f
Si vous n'êtes pas sûr de l'emplacement des fichiers installés, vous devriez
considérer l'utilisation de checkinstall
qui fournit un moyen de
désinstallation propre.
Traditionnellement, roff est le système de traitement de texte principal d'Unix.
Voir roff(7)
, groff(7)
, groff(1)
,
grotty(1)
, troff(1)
, groff_mdoc(7)
,
groff_man(7)
, groff_ms(7)
, groff_me(7)
,
groff_mm(7)
, et « info groff ».
Un bon didacticiel sur les macros -me
existe. Si vous avez groff
(1.18 ou plus récent), cherchez le fichier
/usr/share/doc/groff/meintro.me.gz
et faites ce qui suit :
$ zcat /usr/share/doc/groff/meintro.me.gz | \ groff -Tascii -me - | less -R
Ce qui suit construira un fichier texte :
$ zcat /usr/share/doc/groff/meintro.me.gz | \ GROFF_NO_SGR=1 groff -Tascii -me - | col -b -x > meintro.txt
Pour imprimer, utilisez la sortie PostScript.
$ groff -Tps meintro.txt | lpr $ groff -Tps meintro.txt | mpage -2 | lpr
Préparation :
# apt-get install debiandoc-sgml debiandoc-sgml-doc
Références pour debiandoc-sgml
:
/usr/share/doc/debiandoc-sgml-doc
debiandoc-sgml(1)
SGML permet de gérer plusieurs formats pour un document. Un système SGML facile est Debiandoc, qui est utilisé ici. Cela requiert des conversions mineurs dans le fichier texte original, pour les caractères suivants :
< < > > " " " " (espace non séquable) & & % % © © – – — —
Pour marquer une section en tant que commentaire non imprimable, faites :
<!-- Indiquez le problème ici ... -->
Pour marquer une section en tant que commentaire ou pas à l'impression, faites :
<![ %FIXME; [ Indiquez le problème ici ... ]]>
En SGML, la première définition d'une entité l'emporte. Par exemple :
<!entity % qref "INCLUDE"> <![ %qref; [ <!entity param "Data 1"> ]]> <!entity param "Data 2"> ¶m;
Cela termine en tant que « Data 1 ». Si la première ligne inclut « IGNORE » au lieu de « INCLUDE », cela termine en tant que « Data 2 » (la deuxième ligne est une expression conditionnelle). De plus, les phrases souvent répétées peuvent être définies à l'avance séparément du contexte.
<!entity whoisthis "my"> Hello &whoisthis; friend. This is &whoisthis; book.
Le résultat est :
Hello my friend. This is my book.
Voir le court exemple de SGML sample.sgml
dans les exemples
.
Lorsque des documents SGML deviennent plus gros, TeX cause parfois des erreurs.
Il faut augmenter la taille du bassin dans /etc/texmf/texmf.cnf
(ou mieux éditez /etc/texmf/texmf.d/95NonPath
et lancez
update-texmf
) pour réparer cela.
Préparation :
# apt-get install debian-policy developers-reference \ maint-guide dh-make debhelper # apt-get install packaging-manual # dans le cas de Potato
Références pour le paquetage :
dh-make(1)
Méthode rapide et sale pour paqueter un binaire seul par Joey Hess.
# mkdir -p mypkg/usr/bin mypkg/DEBIAN # cp binary mypkg/usr/bin # cat > mypkg/DEBIAN/control Package: mypackage Version: 1 Architecture: i386 Maintainer: Joey Hess <joeyh@debian.org> Description: my little package Don't expect much. ^D # dpkg-deb -b mypkg
Utilisez dh_make
du paquet dh-make
pour créer
l'architecture du paquet. Ensuite, suivez les instructions de
dh-make(1)
, qui utilise debhelper
dans
debian/rules
.
Une approche plus ancienne est d'utiliser deb-make
du paquet
debmake
. Cela n'utilise aucun script debhelper
et
dépend seulement du shell.
Pour plusieurs paquets source, voir « mc » (dpkg-source -x
mc_4.5.54.dsc) qui utilise « sys-build.mk » par Adam Heath
(doogie@debian.org
) et
« glibc » (dpkg-source -x glibc_2.2.4-1.dsc) qui utilise
un autre système par feu Joel Klecker (espy@debian.org
).
Guide de référence pour Debian
CVS, lun 03 avr 2005 22:57:18 UTCosamu@debian.org
gerbs@free.fr