Table des matières
Je donne quelques indications pour apprendre à programmer sous le système Debian, suffisantes pour suivre le code source mis en paquets. Voici les paquets importants correspondant aux paquets de documentation pour la programmation .
Une référence en ligne est accessible en entrant « man
name
» après l’installation des paquets
manpages
et manpages-dev
. Les
références en ligne des outils GNU tools sont disponibles en entrant
« info nom_programme
» après l’installation des
paquets de documentation pertinents. Vous devrez peut-être inclure les
archives contrib
et non-free
en plus
de l’archive main
car certaines documentations GFDL ne
sont pas considérées comme conformes à DFSG.
Veuillez envisager d’utiliser des outils ds système de gestion de versions. Consulter la Section 10.5, « Git ».
Avertissement | |
---|---|
N’utilisez pas « |
Attention | |
---|---|
Vous devrez installer les programmes directement compilés à partir des
sources dans « |
Astuce | |
---|---|
Les exemples de code pour la création de « Song 99 Bottles of Beer » devraient vous donner de bonnes indications sur pratiquement tous les langages de programmation. |
Le script de l’interpréteur de commandes (« shell script » est un fichier texte dont le bit d’exécution est positionné et qui contient des commandes dans le format suivant :
#!/bin/sh ... command lines
La première ligne indique l’interpréteur qui sera utilisé pour lire et exécuter le contenu de ce fichier.
La lecture des scripts de l’interpréteur de commandes est la meilleure manière de comprendre comment fonctionne un système de type UNIX. Je donne ici quelques indications et rappels de la programmation avec l’interpréteur de commandes. Consultez « Erreurs en shell » (https://www.greenend.org.uk/rjk/2001/04/shell.html) pour apprendre à partir d’erreurs.
Contrairement à l’interpréteur de commandes en mode interactif (consultez Section 1.5, « La commande simple de l’interpréteur de commandes » et Section 1.6, « Traitement des données textuelles à la UNIX »), les scripts de l’interpréteur de commandes utilisent souvent des paramètres, des conditions et des boucles.
De nombreux scripts système peuvent être interprétés par l'un des interpréteurs de commandes POSIX (consulter le Tableau 1.13, « Liste d’interpréteurs de commandes (« shells ») »).
L'interpréteur de commandes POSIX par défaut non interactif
« /usr/bin/sh
» est un lien symbolique pointant vers
/usr/bin/dash
et est utilisé par de nombreux programmes
du système.
L’interpréteur POSIX interactif par défaut est
/usr/bin/bash
.
Évitez d’écrire des scripts de l’interpréteur de commandes avec des
bashismes ou des zshismes afin de les rendre portables entre tous
les interpréteurs POSIX. Vous pouvez le vérifier en utilisant
checkbashisms
(1).
Tableau 12.1. Liste de bashismes typiques
Bon : POSIX | À éviter : bashisme |
---|---|
if [ "$toto" = "$titi" ] ; then … |
if [ "$toto" == "$titi" ] ; then … |
diff -u fichier.c.orig fichier.c |
diff -u fichier.c{.orig,} |
mkdir /tototiti /tototutu |
mkdir /toto{titi,tutu} |
funcname() { … } |
fonction funcname() { … } |
format octal : « \377 » |
format hexadécimal : « \xff » |
La commande « echo
» doit être utilisée avec
les précautions suivantes car son implémentation diffère selon que l’on
utilise les commandes internes ou externes de l’interpréteur de
commandes :
Éviter d’utiliser toutes les options de commandes sauf
« -n
».
Éviter d’utiliser les séquences d’échappement dans les chaînes de caractères car leur prise en compte varie.
Note | |
---|---|
Bien que l’option « |
Astuce | |
---|---|
Utilisez la commande « |
Des paramètres spéciaux de l’interpréteur de commandes sont souvent utilisés dans les scripts de l’interpréteur de commandes.
Tableau 12.2. Liste des paramètres de l’interpréteur de commandes
paramètre de l’interpréteur de commandes | valeur |
---|---|
$0 |
nom de l’interpréteur ou du script de l’interpréteur |
$1 |
premier (1er) paramètre de l’interpréteur |
$9 |
neuvième (9ème) paramètre de l’interpréteur |
$# |
nombres de paramètres positionnels |
"$*" |
"$1 $2 $3 $4 … " |
"$@" |
"$1" "$2" "$3" "$4" … |
$? |
valeur de retour de la commande la plus récente |
$$ |
PID de ce script de l’interpréteur de commandes |
$! |
PID de la tâche de fond la plus récemment lancée |
Les expansions de paramètre les plus courantes à retenir sont mentionnées ci-dessous :
Tableau 12.3. Liste des expansions de paramètre de l’interpréteur
forme de l’expression du paramètre | valeur si var est positionnée |
valeur si var n’est pas positionnée |
---|---|---|
${var:-chaîne} |
« $var » |
« chaîne » |
${var:+chaîne} |
« chaîne » |
« null » |
${var:=chaîne} |
« $var » |
« chaîne » (et lancer
« var=chaîne ») |
${var:?chaîne} |
« $var » |
echo « chaîne » vers stderr (et quitter avec une erreur) |
Ici, les deux points « :
» dans tous ces
opérateurs sont en fait optionnels.
avec « :
» =
opérateur de test pour existe et
différent de null
sans « :
» =
opérateur de test pour existe uniquement
Tableau 12.4. Liste des substitutions-clés de paramètres de l’interpréteur
forme de substitution de paramètre | résultat |
---|---|
${var%suffixe} |
supprimer le motif le plus petit de la partie finale |
${var%%suffixe} |
supprimer le motif le plus grand de la partie finale |
${var#préfixe} |
supprimer le motif le plus petit de la partie initiale |
${var##préfixe} |
supprimer le motif le plus grand de la partie initiale |
Chaque commande retourne un état de sortie qui peut être utilisé pour des expressions conditionnelles.
Succès : 0 (« Vrai »)
Erreur : différent de 0 (« Faux »)
Note | |
---|---|
« 0 » dans le contexte conditionnel de l’interpréteur signifie « Vrai » alors que « 0 » dans le contexte conditionnel de C signifie « Faux ». |
Note | |
---|---|
« |
Les idiomes conditionnels de base à retenir sont les suivants :
« commande &&
si_succès_lancer_aussi_cette_commande ||
true
»
« commande ||
en_cas_de_non_succès_lancer_aussi_cette_commande ||
true
»
Un morceau de script sur plusieurs lignes comme le suivant :
if [ conditional_expression ]; then if_success_run_this_command else if_not_success_run_this_command fi
Ici, le « || true
» était nécessaire pour
s’assurer que ce script de l’interpréteur ne se termine pas accidentellement
à cette ligne lorsque l’interpréteur est appelé avec l’indicateur
« -e
».
Tableau 12.5. Liste des opérateurs de comparaison dans les expressions conditionnelles
équation | condition pour retourner une valeur logique vraie |
---|---|
-e fichier |
fichier existe |
-d fichier |
fichier existe et est un répertoire |
-f fichier |
fichier existe et est un fichier normal (« régulier ») |
-w fichier |
fichier existe et peut être écrit |
-x fichier |
fichier existe et est exécutable |
fichier1 -nt
fichier2 |
fichier1 est plus récent que fichier2 (modification) |
fichier1 -ot
fichier2 |
fichier1 est plus ancien que fichier2 (modification) |
fichier1 -ef
fichier2 |
fichier1 et fichier2 sont sur le même périphérique et le même numéro d’inœud |
Tableau 12.6. Liste des opérateurs de comparaison de chaîne de caractères dans les expressions conditionnelles
équation | condition pour retourner une valeur logique vraie |
---|---|
-z str |
la longueur de str est nulle |
-n str |
la longueur de str est non nulle |
str1 = str2 |
str1 et str2 sont égales |
str1 != str2 |
str1 et str2 ne sont pas égales |
str1 < str2 |
str1 est trié avant str2 (dépendant des paramètres linguistiques) |
str1 > str2 |
str1 est trié après str2 (dépendant des paramètres linguistiques) |
Les opérateurs de comparaison arithmétique entière dans les expressions
conditionnelles sont « -eq
»,
« -ne
», « -lt
»,
« -le
», « -gt
»
et « -ge
».
Il existe un certains nombre d’idiomes de boucles qu’on peut utiliser avec un interpréteur de commandes POSIX.
« for x in toto1 toto2 ... ; do commande ;
done
» boucle en assignant les éléments de la liste
« toto1 toto2 ...
» à la variable
« x
» et en exécutant la
« commande
».
« "while condition ; do commande ; done
»
répète la « commande
» tant que la
« condition
» est vraie.
« until condition ; do commande ; done
» répète
la « commande
» tant que
« « condition
» n’est pas vraie.
« break
» permet de quitter la boucle.
« continue
» permet de reprendre l’itération
suivante de la boucle.
Astuce | |
---|---|
Les itérations numériques semblables à celles du langage C peuvent être réalisées en utilisant
|
Astuce | |
---|---|
Consultez Section 9.4.9, « Répéter une commande en bouclant entre des fichiers ». |
Certaines variables d’environnement populaires pour l’invite de commande normale de l’interpréteur peuvent ne pas être disponibles dans l’environnement d’exécution de votre script.
Pour « $USER
», utilisez « $(id -un)
»
Pour « $UID
», utilisez « $(id -u)
»
Pour « $HOME
», utilisez « $(getent passwd "$(id
-u)"|cut -d ":" -f 6)
» (cela fonctionne aussi dans la Section 4.5.2, « Le système de gestion centralisée moderne »)
En gros, l’interpréteur de commandes traite un script de la manière suivante :
l’interpréteur de commandes lit une ligne :
l’interpréteur de commandes regroupe une partie de la ligne sous forme
d’un élément (« token » si elle
se trouve entre "…"
ou '…'
:
l’interpréteur de commandes découpe les autres parties de la ligne en éléments comme suit :
Espaces : espace
tabulation saut-de-ligne
métacaractères : < > | ; & ( )
l’interpréteur de commandes vérifie les mots
réservés pour chacun des éléments et ajuste son comportement s’il
ne se trouve pas entre "…"
ou '…'
.
mot réservé : if then elif
else fi for in while unless do done case esac
L’interpréteur de commandes étend les alias s’ils ne se trouvent pas entre
"…"
ou '…'
.
l’interpréteur de commandes étend les tilde s’ils ne se trouvent pas entre
"…"
ou '…'
.
« ~
» → répertoire personnel de l’utilisateur
actuel
« ~utilisateur
» →
répertoire personnel de
l’utilisateur
l’interpréteur de commandes étend les paramètres en leur valeur s’ils ne sont pas entre
'…'
.
paramètre :
« $PARAMETRE
» ou
« ${PARAMETRE}
»
l’interpréteur de commandes étend la substitution de
commande si elle n’est pas entre '…'
.
« $( commande )
» → sortie de la
« commande
»
« ` commande `
» → sortie de la
« commande
»
l’interpréteur de commandes étend les motifs
génériques du chemin aux fichiers correspondants s’ils ne sont
pas entre "…"
ou '…'
.
*
→ n’importe quel caractère
?
→ un caractère
[…]
→ un caractère quelconque parmi
« …
»
l’interpréteur de commandes recherche la commande dans ce qui suit et l’exécute.
définition de fonction
commande interne (« builtin »)
fichier exécutable dans
« $PATH
»
l’interpréteur de commandes passe à la ligne suivante et recommence ce traitement depuis le début de la séquence.
Des guillemets simples dans des guillemets doubles n’ont pas d’effet.
Exécuter « set -x
» dans le script de
l’interpréteur ou l’appel du script avec l’option
« -x
» fait imprimer par l’interpréteur de
commandes toutes les commandes exécutées. C’est assez pratique pour le
débogage.
De façon à rendre vos programmes de l’interpréteur de commandes aussi portables que possible dans tous les systèmes Debian, c’est une bonne idée de limiter les programmes utilitaires à ceux fournis par les paquets essentiels.
« aptitude search ~E
» affiche la liste des
essentiels.
« dpkg -L nom_paquet |grep
'/man/man.*/'
» affiche la liste des pages de manuel pour les
commandes que fournit le paquet
nom_paquet
.
Tableau 12.7. Lites des paquets comportant des petits programmes utilitaires pour les scripts de l’interpréteur de commandes
paquet | popularité | taille | description |
---|---|---|---|
dash
|
V:884, I:997 | 191 | petit et rapide interpréteur de commandes compatible POSIX pour
sh |
coreutils
|
V:880, I:999 | 18307 | utilitaires du cœur de GNU |
grep
|
V:782, I:999 | 1266 | GNU grep , egrep et
fgrep |
sed
|
V:790, I:999 | 987 | GNU sed |
mawk
|
V:442, I:997 | 285 | petit et rapide awk |
debianutils
|
V:907, I:999 | 224 | divers utilitaires spécifiques à Debian |
bsdutils
|
V:519, I:999 | 356 | utilitaires de base provenant de 4.4BSD-Lite |
bsdextrautils
|
V:596, I:713 | 339 | utilitaires supplémentaires de 4.4BSD-Lite |
moreutils
|
V:15, I:38 | 231 | utilitaires supplémentaires d’UNIX |
Astuce | |
---|---|
Bien que |
Consulter la Section 1.6, « Traitement des données textuelles à la UNIX » pour des exemples.
Tableau 12.8. Liste des paquets relatifs aux interpréteurs de commandes
paquet | popularité | taille | documentation |
---|---|---|---|
dash
|
V:884, I:997 | 191 | sh : petit et rapide interpréteur compatible POSIX
pour sh |
bash
|
V:838, I:999 | 7175 | sh : « info bash » fourni par
bash-doc |
mawk
|
V:442, I:997 | 285 | AWK : petit et rapide awk |
gawk
|
V:285, I:349 | 2906 | AWK : « info gawk » fourni par
gawk-doc |
perl
|
V:707, I:989 | 673 | Perl : perl (1) et pages HTML
fournies par perl-doc et perl-doc-html |
libterm-readline-gnu-perl
|
V:2, I:29 | 380 | Extension Perl pour la bibliothèque GNU ReadLine/History :
perlsh (1) |
libreply-perl
|
V:0, I:0 | 171 | REPL pour Perl : reply (1) |
libdevel-repl-perl
|
V:0, I:0 | 237 | REPL pour Perl : re.pl (1) |
python3
|
V:718, I:953 | 81 | Python : python3 (1) et
pages HTML fournies par python3-doc |
tcl
|
V:25, I:218 | 21 | Tcl : tcl (3) et les pages de
manuel détaillées fournies par tcl-doc |
tk
|
V:20, I:211 | 21 | Tk : tk (3) et pages de manuel
détaillées fournies par tk-doc |
ruby
|
V:86, I:208 | 29 | Ruby : ruby (1),
erb (1), irb (1),
rdoc (1), ri (1) |
Lorsque vous souhaitez automatiser une tâche sur Debian, vous devez d’abord la scripter avec un langage interprété. La ligne directrice pour le choix de la langue interprétée est la suivante :
utilisez dash
, si c’est une tâche simple qui combine des
programmes en ligne de commandes avec un interpréteur ;
utilisez python3
, si la tâche n’est pas simple et que
vous l’écrivez à partir de zéro ;
utilisez perl
, tcl
,
ruby
..., s'il existe un code existant utilisant l'un de
ces langages sur Debian et qui doit être retouché pour effectuer cette
tâche.
Si le code résultant est trop lent, vous pouvez réécrire uniquement la partie critique pour la vitesse d'exécution dans un langage compilé et l'appeler depuis le langage interprété.
La plupart des interpréteurs offrent des fonctionnalités de base de vérification de la syntaxe et de traçage du code :
« dash -n script.sh » – vérification de la syntaxe d’un script d’interpréteur ;
« dash -x script.sh » – traçage d’un script d’interpréteur ;
« python -m py_compile script.py » – contrôle syntaxique d'un script Python ;
« python -mtrace --trace script.py » – traçage d’un script Python ;
« perl -I .. /libpath -c script.pl » – vérification de la syntaxe d’un script Perl ;
« perl -d:Trace script.pl » – traçage d’un script Perl.
Pour tester le code de dash
, essayez la Section 9.1.4, « Enveloppe pour Readline » qui s'adapte à un environnement interactif de
type bash
.
Pour tester le code de perl
, essayez l'environnement REPL
pour Perl qui s'adapte au REPL (=READ +
EVAL + PRINT + LOOP) de type Python
pour Perl.
Le script d’interpréteur peut être amélioré pour créer un programme
graphique attrayant. L’astuce consiste à utiliser l’un des programmes dits
de dialogue au lieu d’une interaction insipide utilisant les commandes
echo
et read
.
Tableau 12.9. Liste des programmes de dialogue
paquet | popularité | taille | description |
---|---|---|---|
x11-utils
|
V:192, I:566 | 651 | xmessage (1) : afficher un message ou une question
dans une fenêtre (X) |
whiptail
|
V:284, I:996 | 56 | afficher des boîtes de dialogues conviviales depuis des scripts de l’interpréteur de commandes (newt) |
dialog
|
V:11, I:99 | 1227 | afficher des boîtes de dialogues conviviales depuis des scripts de l’interpréteur de commandes (ncurses) |
zenity
|
V:76, I:363 | 183 | afficher des boîtes de dialogue graphiques à partir de scripts d’interpréteur (GTK) |
ssft
|
V:0, I:0 | 75 | Outil frontal de scripts de l’interpréteur de commandes (enrobeur pour zenity, kdialog et dialog avec gettext) |
gettext
|
V:56, I:259 | 5818 | « /usr/bin/gettext.sh » : traduire des messages |
Voici un exemple de programme graphique pour démontrer à quel point c’est facile avec un script d’interpréteur.
Ce script utilise zenity
pour sélectionner un fichier
(par défaut /etc/motd
) et l'afficher.
Le lanceur graphique pour ce script peut être créé en suivant la Section 9.4.10, « Lancer un programme depuis l’interface graphique ».
#!/bin/sh -e # Copyright (C) 2021 Osamu Aoki <[email protected]>, Public Domain # vim:set sw=2 sts=2 et: DATA_FILE=$(zenity --file-selection --filename="/etc/motd" --title="Select a file to check") || \ ( echo "E: File selection error" >&2 ; exit 1 ) # Check size of archive if ( file -ib "$DATA_FILE" | grep -qe '^text/' ) ; then zenity --info --title="Check file: $DATA_FILE" --width 640 --height 400 \ --text="$(head -n 20 "$DATA_FILE")" else zenity --info --title="Check file: $DATA_FILE" --width 640 --height 400 \ --text="The data is MIME=$(file -ib "$DATA_FILE")" fi
Ce type d’approche du programme graphique avec un script d’interpréteur n’est utile que dans le cas de choix simple. Si vous devez écrire un programme avec des complexités, veuillez envisager de l’écrire à partir d’une plateforme plus adaptée.
Les programmes graphiques de gestionnaire de fichiers peuvent être étendus pour effectuer certaines actions fréquentes sur les fichiers sélectionnés à l’aide de paquets d’extension supplémentaires. Ils peuvent également effectuer des actions personnalisées très spécifiques en ajoutant vos scripts personnels.
Pour GNOME, consulter NautilusScriptsHowto.
Pour KDE, consulter Création de menus de service pour Dolphin.
Pour Xfce, consulter Thunar – Actions personnalisées et https://help.ubuntu.com/community/ThunarCustomActions.
Pour LXDE, consulter Actions personnalisées.
Pour traiter les données, sh
doit générer un
sous-processus exécutant cut
, grep
,
sed
, etc., et est lent. D’autre part,
perl
a des capacités internes pour traiter les données et
est rapide. Un certain nombre de scripts d’entretien du système Debian
utilisent perl
.
Considérons un bout de code uniligne en AWK et ses équivalents en Perl :
awk '($2=="1957") { print $3 }' |
Il est équivalent à l’une quelconque des lignes suivantes :
perl -ne '@f=split; if ($f[1] eq "1957") { print "$f[2]\n"}' |
perl -ne 'if ((@f=split)[1] eq "1957") { print "$f[2]\n"}' |
perl -ne '@f=split; print $f[2] if ( $f[1]==1957 )' |
perl -lane 'print $F[2] if $F[1] eq "1957"' |
perl -lane 'print$F[2]if$F[1]eq+1957' |
La dernière est une devinette. Elle tire parti des fonctionnalités suivantes de Perl :
L’espace est optionnel.
Il existe une conversion automatique des nombres en chaîne de caractères.
Astuces d'exécution de Perl à travers des options de la ligne de commande :
perlrun
(1)
Variables spéciales Perl : perlvar
(1)
Cette flexibilité est la force de Perl. En même temps, cela nous permet de créer des codes énigmatiques et fouillis. Soyez donc prudent.
Tableau 12.10. Liste des paquets relatifs à un compilateur
paquet | popularité | taille | description |
---|---|---|---|
gcc
|
V:167, I:550 | 36 | compilateur GNU C |
libc6-dev
|
V:248, I:567 | 12053 | bibliothèque GNU C : bibliothèques de développement et fichiers d’en-tête |
g++
|
V:56, I:501 | 13 | compilateur GNU C++ |
libstdc++-10-dev
|
V:14, I:165 | 17537 | bibliothèque GNU C++ standard v3 – fichiers de développement |
cpp
|
V:334, I:727 | 18 | préprocesseur GNU C |
gettext
|
V:56, I:259 | 5818 | utilitaires d'internationalisation GNU |
glade
|
V:0, I:5 | 1204 | constructeur d'interface utilisateur en GTK |
valac
|
V:0, I:4 | 725 | langage de type C# pour le système GObject |
flex
|
V:7, I:73 | 1243 | générateur d’analyse lexicale rapide compatible avec LEX |
bison
|
V:7, I:80 | 3116 | générateur d’analyseurs syntaxiques compatible avec YACC |
susv2
|
I:0 | 16 | aller chercher « The Single UNIX Specifications v2 » |
susv3
|
I:0 | 16 | aller chercher « The Single UNIX Specifications v3 » |
susv4
|
I:0 | 16 | aller chercher « The Single UNIX Specifications v4 » |
golang
|
I:20 | 11 | compilateur du langage de programmation Go |
rustc
|
V:3, I:14 | 8860 | langage Rust de programmation système |
haskell-platform
|
I:1 | 12 | bibliothèques et outils standard d’Haskell |
gfortran
|
V:6, I:62 | 15 | compilateur GNU Fortran 95 |
fpc
|
I:2 | 103 | Free Pascal |
Ici, la Section 12.3.3, « Flex -- un meilleur Lex » et la Section 12.3.4, « Bison -- un meilleur Yacc » sont incluses pour indiquer comment un programme de type compilateur peut être écrit en langage C en compilant une description de niveau supérieur en langage C.
Vous pouvez définir un environnement propre pour compiler des programmes écrits dans le langage de programmation C par ce qui suit :
# apt-get install glibc-doc manpages-dev libc6-dev gcc build-essential
Le paquet libc6-dev
, c’est-à-dire la bibliothèque GNU C,
fournit la bibliothèque C standard
qui est une collection de fichiers d’en-têtes et de routines de bibliothèque
utilisée par le langage de programmation C.
Consultez les références pour C comme suit :
« info libc
» (références des fonctions de la
bibliothèque C)
gcc
(1) et « info gcc
»
chaque_nom_de_fonction_de la_bibliothèque_C
(3)
Kernighan & Ritchie, « Le langage de programmation C », 2ème édition (Prentice Hall)
Un exemple simple « example.c
» peut être
compilé avec la bibliothèque « libm
» pour
donner l’exécutable « run_example
» par ce qui
suit :
$ 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); /* prevent buffer overflow */ y[10] = '\0'; /* fill to make sure string ends with '\0' */ printf("%5i, %5.3f, %10s, %10s\n", argc, x, y, argv[1]); return 0; } EOF $ gcc -Wall -g -o run_example example.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 « /usr/lib/libm.so
» depuis le
paquet libc6
pour sqrt
(3). La
bibliothèque réelle se trouve dans « /lib/
»
avec le nom de fichier « libm.so.6
» avec un
lien symbolique vers « libm-2.7.so
».
Regardez le dernier paramètre du texte en sortie. Il y a plus de 10
caractères bien que « %10s
» soit indiqué.
L’utilisation de fonctions effectuant des opérations sur des pointeurs en
mémoire sans vérification des limites, telles que
sprintf
(3) et strcpy
(3) a été rendue
obsolète afin d’éviter les exploits de débordements de tampons qui utilisent
les effets des débordements ci-dessus. Utilisez
snprintf
(3) et strncpy
(3) en
remplacement..
Flex est un générateur d’analyse lexicale rapide compatible avec Lex.
On trouve un didacticiel de flex
(1) dans
« info flex
».
Plusieurs exemples simples sont disponibles dans
« /usr/share/doc/flex/examples/
». [7]
Un certain nombre de paquets fournissent un analyseur LR à lecture anticipée (« lookahead ») compatible avec Yacc ou un générateur d’analyseur LALR sous Debian.
On trouve un didacticiel de bison
(1) dans
« info bison
».
Vous devez fournir vos propre « main()
» et
« yyerror()
».
« main()
» appelle
« yyparse()
» qui appelle
« yylex()
», habituellement créé avec Flex.
Voici un exemple de création de programme de calcul dans un terminal.
Créons example.y
:
/* calculator source for bison */ %{ #include <stdio.h> extern int yylex(void); extern int yyerror(char *); %} /* declare tokens */ %token NUMBER %token OP_ADD OP_SUB OP_MUL OP_RGT OP_LFT OP_EQU %% calc: | calc exp OP_EQU { printf("Y: RESULT = %d\n", $2); } ; exp: factor | exp OP_ADD factor { $$ = $1 + $3; } | exp OP_SUB factor { $$ = $1 - $3; } ; factor: term | factor OP_MUL term { $$ = $1 * $3; } ; term: NUMBER | OP_LFT exp OP_RGT { $$ = $2; } ; %% int main(int argc, char **argv) { yyparse(); } int yyerror(char *s) { fprintf(stderr, "error: '%s'\n", s); }
Créons example.l
:
/* calculator source for flex */ %{ #include "example.tab.h" %} %% [0-9]+ { printf("L: NUMBER = %s\n", yytext); yylval = atoi(yytext); return NUMBER; } "+" { printf("L: OP_ADD\n"); return OP_ADD; } "-" { printf("L: OP_SUB\n"); return OP_SUB; } "*" { printf("L: OP_MUL\n"); return OP_MUL; } "(" { printf("L: OP_LFT\n"); return OP_LFT; } ")" { printf("L: OP_RGT\n"); return OP_RGT; } "=" { printf("L: OP_EQU\n"); return OP_EQU; } "exit" { printf("L: exit\n"); return YYEOF; } /* YYEOF = 0 */ . { /* ignore all other */ } %%
Puis exécutons comme suit à partir de l’invite de l’interpréteur pour tester cet exemple :
$ bison -d example.y $ flex example.l $ gcc -lfl example.tab.c lex.yy.c -o example $ ./example 1 + 2 * ( 3 + 1 ) = L: NUMBER = 1 L: OP_ADD L: NUMBER = 2 L: OP_MUL L: OP_LFT L: NUMBER = 3 L: OP_ADD L: NUMBER = 1 L: OP_RGT L: OP_EQU Y: RESULT = 9 exit L: exit
Des outils de type lint pour aider à l’analyse du code statique automatique.
Des outils de type Indent peuvent aider pour des révisions humaines du code en reformatant les codes sources de manière cohérente.
Des outils de type Ctags peuvent aider pour les révisions humaines de code en générant un fichier d’index (ou de balise) des noms trouvés dans les codes source.
Astuce | |
---|---|
Configurer votre éditeur préféré ( |
Tableau 12.12. Liste des outils d’analyse du code statique :
paquet | popularité | taille | description |
---|---|---|---|
vim-ale
|
I:0 | 2591 | moteur de vérification syntaxique asynchrone pour Vim 8 et NeoVim |
vim-syntastic
|
I:3 | 1379 | bidouilles de vérification de la syntaxe pour vim |
elpa-flycheck
|
V:0, I:1 | 808 | vérification moderne de la syntaxe à la volée pour Emacs |
elpa-relint
|
V:0, I:0 | 147 | recherche d’erreurs d’expressions rationnelles dans Emacs Lisp |
cppcheck-gui
|
V:0, I:1 | 7224 | outil graphique d'analyse statique du code C/C++ |
shellcheck
|
V:2, I:13 | 18987 | outil d’analyse syntaxique pour les scripts d’interpréteur |
pyflakes3
|
V:2, I:15 | 20 | vérificateur passif des programmes en Python 3 |
pylint
|
V:4, I:20 | 2018 | vérificateur de code statique Python |
perl
|
V:707, I:989 | 673 | interpréteur ayant un vérificateur de code statique interne :
B::Lint (3perl) |
rubocop
|
V:0, I:0 | 3247 | analyseur de code statique en Ruby |
clang-tidy
|
V:2, I:11 | 21 | outil d’analyse de C++ basé sur clang |
splint
|
V:0, I:2 | 2320 | outil pour vérifier de manière statique les bogues d’un programme en C |
flawfinder
|
V:0, I:0 | 205 | outil pour examiner le code source en C/C++ et rechercher des faiblesses du point de vue de la sécurité |
black
|
V:3, I:13 | 660 | formateur de code Python intransigeant |
perltidy
|
V:0, I:4 | 2493 | indenteur et formateur de script Perl |
indent
|
V:0, I:7 | 431 | programme de formatage de code source en langage C |
astyle
|
V:0, I:2 | 785 | indenteur de code source pour C, C++, Objective-C, C# et Java |
bcpp
|
V:0, I:0 | 111 | embellisseur pour C(++) |
xmlindent
|
V:0, I:1 | 53 | reformateur de flux XML |
global
|
V:0, I:2 | 1908 | outils de recherche et de navigation dans le code source |
exuberant-ctags
|
V:2, I:20 | 341 | constructeur des index de fichiers de balises des définitions du code source |
universal-ctags
|
V:1, I:11 | 3386 | constructeur des index de fichiers de balises des définitions du code source |
Le débogage est une partie de l’activité de programmation. Savoir comment déboguer des programmes fera de vous un bon utilisateur de Debian qui pourra produire des rapports de bogues documentés.
Le debogueur primaire sous Debian est
gdb
(1), il vous permet d’inspecter un programme alors
qu’il tourne.
Installons gdb
et les programmes associés par ce qui
suit :
# apt-get install gdb gdb-doc build-essential devscripts
Des bons tutoriels sur gdb
sont disponibles :
« info gdb
» ;
« Déboguer avec GDB » dans
/usr/share/doc/gdb-doc/html/gdb/index.html
;
« tutoriel sur le web ».
Voici un exemple simple d’utilisation de gdb
(1) sur un
« programme
» compilé avec l’option
« -g
» qui produit les informations de
débogage :
$ gdb program (gdb) b 1 # set break point at line 1 (gdb) run args # run program with args (gdb) next # next line ... (gdb) step # step forward ... (gdb) p parm # print parm ... (gdb) p parm=12 # set value to 12 ... (gdb) quit
Astuce | |
---|---|
De nombreuses commandes de |
Étant donné que par défaut tous les binaires installés doivent être réduits
à l’essentiel sur le système Debian, la plupart des symboles de débogage
sont supprimés dans les paquets normaux. Pour déboguer les paquets Debian
avec gdb
(1), les paquets *-dbgsym
doivent être installés (par exemple, coreutils-dbgsym
dans le cas de coreutils
). Les paquets source génèrent
automatiquement les paquets *-dbgsym
avec les paquets
binaires normaux et ces paquets de débogage sont placés séparément dans
l’archive debian-debug. Veuillez vous
référer aux articles sur le wiki de
Debian pour plus d’informations.
Si un paquet à déboguer ne fournit pas son paquet
*-dbgsym
, vous devrez l’installer après l’avoir
reconstruit comme suit :
$ mkdir /path/new ; cd /path/new $ sudo apt-get update $ sudo apt-get dist-upgrade $ sudo apt-get install fakeroot devscripts build-essential $ apt-get source package_name $ cd package_name* $ sudo apt-get build-dep ./
Corriger les bogues si nécessaire.
Modifier la version du paquet pour ne pas entrer en collision avec les
versions officielles de Debian, par exemple, en ajoutant
« +debug1
» pour la compilation d’une version
de paquet existante, ou « ~pre1
» pour la
compilation d’une version de paquet qui n’est pas encore diffusée de la
manière suivante :
$ dch -i
Compiler et installer les paquets avec les symboles de débogage comme suit :
$ export DEB_BUILD_OPTIONS="nostrip noopt" $ debuild $ cd .. $ sudo debi package_name*.changes
Vous devrez vérifier les scripts de construction du paquet et vous assurer
que les options « CFLAGS=-g -Wall
» sont
positionnées pour la compilation des binaires.
Si vous rencontrez un plantage de programme, signaler le bogue avec un copier-coller des informations de trace est une bonne idée.
La trace d’appels peut être obtenue avec gdb
en utilisant
une des manières suivantes :
Approche « plantage dans GDB » :
exécutez le programme à partir de GDB ;
plantez le programme ;
tapez « bt
» à l’invite de GDB.
Approche « plantage d’abord » :
mettez à jour le fichier « /etc/security/limits.conf » pour inclure l’élément suivant :
* soft core unlimited
tapez « ulimit -c unlimited
» à l’invite de
l’interpréteur ;
exécutez le programme à partir de cette invite de l’interpréteur ;
faites planter le programme pour produire un fichier core dump ;
chargez le fichier core dump dans GDB en
tant que « gdb gdb ./program_binary core
» ;
tapez « bt
» à l’invite de GDB.
Pour une situation de boucle infinie ou de clavier gelé, vous pouvez forcer
le plantage du programme en appuyant sur Ctrl-\
ou
Ctrl-C
ou en exécutant « kill -ABRT
PID
» (consulter la Section 9.4.12, « Tuer un processus »).
Astuce | |
---|---|
Souvent, vous voyez une trace où une ou plusieurs des lignes de départ se
trouvent dans « $ MALLOC_CHECK_=2 gdb hello |
Tableau 12.14. Liste des commandes avancées de gdb
commande | description des objectifs des commandes |
---|---|
(gdb) thread apply all bt |
obtenir une trace de tous les processus d’un programme multi-processus (multi-threaded) |
(gdb) bt full |
obtenir les paramètres qui se trouvent sur la pile d’appel des fonctions |
(gdb) thread apply all bt full |
obtenir une trace et les paramètres en combinant les options précédentes |
(gdb) thread apply all bt full 10 |
obtenir une trace et les paramètres des 10 premiers appels en supprimant ce qui n’est pas significatif |
(gdb) set logging on |
écrire le journal de sortie de gdb dans un fichier (le
fichier par défaut est « gdb.txt ») |
Utilisez ldd
(1) pour trouver les dépendances d’un
programme avec des bibliothèques :
$ ldd /usr/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
(1) fonctionne dans un environnement
`chroot`é, les bibliothèques ci-dessus doivent être disponibles dans votre
environnement `chroot`é.
Consultez Section 9.4.6, « Tracer l’activité d’un programme ».
Il existe plusieurs outils de traçage d’appels dynamique disponibles dans Debian. Consulter la Section 9.4, « Surveiller, contrôler et démarrer l’activité des programmes ».
Si un programme apercu1
de GNOME a reçu une erreur X,
vous devriez obtenir un message comme suit :
The program 'preview1' received an X Window System error.
Dans ce cas, vous pouvez essayer de faire tourner le programme avec
« --sync
» et arrêter sur la fonction
« gdk_x_error
» de manière à obtenir une trace.
Il y a plusieurs outils de détection des fuites de mémoire disponibles sous Debian.
Tableau 12.15. Liste des outils de détection des fuites de mémoire
paquet | popularité | taille | description |
---|---|---|---|
libc6-dev
|
V:248, I:567 | 12053 | mtrace (1) : fonctionnalité de débogage de malloc
dans glibc |
valgrind
|
V:6, I:37 | 78191 | débogueur mémoire et optimiseur |
electric-fence
|
V:0, I:3 | 73 | débogueur malloc (3) |
libdmalloc5
|
V:0, I:2 | 390 | bibliothèque de débogage de l’allocation mémoire |
duma
|
V:0, I:0 | 296 | bibliothèque permettant de détecter les dépassements et les sous-alimentations de tampon dans les programmes C et C++ |
leaktracer
|
V:0, I:1 | 56 | traceur de fuites de mémoire pour les programmes C++ |
Tableau 12.16. Liste des paquets d'outil de construction
paquet | popularité | taille | documentation |
---|---|---|---|
make
|
V:151, I:555 | 1592 | « info make » fourni par
make-doc |
autoconf
|
V:31, I:230 | 2025 | « info autoconf » fourni par
autoconf-doc |
automake
|
V:30, I:228 | 1837 | « info automake » fourni par
automake1.10-doc |
libtool
|
V:25, I:212 | 1213 | « info libtool » fourni par
libtool-doc |
cmake
|
V:17, I:115 | 36607 | cmake (1), système make multiplateforme et au code source
ouvert |
ninja-build
|
V:6, I:41 | 428 | ninja (1), petit système de construction le plus proche de
l’esprit de Make |
meson
|
V:3, I:22 | 3759 | meson (1), système de construction à haute productivité
sur au-dessus de ninja |
xutils-dev
|
V:0, I:9 | 1484 | imake (1), xmkmf (1), etc. |
Make est un utilitaire destiné à la maintenance
d’un groupe de programmes. Lors de l’exécution de
make
(1), make
lit le fichier de
règles, « Makefile
» et met à jour une cible si
elle dépend de fichiers qui ont été modifiés depuis que la cible a été
modifiée pour la dernière fois ou si la cible n’existe pas. L’exécution de
ces mises à jour peut être faite simultanément.
La syntaxe du fichier de règles est la suivante :
target: [ prerequisites ... ] [TAB] command1 [TAB] -command2 # ignore errors [TAB] @command3 # suppress echoing
Ici, « [TAB]
» est un code de
tabulation. Chaque ligne est interprétée par l’interpréteur de commandes
après que make ait effectué la substitution des variables. Utilisez
« \
» à la fin d’une ligne pour poursuivre le
script. Utilisez « $$
» pour entrer un
« $
» pour les valeurs des variables
d’environnement d’un script de l’interpréteur de commandes.
On peut écrire des règles implicites pour la cible et les prérequis, par exemple, de la manière suivante :
%.o: %.c header.h
Ici, la cible contient le caractère « %
»
(exactement 1 caractère). Le caractère « %
»
peut correspondre à n’importe quelle sous-chaîne non vide des noms de
fichiers de la cible actuelle. De même pour les prérequis, utilisez
« %
» pour afficher la manière dont leur nom
est en relation avec le nom de la cible actuelle.
Tableau 12.17. Liste des variables automatiques de make
variables automatiques | valeur |
---|---|
$@ |
cible |
$< |
première exigence |
$? |
toutes les exigences plus récentes |
$^ |
toutes les exigences |
$* |
« % » correspond au radical dans le motif cible |
Tableau 12.18. Liste de l’expansion des variables de make
expansion de la variable | description |
---|---|
toto := titi |
expansion à la volée |
toto2 = titi |
expression récursive |
toto3+= titi |
ajouter |
Exécutez « make -p -f/dev/null
» afin de voir
les règles automatiques internes.
Autotools est une suite d'outils de programmation conçus pour aider à rendre les paquets de code source portables sur de nombreux systèmes de type Unix .
Autoconf est un outil permettant de produire
un script d’interpréteur « configure
» à partir de
« configure.ac
».
« configure
» est utilisé ultérieurement pour produire un
« Makefile
» à partir du modèle
« Makefile.in
».
Automake est un outil permettant de produire
un « Makefile.in
» à partir de
« Makefile.am
».
Libtool est un script d’interpréteur permettant de résoudre le problème de portabilité des logiciels lors de la compilation de bibliothèques partagées à partir du code source.
Avertissement | |
---|---|
Ne pas écraser les fichiers du système avec les programmes que vous avez compilés en les installant. |
Debian ne touche pas aux fichiers se trouvant dans
« /usr/local/
» ou
« /opt
». Donc, si vous compilez un programme
depuis ses sources, installez-le dans
« /usr/local/
» de manière à ce qu’il
n’interfère pas avec Debian.
$ cd src $ ./configure --prefix=/usr/local $ make # this compiles program $ sudo make install # this installs the files in the system
Si vous avez les sources d’origine et s’ils utilisent
autoconf
(1) et automake
(1) et si
vous-vous souvenez comment vous l’avez configuré, exécutez-le comme suit
pour désinstaller le programme :
$ ./configure all-of-the-options-you-gave-it
$ sudo make uninstall
Sinon, si vous êtes absolument certain que le processus d’installation n’a
mis des fichiers que sous « /usr/local/
» et
qu’il n’y a là rien d’important, vous pouvez supprimer tout son contenu
avec :
# find /usr/local -type f -print0 | xargs -0 rm -f
Si vous n’êtes pas certain de l’emplacement où les fichiers ont été
installés, vous devriez envisager d’utiliser
checkinstall
(8) du paquet
checkinstall
, qui fournit un chemin propre pour la
désinstallation. Il prend maintenant en charge la création d’un paquet
Debian à l’aide de l’option « -D
».
Le système de construction des logiciels a évolué :
Autotools au-dessus de Make a été la norme de facto pour l'infrastructure de construction portable depuis les années 1990. Ce système est extrêmement lent ;
CMake, initialement publié en 2000, a considérablement amélioré la vitesse, mais il était à l'origine construit sur Make, intrinsèquement lent (aujourd'hui, Ninja peut être son dorsal) ;
Ninja initialement publié en 2012 est destiné à remplacer Make pour une meilleure vitesse de construction et est conçu pour que ses fichiers d'entrée soient générés par un système de construction de plus haut niveau ;
Meson, initialement publié en 2013, est le nouveau système de construction de haut niveau, populaire et rapide, qui utilise Ninja comme dorsal.
Consultez les documents disponibles dans « The Meson Build system » et « The Ninja build system ».
Des pages web dynamiques et interactives simples peuvent être faites de la manière suivante :
Les requêtes sont présentées au navigateur de l’utilisateur en utilisant des formulaires HTML.
Remplir et cliquer sur les entrées de formulaires envoie une des chaînes d’URL suivantes avec des paramètres codés depuis le navigateur vers le serveur web.
« https://www.foo.dom/cgi-bin/programme.pl?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3
»
« https://www.foo.dom/cgi-bin/programme.py?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3
»
« https://www.foo.dom/programme.php?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3
»
« %nn
» dans l’URL est remplacé par le
caractère dont la valeur hexadécimale est nn
.
La variable d’environnement est définie à :
« QUERY_STRING="VAR1=VAL1 VAR2=VAL2
VAR3=VAL3"
».
Le programme CGI (l’un quelconque des
« programme.*
») sur le serveur web s’exécute
lui-même avec la variable d’environnement
« $QUERY_STRING
».
La sortie standard (stdout)
du programme CGI est envoyée
au navigateur web et présentée sous forme d’une page web dynamique
interactive.
Pour des raisons de sécurité, il est préférable de ne pas réaliser soi-même de nouvelles bidouilles pour analyser les paramètres CGI. Il existe des modules bien établis pour cela, en Perl et Python. PHP est fourni avec ces fonctionnalités. Lorsqu’il est nécessaire d’enregistrer des données du client, on utilise des cookies HTTP. Lorsqu’un traitement de données est nécessaire côté client, on utilise fréquemment Javascript.
Pour davantage d’informations, consultez Common Gateway Interface, The Apache Software Foundation et JavaScript.
Rechercher « CGI tutorial » sur Google en entrant l’URL encodée https://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial directement dans la barre d’adresse du navigateur est une bonne méthode pour voir un script CGI en action sur le serveur Google.
Il existe des programmes pour convertir les codes sources.
Tableau 12.19. Liste des outils de conversion de code source
paquet | popularité | taille | mot clé | description |
---|---|---|---|---|
perl
|
V:707, I:989 | 673 | AWK→PERL | convertir le code source de AWK vers PERL : a2p (1) |
f2c
|
V:0, I:3 | 442 | FORTRAN→C | convertir le code source de FORTRAN 77 vers C/C++ :
f2c (1) |
intel2gas
|
V:0, I:0 | 178 | intel→gas | convertisseur depuis NASM (format Intel) vers l’Assembleur GNU (GAS) |
Si vous désirez créer un paquet Debian, lisez ce qui suit :
Chapitre 2, Gestion des paquets Debian pour comprendre les bases du système de paquets
Section 2.7.13, « Porter un paquet vers le système stable » pour comprendre les bases du processus de portage
Section 9.11.4, « Système protégé (chroot) » pour comprendre les techniques de base d’un environnement isolé (« chroot »)
debuild
(1) et sbuild
(1)
Section 12.5.2, « Déboguer un paquet Debian » pour recompiler avec les informations de débogage
Guide pour les responsables
Debian (le paquet debmake-doc
)
Référence du développeur
Debian (paquet developers-reference
)
Charte Debian (paquet
debian-policy
)
Il existe des paquets tels que debmake
,
dh-make
, dh-make-perl
, etc., qui
facilitent la réalisation des paquets.