Capitolo 1. Tutorial GNU/Linux

Indice

1.1. Nozioni di base sulla console
1.1.1. Il prompt di shell
1.1.2. Il prompt di shell in una GUI
1.1.3. L'account root
1.1.4. Il prompt di shell di root
1.1.5. Strumenti di amministrazione del sistema con interfaccia utente grafica
1.1.6. Console virtuali
1.1.7. Come uscire dal prompt dei comandi
1.1.8. Come spegnere il sistema
1.1.9. Ripristinare una console funzionante
1.1.10. Suggerimenti per pacchetti aggiuntivi per i principianti
1.1.11. Un account utente extra
1.1.12. Configurazione di sudo
1.1.13. Tempo di giocare
1.2. File system stile Unix
1.2.1. Nozioni di base sui file Unix
1.2.2. Aspetti tecnici del file system
1.2.3. Permessi del file system
1.2.4. Controllo dei permessi per i file appena creati: umask
1.2.5. Permessi per gruppi di utenti (gruppi)
1.2.6. Orari
1.2.7. Collegamenti
1.2.8. Pipe con nome (FIFO)
1.2.9. Socket
1.2.10. File di device
1.2.11. File di device speciali
1.2.12. procfs e sysfs
1.2.13. tmpfs
1.3. Midnight Commander (MC)
1.3.1. Personalizzazione di MC
1.3.2. Avvio di MC
1.3.3. Gestore dei file in MC
1.3.4. Trucchetti per la riga di comando di MC
1.3.5. L'editor interno di MC
1.3.6. Il visualizzatore interno di MC
1.3.7. Funzionalità di avvio automatico di MC
1.3.8. File system virtuale di MC
1.4. Ambiente di lavoro di base in stile Unix
1.4.1. La shell di login
1.4.2. Personalizzare bash
1.4.3. Associazioni di tasti speciali
1.4.4. Operazioni del mouse
1.4.5. Il paginatore
1.4.6. L'editor di testo
1.4.7. Impostare un editor di testi predefinito
1.4.8. Usare vim
1.4.9. Registrare le attività della shell
1.4.10. Comandi Unix di base
1.5. Il semplice comando di shell
1.5.1. Esecuzione dei comandi e variabili d'ambiente
1.5.2. La variabile "$LANG"
1.5.3. La variabile "$PATH"
1.5.4. La variabile "$HOME"
1.5.5. Opzioni della riga di comando
1.5.6. Glob della shell
1.5.7. Valore restituito dal comando
1.5.8. Sequenze tipiche di comandi e ridirezione della shell
1.5.9. Alias di comandi
1.6. Elaborazione di testo stile Unix
1.6.1. Strumenti Unix per il testo
1.6.2. Espressioni regolari
1.6.3. Espressioni di sostituzione
1.6.4. Sostituzione globale con espressioni regolari
1.6.5. Estrarre dati da file con tabelle di testo
1.6.6. Frammenti di script per comandi con pipe

Penso che imparare un sistema informatico sia come imparare una lingua straniera. Anche se le guide e la documentazione sono utili, si deve fare pratica diretta. Per aiutare il lettore a iniziare dolcemente, ho elaborato alcuni punti base.

Il potente design di Debian GNU/Linux deriva dal sistema operativo Unix, cioè un sistema operativo multiutente e multitasking. Bisogna imparare a sfruttare la potenza di queste caratteristiche e le somiglianze tra Unix e GNU/Linux.

Non bisogna scappare dai testi pensati per Unix e affidarsi solamente a testi su GNU/Linux dato che in questo modo ci si priva di molte informazioni utili.

[Nota] Nota

Se si è usato tramite strumenti a riga di comando un sistema *nix per un certo tempo, probabilmente si sa già tutto ciò che viene spiegato qui. Si usi questa sezione come un ripasso e per consultazioni.

All'avvio del sistema, se non è stata installato alcun ambiente con GUI come il sistema desktop GNOME o KDE. Supponiamo che il proprio nome host sia pippo, il prompt di login apparirà come segue.

Se è stato installato un ambiente GUI, allora ci si può comunque spostare ad un prompt di login a caratteri premendo Ctrl-Alt-F3 e si può ritornare alla GUI con Ctrl-Alt-F2 (vedere Sezione 1.1.6, «Console virtuali» in seguito per maggiori informazioni).

foo login:

Al prompt di login digitare il proprio nome utente, ad esempio pinguino e premere il tasto Invio, poi digitare la propria password e premere di nuovo Invio.

[Nota] Nota

Nella tradizione Unix, il nome utente e la password di un sistema Debian distinguono le lettere maiuscole dalle minuscole. Il nome utente di solito viene scelto usando solo lettere minuscole. Il primo account utente viene normalmente creato durante l'installazione. Account utente aggiuntivi possono essere creati da root con adduser(8).

Il sistema si presenta con il messaggio di benvenuto memorizzato in "/etc/motd" (Message Of The Day, messaggio del giorno) e fornisce un prompt dei comandi.

Debian GNU/Linux 11 foo tty1

foo login: penguin
Password:
Linux foo 5.10.0-6-amd64 #1 SMP Debian 5.10.28-1 (2021-04-09) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Thu May 13 08:47:13 JST 2021 on tty1
foo:~$

Si è ora nella shell. La shell interpreta i comandi dell'utente.

Se è stato installato un ambiente con GUI durante l'installazione, all'avvio del sistema viene presentata una schermata grafica di login. Si inseriscono il nome utente e la password per fare il login come utente non privilegiato. Usare il tasto Tab per spostarsi dal campo del nome utente a quello della password e viceversa, oppure usare il mouse e il clic principale.

Si può ottenere il prompt di shell in un ambiente GUI avviando un programma emulatore di terminale X come gnome-terminal(1), rxvt(1) o xterm(1). Nell'ambiente desktop GNOME può essere fatto premendo il tasto SUPER (tasto Windows) e digitando "terminal" per cercare il prompt.

In altri sistemi Desktop (come fluxbox), potrebbe non esserci un punto evidente per l'apertura del menu. Se si è in questa condizione, provare a fare clic, con il tasto destro, sullo sfondo della schermata del desktop e sperare che appaia un menu.

L'account root viene anche indicato come superutente o utente privilegiato. Da questo account si possono eseguire i seguenti compiti amministrativi.

  • Leggere, scrivere e cancellare qualsiasi file sul sistema indipendentemente dai suoi permessi.

  • Impostare il proprietario e i permessi di qualunque file sul sistema.

  • Impostare la password di qualsiasi utente non privilegiato nel sistema.

  • Fare il login in qualsiasi account senza la password.

Questi poteri illimitati dell'account root rendono necessario essere prudenti e responsabili nel loro uso.

[Avvertimento] Avvertimento

Non comunicare mai la password di root ad altri.

[Nota] Nota

