Non usate "test" come nome di un file eseguibile di prova.
test
è un comando interno di shell.
Riferimenti:
/usr/share/doc/pacchetti
Unix / Programming
Information
Molti documenti info più lunghi possono essere ottenuti rilegati da GNU
.
Le quattro sezioni a seguire contengono dei semplici scripts, in linguaggi
differenti, per creare un file di testo contenente le informazioni di account,
da aggiungere a /etc/passwd
, utilizzando un "batch
processor" come il programma newusers
. Ogni script richiede
come input un file con le righe sotto forma di nome cognome
password. (Le directory home reali di ciascun utente non vengono create
con questi script.)
Leggere gli shell script è il miglior modo per comprendere il funzionamento di un sistema tipo Unix. Qui fornisco alcuni indirizzi per la programmazione nella shell.
Riferimenti per Bash:
bash(1)
BASH Programming -
Introduction HOWTO
per iniziare.
(Installate il pacchetto bash-doc
per vedere dei file di esempio.)
Esempio di programma breve (crea delle voci di account per
newusers
a partire da un input standard):
#!/bin/bash # (C) Osmu 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
Parecchi pacchetti forniscono una shell POSIX shell in Debian:
dash
(Sarge)
ash
(Woody)
bash
pdksh
Se scrivete uno script che sia portabile, è meglio scriverlo come script POSIX.
Usate /bin/sh
collegato a ash
o (dash
)
per testarne la complianza con POSIX. Evitate di scrivere gli script con dei
bashismi.
Ecco parecchi parametri speciali da ricordare:
$0 = nome della shell o dello script $1 = primo(1) argomento della shell ... $9 = nono(9) argomento della shell $# = numero dei parametri posizionali "$*" = "$1 $2 $3 $4 ... $n" "$@" = "$1" "$2" "$3" "$4" ... "$n" $? = stato di uscita del comando più recente $$ = PID di questo script $! = PID del processo più recente lanciato in background
Espansioni dei parametri basilari da ricordare:
Forma Se var è impostata(*) Se var non è impostata(*) ${var:-stringa} $var stringa ${var:+stringa} stringa null ${var:=stringa} $var stringa (e lancia var=stringa) ${var:?stringa} $var (echo stringa ed esce)
I due punti, qui, `:' in tutti questi operatori sono opzionali.
Sostituzioni dei parametri basilari da ricordare:
Forma Risultato ${var%suffisso} Rimuove il più piccolo pattern suffisso ${var%%suffisso} Rimuove il più largo pattern suffisso ${var#prefisso} Rimuove il più piccolo pattern prefisso ${var##prefisso} Rimuove il più largo pattern prefisso
Redirezione basilare da ricordare (dove [n] è un numero opzionale):
[n]> file Redireziona l'output standard (o n) a file. [n]>> file Aggiunge l'output standard (o n) a file. [n]< file Redireziona l'input standard (o n) da file. [n1]>&n2 Redireziona l'output standard (o n1) a n2. > file >&2 Redireziona l'output standard e di errore a file. | comando Con una pipe invia l'output standard (o n) a comando. >&2 | comando Coun una pipe invia l'output standard e di errore a comando.
Ciascun comando ritorna uno stato di uscita che può essere utilizzato per le espressioni condizionali:
Notate che l'utilizzo del valore 0 per "vero" differisce dalle
convenzioni usuali in altre aree di programmazione. In aggiunta, `[' è
l'equivalente del comando test
, che valuta i suoi argomenti fino a
`]' come espressione condizionale.
Idiomi condizionali basilari da ricordare sono:
comando && se_successo_lancia_anche_questo_comando comando || se_non_ha_successo_lancia_anche_questo_comando if [ espressione_condizionale ]; then se_ha_successo_lancia_anche_questo_comando else se_non_ha_successo_lancia_anche_questo_comando fi
Gli operatori per la comparazione dei file nelle espressioni condizionali sono:
-e file Vero se file esiste. -d file Vero se file esiste ed è una directory. -f file Vero se file esiste ed è un file regolare. -w file Vero se file esiste ed è scrivibile. -x file Vero se file esiste ed è eseguibile. file1 -nt file2 Vero se file1 è più recente di file2. (modificato) file1 -ot file2 Vero se file1 è più vecchio di file2. (modificato) file1 -ef file2 Vero se se sono gli stessi numeri di inode e device.
Gli operatori di comparazione delle stringhe nelle espressioni condizionali sono:
-z str Vero se la lunghezza di str è zero. -n str Vero se la lunghezza di str è non-zero. str1 == str2 Vero se str sono uguali. str1 = str2 Vero se str sono uguali. ( = può essere usato al posto di == ) str1 != str2 Vero se str non sono uguali. str1 < str2 Vero se str1 viene prima di str2 (dipende da locale). str1 > str2 Vero se str1 viene dopo str2 (dipende da locale).
Gli operatori aritmetici di comparazione degli interi nelle espressioni condizionali sono -eq, -ne, -lt, -le, -gt, o -ge.
La shell processa uno script come segue:
Le virgolette semplici all'interno delle doppie non hanno effetto.
Referimenti per Awk:
mawk(1)
ed gawk(1)
Esempio di programma breve (crea delle voci di account per
newusers
):
#!/usr/bin/awk -f # Script per creare un file utilizzabile con il comando 'newusers', # a partire da un file che contiene user IDs e passwords sotto forma di: # Nome Cognome password # 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 \ ) }
Due sono i pacchetti che forniscono il POSIX awk
in Debian:
mawk
gawk
Questo è l' interprete su un sistema simil-Unix.
Riferimenti per Perl:
perl(1)
Esempio di programma breve (crea delle voci di account per
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" }
Installate Perl module <module name>:
# perl -MCPAN -e 'install <module name>'
E' un valido interprete object-oriented.
Riferimenti per Python:
python(1)
Esempio di programma breve (crea delle voci di account per
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)) # above crash with wrong # of parameters :-) 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)
Riferimenti per Make:
make(1)
Semplici variabili automatiche:
Regole di sintassi:
Obiettivo: [ Prerequisito ... ] [TAB] command1 [TAB] -command2 # ignora gli errori [TAB] @command3 # sopprime l'echoing
Qui [TAB] è un codice TAB. Ogni riga viene interpretata dalla shell dopo la sostituzione della variabile da parte di make. Usate \ alla fine della riga per continuare a capo lo script. Usate $$ per $ per le variabili d'ambiente dello shell script.
Regola delle equivalenze implicite:
.c: header.h == % : %.c header.h .o.c: header.h == %.c: %.o header.h
Variabili automatiche per le summenzionate regole:
foo.o: new1.c new2.c.c old1.c new3.c $@ == foo.o (obiettivo) $< == new1.c (il primo) $? == new1.c new2.c new3.c (i più recenti) $^ == new1.c new2.c.c old1.c new3.c (tutti) $* == `%' motivo corrispondente al motivo obiettivo.
Riferimenti delle variabili:
foo1 := bar # Espansione unica foo2 = bar # Espansione ricorsiva foo3 += bar # Appendi SRCS := $(wildcard *.c) OBJS := $(foo:c=o) OBJS := $(foo:%.c=%.o) OBJS := $(patsubst %.c,%.o,$(foo)) DIRS = $(dir directory/filename.ext) # Estrae la "directory" $(notdir NAMES...), $(basename NAMES...), $(suffix NAMES...) ...
Per vedere le regole interne automatiche, lanciate make -p -f/dev/null.
Preparazione:
# apt-get install glibc-doc manpages-dev libc6-dev gcc
Riferimenti per C:
gcc(1)
each_C_library_function_name(3)
gcc
)
Un semplice esempio di compilazione di example.c
, con una libreria
libm
in un eseguibile 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); /* 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
Qui, -lm è necessario per il link della libreria
libm per sqrt(). La libreria vera è in
/lib
con il nome libm.so.6
, link simbolico a
libm-2.1.3.so
.
Guardate l'ultimo parametro nel testo risultante. Ci sono più di 10 caratteri, anche se viene specificato %10s.
L'uso di puntatori di funzioni che richiedano operazioni in memoria senza
controlli sui loro "confini", tipo sprintf
e
strcpy
, non è considerato sufficiente a prevenire gli effetti di
exploit tipo buffer overflow, che annullano gli effetti di overrun.
Utilizzate, invece, snprintf
e strncpy
.
gdb
Preparazione:
# apt-get install gdb
Riferimenti per gdb
:
gdb(1)
http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html
Per il debugging di un programma compilato con l'opzione -g, usate
gdb
. Molti comandi possono essere abbreviati. L'espansione del
comando mediante tab funziona come per la shell.
$ gdb program (gdb) b 1 # imposta il punto di interruzione alla riga 1 (gdb) run arg1 arg2 arg3 # lancia il programma (gdb) next # riga successiva ... (gdb) step # un passo avanti ... (gdb) p parm # stampa parm ... (gdb) p parm=12 # imposta il valore di parm a 12
Anche i seguenti comandi possono essere utili.
ldd
: stampa le dipendenze delle librerie condivise
strace
: traccia le chiamate di sistema ed i segnali
ltrace
: traccia le chiamate alle librerie
Per il debugging da emacs, fate riferimento a Riassunto dei comandi per emacs e vim, Sezione 11.3.4.
Usate ldd
per scoprire da quali librerie dipende un programma:
$ 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)
Affinchè ls
funzioni in un ambiente chroot
ato le
librerie di cui sopra devono essere disponibili all'interno dell'ambiente
chroot
ato.
Utili anche i seguenti comandi:
strace
: traccia le chiamate di sistema ed i segnali
ltrace
: traccia le chiamate alle librerie
Parecchi sono gli strumenti per il riconoscimento dei memory leak in Debian.
njamd
valgrind
dmalloc
electric-fence
memprof
memwatch
mpatrol
leaktracer
libgc6
Parasoft
. (non-free, commerciale, a
pagamento)
Vedere anche Debugging
Tools for Dynamic Storage Allocation and Memory Management
.
flex
è un veloce generatore ed analizzatore lessicale.
Riferimenti per flex
:
flex(1)
Al vostro programma dovete fornire una propria main()
e
yywrap()
, altrimenti program.l
apparirà come
nell'esempio qui sotto, tentando la compilazione senza librerie
(yywrap
è una macro; %option main diventa
implicitamente %option noyywrap):
%option main %% .|\n ECHO ; %%
In alternativa, potete compilarlo con l'opzione -lfl al termine della riga di comando cc (tipo ATT-Lex con -ll). In questo caso nessuna %option è richiesta.
Alcuni pacchetti forniscono un LALR parser generator Yacc-compatible in Debian:
bison
: GNU LALR parser generator
byacc
: Il Berkeley LALR parser generator
byyacc
: Backtracking parser generator basato su byacc
Riferimenti per bison
:
bison(1)
Dovete fornire la vostra main()
e yyerror()
.
main()
chiama yyparse()
che chiama
yylex()
, normalmente creata con FleX.
%% %%
autoconf
è uno strumento per produrre degli shell script in grado
di configurare automaticamente il codice sorgente dei programmi usando l'intero
sistema di compilazione GNU, adattandoli a molti tipi di sistema simil-Unix.
autoconf
produce lo script di configurazione
configure
. configure
crea automaticamente un
Makefile
personalizzato e Makefile.am
.
Debian non tocca i file in /usr/local
(vedere Supportare le differenze, Sezione 2.5).
Quindi, se compilate un programma dai sorgenti, installatelo in
/usr/local
, così non interferirà con Debian.
$ cd src $ ./configure --prefix=/usr/local $ make $ make install # questo comando mette i file nel sistema
Se avete ancora il sorgente e Se utilizza
autoconf
/automake
e se ricordate come l'avete
configurato:
$ ./configure tutte-le-opzioni-che-avevate-dato # make uninstall
In alternativa, se siete assolutamente sicuri che il processo di installazione
pone i file solo sotto /usr/local
e che non c'è nulla di
importante lì, potete cancellarne utto il contenuto con:
# find /usr/local -type f -print0 | xargs -0 rm -f
Se non siete sicuri di dove i file siano installati, dovreste prendere in
considerazione l'uso di checkinstall
, che fornisce un percorso
pulito per la disinstallazione.
Tradizionalmente, roff è il principale sistema di scrittura testo in Unix.
Vedere 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)
, ed "info groff".
Esiste un buon tutorial sulle macro -me
. Se avete groff (1.18 o
più recente), trovate /usr/share/doc/groff/meintro.me.gz
e fate
quanto segue:
$ zcat /usr/share/doc/groff/meintro.me.gz | \ groff -Tascii -me - | less -R
Quanto segue profurrà un file totalmente in formato testo:
$ zcat /usr/share/doc/groff/meintro.me.gz | \ GROFF_NO_SGR=1 groff -Tascii -me - | col -b -x > meintro.txt
Per la stampa, usate l'output PostScript.
$ groff -Tps meintro.txt | lpr $ groff -Tps meintro.txt | mpage -2 | lpr
Preparazione:
# apt-get install debiandoc-sgml debiandoc-sgml-doc
Riferimenti per debiandoc-sgml
:
/usr/share/doc/debiandoc-sgml-doc
debiandoc-sgml(1)
SGML permette la gestione dei formati multipli dei documenti. Un sistema SGML semplice è Debiandoc, utilizzato qui. Richiede delle comversioni minori dai files di testo originali per i seguenti caratteri:
< < > > " " " " (spazio non divisibile) & & % % © © – – — —
Per marcare una sezione come commento non stampabile, date:
<!-- Il commento va qui ... -->
Per marcare una sezione con un commento modificabile, date:
<![ %FIXME [ Il commento va qui ... ]]>
In SGML, la prima definizione di un'entità vince. Per esempio:
<!entity % qref "INCLUDE"> <![ %qref [ <!entity param "Data 1"> ]]> <!entity param "Data 2"> ¶m;
Questa termina come "Data 1". Se la prima riga è, invece, "IGNORE", questa terminerà come "Data 2" (La seconda riga è un'affermazione condizionale). Anche le frasi ripetute possono essere definite a priori, separatamente dal contesto.
<!entity dichièquesto "mio"> Ciao amico &dichièquesto;. Questo è il &dichièquesto; libro.
Che dà ciò come risultato:
Ciao amico mio. Questo è il mio libro.
Vedere il breve esempio in SGML sample.sgml
in esempi
.
Quando i documenti SGML diventano voluminosi, talvolta TeX può dare degli
errori. Dovete, in tal caso, aumentare le dimensioni del pool in
/etc/texmf/texmf.cnf
(o, più appropriatamente modificate
/etc/texmf/texmf.d/95NonPath
e lanciate update-texmf
)
per risolvere questo problema.
Preparazione:
# apt-get install debian-policy developers-reference \ maint-guide dh-make debhelper # apt-get install packaging-manual # se su Potato
Riferimenti per il packaging:
dh-make(1)
Metodo spiccio per impacchettare un singolo binario, da Joey Hess.
# mkdir -p mypkg/usr/bin mypkg/DEBIAN # cp binary mypkg/usr/bin # cat > mypkg/DEBIAN/control Package: miopacchetto Version: 1 Architecture: i386 Maintainer: Joey Hess <joeyh@debian.org> Description: il mio piccolo pacchetto Non vi aspettate granchè. ^D # dpkg-deb -b mypkg
Usate dh_make
dal pacchetto dh-make
per creare un
pacchetto base. Poi, procedete secondo le istruzioni contenute in
dh-make(1)
. Queste usano debhelper
in
debian/rules
.
Un approccio più datato è quello di usare deb-make
dal pacchetto
debmake
. Non usa nessuno script debhelper
e dipende
esclusivamente dalla shell.
Per degli esempi di pacchetti con sorgenti multipli vedete "mc"
(dpkg-source -x mc_4.5.54.dsc), che usa "sys-build.mk"
di Adam Heath (doogie@debian.org
) e
"glibc" (dpkg-source -x glibc_2.2.4-1.dsc), che usa un
altro sistema di Joel Klecker (espy@debian.org
).
La guida Debian
1.07-6, mer giu 23 21:21:03 UTC 2004osamu@debian.org
dsewell@virginia.edu
mc0315@mclink.it