Cuprins
Vă ofer câteva sfaturi pentru cei care doresc să învețe programarea pe sistemul Debian la un nivel suficient pentru a putea urmări codul sursă al pachetelor. Iată câteva pachete importante și documentația aferentă pentru programare.
Referințele sunt disponibile introducând „man nume” după
instalarea pachetelor manpages și
manpages-dev. Referințele pentru instrumentele GNU sunt
disponibile prin tastarea „info nume_program” după
instalarea pachetelor de documentație relevante. Este posibil să fie
necesar să includeți arhivele contrib și
non-free în plus față de arhiva main,
deoarece unele documentații GFDL nu sunt considerate conforme cu DFSG.
Vă recomandăm să utilizați instrumentele sistemului de control al versiunilor. Consultați Secțiune 10.5, „Git”.
|
Avertisment |
|---|---|
|
Nu folosiți „ |
|
Atenție |
|---|---|
|
Ar trebui să instalați programele software compilate direct din sursă în
„ |
|
Indicație |
|---|---|
|
Exemplele de cod pentru crearea melodiei „99 Bottles of Beer” ar trebui să vă ofere idei utile pentru aproape toate limbajele de programare. |
Scriptul shell este un fișier text cu dreptul de execuție activat și conține comenzi în următorul format.
#!/bin/sh ... command lines
Prima linie specifică interpretul shell care citește și execută conținutul acestui fișier.
Citirea scripturilor shell este cea mai bună modalitate de a înțelege cum funcționează un sistem de tip Unix. Aici vă ofer câteva indicații și sfaturi utile pentru programarea în shell. Consultați „Greșeli în shell” (https://www.greenend.org.uk/rjk/2001/04/shell.html) pentru a învăța din greșeli.
Spre deosebire de modul interactiv al shell-ului (a se vedea Secțiune 1.5, „Comanda simplă de shell” și Secțiune 1.6, „Procesarea textului în stilul Unix”), scripturile shell utilizează frecvent parametri, condiții și bucle.
Multe scripturi de sistem pot fi interpretate de oricare dintre shell-urile POSIX (vedeți Tabel 1.13, „Lista programelor shell”).
Shell-ul POSIX implicit, neinteractiv, „/usr/bin/sh”,
este o legătură simbolică care indică spre /usr/bin/dash
și este utilizat de multe programe din sistem.
Shell-ul POSIX interactiv implicit este /usr/bin/bash.
Evitați să scrieți un script de shell care conține „bashisme” (particularități ale shell-ului bash) sau
„zshisme>” (particularități ale
shell-ului zsh), pentru a-l face compatibil cu toate shell-urile
POSIX. Puteți verifica acest lucru folosind
checkbashisms(1).
Tabel 12.1. Lista expresiilor tipice din Bash („bashisme”)
| Bine: POSIX | De evitat: „bashismul” |
|---|---|
if [ "$foo" = "$bar" ] ; then … |
if [ "$foo" == "$bar" ] ; then … |
diff -u fișier.c.orig fișier.c |
diff -u fișier.c{.orig,} |
mkdir /foobar /foobaz |
mkdir /foo{bar,baz} |
funcname() { … } |
funcția funcname() { … } |
format octal: "\377" |
format hexazecimal: "\xff" |
Comanda „echo” trebuie utilizată cu următoarele
precauții, deoarece implementarea sa diferă între comenzile interne ale
shell-ului și cele externe.
Evitați utilizarea oricăror opțiuni ale comenzii «echo» cu excepția
„-n”.
Evitați utilizarea secvențelor de eludare în șir, deoarece gestionarea acestora variază.
|
Notă |
|---|---|
|
Deși opțiunea „ |
|
Indicație |
|---|---|
|
Folosiți comanda „ |
În scripturile shell se utilizează frecvent parametri speciali ai shell-ului.
Tabel 12.2. Lista parametrilor shell-ului
| prametru shell | valoare |
|---|---|
$0 |
numele shell-ului sau al scriptului shell |
$1 |
primul (1) argument al shell-ului |
$9 |
al nouălea (9-lea) argument al shell-ului |
$# |
numărul parametrilor de poziție |
"$*" |
"$1 $2 $3 $4 … " |
"$@" |
"$1" "$2" "$3" "$4" … |
$? |
starea de ieșire a celei mai recente comenzi |
$$ |
PID-ul acestui script de shell |
$! |
PID-ul celei mai recente sarcini de fundal pornite |
Expansiunile parametrilor de bază pe care trebuie să le rețineți sunt următoarele.
Tabel 12.3. Lista expansiunilor parametrilor shell-ului
| forma expresiei parametrului | valoarea dacă var este definită |
valoarea dacă var nu este definită |
|---|---|---|
${var:-string} |
"$var" |
„șir” |
${var:+string} |
„șir” |
„null” |
${var:=string} |
"$var" |
„șir” (și execută „var=șir”) |
${var:?string} |
"$var" |
afișează „șirul” la stderr (și iese cu eroare) |
Aici, caracterul „:” din toți acești operatori este, de
fapt, opțional.
cu „:” operatorul =
verifică dacă există și nu este nul
fără „:” operatorul =
verifică doar dacă există
Tabel 12.4. Lista substituțiilor parametrilor cheie ai shell-ului
| forma de substituire a parametrilor | rezultatul |
|---|---|
${var%suffix} |
elimină cel mai mic model de sufix |
${var%%suffix} |
elimină cel mai mare model de sufix |
${var#prefix} |
elimină cel mai mic model de prefix |
${var##prefix} |
elimină cel mai mare model de prefix |
Fiecare comandă returnează un cod de ieșire care poate fi utilizat în expresii condiționale.
Succes: 0 („True” - adevărat)
Eroare: diferit de 0 („False” - fals)
|
Notă |
|---|---|
|
În contextul condițional al shell-ului, „0” înseamnă „Adevărat”, în timp ce în contextul condițional al limbajului C, „0” înseamnă „Fals”. |
|
Notă |
|---|---|
|
„ |
Expresiile condiționale de bază pe care trebuie să le rețineți sunt următoarele.
„comandă &&
dacă_succes_execută_și_această_comandă ||
true”
„comandă ||
dacă_nu_a_reușit_execută_și_această_comandă ||
true”
Un fragment de cod cu mai multe linii, ca în exemplul următor
if [ conditional_expression ]; then if_success_run_this_command else if_not_success_run_this_command fi
Aici a fost necesară adăugarea secvenței „|| true” pentru
a se asigura că acest script de shell nu se închide accidental la această
linie atunci când shell-ul este invocat cu opțiunea „-e”.
Tabel 12.5. Lista operatorilor de comparare a fișierelor în expresia condițională
| ecuație | condiție care returnează valoarea logică „adevărat” |
|---|---|
-e fișier |
fișierul există |
-d fișier |
fișierul există și este un director |
-f fișier |
fișierul există și este un fișier obișnuit |
-w fișier |
fișierul există și poate fi accesat pentru scriere |
-x fișier |
fișierul există și este executabil |
fișier1 -nt
fișier2 |
fișier1 este mai recent decât fișier2 (data modificării) |
fișier1 -ot
fișier2 |
fișier1 este mai vechi decât fișier2 (data modificării) |
fișier1 -ef
fișier2 |
fișier1 și fișier2 se află pe același dispozitiv și au același număr de nod-i |
Tabel 12.6. Lista operatorilor de comparare a șirurilor în expresia condițională
| ecuație | condiție care returnează valoarea logică „adevărat” |
|---|---|
-z șir |
lungimea șirului este zero |
-n șir |
lungimea șirului este diferită de zero |
șir1 = șir2 |
șirul1 și șirul2 sunt egale |
șir1 != șir2 |
șirul1 și șirul2 nu sunt egale |
șir1 < șir2 |
șirul1 este sortat înaintea șirului2 (în funcție de configurația regională) |
șir1 > șir2 |
șirul1 este sortat după șirul2 (în funcție de configurația regională) |
Operatorii aritmetici de comparare a
numerelor întregi din expresia condițională sunt „-eq”,
„-ne”, „ -lt„,
”-le„, ”-gt„ și
”-ge".
În shell-ul POSIX există mai multe expresii de tip buclă care pot fi utilizate.
„for x in foo1 foo2 … ; do comanda ; done” efectuează o
buclă prin atribuirea elementelor din lista „foo1 foo2 …”
variabilei „x” și executarea
„comenzii”.
„while condiție ; do comanda ; done” repetă
„comanda” atâta timp cât „condiția”
este adevărată.
„until condiție ; do comanda ; done” repetă
„comanda” atâta timp cât „condiția” nu
este adevărată.
„break” permite ieșirea din buclă.
„continue” permite reluarea următoarei iterații a buclei.
|
Indicație |
|---|---|
|
Iterarea numerică specifică limbajului C poate fi
realizată folosind |
|
Indicație |
|---|---|
|
Consultați Secțiune 9.4.9, „Repetarea unei comenzi care parcurge fișierele”. |
Este posibil ca unele variabile de mediu uzuale pentru linia de comandă a shell-ului standard să nu fie disponibile în mediul de execuție al scriptului dumneavoastră.
Pentru „$USER”, folosiți „$(id -un)”
Pentru „$UID”, folosiți „$(id -u)”
Pentru „$HOME”, folosiți „$(getent passwd „$(id
-u)”|cut -d „:” -f 6)” (această comandă funcționează, de asemenea,
pe Secțiune 4.5.2, „Sistemul modern de gestionare centralizată”)
Shell-ul procesează un script aproximativ după următoarea secvență.
Shell-ul citește o linie.
Shell-ul grupează o parte a liniei ca un singur
element (token) dacă aceasta se află între "…"
sau '…'.
Shell-ul împarte restul unei linii în elemente (token-uri) după cum urmează.
Spații-albe: spațiu
tabulator linie-nouă
Metacaractere::< > | ; & ( )
Shell-ul verifică cuvântul rezervat
pentru fiecare token, pentru a-și adapta comportamentul în cazul în care
acesta nu se află între "…" sau '…'.
cuvânt rezervat: if then elif
else fi for in while unless do done case esac
Shell-ul extinde alias dacă acesta nu se
află între "…" sau '…'.
Shell-ul expandează tilde dacă nu se află
între "…" sau '…'.
„~” → directorul personal al utilizatorului curent
„~utilizator” → directorul personal
al utilizatorului
Shell-ul înlocuiește parametrul cu
valoarea acestuia, dacă nu se află între '…'.
parametru:
„$PARAMETER” sau „${PARAMETER}”
Shell-ul extinde substituirea comenzii
dacă aceasta nu se află între '…'.
„$( comandă )” → ieșirea comenzii
„comandă”
„` comandă `” → rezultatul comenzii
„comandă”
Shell-ul extinde expresia de tip glob (cu caractere
joker) pentru ruta la numele de fișiere corespunzătoare, dacă
acestea nu se află între "…" sau '…'.
* → orice caractere
? → un caracter
[…] → oricare dintre caracterele din
"…"
Shell-ul caută comanda din următoarele și o execută.
definiția funcției
comanda internă
fișierul executabil din
„$PATH”
Shell-ul trece la linia următoare și repetă acest proces de la începutul secvenței.
Ghilimelele simple între ghilimele duble nu au niciun efect.
Executarea comenzii „set -x” în shell sau lansarea
shell-ului cu opțiunea „-x” determină shell-ul să afișeze
toate comenzile executate. Acest lucru este foarte util pentru depanare.
Pentru a face programul dvs. de tip shell cât mai portabil posibil pe sistemele Debian, este recomandat să limitați utilizarea programelor utilitare la cele furnizate de pachetele esențiale.
«aptitude search ~E» listează pachetele esențiale.
«dpkg -L nume_pachet | grep
'/man/man.*/'» afișează paginile de manual pentru comenzile
oferite de pachetul nume_pachet.
Tabel 12.7. Lista pachetelor care conțin mici programe utilitare pentru scripturi shell
| pachet | popcon(popularitate) | dimensiune | descriere |
|---|---|---|---|
dash
|
V:912, I:998 | 207 | un shell mic și rapid, compatibil cu POSIX, pentru sh |
coreutils
|
V:897, I:1000 | 17994 | instrumente de bază GNU |
grep
|
V:768, I:1000 | 1297 | GNU grep, egrep și
fgrep |
sed
|
V:810, I:1000 | 987 | GNU sed |
mawk
|
V:468, I:998 | 295 | mic și rapid awk |
debianutils
|
V:921, I:997 | 225 | diverse instrumente specifice Debian |
bsdutils
|
V:443, I:999 | 335 | instrumente de bază din 4.4BSD-Lite |
bsdextrautils
|
V:734, I:851 | 361 | instrumente extra din 4.4BSD-Lite |
moreutils
|
V:16, I:38 | 231 | instrumente Unix suplimentare |
|
Indicație |
|---|---|
|
Deși |
Consultați Secțiune 1.6, „Procesarea textului în stilul Unix” pentru exemple.
Tabel 12.8. Lista pachetelor legate de interpret
| pachet | popcon(popularitate) | dimensiune | documentație |
|---|---|---|---|
dash
|
V:912, I:998 | 207 | sh: un shell mic și rapid, compatibil cu POSIX,
pentru sh |
bash
|
V:874, I:999 | 7277 | sh: „info bash” furnizat de
bash-doc |
mawk
|
V:468, I:998 | 295 | AWK: o versiune compactă și rapidă a
awk |
gawk
|
V:253, I:311 | 3289 | AWK: „info gawk” furnizat de
gawk-doc |
perl
|
V:673, I:991 | 841 | Perl: perl(1) și paginile
HTML furnizate de perl-doc și
perl-doc-html |
libterm-readline-gnu-perl
|
V:2, I:28 | 439 | Extensie Perl pentru biblioteca GNU ReadLine/History:
perlsh(1) |
libreply-perl
|
V:0.01, I:0.11 | 171 | REPL pentru Perl: reply(1) |
libdevel-repl-perl
|
V:0.03, I:0.55 | 237 | REPL pentru Perl: re.pl(1) |
python3
|
V:719, I:971 | 82 | Python: python3(1) și
paginile HTML furnizate de python3-doc |
tcl
|
V:25, I:185 | 20 | Tcl: tcl(3) și paginile de
manual detaliate furnizate de tcl-doc |
tk
|
V:19, I:179 | 20 | Tk: tk(3) și paginile de manual
detaliate furnizate de tk-doc |
ruby
|
V:70, I:167 | 32 | Ruby: ruby(1),
erb(1), irb(1),
rdoc(1), ri(1) |
Când doriți să automatizați o sarcină în Debian, ar trebui să o programați mai întâi într-un limbaj interpretat. Ghidul pentru alegerea limbajului interpretat este:
Folosiți dash dacă sarcina este una simplă, care combină
programe CLI cu un program shell.
Folosiți python3 dacă sarcina nu este una simplă și o
scrieți de la zero.
Folosiți perl, tcl,
ruby, ... dacă există un cod existent în Debian care
utilizează unul dintre aceste limbaje și care trebuie modificat pentru a
îndeplini sarcina.
Dacă codul rezultat este prea lent, puteți rescrie doar porțiunea esențială pentru viteza de execuție într-un limbaj compilat și o puteți apela din limbajul interpretat.
Majoritatea interpreților oferă funcționalități de bază pentru verificarea sintaxei și urmărirea codului.
«dash -n script.sh» - Verificarea sintaxei unui script Shell
«dash -x script.sh» - Trasarea execuției unui script Shell
«python -m py_compile script.py» - Verificarea sintaxei unui script Python
«python -mtrace --trace script.py» - Trasarea execuției unui script Python
“perl -I ../libpath -c script.pl” - Verificarea sintaxei unui script Perl
“perl -d:Trace script.pl” - Trasarea execuției unui script Perl
Pentru a testa codul pentru dash, încercați Secțiune 9.1.4, „Readline wrapper (învăluitorul «readline»)”, care oferă un mediu interactiv similar cu
bash.
Pentru a testa codul în Perl, încercați mediul REPL
pentru Perl, care oferă un mediu de tip Python
– adică un mediu REPL (=READ + EVAL +
PRINT + LOOP) pentru Perl.
Scriptul Shell poate fi îmbunătățit pentru a crea un program cu interfață
grafică atractivă. Secretul constă în utilizarea unuia dintre așa-numitele
programe de tip dialog, în locul interacțiunii monotone bazate pe comenzile
echo și read.
Tabel 12.9. Lista programelor de dialog
| pachet | popcon(popularitate) | dimensiune | descriere |
|---|---|---|---|
x11-utils
|
V:227, I:568 | 651 | xmessage(1): afișează un mesaj sau o solicitare într-o
fereastră (X) |
whiptail
|
V:300, I:996 | 61 | afișează casete de dialog ușor de utilizat din scripturi shell (newt) |
dialog
|
V:9, I:82 | 520 | afișează casete de dialog ușor de utilizat din scripturi shell (ncurses) |
zenity
|
V:67, I:358 | 194 | afișează casete de dialog grafice din scripturi shell (GTK) |
ssft
|
V:0.01, I:0.18 | 75 | Instrument de interfață pentru scripturi Shell (înveliș pentru zenity, kdialog și dialog cu gettext) |
gettext
|
V:54, I:230 | 7165 | "/usr/bin/gettext.sh": traduce mesajul |
Iată un exemplu de program cu interfață grafică care demonstrează cât de ușor este să realizezi acest lucru folosind doar un script de shell.
Acest script utilizează zenity pentru a selecta un fișier
(implicit /etc/motd) și a-l afișa.
Lansatorul GUI pentru acest script poate fi creat urmând instrucțiunile de la Secțiune 9.4.10, „Pornirea unui program din interfața grafică”.
#!/bin/sh -e
# Copyright (C) 2021 Osamu Aoki <osamu@debian.org>, 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
Acest tip de abordare a programelor cu interfață grafică (GUI) folosind scripturi shell este utilă doar în cazurile simple. Dacă intenționați să scrieți un program mai complex, vă recomandăm să îl scrieți pe o platformă mai performantă.
Programele de gestionare a fișierelor cu interfață grafică pot fi extinse pentru a efectua anumite operații uzuale asupra fișierelor selectate, folosind pachete de extensii suplimentare. De asemenea, pot fi configurate să execute operații personalizate foarte specifice prin adăugarea propriilor scripturi.
Pentru GNOME, consultați NautilusScriptsHowto.
Pentru KDE, consultați Creating Dolphin Service Menus (Crearea meniurilor de servicii Dolphin).
Pentru Xfce, consultați Thunar - Custom Actions (Thunar - Acțiuni personalizate) și https://help.ubuntu.com/community/ThunarCustomActions.
Pentru LXDE, consultați Custom Actions (Acțiuni personalizate).
Pentru a procesa datele, sh trebuie să lanseze subprocese
care execută cut, grep,
sed etc., iar acest lucru este lent. Pe de altă parte,
perl dispune de capacități interne de procesare a datelor
și este rapid. De aceea, multe scripturi de întreținere a sistemului pe
Debian folosesc perl.
Să analizăm următorul fragment de script AWK de o singură linie și echivalentele sale în Perl.
awk '($2=="1957") { print $3 }' |
Aceasta este echivalentă cu oricare dintre următoarele linii.
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' |
Ultima este o ghicitoare. Aceasta a folosit următoarele caracteristici ale limbajului Perl.
Spațiul în alb este opțional.
Există o conversie automată de la număr la șir de caractere.
Trucuri pentru executarea Perl prin opțiuni de linie de comandă:
perlrun(1)
Variabile speciale Perl: perlvar(1)
Această flexibilitate este punctul forte al limbajului Perl. În același timp, aceasta ne permite să creăm coduri criptice și încâlcite. Așadar, fiți atenți.
Tabel 12.10. Lista pachetelor legate de compilator
| pachet | popcon(popularitate) | dimensiune | descriere |
|---|---|---|---|
gcc
|
V:157, I:565 | 36 | compilatorul GNU C |
libc6-dev
|
V:274, I:584 | 12694 | biblioteca GNU C: biblioteci de dezvoltare și fișiere de antet |
g++
|
V:58, I:528 | 13 | compilatorul GNU C++ |
libstdc++-14-dev
|
V:33, I:234 | 24527 | biblioteca standard GNU C++ v3 (fișiere de dezvoltare) |
cpp
|
V:339, I:727 | 18 | preprocesorul GNU C |
gettext
|
V:54, I:230 | 7165 | instrumente de internaționalizare GNU |
glade
|
V:0.6, I:3.2 | 1613 | constructor de interfețe grafice de utilizator GTK |
valac
|
V:0.3, I:3.4 | 532 | limbaj similar cu C# pentru sistemul GObject |
flex
|
V:7, I:69 | 1247 | generator de analizare lexicală rapidă compatibil cu LEX- |
bison
|
V:7, I:74 | 3122 | generator de analizare compatibil cu YACC |
susv2
|
I:0.04 | 16 | preia „Specificațiile UNIX unice v2” |
susv3
|
I:0.06 | 16 | preia „Specificațiile UNIX unice v3” |
susv4
|
I:0.05 | 16 | preia „Specificațiile UNIX unice v4” |
golang
|
I:21 | 12 | compilator pentru limbajul de programare Go |
rustc
|
V:5, I:18 | 13748 | limbajul de programare de sisteme Rust |
gfortran
|
V:5, I:53 | 15 | compilatorul GNU Fortran 95 |
fpc
|
I:2.5 | 101 | Free Pascal |
Aici, Secțiune 12.3.3, „Flex — o versiune îmbunătățită a Lex” și Secțiune 12.3.4, „Bison — o versiune îmbunătățită a Yacc” sunt incluse pentru a arăta cum se pot scrie programe de tip compilator în limbajul C, prin compilarea unei descrieri de nivel superior în limbajul C.
Puteți configura mediul necesar pentru a compila programe scrise în limbajul de programare C urmând pașii de mai jos.
# apt-get install glibc-doc manpages-dev libc6-dev gcc build-essential
Pachetul libc6-dev, adică biblioteca GNU C, oferă biblioteca standard C, care este o colecție
de fișiere antet și rutine de bibliotecă utilizate de limbajul de programare
C.
A se vedea următoarele referințe pentru limbajul C.
„info libc” (referința funcțiilor bibliotecii C)
gcc(1) și «info gcc»
each_C_library_function_name(3)
Kernighan & Ritchie, „The C Programming Language” - Limbajul de programare C, ediția a II-a (Prentice Hall)
Un exemplu simplu, „example.c”, poate fi compilat
împreună cu biblioteca „libm” într-un fișier executabil
„run_example” după cum urmează.
$ 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
Aici, „-lm” este necesar pentru a lega biblioteca
„/usr/lib/libm.so” din pachetul libc6
pentru sqrt(3). Biblioteca propriu-zisă se află în
„/lib/” cu numele de fișier
„libm.so.6”, care este o legătură simbolică către
„libm-2.7.so”.
Uită-te la ultimul parametru din textul afișat. Are mai mult de 10
caractere, deși s-au specificat „%10s”.
Utilizarea funcțiilor de operare cu memoria prin intermediul indicatoare
fără verificări de limite, precum sprintf(3) și
strcpy(3), este învechită pentru a preveni exploatările
de tip „buffer overflow” (debordare a memoriei tampon) care profită de
efectele de depășire menționate mai sus. În schimb, utilizați
snprintf(3) și strncpy(3).
Flex este un generator de analizare lexicală rapidă, compatibil cu Lex.
Tutorialul pentru flex(1) poate fi găsit în
«info flex».
Multe exemple simple pot fi găsite în
„/usr/share/doc/flex/examples/”. [7]
În Debian, există mai multe pachete care oferă un generator de analizare LR cu citire anticipată compatibil cu Yacc sau un generator de analizare LALR.
Tabel 12.11. Lista generatoarelor de analizare LALR compatibile cu Yacc
| pachet | popcon(popularitate) | dimensiune | descriere |
|---|---|---|---|
bison
|
V:7, I:74 | 3122 | generator de analizare LALR GNU |
byacc
|
V:0.1, I:3.2 | 263 | generator de analizare LALR Berkeley |
btyacc
|
V:0.01, I:0.06 | 251 | generator de analizare cu capacitate de urmărire bazat pe
byacc |
Tutorialul pentru bison(1) poate fi găsit în
«info bison».
Trebuie să furnizați propriile funcții „main()” și
„yyerror()”. Funcția „main()” apelează
funcția „yyparse()”, care la rândul ei apelează funcția
„yylex()”, create de obicei cu ajutorul Flex.
Iată un exemplu de creare a unui program simplu de calculator pentru terminal.
Să creăm 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);
}
Să creăm 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 */ }
%%
Apoi, pentru a încerca acest lucru, executați următoarea comandă din linia de comandă:
$ 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
Instrumentele de tip Lint pot facilita efectuarea automată a analizei statice a codului.
Instrumentele de tip Indent pot facilita revizuirea manuală a codului prin reformatarea consecventă a codurilor sursă.
Instrumentele precum Ctags pot ajuta la revizuirea manuală a codului prin generarea unui fișier index (sau de etichete) cu numele identificate în codurile sursă.
|
Indicație |
|---|---|
|
Configurarea editorului preferat ( |
Tabel 12.12. Lista instrumentelor pentru analiza statică a codului
| pachet | popcon(popularitate) | dimensiune | descriere |
|---|---|---|---|
vim-ale
|
I:0.82 | 2833 | motor lint asincron pentru Vim 8 și NeoVim |
vim-syntastic
|
I:2.3 | 1379 | trucuri pentru verificarea sintaxei în Vim |
elpa-flycheck
|
V:0.1, I:1.6 | 815 | verificare sintactică din mers pentru Emacs |
elpa-relint
|
I:0.05 | 150 | instrument de detectare a erorilor în expresiile regulate Emacs Lisp |
cppcheck-gui
|
V:0.1, I:1.1 | 7682 | instrument pentru analiza statică a codului C/C++ (interfață grafică) |
shellcheck
|
V:3, I:16 | 22859 | instrument de analizare sintatică a scripturilor shell |
pyflakes3
|
V:2, I:15 | 20 | verificator pasiv al programelor Python 3 |
pylint
|
V:4, I:20 | 2089 | verificator static al codului Python |
perl
|
V:673, I:991 | 841 | interpret cu verificator intern de cod static:
B::Lint(3perl) |
rubocop
|
V:0.11, I:0.96 | 3981 | analizator de cod static Ruby |
clang-tidy
|
V:2, I:12 | 22 | instrument de analizare sintactică a codului C++ bazat pe clang |
splint
|
V:0.1, I:1.0 | 2328 | instrument pentru verificarea statică a programelor C în vederea depistării erorilor |
flawfinder
|
V:0.07, I:0.52 | 205 | instrument pentru examinarea codului sursă C/C++ și identificarea vulnerabilităților de securitate |
black
|
V:4, I:16 | 9975 | instrument de formatare a codului Python fără compromisuri |
perltidy
|
V:0.5, I:3.2 | 3086 | instrument de indentare și reformatare a scripturilor Perl |
indent
|
V:0.4, I:5.3 | 438 | program de formatare a codului sursă în limbajul C |
astyle
|
V:0.2, I:2.6 | 769 | instrument de indentare a codului sursă pentru limbajele C, C++, Objective-C, C# și Java |
bcpp
|
V:0.02, I:0.29 | 114 | instrument de formatare elegantă pentru C(++) |
xmlindent
|
V:0.08, I:0.85 | 52 | instrument de reformatare a fluxului XML |
global
|
V:0.2, I:1.7 | 1923 | instrumente de căutare și navigare în codul sursă |
exuberant-ctags
|
V:2, I:14 | 341 | creează indexuri ale fișierelor de etichete pentru definițiile codului sursă |
universal-ctags
|
V:1, I:12 | 4238 | creează indexuri ale fișierelor de etichete pentru definițiile codului sursă |
Depanarea este o parte importantă a activităților de programare. Dacă știi să depanezi programele, devii un utilizator Debian competent, capabil să întocmească rapoarte de erori relevante.
Tabel 12.13. Lista pachetelor de depanare
| pachet | popcon(popularitate) | dimensiune | documentație |
|---|---|---|---|
gdb
|
V:82, I:158 | 12478 | «info gdb» furnizat de gdb-doc |
ddd
|
V:0.4, I:5.6 | 4210 | «info ddd» furnizat de ddd-doc |
Principalul depanator din Debian este
gdb(1), care vă permite să examinați un program în timpul
execuției.
Să instalăm gdb și programele asociate urmând pașii de
mai jos.
# apt-get install gdb gdb-doc build-essential devscripts
Un bun tutorial despre gdb este disponibil:
«info gdb»
„Depanarea cu GDB” în
/usr/share/doc/gdb-doc/html/gdb/index.html
Iată un exemplu simplu de utilizare a gdb(1) pe un
„program” compilat cu opțiunea „-g”
pentru a genera informații de depanare.
$ 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
|
Indicație |
|---|---|
|
Multe comenzi |
Deoarece toate fișierele binare instalate trebuie să fie curățate de
simboluri în sistemul Debian în mod implicit, majoritatea simbolurilor de
depanare sunt eliminate din pachetul standard. Pentru a depana pachetele
Debian cu gdb(1), trebuie instalate pachetele
*-dbgsym (de exemplu, coreutils-dbgsym
în cazul coreutils). Pachetele sursă generează automat
pachete *-dbgsym împreună cu pachetele binare normale,
iar aceste pachete de depanare sunt plasate separat în arhiva debian-debug. Vă rugăm să consultați articolele de pe Debian Wiki pentru mai
multe informații.
Dacă un pachet care urmează să fie depanat nu include pachetul
*-dbgsym, trebuie să îl instalați după ce îl recompilați,
urmând pașii de mai jos.
$ 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 ./
Remediați erorile, dacă este necesar.
Actualizați versiunea pachetului la una care nu intră în conflict cu
versiunile oficiale Debian, de exemplu una la care se adaugă
„+debug1” atunci când recompilați o versiune existentă a
pachetului, sau una la care se adaugă „~pre1” atunci când
compilați o versiune a pachetului care nu a fost încă lansată, urmând pașii
de mai jos.
$ dch -i
Compilați și instalați pachetele cu simboluri de depanare urmând pașii de mai jos.
$ export DEB_BUILD_OPTIONS="nostrip noopt" $ debuild $ cd .. $ sudo debi package_name*.changes
Trebuie să verificați scripturile de compilare ale pachetului și să vă
asigurați că utilizați „CFLAGS=-g -Wall” pentru
compilarea fișierelor binare.
Când programul se „prăbușește” (crash), este recomandat să trimiteți un raport de eroare care să conțină informațiile traseului de execuție copiate și lipite.
Urmărirea traseului de execuție poate fi obținută prin
gdb(1) folosind una dintre următoarele metode:
Abordarea „Crash-in-GDB”:
Rulați programul din GDB.
Blocați programul (faceți-l să se prăbușească).
Tastați „bt” în promptul GDB.
Abordarea „crash-first”:
Actualizați fișierul „/etc/security/limits.conf” pentru a include următoarele:
* soft core unlimited
Tastați «ulimit -c unlimited» în promptul shell-ului.
Rulați programul din acest prompt shell.
Provocați prăbușirea programului pentru a genera un fișier core dump.
Încărcați fișierul core dump în GDB folosind
comanda «gdb gdb ./program_binary core».
Tastați „bt” în promptul GDB.
În cazul unei bucle infinite sau al blocării tastaturii, puteți forța
închiderea programului apăsând Ctrl-\ sau
Ctrl-C sau executând comanda „kill -ABRT
PID”. (Consultați Secțiune 9.4.12, „Omorârea unui proces”)
|
Indicație |
|---|---|
|
Adesea, se întâmplă să vezi o urmă de execuție în care una sau mai multe
dintre primele linii sunt de tipul „ $ MALLOC_CHECK_=2 gdb hello |
Tabel 12.14. Lista comenzilor avansate gdb
| comandă | descrierea obiectivelor comenzii |
|---|---|
(gdb) thread apply all bt |
obține o urmărire a traseului de execuție pentru toate firele de execuție ale unui program cu mai multe fire de execuție |
(gdb) bt full |
obține parametrii aflați în stiva de apeluri de funcții |
(gdb) thread apply all bt full |
obține o urmărire a traseului de execuției și parametrii ca urmare a combinării opțiunilor anterioare |
(gdb) thread apply all bt full 10 |
obțineți o urmărire a traseului de execuție și parametrii pentru primele 10 apeluri, pentru a elimina rezultatele irelevante |
(gdb) set logging on |
înregistrează jurnalul ieșirii gdb într-un fișier
(implicit este „gdb.txt”) |
Folosiți ldd(1) pentru a afla de ce biblioteci depinde un
program, urmând pașii de mai jos.
$ 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)
Pentru ca ls(1) să funcționeze într-un mediu „chroot”,
bibliotecile menționate mai sus trebuie să fie disponibile în mediul
„chroot”.
Consultați Secțiune 9.4.6, „Urmărirea activităților programului”.
În Debian sunt disponibile mai multe instrumente de urmărire dinamică a apelurilor. Consultați Secțiune 9.4, „Monitorizarea, controlul și inițierea activităților programului”.
Dacă un program GNOME preview1 a primit o eroare X, ar
trebui să apară următorul mesaj.
The program 'preview1' received an X Window System error.
În acest caz, puteți încerca să rulați programul cu opțiunea
„--sync” și să opriți execuția la funcția
„gdk_x_error” pentru a obține o urmărire a traseului
execuției.
În Debian sunt disponibile mai multe instrumente de detectare a „scurgerilor” de memorie.
Tabel 12.15. Lista instrumentelor de detectare a „scurgerilor” de memorie
| pachet | popcon(popularitate) | dimensiune | descriere |
|---|---|---|---|
libc6-dev
|
V:274, I:584 | 12694 | mtrace(1): funcționalitate de depanare a malloc în glibc |
valgrind
|
V:6, I:34 | 87847 | instrument de depanare și optimizare a memoriei |
electric-fence
|
V:0.1, I:2.2 | 69 | instrument de depanare malloc(3) |
libdmalloc5
|
V:0.02, I:0.66 | 380 | bibliotecă de depanare a alocării memoriei |
duma
|
V:0.01, I:0.07 | 297 | bibliotecă pentru detectarea depășirilor și a subutilizărilor de memorie tampon în programele C și C++ |
leaktracer
|
V:0.01, I:0.40 | 56 | instrument de depistare a scurgerilor de memorie pentru programe C++ |
Tabel 12.16. Lista pachetelor de instrumente de construire
| pachet | popcon(popularitate) | dimensiune | documentație |
|---|---|---|---|
make
|
V:152, I:566 | 1762 | «info make» furnizat de make-doc |
autoconf
|
V:29, I:206 | 2197 | «info autoconf» furnizat de
autoconf-doc |
automake
|
V:28, I:205 | 1932 | «info automake» furnizat de
automake1.10-doc |
libtool
|
V:24, I:189 | 1245 | «info libtool» furnizat de libtool-doc |
cmake
|
V:19, I:120 | 44267 | cmake(1) sistem de compilare multiplatformă, cu
codul-sursă deschis |
ninja-build
|
V:8, I:53 | 456 | ninja(1) un sistem de compilare compact, care se apropie
cel mai mult de spiritul Make |
meson
|
V:7, I:29 | 4186 | meson(1) sistem de compilare de înaltă productivitate
bazat pe ninja |
xutils-dev
|
V:0.6, I:7.4 | 1495 | imake(1), xmkmf(1), etc. |
Make este un instrument destinat gestionării
grupurilor de programe. La executarea comenzii make(1),
make citește fișierul de reguli,
„Makefile”, și actualizează o țintă dacă aceasta depinde
de fișiere prealabile care au fost modificate de la ultima modificare a
țintei respective sau dacă ținta nu există. Executarea acestor actualizări
poate avea loc simultan.
Sintaxa fișierului de reguli este următoarea.
target: [ prerequisites ... ] [TAB] command1 [TAB] -command2 # ignore errors [TAB] @command3 # suppress echoing
Aici „[TAB]” reprezintă un cod TAB (codul de
tabulare). Fiecare linie este interpretată de shell după ce se efectuează
substituirea variabilelor. Folosiți „\” la sfârșitul unei
linii pentru a continua scriptul. Folosiți „$$” pentru a
introduce „$” ca valori de mediu pentru un script de
shell.
Regulile implicite pentru țintă și condițiile prealabile pot fi formulate, de exemplu, după cum urmează.
%.o: %.c header.h
În acest caz, ținta conține caracterul „%” (exact
unul). „%” poate corespunde oricărui subșir non-vid din
numele de fișiere țintă efective. De asemenea, condițiile preliminare
utilizează „%” pentru a ilustra modul în care numele lor
se raportează la numele țintei efective.
Tabel 12.17. Lista variabilelor automate «make»
| variabila automată | valoare |
|---|---|
$@ |
ținta |
$< |
prima cerință prealabilă |
$? |
toate cerințele prealabile mai recente |
$^ |
toate cerințele prealabile |
$* |
„%” corespunde cu rădăcina din modelul țintă |
Tabel 12.18. Lista expansiunilor variabilelor «make»
| expansiunea variabilei | descriere |
|---|---|
foo1 := bar |
expansiune unică |
foo2 = bar |
expansiune recursivă |
foo3 += bar |
adăugare |
Rulați «make -p -f/dev/null» pentru a vedea regulile
interne automate.
Autotools este o suită de instrumente de programare concepută pentru a facilita portabilitatea pachetelor de cod sursă pe numeroase sisteme de tip Unix.
Autoconf este un instrument care generează
un script shell „configure” din
„configure.ac”.
«configure» este utilizat ulterior pentru a genera
fișierul «Makefile» pornind de la șablonul
„Makefile.in”.
Automake este un instrument care generează
fișierul „Makefile.in” din fișierul
„Makefile.am”.
Libtool este un script shell care rezolvă problema portabilității software-ului la compilarea bibliotecilor partajate din codul sursă.
|
Avertisment |
|---|---|
|
Nu suprascrieți fișierele de sistem cu programele compilate atunci când le instalați. |
Debian nu modifică fișierele din „/usr/local/” sau
„/opt”. Așadar, dacă compilați un program din sursă,
instalați-l în „/usr/local/”, pentru a nu interfera cu
Debian.
$ cd src $ ./configure --prefix=/usr/local $ make # this compiles program $ sudo make install # this installs the files in the system
Dacă dispuneți de sursa originală și dacă aceasta utilizează
autoconf(1)/automake(1) și dacă vă
amintiți cum ați configurat-o, executați următoarele comenzi pentru a
dezinstala programul.
$ ./configure all-of-the-options-you-gave-it
$ sudo make uninstall
Alternativ, dacă sunteți absolut sigur că procesul de instalare plasează
fișierele numai în directorul „/usr/local/” și că acolo
nu se află nimic important, puteți șterge tot conținutul acestuia urmând
pașii de mai jos.
# find /usr/local -type f -print0 | xargs -0 rm -f
Dacă nu știți exact unde sunt instalate fișierele, vă recomandăm să folosiți
checkinstall(8) din pachetul
checkinstall, care asigură o dezinstalare completă. Acum
acceptă crearea unui pachet Debian cu opțiunea „-D”.
Sistemul de construire a software-ului a evoluat:
Autotools, care a precedat Make, a reprezentat standardul de facto pentru infrastructura de compilare portabilă încă din anii 1990. Acesta este extrem de lent.
CMake, lansat inițial în 2000, a îmbunătățit semnificativ viteza, dar a fost construit inițial pe baza instrumentului Make, care este lent prin natura sa. În prezent, Ninja poate fi folosit ca motor al acestuia.
Ninja, lansat inițial în 2012, are rolul de a înlocui Make pentru a îmbunătăți și mai mult viteza de compilare și este conceput astfel încât fișierele sale de intrare să fie generate de un sistem de compilare de nivel superior.
Meson, lansat inițial în 2013, este un sistem de compilare de nivel superior, popular și rapid, care utilizează Ninja ca motor.
Consultați documentele disponibile la „Sistemul de compilare Meson” și „Sistemul de compilare Ninja”.
Paginile web dinamice și interactive simple pot fi create după cum urmează.
Întrebările sunt prezentate utilizatorului navigatorului folosind formulare HTML.
Completarea câmpurilor formularului și apăsarea butonului de trimitere trimite unul dintre următoarele șiruri URL cu parametri codificați din navigator către serverul web.
"https://www.foo.dom/cgi-bin/program.pl?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3"
"https://www.foo.dom/cgi-bin/program.py?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3"
"https://www.foo.dom/program.php?VAR1=VAL1&VAR2=VAL2&VAR3=VAL3"
„%nn” din adresa URL este înlocuit cu un caracter cu
valoarea hexazecimală nn.
Variabila de mediu este configurată astfel:
"QUERY_STRING="VAR1=VAL1 VAR2=VAL2 VAR3=VAL3"".
Programul CGI (oricare dintre programele de tip
„program.*”) de pe serverul web se execută cu variabila
de mediu „$QUERY_STRING”.
stdout ieșirea standard a programului CGI este transmisă
către navigatorul web și este afișată sub forma unei pagini web dinamice
interactive.
Din motive de securitate, este recomandat să nu creați manual noi metode de analizare a parametrilor CGI. Există module consacrate pentru acest scop în Perl și Python. PHP include deja aceste funcționalități. Când este necesară stocarea datelor pe partea clientului, se utilizează cookie-urile HTTP. Când este necesară procesarea datelor pe partea clientului, se utilizează frecvent Javascript.
Pentru mai multe informații, consultați Common Gateway Interface, The Apache Software Foundation și JavaScript.
Căutarea expresiei „CGI tutorial” în Google, introducând adresa URL codificată https://www.google.com/search?hl=en&ie=UTF-8&q=CGI+tutorial direct în bara de adrese a browserului, este o modalitate bună de a vedea scriptul CGI în acțiune pe serverul Google.
Există programe pentru conversia codurilor sursă.
Tabel 12.19. Lista instrumentelor de conversie a codului sursă
| pachet | popcon(popularitate) | dimensiune | cuvânt-cheie | descriere |
|---|---|---|---|---|
perl
|
V:673, I:991 | 841 | AWK→PERL | convertește codurile sursă din AWK în PERL: a2p(1) |
f2c
|
V:0.1, I:2.0 | 443 | FORTRAN→C | convertește codurile sursă din FORTRAN 77 în C/C++:
f2c(1) |
intel2gas
|
V:0.02, I:0.20 | 178 | intel→gas | convertor de la NASM (format Intel) la GNU Assembler (GAS) |
Dacă doriți să creați un pachet Debian, citiți informațiile de mai jos.
Cap. 2, Gestionarea pachetelor Debian pentru a înțelege principiile de bază ale sistemului de pachete
Secțiune 2.7.13, „Adaptarea unui pachet la sistemul stabil” pentru a înțelege principiile de bază ale procesului de portabilitate
Secțiune 9.11.4, „Sistemul chroot” pentru a înțelege tehnicile de bază ale „chroot”
debuild(1), și sbuild(1)
Secțiune 12.5.2, „Depanarea pachetului Debian” pentru recompilarea în scopul depanării
Guide for Debian
Maintainers - Ghid pentru administratorii Debian (pachetul
debmake-doc)
Debian Developer's
Reference - Ghidul de referință pentru dezvoltatorii Debian
(pachetul developers-reference)
Debian Policy Manual - Manualul de
politici Debian (pachetul debian-policy)
Există pachete precum debmake,
dh-make, dh-make-perl etc., care
facilitează procesul de creare a pachetelor.