I permessi di un file (inclusi i device hardware come CD-ROM, ecc. che sono nient'altro che un altro file per il sistema Debian) lo possono rendere inutilizzabile o inaccessibile per gli utenti non root. Benché usare l'account root sia un metodo veloce per affrontare questo tipo di situazione, la sua soluzione dovrebbe essere l'impostazione degli appropriati permessi e gruppi proprietari per il file (vedere Sezione 1.2.3, «Permessi del file system»).

Quando il menu del desktop non avvia gli strumenti con interfaccia grafica per l'amministrazione di sistema con i privilegi appropriati, si può avviarli dal prompt di shell di root degli emulatori di terminale, quali gnome-terminal(1), rxvt(1) o xterm(1). Vedere Sezione 1.1.4, «Il prompt di shell di root» e Sezione 7.8, «Connessione a server X».

[Avvertimento] Avvertimento

Non avviare mai il gestore di sessioni/display manager della GUI dall'account root inserendo root al prompt di un display manager come gdm3(1).

Non eseguire mai in X Window programmi con interfaccia utente grafica non fidati da remoto quando sono visualizzate informazioni critiche, dato che potrebbero spiare lo schermo X.

Nel sistema Debian standard, ci sono sei console a caratteri in stile VT100 disponibili tra cui ci si può spostare per avviare una shell di comando direttamente sull'host Linux. A meno che non si sia in un ambiente con interfaccia grafica, si può passare da una console virtuale all'altra usando simultaneamente il tasto_Alt_sinistro e uno dei tasti F1F6. Ogni console a caratteri permette un login indipendente nell'account e offre un ambiente multiutente. L'ambiente multiutente è una bellissima caratteristica di Unix e ci si può abituare presto a dipendere da esso.

Se si è nell'ambiente con GUI, si accede alla console a caratteri 3 premendo i tasti Ctrl-Alt-F3, cioè premendo contemporaneamente il tasto_Ctrl_sinistro, il tasto_Alt_sinistro e il tasto_F3. Si può tornare all'ambiente GUI, che di solito è in esecuzione sulla console virtuale 2, premendo Alt-F2.

In alternativa ci si può spostare in un'altra console virtuale, per esempio la console 3, dalla riga di comando.

# chvt 3

Esattamente come ogni altro SO moderno in cui le operazioni su file comportano una cache dei dati in memoria per migliorare le prestazioni, il sistema Debian ha bisogno della appropriata procedura di spegnimento prima che l'alimentazione possa essere staccata in modo sicuro. Questo serve a preservare l'integrità dei file, forzando la scrittura su disco di tutti i cambiamenti avvenuti in memoria. Se è disponibile il controllo software dell'alimentazione, la procedura di spegnimento automaticamente toglie l'alimentazione al sistema. (In caso contrario può essere necessario tener premuto per alcuni secondi il tasto di accensione/spegnimento.)

Si può spegnere il sistema dalla riga di comando nella normale modalità multiutente.

# shutdown -h now

Si può spegnere il sistema dalla riga di comando nella modalità single-user.

# poweroff -i -f

Vedere Sezione 6.3.8, «Spegnere il sistema remoto su SSH».

Sebbene anche l'installazione minima del sistema Debian, senza alcun ambiente desktop, fornisca le funzionalità Unix di base è una buona idea installare con apt-get(8) alcuni pacchetti aggiuntivi per la riga di comando e i terminali a caratteri basati su curses, come mc e vim con cui i principianti possono fare i primi passi. Eseguire i comandi seguenti.

# apt-get update
 ...
# apt-get install mc vim sudo aptitude
 ...

Se questi pacchetti sono già installati, nessun nuovo pacchetto sarà installato.


Potrebbe essere una buona idea leggere un po' di documentazione.


Si possono installare alcuni di questi pacchetti usando i comandi seguenti.

# apt-get install package_name

Per la tipica postazione di lavoro di un unico utente, come il sistema desktop Debian su un PC portatile, è frequente l'uso di una semplice configurazione di sudo(8), come qui di seguito descritto, per permettere all'utente non privilegiato, ad esempio pinguino, di ottenere privilegi di amministratore con la sola propria password, senza quella dell'utente root.

# echo "penguin  ALL=(ALL) ALL" >> /etc/sudoers

In alternativa è uso comune usare la configurazione seguente per permettere all'utente non privilegiato, ad esempio pinguino, di ottenere privilegi di amministratore senza alcuna password.

# echo "penguin  ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers

Questo trucco dovrebbe essere usato esclusivamente per le postazioni di lavoro con un solo utente, in cui l'utente è anche l'amministratore.

[Avvertimento] Avvertimento

Non impostare account per utenti regolari su postazioni di lavoro multi-utente in questo modo perché ciò sarebbe un grosso problema per la sicurezza del sistema.

[Attenzione] Attenzione

Nell'esempio precedente la password e l'account di pinguino richiedono altrettanta protezione della password e account dell'utente root.

I privilegi di amministrazione in questo contesto sono forniti a qualcuno che è autorizzato ad eseguire i compiti di amministrazione del sistema sulla macchina. Non dare mai tali privilegi ad un manager del dipartimento di Amministrazione della propria azienda o al proprio capo, a meno che non siano autorizzati e capaci.

[Nota] Nota

Per fornire privilegi di accesso a specifici device e file, si dovrebbe considerare l'uso dei gruppi per dare un accesso limitato, invece di usare i privilegi di root attraverso sudo(8).

Con una configurazione più attenta e precisa, sudo(8) può garantire privilegi amministrativi limitati ad altri utenti in un sistema condiviso, senza rendere nota la password di root. Questo può aiutare la tracciabilità su host con più di un amministratore, in modo che si possa dire chi ha fatto cosa. D'altra parte si potrebbe anche volere che nessuno abbia tali privilegi.

In GNU/Linux ed altri sistemi operativi *nix, i file sono organizzati in directory. Tutti i file e le directory sono organizzati in un unico grande albero che ha la sua radice in "/". Viene chiamato albero perché il file system, se viene disegnato, ha l'aspetto di un albero messo però sottosopra.

Questi file e directory possono essere sparsi su diversi dispositivi. mount(8) serve per attaccare il file system trovato su un qualche dispositivo al grande albero dei file. Al contrario, umount(8) lo stacca. Nei kernel Linux recenti mount(8) con alcune opzioni può collegare parte di un albero dei file in qualche altra posizione o può montare file system come condivisi, privati, slave o non-collegabili. Le opzioni di montaggio supportate per ciascun file system sono disponibili in "/usr/share/doc/linux-doc-*/Documentation/filesystems/".

Nei sistemi Unix vengono chiamate directory quelle che in altri sistemi sono chiamate cartelle. Notare anche che non esiste in nessun sistema Unix un concetto di unità, come "A:". C'è un solo unico file system e tutto vi è incluso. Questo è un grandissimo vantaggio rispetto a Windows.

Ecco alcune nozioni di base sui file Unix.

[Nota] Nota

Benché si possa usare quasi qualsiasi lettera o simbolo nel nome di un file, in pratica farlo non è una bella idea. È meglio evitare qualsiasi carattere che ha spesso un significato particolare sulla riga di comando, inclusi spazi, tabulazioni, a capo e altri caratteri speciali: { } ( ) [ ] ' ` " \ / > < | ; ! # & ^ * % @ $. Se si vuole separare delle parole all'interno di un nome file, buone alternative sono un punto, un trattino ed il segno di sottolineatura. Si può anche scrivere in maiuscolo ogni parola, "InQuestoModo". Gli utenti Linux esperti tendono ad evitare l'uso degli spazi nei nomi dei file.

[Nota] Nota

La parola "root" può significare l'"utente root" o la "directory root". Il contesto in cui il termine viene usato dovrebbe rendere chiaro il suo significato.

[Nota] Nota

La parola percorso non è usata solamente per un nome di file pienamente qualificato come descritto in precedenza, ma anche per il percorso di ricerca dei comandi. Il significato è di solito reso chiaro dal contesto.

Le linee guida raccomandate per la gerarchia dei file sono descritte in dettaglio nel Filesystem Hierarchy Standard ("/usr/share/doc/debian-policy/fhs/fhs-2.3.txt.gz" e in hier(7)). Come inizio si dovrebbe tenere a mente quanto segue.


Nella scia della tradizione Unix, il sistema Debian GNU/Linux fornisce il file system in cui risiedono i dati fisici nel disco fisso e negli altri dispositivi di memorizzazione, ed inoltre le interazioni con i dispositivi hardware come gli schermi delle console e le console seriali remote vengono rappresentate in un modo unificato in "/dev/".

Ogni file, directory, pipe con nome (un modo per due programmi di scambiare dati) o dispositivo fisico presente in un sistema Debian GNU/Linux ha una struttura di dati chiamata inode che descrive gli attributi ad esso associati come l'utente che lo possiede (proprietario), il gruppo a cui appartiene, la data dell'ultimo accesso ad esso, ecc. L'idea di rappresentare praticamente tutto nel file system è stata un'innovazione di Unix e i kernel Linux moderni hanno sviluppato questa idea e sono andati oltre. Ora anche le informazioni sui processi in esecuzione sul computer possono essere trovate nel file system.

La rappresentazione astratta e unificata di entità fisiche e di processi interni è molto potente dato che permette di usare lo stesso comando per lo stesso tipo di operazione su molti tipi di device completamente diversi l'uno dall'altro. È anche possibile cambiare il modo in cui il kernel funziona scrivendo dati in file speciali che sono collegati ai processi in esecuzione.

[Suggerimento] Suggerimento

Per identificare la corrispondenza tra l'albero dei file e le entità fisiche, eseguire mount(8) senza opzioni.

I permessi del file system di sistemi *nix sono definiti e influenzano tre categorie di utenti.

  • L'utente che è il proprietario del file (u).

  • Gli altri utenti del gruppo a cui appartiene il file (g).

  • Tutti gli altriutenti (o) a cui ci si riferisce anche con i termini "mondo" e "tutti".

Per un file, a ciascun permesso corrispondono le seguenti azioni.

  • Il permesso di lettura (r) permette al proprietario di esaminare il contenuto del file.

  • Il permesso di scrittura (w) permette al proprietario di modificare il file.

  • Il permesso di esecuzione (x) permette al proprietario di eseguire il file come comando.

Per una directory, a ciascun permesso corrispondono le seguenti azioni.

  • Il permesso di lettura (r) permette al proprietario di elencare il contenuto della directory.

  • Il permesso di scrittura (w) permette al proprietario di aggiungere o rimuovere file dalla directory.

  • Il permesso di esecuzione (x) permette al proprietario di accedere ai file nella directory.

In questo caso il permesso di esecuzione su una directory non solo significa poter leggere i file in quella directory ma anche poterne vedere gli attributi, come la dimensione e la data di modifica.

Per visualizzare le informazioni sui permessi (ed altro) di file e directory si usa ls(1). Quando chiamato con l'opzione "-l" mostra, nell'ordine elencato in seguito, le seguenti informazioni.

  • Tipo di file (primo carattere).

  • Permessi di accesso al file (nove caratteri, tre ciascuno per utente, gruppo e altri, in questo ordine).

  • Numero di collegamenti fisici al file.

  • Nome dell'utente proprietario del file.

  • Nome del gruppo a cui il file appartiene.

  • Dimensione in caratteri (byte) del file.

  • Data ed ora del file (mtime).

  • Nome del file.


Per cambiare il proprietario di un file da un account root si usa chown(1). Per cambiare il gruppo di un file dall'account del proprietario o da quello di root si usa chgrp(1). Per cambiare i permessi di accesso di file o directory dall'account del proprietario o da quello di root si usa chmod(1). La sintassi di base per manipolare un file pippo è la seguente.

# chown newowner foo
# chgrp newgroup foo
# chmod  [ugoa][+-=][rwxXst][,...] foo

Per esempio si può fare in modo che l'utente pippo sia il proprietario di un albero di directory condivisa dal gruppo pluto con i seguenti comandi.

# cd /some/location/
# chown -R foo:bar .
# chmod -R ug+rwX,o=rX .

Ci sono altri tre bit speciali di permessi.

  • Il bit set user ID (s o S al posto del permesso x dell'utente).

  • Il bit set group ID (s o S al posto del permesso x del gruppo).

  • Il bit sticky (t o T al posto del permesso x degli altri).

Nell'output di "ls -l" il valore di questi bit è maiuscolo se il bit di permesso di esecuzione nascosto da essi è non impostato.

L'impostazione del bit set user ID per un file eseguibile permette ad un utente di eseguire quel file con l'ID del proprietario del file (per esempio root). In modo simile, l'impostazione del bit set group ID per un file eseguibile permette ad un utente di eseguire il file con l'ID del gruppo a cui appartiene il file (per esempio root). Poiché l'impostazione di questi bit può causare rischi in termini di sicurezza, il loro uso richiede una particolare cautela.

L'impostazione del bit set group ID per una directory abilita lo schema di creazione di file in stile BSD, in cui tutti i file creati nella directory appartengono al gruppo della directory.

L'impostazione dello sticky bit per una directory impedisce la rimozione di un file nella directory da parte dell'utente che non ne è il proprietario. Per preservare i contenuti di un file in directory con permessi di scrittura per tutti, come "/tmp" o in directory con permessi di scrittura per un gruppo, non solo si deve impostare il permesso di scrittura per il file, ma anche impostare lo sticky bit per la directory. In caso contrario, qualunque utente con i permessi di scrittura per la directory può rimuovere il file e crearne uno nuovo con lo stesso nome.

Ecco alcuni interessanti esempi di permessi dei file.

$ ls -l /etc/passwd /etc/shadow /dev/ppp /usr/sbin/exim4
crw------T 1 root root   108, 0 Oct 16 20:57 /dev/ppp
-rw-r--r-- 1 root root     2761 Aug 30 10:38 /etc/passwd
-rw-r----- 1 root shadow   1695 Aug 30 10:38 /etc/shadow
-rwsr-xr-x 1 root root   973824 Sep 23 20:04 /usr/sbin/exim4
$ ls -ld /tmp /var/tmp /usr/local /var/mail /usr/src
drwxrwxrwt 14 root root  20480 Oct 16 21:25 /tmp
drwxrwsr-x 10 root staff  4096 Sep 29 22:50 /usr/local
drwxr-xr-x 10 root root   4096 Oct 11 00:28 /usr/src
drwxrwsr-x  2 root mail   4096 Oct 15 21:40 /var/mail
drwxrwxrwt  3 root root   4096 Oct 16 21:20 /var/tmp

Esiste un metodo numerico alternativo per descrivere i permessi dei file con chmod(1); tale metodo numerico usa numeri ottali (base=8) di 3 o 4 cifre.


Sembra complicato, ma è in realtà piuttosto semplice. Se si guardano le prime colonne (2-10) nell'output del comando "ls -l" e le si leggono come una rappresentazione binaria (base=2) dei permessi sui file (dove "-" equivale a "0" e "rwx" equivalgono a "1"), le ultime 3 cifre del valore numerico dei permessi dovrebbero apparire come la corretta rappresentazione dei permessi sui file in numerazione ottale (base=8).

Per esempio, provare a fare quanto segue.

$ touch foo bar
$ chmod u=rw,go=r foo
$ chmod 644 bar
$ ls -l foo bar
-rw-r--r-- 1 penguin penguin 0 Oct 16 21:39 bar
-rw-r--r-- 1 penguin penguin 0 Oct 16 21:35 foo
[Suggerimento] Suggerimento

Se si deve aver accesso alle informazioni visualizzate da "ls -l" in script di shell, si dovrebbero usare i comandi pertinenti, come test(1), stat(1) e readlink(1). Si possono usare anche i comandi interni della shell come "[" o "test".

Per far sì che i permessi di un gruppo vengano applicati ad un particolare utente, tale utente deve essere inserito come membro del gruppo usando "sudo vigr" per /etc/group e "sudo vigr -s" per /etc/gshadow. Per abilitare la nuova configurazione dei gruppi è necessario fare il log out e quindi di nuovo il login (oppure eseguire "exec newgrp").

[Nota] Nota

In alternativa, si possono aggiungere dinamicamente gli utenti ai gruppi durante il processo di autenticazione aggiungendo la riga "auth optional pam_group.so" al file "/etc/pam.d/common-auth" e configurando "/etc/security/group.conf". (Vedere Capitolo 4, Autenticazione e controllo degli accessi.)

I dispositivi hardware sono, in un sistema Debian, semplicemente un altro tipo di file. Se si hanno problemi ad accedere a dispositivi quali CD-ROM e chiavette USB da un account utente, si dovrebbe inserire quell'utente nel gruppo appropriato.

Alcuni importanti gruppi pre-impostati dal sistema permettono ai loro membri l'accesso a file e device particolari senza i privilegi di root.


[Suggerimento] Suggerimento

È necessario far parte del gruppo dialout per riconfigurare il modem, comporre numeri, ecc. Se però root crea file di configurazione predefiniti per i peer fidati in "/etc/ppp/peers/", è necessario solamente far parte del grupo dip per creare una connessione IP dialup a tali peer fidati usando i comandi pppd(8), pon(1) e poff(1).

Alcuni importanti gruppi pre-impostati dal sistema permettono ai loro membri di eseguire particolari comandi senza i privilegi di root.


Per l'elenco completo degli utenti e gruppi forniti dal sistema, vedere la recente versione del documento "Utenti e gruppi" in "/usr/share/doc/base-passwd/users-and-groups.html" fornito dal pacchetto base-passwd.

Vedere passwd(5), group(5), shadow(5), newgrp(1), vipw(8), vigr(8) e pam_group(8) per informazioni sui comandi di gestione di utenti e gruppi sul sistema.

Ci sono tre tipi di orari per un file GNU/Linux.


[Nota] Nota

ctime non è l'orario di creazione del file.

[Nota] Nota

L'attuale significato di atime sui sistemi GNU/Linux potrebbe essere diverso dalla sua definizione storica in Unix.

  • La sovrascrittura di un file cambia tutti gli attributi mtime, ctime e atime del file.

  • Il cambiamento del proprietario o dei permessi di un file cambia gli attributi ctime e atime del file.

  • La lettura di un file cambia l'attributo atime di un file nei sistemi Unix storici.

  • La lettura di un file cambia l'attributo atime di un file in un sistema GNU/Linux se il file system è montato con "strictatime".

  • Leggere un file per la prima volta o dopo un giorno modifica l'attributo atime del file stesso su sistemi GNU/Linux, se il filesystem è stato montato con "relatime". (comportamento di default da Linux 2.6.30)

  • Leggere un file non modifica l'attributo atime del file stesso su sistemi GNU/Linux se il filesystem è stato montato con "noatime".

[Nota] Nota

Le opzioni di mount "noatime" e "relatime" sono introdotte per migliorare le prestazioni in lettura del file system nei normali casi d'uso. Semplici operazioni di lettura dei file con l'opzione "strictatime" comportano lunghe operazioni di scrittura per aggiornare l'attributo atime. L'attributo atime però è raramente utilizzato, a parte per il file mbox(5). Vedere mount(8).

Usare il comando touch(1) per cambiare l'orario di file esistenti.

Per gli orari, il comando ls produce in output stringhe localizzate con la localizzazione non inglese ("it_IT.UTF-8").

$ LANG=C  ls -l foo
-rw-rw-r-- 1 penguin penguin 0 Oct 16 21:35 foo
$ LANG=en_US.UTF-8  ls -l foo
-rw-rw-r-- 1 penguin penguin 0 Oct 16 21:35 foo
$ LANG=fr_FR.UTF-8  ls -l foo
-rw-rw-r-- 1 penguin penguin 0 oct. 16 21:35 foo
[Suggerimento] Suggerimento

Vedere Sezione 9.3.4, «Visualizzazione personalizzata di date e orari» per personalizzare l'output di "ls -l".

Ci sono due metodi per associale un file "pippo" ad un diverso nome file "pluto".

Vedere l'esempio seguente per notare i cambiamenti nel conteggio dei collegamenti e le sottili differenze tra i risultati del comando rm.

$ umask 002
$ echo "Original Content" > foo
$ ls -li foo
1449840 -rw-rw-r-- 1 penguin penguin 17 Oct 16 21:42 foo
$ ln foo bar     # hard link
$ ln -s foo baz  # symlink
$ ls -li foo bar baz
1449840 -rw-rw-r-- 2 penguin penguin 17 Oct 16 21:42 bar
1450180 lrwxrwxrwx 1 penguin penguin  3 Oct 16 21:47 baz -> foo
1449840 -rw-rw-r-- 2 penguin penguin 17 Oct 16 21:42 foo
$ rm foo
$ echo "New Content" > foo
$ ls -li foo bar baz
1449840 -rw-rw-r-- 1 penguin penguin 17 Oct 16 21:42 bar
1450180 lrwxrwxrwx 1 penguin penguin  3 Oct 16 21:47 baz -> foo
1450183 -rw-rw-r-- 1 penguin penguin 12 Oct 16 21:48 foo
$ cat bar
Original Content
$ cat baz
New Content

Il collegamento fisico può essere creato all'interno dello stesso file system e condivide lo stesso numero di inode, come rivela l'opzione "-i" di ls(1).

Il collegamento simbolico ha sempre permessi di accesso nominali "rwxrwxrwx, come mostrato nell'esempio precedente, ma con gli effettivi permessi di accesso stabiliti dai permessi del file a cui punta.

[Attenzione] Attenzione

In generale è una buona idea non creare collegamenti simbolici complicati o non creare collegamenti fisici per nulla, a meno di non avere una ragione molto buona per farlo. Possono diventare degli incubi quando la combinazione logica dei collegamenti simbolici crea cicli ricorsivi nel file system.

[Nota] Nota

È in generale preferibile usare collegamenti simbolici piuttosto che fisici, a meno che non sia abbia una buona ragione per usare un collegamento fisico.

La directory "." punta alla directory in cui appare, perciò il conteggio dei collegamenti per ogni nuova directory inizia da 2. La directory ".." punta alla directory genitore, perciò il conteggio dei collegamenti di una directory aumenta con l'aggiunta di nuove sottodirectory.

Se si è appena passati da Windows a Linux, appare presto chiaro come sia ben progettato il collegamento dei nomi di file in Unix se paragonato con i collegamenti in ambiente Windows che sono l'equivalente più prossimo in quel sistema. Dato che sono implementati nel file system, le applicazioni non possono vedere alcuna differenza tra un file collegamento ed un originale. Nel caso di collegamenti fisici, non c'è realmente nessuna differenza.

Una pipe con nome è un file che si comporta da pipe. Si mette qualcosa dentro il file e questa cosa esce dall'altra parte. Questa è chiamata una FIFO (First-In-First_Out, primo ad entrare-primo ad uscire): la prima cosa che viene immessa nella pipe è la prima ad uscire dall'altra estremità.

Se si scrive su una pipe con nome, il processo che sta eseguendo la scrittura nella pipe non termina fino a che l'informazione scritta nella pipe non viene letta. Se si legge da una pipe con nome, il processo di lettura attende che non ci sia più nulla da leggere prima di terminare. La dimensione della pipe è sempre zero: non archivia dati, ma semplicemente collega due processi come fa la funzionalità fornita dalla sintassi per pipe "|" della shell. Tuttavia, dato che questa pipe ha un nome, i due processi non devono essere nella stessa riga di comando e nemmeno essere eseguiti dallo stesso utente. Le pipe sono un'innovazione di Unix di grandissimo impatto.

Per esempio, provare a fare quanto segue.

$ cd; mkfifo mypipe
$ echo "hello" >mypipe & # put into background
[1] 8022
$ ls -l mypipe
prw-rw-r-- 1 penguin penguin 0 Oct 16 21:49 mypipe
$ cat mypipe
hello
[1]+  Done                    echo "hello" >mypipe
$ ls mypipe
mypipe
$ rm mypipe

I file di device fanno riferimento a dispositivi fisici o virtuali sul sistema, come i dischi fissi, la scheda video, lo schermo o la tastiera. Un esempio di dispositivo virtuale è la console, rappresentata da "/dev/console".

Ci sono 2 tipi di file di device.

  • Device a caratteri

    • Vi si accede un carattere alla volta.

    • 1 carattere = 1 byte

    • Es., device della tastiera, porta seriale, ...

  • Device a blocchi

    • Vi si accede in base a unità più grandi chiamate blocchi.

    • 1 blocco > 1 byte

    • Es., dischi fissi, ...

I file di device possono essere letti e scritti, anche se è probabile che i file contengano dati binari che appaiono come farfuglii incomprensibili per le persone. La scrittura diretta di dati in questi file è utile a volte per trovare la soluzione a problemi con le connessioni hardware. Si può, per esempio, fare il dump di un file di testo in un device di stampa "/dev/lp0" o inviare comandi del modem alla porta seriale appropriata "/dev/ttyS0". Ma, a meno che ciò non venga fatto con cautela, può causare grandissimi disastri. Perciò, essere prudenti.

[Nota] Nota

Per il normale accesso ad una stampante, usare lp(1).

I numeri di nodo dei device sono visualizzati se si esegue ls(1) come nell'esempio seguente.

$ ls -l /dev/sda /dev/sr0 /dev/ttyS0 /dev/zero
brw-rw---T  1 root disk     8,  0 Oct 16 20:57 /dev/sda
brw-rw---T+ 1 root cdrom   11,  0 Oct 16 21:53 /dev/sr0
crw-rw---T  1 root dialout  4, 64 Oct 16 20:57 /dev/ttyS0
crw-rw-rw-  1 root root     1,  5 Oct 16 20:57 /dev/zero
  • "/dev/sda" ha major number del device 8 e minor number del device 0. È accessibile in lettura e scrittura dagli utenti che appartengono al gruppo disk.

  • "/dev/sr0" ha major number del device 11 e minor number del device 0. È accessibile in lettura e scrittura dagli utenti che appartengono al gruppo cdrom.

  • "/dev/ttyS0" ha major number del device 4 e minor number del device 64. È accessibile in lettura e scrittura dagli utenti che appartengono al gruppo dialout.

  • "/dev/zero" ha major number del device 1 e minor number del device 5. È accessibile in lettura e scrittura da chiunque.

Nei sistemi Linux moderni il file system sotto "/dev" viene popolato automaticamente dal meccanismo udev(7).

procfs e sysfs, montati in "/proc" e "/sys" sono pseudo-file system ed espongono strutture interne di dati del kernel nello spazio utente. In altre parole, queste voci sono virtuali, funzionano cioè come una comoda finestra sul funzionamento del sistema operativo.

La directory "/proc" contiene (tra le altre cose) una sottodirectory per ciascun processo in esecuzione sul sistema che prende nome dall'ID del processo (PID). Le utilità di sistema, come ps(1), che accedono alle informazioni sui processi, ottengono le loro informazioni da questa struttura di directory.

Le directory in "/proc/sys/" contengono interfacce per cambiare certi parametri del kernel durante l'esecuzione. (Si può fare la stessa cosa tramite comandi sysctl(8) specifici o tramite il suo file di precaricamento/configurazione "/etc/sysctl.conf".)

Le persone spesso vanno in panico quando si accorgono di un file in particolare, "/proc/kcore" che è particolarmente enorme. È (più o meno) una copia del contenuto della memoria del computer ed è usato per fare il debug del kernel. È un file virtuale che punta alla memoria del computer perciò non ci si preoccupi della sua dimensione.

La directory "/sys" contiene strutture dati del kernel esportate, i loro attributi e i collegamenti tra di esse. Contiene anche interfacce per cambiare alcuni parametri del kernel durante l'esecuzione.

Vedere proc.txt(.gz)", "sysfs.txt(.gz)" e altri documenti correlati nella documentazione del kernel Linux ("/usr/share/doc/linux-doc-*/Documentation/filesystems/*") fornita dai pacchetti linux-doc-*.

tmpfs è un file system temporaneo che contiene tutti i file nella memoria virtuale. I dati del tmpfs nella page cache in memoria possono essere spostati nello spazio di swap su disco quando necessario.

La directory "/run" viene montata come il tmpfs nelle prime fasi del processo di avvio. Ciò vi permette la scrittura anche quando la directory "/" è montata in sola lettura. Questa è la nuova posizione per la memorizzazione dei file transitori e sostituisce diverse posizioni descritte nella versione 2.3 del Filesystem Hierarchy Standard(Standard per la gerarchia del file system):

  • "/var/run" → "/run"

  • "/var/lock" → "/run/lock"

  • "/dev/shm" → "/run/shm"

Vedere "tmpfs.txt(.gz)" nella documentazione del kernel Linux ("/usr/share/doc/linux-doc-*/Documentation/filesystems/*") fornita dai pacchetti linux-doc-*.

Midnight Commander (MC) è un "coltellino svizzero" GNU per la console Linux ed altri ambienti in terminale. Dà ai principianti la possibilità di usare una console comandata da menu che è molto più facile da imparare dei comandi Unix standard.

Potrebbe essere necessario installare il pacchetto di Midnight Commander che si chiama "mc" con il seguente comando.

$ sudo apt-get install mc

Usare il comando mc(1) per esplorare il sistema Debian. È il modo migliore di imparare. Esplorare qualche posizione interessante usando semplicemente i tasti freccia e il tasto Invio.

  • "/etc" e le sue sottodirectory

  • "/var/log" e le sue sottodirectory

  • "/usr/share/doc" e le sue sottodirectory

  • "/sbin" e "/bin"

L'editor interno ha un interessante schema per il taglia e incolla. La pressione di F3 marca l'inizio di una selezione, una seconda pressione di F3 marca la fine della selezione e la evidenzia. Si può poi muovere il cursore. Se si preme F6, l'area selezionata viene spostata nella posizione del cursore. Se si preme F5 l'area selezionata viene copiata ed inserita alla posizione del cursore. F2 salva il file. F10 fa uscire. La maggior parte dei tasti cursore funziona in modo intuitivo.

Si può avviare direttamente questo editor su di un file usando uno dei comandi seguenti.

$ mc -e filename_to_edit
$ mcedit filename_to_edit

Questo non è un editor multi-finestra, ma si possono usare più console Linux per ottenere lo stesso effetto. Per copiare tra finestre, usare i tasti Alt-Fn per cambiare console virtuale e usare "File→Insert file" o "File→Copy to file" per spostare una porzione di un file in un altro file.

Questo editor interno può essere rimpiazzato da qualsiasi editor esterno a propria scelta.

Inoltre molti programmi usano la variabile d'ambiente "$EDITOR" o "$VISUAL" per decidere quale editor usare. Se inizialmente non ci si trova a proprio agio con vim(1) o nano(1), si può impostare queste variabili a "mcedit" aggiungendo le righe seguenti al file "~/.bashrc".

export EDITOR=mcedit
export VISUAL=mcedit

Io raccomando di impostarle a "vim", se possibile.

Se non ci si trova a proprio agio con vim(1), si può continuare ad usare mcedit(1) per la maggior parte dei compiti di manutenzione del sistema.

Anche se MC permette di fare quasi tutto, è bene imparare come usare gli strumenti a riga di comando invocati dal prompt di shell e prendere familiarità con l'ambiente di lavoro in stile Unix.

Dato che la shell di login può essere utilizzata da alcuni programmi di inizializzazione del sistema, è prudente mantenerla come bash(1) e evitare di cambiare la shell di login in chsh(1).

Se si desidera usare un prompt di shell interattiva diverso, impostarlo dalla configurazione dell'emulatore di terminale in GUI o avviarlo da ~/.bashrc, ad esempio mettendoci "exec /usr/bin/zsh -i -l" o "exec /usr/bin/fish -i -l".


[Suggerimento] Suggerimento

Sebbene le shell in stile POSIX condividano la stessa sintassi di base, esse possono differire nel comportamento relativo a cose anche basilari, come le variabili della shell e l'espansione dei modelli glob. Per i dettagli controllare la loro documentazione.

In questo capitolo del tutorial la shell interattiva considerata è sempre bash.

Il funzionamento del mouse per il testo nel sistema Debian mescola 2 stile con alcune peculiarità:

  • Funzioni del mouse in stile Unix tradizionali:

    • uso di 3 pulsanti (clic)

    • uso di PRIMARY (principale)

    • usato da applicazioni X come xterm e applicazioni testuali nella console Linux

  • Funzionamento del mouse moderno in stile GUI:

    • uso di 2 pulsanti (trascina e clic)

    • uso di PRIMARY (principale) e CLIPBOARD (appunti)

    • usato in applicazioni GUI moderne come gnome-terminal


Qui, la selezione PRINCIPALE è l'intervallo di testo evidenziato. All'interno del programma di terminale viene usato invece Shift-Ctrl-C per evitare di terminare un programma in esecuzione.

La rotella centrale presente nei mouse moderni viene considerata come il pulsante di mezzo e può essere usata per fare il corrispondente clic. Cliccare contemporaneamente con i pulsanti destro e sinistro funziona da clic di mezzo nelle situazioni in cui si hanno mouse a 2 pulsanti.

Per poter usare il mouse in una console a caratteri Linux, è necessario che gpm(8) sia in esecuzione come demone.

Si dovrebbe diventare competenti in una delle varianti dei programmi Vim o Emacs che sono popolari sui sistemi *nix.

Penso che abituarsi ai comandi Vim sia la cosa giusta da fare, dato che un editor Vi è sempre presente nel mondo Linux/Unix. (In realtà, il vi originale o il nuovo nvi sono programmi che si trovano ovunque. Io ho scelto invece Vim per i principianti dato che offre l'aiuto attraverso il tasto F1 pur essendo abbastanza simile e più potente.)

Se si sceglie invece Emacs o XEmacs come editor preferito, si sta facendo comunque davvero un'ottima scelta, specialmente per la programmazione. Emacs ha una vastità di altre funzionalità, incluso il funzionamento come newsreader, editor di directory, programma di posta, ecc. Quando usato per la programmazione o la scrittura di script, riconosce intelligentemente il formato che si sta usando e cerca di fornire assistenza. Alcune persone sostengono che l'unico programma di cui hanno bisogno su Linux è Emacs. Dieci minuti spesi ad imparare Emacs ora possono far risparmiare ore in futuro. È caldamente raccomandato avere a portata di mano il manuale di GNU Emacs da consultare quando si sta imparando Emacs.

Tutti questi programmi sono di solito forniti con un programma tutor che aiuta ad impararli facendo pratica. Avviare Vim digitando "vim" e premere il tasto F1. Si dovrebbero leggere come minimo le prime 35 righe. Poi seguire il corso di apprendimento in linea muovendo il cursore su "|tutor|" e premendo Ctrl-].

[Nota] Nota

I buoni editor, come Vim ed Emacs, possono gestire correttamente testi UTF-8 e testi in altre codifiche esotiche. È opportuno usare l'ambiente GUI con la localizzazione UTF-8 e installare i programmi e i tipi di carattere necessari. Gli editor hanno opzioni per impostare la codifica dei file indipendentemente dall'ambiente GUI. Fare riferimento alla loro documentazione sui testi multibyte.

vim(1) recente si avvia con la sana opzione "nocompatible" e entra nella modalità NORMAL.[1]


Usare il programma "vimtutor" per imparare ad usare vim attraverso un corso tutorial interattivo.

Il programma vim cambia il suo comportamento in risposta ai tasti premuti in base alla modalità (mode). La digitazione con i tasti nel buffer è fatta soprattutto in modalità INSERT e in modalità REPLACE. Spostare il cursore viene fatto soprattutto in modalità NORMAL. La selezione interattiva viene fatta in modalità VISUAL. Se si digita ":" in modalità NORMAL si cambia la sua modalità in Ex-mode. Ex-mode accetta comandi.

[Suggerimento] Suggerimento

Vim viene distribuito con il pacchetto Netrw. Netrw supporta lettura e scrittura di file, navigazione di directory in una rete e navigazione locale! Provare Netrw con "vim ." (un punto come argomento) e leggere il suo manuale con ":help netrw".

Per la configurazione avanzata di vim, vedere Sezione 9.2, «Personalizzare vim».

È bene imparare i comandi Unix di base. Il termine "Unix" è qui usato in senso lato; ogni SO clone di Unix offre di solito comandi equivalenti. Il sistema Debian non fa eccezione. Non ci si preoccupi se, al momento, alcuni comandi non funzionano come si vorrebbe. Se si usa alias nella shell, i corrispondenti output dei comandi sono diversi. Questi esempi non sono pensati per essere eseguiti necessariamente in questo ordine.

Provare tutti i comandi seguenti da un account utente non privilegiato.

Tabella 1.17. Elenco di comandi Unix di base

comando descrizione
pwd mostra il nome della directory attuale/di lavoro
whoami mostra il nome dell'utente attuale
id mostra l'identità dell'utente attuale (nome, uid, gid e gruppi associati)
file pippo mostra che tipo di file sia il file "pippo"
type -p nomecomando mostra la posizione del file del comando "nomecomando"
which nomecomando " "
type nomecomando mostra informazioni sul comando "nomecomando"
apropos parola-chiave trova comandi riguardanti "parola-chiave"
man -k parola-chiave " "
whatis nomecomando mostra una spiegazione di una riga sul comando "nomecomando"
man -a nomecomando mostra una spiegazione del comando "nomecomando" (in stile Unix)
info nomecomando mostra una spiegazione piuttosto lunga del comando "nomecomando" (in stile GNU)
ls elenca il contenuto di directory (non i file punto e le directory)
ls -a elenca il contenuto di directory (tutti i file e directory)
ls -A elenca il contenuto di directory (quasi tutti i file e directory, cioè salta ".." e ".")
ls -la elenca tutto il contenuto di directory con informazioni dettagliate
ls -lai elenca tutto il contenuto di directory con numeri di inode e informazioni dettagliate
ls -d elenca tutte le directory dentro la directory attuale
tree mostra il contenuto in forma di albero
lsof pippo mostra lo stato aperto per il file "pippo"
lsof -p pid mostra i file aperti dal processo con ID "pid"
mkdir pippo crea una nuova directory "pippo" nella directory attuale
rmdir pippo rimuove la directory "pippo" nella directory attuale
cd pippo cambia directory spostandosi nella directory "pippo" nella directory attuale o in una directory elencata nella variabile "$CDPATH"
cd / cambia directory spostandosi nella directory radice
cd cambia directory spostandosi nella directory home dell'utente
cd /pippo cambia directory spostandosi nella directory con percorso assoluto "/pippo"
cd .. cambia directory spostandosi nella directory genitore
cd ~pippo cambia directory spostandosi nella directory home dell'utente "pippo"
cd - cambia directory spostandosi nella directory precedente
</etc/motd pager mostra il contenuto di "/etc/motd" usando il paginatore predefinito
touch filediprova crea un file "filediprova" vuoto
cp pippo pluto copia un file "pippo" esistente in un nuovo file "pluto"
rm filediprova rimuove il file "filediprova"
mv pippo pluto rinomina un file "pippo" esistente con il nuovo nome "pluto" ("pluto" non deve esistere)
mv pippo pluto muove un file "pippo" esistente nella nuova posizione "pluto/pippo" (la directory "pluto" deve esistere)
mv pippo pluto/paperino muove un file "pippo" esistente in una nuova posizione con il nuovo nome "pluto/paperino" (la directory "pluto" deve esistere ma non deve esistere "bar/baz")
chmod 600 pippo fa sì che il file "pippo" esistente sia non leggibile e non scrivibile da altri (e non eseguibile per nessuno)
chmod 644 pippo fa sì che il file "pippo" esistente sia leggibile ma non scrivibile da altri (e non eseguibile per nessuno)
chmod 755 pippo fa sì che il file "pippo" esistente sia leggibile ma non scrivibile da altri (ed eseguibile per tutti)
find . -name modello trova nomi di file corrispondenti al "modello" di shell (lento)
locate -d . modello trova nomi di file corrispondenti al "pattern" di shell (più veloce, usa un database generato regolarmente)
grep -e "modello" *.html trova un "modello" in tutti i file nella directory attuale che terminano con ".html" e mostra tutte le corrispondenze
top mostra informazioni sui processi a tutto schermo, digitare "q" per uscire
ps aux | pager mostra informazioni su tutti i processi in esecuzione usando output in stile BSD
ps -ef | pager mostra informazioni su tutti i processi in esecuzione usando output in stile system V Unix
ps aux | grep -e "[e]xim4*" mostra tutti i processi che stanno eseguendo "exim" e "exim4"
ps axf | pager mostra informazioni su tutti i processi in esecuzione usando output in ASCII art
kill 1234 uccide un processo identificato dall'ID "1234"
gzip pippo comprime pippo" per creare "pippo.gz", usando la codifica Lempel-Ziv (LZ77)
gunzip pippo.gz decomprime "pippo.gz" per creare "pippo"
bzip2 pippo comprime "pippo" per creare "pippo.bz2", usando l'algoritmo Burrows-Wheeler per la compressione di testo con ordinamento di blocchi e la codifica Huffman (compressione migliore di gzip)
bunzip2 pippo.bz2 decomprime "pippo.bz2" per creare "pippo"
xz pippo comprime "pippo" per creare "pippo.xz", usando l'algoritmo Lempel–Ziv–Markov chain (compressione migliore di bzip2)
unxz pippo.xz decomprime "pippo.xz" per creare "pippo"
tar -xvf pippo.tar estrae i file dall'archivio "pippo.tar"
tar -xvzf pippo.tar.gz estrae file dall'archivio "pippo.tar.gz" compresso con gzip
tar -xvjf pippo.tar.bz2 estrae file dall'archivio "pippo.tar.bz2"
tar -xvJf pippo.tar.xz estrae file dall'archivio "pippo.tar.xz"
tar -cvf pippo.tar pluto/ archivia i contenuti della directory "pluto/" nell'archivio "pippo.tar"
tar -cvzf pippo.tar.gz pluto/ archivia i contenuti della directory "pluto/" nell'archivio compresso "pippo.tar.gz"
tar -cvjf pippo.tar.bz2 pluto/ archivia i contenuti della directory "plutor/" nell'archivio "pippo.tar.bz2"
tar -cvJf pippo.tar.xz pluto/ archivia i contenuti della directory "plutor/" nell'archivio "pippo.tar.xz"
zcat README.gz | pager mostra i contenuti del file compresso "README.gz" usando il paginatore predefinito
zcat README.gz > pippo crea un file "pippo con i contenuti di "README.gz" decompressi
zcat README.gz >> pippo aggiunge i contenuti di "README.gz" decompressi in coda al file "pippo" (se il file non esiste, lo crea)

[Nota] Nota

Unix tradizionalmente nasconde i nomi di file che iniziano con ".". Sono tradizionalmente file contenenti informazioni di configurazione e preferenze dell'utente.

Per il comando cd vedere builtins(7).

Il paginatore predefinito del sistema di base di Debian è more(1) che non ha lo scorrimento all'indietro. Installando il pacchetto less, con la riga di comando "apt-get install less", less(1) diventa il paginatore predefinito e si può così scorrere il testo all'indietro usando i tasti freccia.

I caratteri "[" e "]" nella espressione regolare del comando "ps aux | grep -e "[e]xim4*"" sopra citato, permettono a grep di evitare di trovare corrispondenza con sé stesso. La parte "4*" nella espressione regolare significa 0 o più ripetizioni del carattere "4" e perciò permette a grep di trovare corrispondenza sia con "exim" sia con "exim4". Sebbene il carattere "*" sia usato nei nomi di file con metacaratteri della shell e nelle espressioni regolari, il suo significato è diverso nei due casi. Si possono imparare le espressioni regolari da grep(1).

Come esercizio, esplorare le directory e dare un'occhiata al sistema usando i comandi citati sopra. Se si hanno domande su uno qualsiasi dei comandi in console, assicurarsi di leggere la pagina di manuale.

Per esempio, provare a fare quanto segue.

$ man man
$ man bash
$ man builtins
$ man grep
$ man ls

Può essere un po' difficile abituarsi allo stile delle pagine man perché sono piuttosto concise, in particolar modo le più vecchie e tradizionali. Una volta che ci si fa la mano, però, si apprezza la loro concisione.

Notare che molti comandi in stile Unix, inclusi quelli da GNU e BSD, mostrano una breve informazione di aiuto se li si invoca in uno dei modi seguenti (o in alcuni casi se lo si fa senza usare opzioni).

$ commandname --help
$ commandname -h

Ora si ha un'idea di come usare il sistema Debian; è tempo di dare uno sguardo più approfondito al meccanismo di esecuzione dei comandi nel sistema Debian. Qui la realtà è stata semplificata ad uso del principiante. Vedere bash(1) per una spiegazione esatta.

Un semplice comando è formato da una sequenza di componenti.

  1. Assegnazioni di variabili (opzionale)

  2. Nome del comando

  3. Opzioni (opzionali)

  4. Ridirezioni (opzionali, > , >> , < , << , ecc.)

  5. Operatori di controllo (opzionale, && , || , a-capo , ; , & , ( , ) )

I valori di alcune variabili d'ambiente cambiano il comportamento di alcuni comandi Unix.

I valori predefiniti delle variabili d'ambiente sono impostati inizialmente dal sistema PAM e poi alcuni di essi possono essere reimpostati da alcuni programmi applicativi.

  • Il sistema PAM come pam_env può impostare variabili d'ambiente con /etc/pam.conf", "/etc/environment" e "/etc/default/locale".

  • Il display manager, come gdm3 può reimpostare variabili d'ambiente per la sessione GUI con "~/.profile".

  • L'inizializzazione dei programmi specifica per l'utente può reimpostare variabili d'ambiente con "~/.profile", "~/.bash_profile" e "~/.bashrc".

La localizzazione predefinita è definita nella variabile d'ambiente "$LANG" ed è configurata nella forma "LANG=xx_YY.UTF-8" dall'installatore o dalla successiva configurazione della GUI, es. "Impostazioni" → "Regione e lingua" → "Lingua" / "Formati" per GNOME.

[Nota] Nota

Io raccomando di configurare l'ambiente di sistema usando per il momento solo la variabile "$LANG" e di tenersi alla larga dalle variabili "$LC_*" a meno che non sia strettamente necessario.

Il valore completo di localizzazione impostato nella variabile "$LANG" consiste di 3 parti: "xx_YY.ZZZZ".



Una tipica esecuzione di un comando usa una sequenza sulla riga della shell come la seguente.

$ echo $LANG
en_US.UTF-8
$ date -u
Wed 19 May 2021 03:18:43 PM UTC
$ LANG=fr_FR.UTF-8 date -u
mer. 19 mai 2021 15:19:02 UTC

In questo caso il programma date(1) viene eseguito con differenti valori di localizzazione.

La maggior parte delle invocazioni di comandi non è solitamente preceduta da definizioni di variabili d'ambiente. In alternativa all'esempio precedente, si può eseguire quanto segue.

$ LANG=fr_FR.UTF-8
$ date -u
mer. 19 mai 2021 15:19:24 UTC
[Suggerimento] Suggerimento

Quando si segnala un bug, è una buona idea, se si usa un ambiente non inglese, eseguire e controllare il comando nella localizzazione "en_US.UTF-8".

Per dettagli più specifici sulla configurazione della localizzazione vedere Sezione 8.1, «La localizzazione».

È bene cercare di ricordare i seguenti idiomi per comandi di shell che vengono digitati sulla stessa riga come parte del comando di shell.

Tabella 1.23. Idiomi per comandi di shell

idioma per comando descrizione
comando & esegue comando sullo sfondo in una sotto-shell
comando1 | comando2 invia tramite pipe lo standard output di comando1 allo standard input di comando2 (esecuzione concorrente)
comando1 2>&1 | comando2 invia tramite pipe sia lo standard output sia lo standard error di comando1 allo standard input di comando2 (esecuzione concorrente)
comando1 ; comando2 esegue comando1 e comando2 in sequenza
comando1 && comando2 esegue comando1; se ha successo, esegue comando2 in sequenza (restituisce lo stato di successo se sia comando1 sia comando2 hanno successo)
comando1 || comando2 esegue comando1; se non ha successo, esegue comando2 in sequenza (restituisce lo stato di successo se comando1 o comando2 ha successo)
comando > pippo ridirige lo standard output di comando al file "pippo" (sovrascrivendolo)
comando 2> pippo ridirige lo standard error di comando al file "pippo" (sovrascrivendolo)
comando >> pippo ridirige lo standard output di comando al file "pippo" (aggiungendo in coda)
comando 2>> pippo ridirige lo standard error di comando al file "pippo" (aggiungendo in coda)
comando > pippo 2>&1 ridirige sia lo standard output sia lo standard error di comando al file pippo
comando < pippo usa come standard input di comando il file "pippo"
comando << delimitatore usa come standard input di comando le righe che seguono fino a che non viene incontrato il testo "delimitatore" (inserire un documento)
comando <<- delimitatore usa come standard input di comando le righe che seguono fino a che non viene incontrato il testo "delimitatore"; i caratteri di tabulazione iniziali vengono eliminate dal testo (inserire un documento)

Il sistema Debian è un sistema multi-tasking. I compiti sullo sfondo permettono agli utenti di eseguire più programmi in una singola shell. La gestione dei processi sullo sfondo coinvolge i comandi interni della shell jobs, fg, bg e kill. Leggere le sezioni "SIGNALS" e "JOB CONTROL" di bash(1) e builtins(1).

Per esempio, provare a fare quanto segue.

$ </etc/motd pager
$ pager </etc/motd
$ pager /etc/motd
$ cat /etc/motd | pager

Benché tutti i 4 esempi di ridirezione della shell mostrino la stessa cosa, l'ultimo esempio esegue un comando cat aggiuntivo e spreca risorse senza motivo.

La shell permette di aprire file usando il comando interno execcon un descrittore di file arbitrario.

$ echo Hello >foo
$ exec 3foo 4bar  # open files
$ cat <&3 >&4       # redirect stdin to 3, stdout to 4
$ exec 3<&- 4>&-    # close files
$ cat bar
Hello

I descrittori di file 0-2 sono predefiniti.


Nell'ambiente di lavoro Unix, l'elaborazione del testo viene fatta instradando il testo tramite pipe attraverso catene di strumenti standard per l'elaborazione del testo. Questa è stata un'altra fondamentale innovazione di Unix.

Ci sono alcuni strumenti di elaborazione del testo che sono usati molto spesso in un sistema *nix.

Se non si è sicuri di cosa facciano esattamente questi comandi, usare "man comando" per scoprirlo.

[Nota] Nota

Il criterio di ordinamento e le espressioni di intervalli dipendono dalla localizzazione. Se si desidera ottenere il comportamento tradizionale di un comando, usare la localizzazione C o C.UTF-8 invece delle normali UTF-8 (vedere Sezione 8.1, «La localizzazione»).

[Nota] Nota

Le espressioni regolari Perl (perlre(1)), le PCRE (Perl Compatible Regular Expressions) e le espressioni regolari Python fornite dal modulo re hanno molte estensioni comuni delle normali ERE.

Le espressioni regolari sono usate in molti strumenti di elaborazione del testo. Sono analoghe ai modelli di glob della shell, ma sono più complesse e potenti.

Una espressione regolare descrive il modello a cui trovare corrispondenza ed è composta da caratteri di testo e metacaratteri.

Un metacarattere è semplicemente un carattere con un significato speciale. Ci sono 2 stili principali, BRE e ERE, a seconda degli strumenti di testo descritti in precedenza.


Le espressioni regolari di emacs sono fondamentalmente BRE, ma sono state estese per trattare "+" e "?" come i metacaratteri nelle ERE. Perciò, nelle espressioni regolari di emacs, non è necessario proteggerli con il carattere di escape "\".

Per effettuare ricerche di testo usando espressioni regolari si può usare grep(1).

Per esempio, provare a fare quanto segue.

$ egrep 'GNU.*LICENSE|Yoyodyne' /usr/share/common-licenses/GPL
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
Yoyodyne, Inc., hereby disclaims all copyright interest in the program

Per le espressioni di sostituzione alcuni caratteri hanno un significato particolare.


Per le stringhe di sostituzione Perl viene usato «$&» invece di «&» e «$n» invece di «\n».

Per esempio, provare a fare quanto segue.

$ echo zzz1abc2efg3hij4 | \
sed -e 's/\(1[a-z]*\)[0-9]*\(.*\)$/=&=/'
zzz=1abc2efg3hij4=
$ echo zzz1abc2efg3hij4 | \
sed -e 's/\(1[a-z]*\)[0-9]*\(.*\)$/\2===\1/'
zzzefg3hij4===1abc
$ echo zzz1abc2efg3hij4 | \
perl -pe 's/(1[a-z]*)[0-9]*(.*)$/$2===$1/'
zzzefg3hij4===1abc
$ echo zzz1abc2efg3hij4 | \
perl -pe 's/(1[a-z]*)[0-9]*(.*)$/=$&=/'
zzz=1abc2efg3hij4=

In questo esempio si faccia particolare attenzione allo stile delle espressioni regolari tra parentesi e come le stringhe corrispondenti siano usate nel processo di sostituzione del testo dai diversi strumenti.

Queste espressioni regolari possono essere usate per spostare il cursore e per fare sostituzioni di testo anche in alcuni editor.

La barra inversa, "\" alla fine della prima riga nella riga di comando di shell protegge il carattere di a capo rendendolo uno spazio e continuando l'input della riga di comando di shell nella riga successiva.

Leggere tutte le pagine man relative per imparare l'uso di questi comandi.

Considerare per esempio un file ti testo chiamato "DPL" in cui sono elencati, in un formato separato da spazi, alcuni nomi di leader del progetto Debian pre-2004 e la data della loro installazione.

Ian     Murdock   August  1993
Bruce   Perens    April   1996
Ian     Jackson   January 1998
Wichert Akkerman  January 1999
Ben     Collins   April   2001
Bdale   Garbee    April   2002
Martin  Michlmayr March   2003

Awk viene usato spesso per estrarre dati da questo tipo di file.

Per esempio, provare a fare quanto segue.

$ awk '{ print $3 }' <DPL                   # month started
August
April
January
January
April
April
March
$ awk '($1=="Ian") { print }' <DPL          # DPL called Ian
Ian     Murdock   August  1993
Ian     Jackson   January 1998
$ awk '($2=="Perens") { print $3,$4 }' <DPL # When Perens started
April 1996

Questo tipo di file può anche essere analizzato con le shell tipo Bash.

Per esempio, provare a fare quanto segue.

$ while read first last month year; do
    echo $month
  done <DPL
... same output as the first Awk example

In questo caso, il comando incorporato read usa i caratteri in "$IFS" (internal field separator, separatore di campi interno) per suddividere le righe in parole.

Se si modifica "$IFS" in ":", si possono analizzare facilmente con la shell i file "/etc/passwd".

$ oldIFS="$IFS"   # save old value
$ IFS=':'
$ while read user password uid gid rest_of_line; do
    if [ "$user" = "bozo" ]; then
      echo "$user's ID is $uid"
    fi
  done < /etc/passwd
bozo's ID is 1000
$ IFS="$oldIFS"   # restore old value

(Se si usa Awk per fare la stessa cosa, usare "FS=':'" per impostare il separatore di campi.)

IFS viene anche usato dalla shell per suddividere i risultati dell'espansione di parametri, sostituzione di comandi ed espansioni aritmetiche. Queste non avvengono all'interno delle virgolette singole o doppie. Il valore predefinito di IFS è la combinazione di spazio, tab e <a capo>.

Essere prudenti nell'uso di questi trucchetti di shell con IFS. Possono accadere strane cose quando la shell interpreta alcune parti dello script come suo input.

$ IFS=":,"                        # use ":" and "," as IFS
$ echo IFS=$IFS,   IFS="$IFS"     # echo is a Bash builtin
IFS=  , IFS=:,
$ date -R                         # just a command output
Sat, 23 Aug 2003 08:30:15 +0200
$ echo $(date -R)                 # sub shell --> input to main shell
Sat  23 Aug 2003 08 30 36 +0200
$ unset IFS                       # reset IFS to the default
$ echo $(date -R)
Sat, 23 Aug 2003 08:30:50 +0200

Gli script seguenti fanno alcune cose carine se inseriti in una pipe.


Uno script di shell di una riga può operare reiteratamente su più file usando find(1) e xargs(1) per fare compiti piuttosto complicati. Vedere Sezione 10.1.5, «Esempi di invocazione per la selezione di file» e Sezione 9.4.9, «Ripetere un comando su diversi file».

Quando usare la shell in modalità interattiva diventa troppo complicato, considerare la scrittura di uno script di shell (vedere Sezione 12.1, «Script shell»).



[1] Anche il vecchio vim può avviarsi nella modalità "nocompatible" sensata se lo si avvia con l'opzione "-N".