Nella precedente lezione ( Lezione 9 - Permessi), abbiamo visto alcune delle implicazioni di Linux come sistema operativo multi-utente. In questa lezione esamineremo la natura multitasking di Linux, e come è gestita con l'interfaccia a riga di comando.
Come con ogni sistema operativo multitasking, Linux esegue processi multipli simultanei. O, per meglio dire, questi processi sembrano davvero simultanei. In realtà, un computer con un singolo processore può eseguire un solo processo alla volta, ma il kernel Linux attribuisce a ogni processo una frazione del turno di esecuzione del processore, e ogni processo appare in esecuzione nello stesso momento.
Ci sono diversi comandi che possono essere usati per controllare i processi. Questi sono:
L'argomento che tratteremo ora potrà sembrare piuttosto oscuro, ma
risulterà molto pratico per l'utente medio che lavora per lo più
con l'interfaccia grafica. È possibile che non lo sappiate, ma la
maggior parte (se non tutti) dei programmi grafici possono essere eseguiti
dalla riga di comando. Ecco un esempio: c'è un piccolo programma di
nome xload
, fornito col sistema X Window, che mostra un grafico
rappresentante il carico del sistema. Puoi eseguire questo programma digitando:
[io@linuxbox io]$ xload
Notate l'apparire della piccola finestra di xload, che inizia a mostrare il grafico del carico del sistema. Notate anche che, dopo che avete lanciato il programma, il prompt non è ricomparso. La shell sta aspettando che il programma finisca prima di ridare il prompt. Se chiudete la finestra di xload, il programma xload termina e ritorna il prompt.
Ora, per renderci la vita un po' più facile, eseguiremo ancora il
programma xload
, ma questa volta lo metteremo in background così
il prompt ritornerà visibile. Per fare questo, eseguiamo xload
nel modo seguente:
[io@linuxbox io]$ xload &
[1] 1223
[io@linuxbox io]$
In questo caso, il prompt è ritornato perché il processo è stato messo in background.
Ora, immaginate di aver dimenticato di usare il simbolo "&" per mettere
il programma in background. C'è ancora un po' di speranza. Potete
digitare control-z e il processo sarà sospeso. Il processo esiste
ancora, ma è inattivo. Per riattivare il processo in background, digita
il comando bg
(abbreviazione di background). Ecco un esempio:
[io@linuxbox io]$ xload
[2]+ Stopped xload
[io@linuxbox io]$ bg
[2]+ xload &
Ora che abbiamo un processo in background, potrebbe essere utile visualizzare
una lista dei processi avviati da noi. Per fare questo, possiamo usare sia il
comando jobs
, sia ps
, un comando ancora più potente.
[io@linuxbox io]$ jobs
[1]+ Running xload &
[io@linuxbox io]$ ps
PID TTY TIME CMD
1211 pts/4 00:00:00 bash
1246 pts/4 00:00:00 xload
1247 pts/4 00:00:00 ps
Supponendo che si abbia un programma che non risponde più;
come fate a sbarazzartene?
Userete il comando kill, naturalmente. Proviamolo su xload
. Prima
dovete identificare il processo che volete uccidere. Per far questo potete
usare jobs
o ps
. Se usate jobs
otterrete un numero
di job. Con ps
vi viene fornito un id del processo (PID). Lo faremo
in entrambi i modi:
[io@linuxbox io]$ xload &
[1] 1292
[io@linuxbox io]$ jobs
[1]+ In esecuzione xload &
[io@linuxbox io]$ kill %1
[io@linuxbox io]$ xload &
[2] 1293
[1] Terminato xload
[io@linuxbox io]$ ps
PID TTY TIME CMD
1280 pts/5 00:00:00 bash
1293 pts/5 00:00:00 xload
1294 pts/5 00:00:00 ps
[io@linuxbox io]$ kill 1293
[2]+ Terminated xload
Anche se il comando kill è usato per "uccidere" i processi, il suo scopo
reale è quello di inviare segnali ai processi. Quasi sempre si
finisce con l'inviare un segnale che dice al processo di sparire, ma di segnali
se ne possono inviare anche di altro tipo. I programmi (se scritti
adeguatamente) rimangono in ascolto dei segnali che provengono dal sistema
operativo e rispondono a questi, molto spesso per consentire dei metodi di
terminazione non aggressivi. Per esempio, un editor di testo può
ascoltare ogni segnale che indica che l'utente è uscito dal sistema, o
che il computer sta per essere spento. Quando l'editor riceve questo segnale,
salva il lavoro in corso prima di uscire. Il comando kill
può
inviare una varietà di segnali ai processi. Digitando:
kill -l
si avrà una lista dei segnali che sono inviabili con kill
.
La maggior parte sono piuttosto oscuri, ma alcuni sono utili da conoscere:
Segnale | Nome | Descrizione |
1 | SIGHUP |
Segnale di aggancio (Hang up). I programmi possono ascoltare questo segnale e agire (o non agire) di conseguenza. |
2 | SIGINT |
Segnale di interruzione. Questo segnale è inviato ai processi per interromperli. I programmi possono elaborare questo segnale e agire di conseguenza. Puoi dare questo segnale anche direttamente digitando control-c nella finestra del terminale dove il programma viene eseguito. |
15 | SIGTERM |
Segnale di conclusione. Questo segnale è inviato ai processi per concluderli. Inoltre, i programmi possono elaborare questo segnale e agire di conseguenza. Puoi inviare questo segnale anche direttamente digitando control-c nella finestra di terminale dove il programma è stato eseguito. Questo è il segnale predefinito inviato dal comando kill se non è specificato nessun segnale. |
9 | SIGKILL |
Segnale di kill. Questo segnale provoca la conclusione immediata del processo dal kernel Linux. I programmi non possono captare questo segnale. |
Ora, supponiamo che abbiate un programma bloccato senza speranza e vogliate liberavene. Ecco cosa dovete fare:
ps
per ottenere l'id del processo (PID) che
volete terminare.kill
per questo PID.
[io@linuxbox io]$ ps x | grep programma_difettoso
PID TTY STAT TIME COMMAND
2931 pts/5 SN 0:00 programma_difettoso
[io@linuxbox io]$ kill -SIGTERM 2931
[io@linuxbox io]$ kill -SIGKILL 2931
Nell'esempio sopra abbiamo usato il comando ps
con l'opzione x per
elencare tutti i nostri processi (anche quelli non avviati dal nostro terminale).
Inoltre, abbiamo ridiretto tramite una pipe l'output del comando
ps
verso grep
per avere l'elenco soltanto dei programmi che
ci interessano. Poi abbiamo usato kill
per inviare un segnale
SIGTERM al programma difettoso.
Nella pratica, è molto comune farlo nel modo descritto di seguito
poiché il segnale predefinito inviato da kill è SIGTERM e kill
può usare anche il numero del segnale al posto del nome:
[io@linuxbox io]$ kill 2931
Poi, se il processo non si conclude, forzatelo con il segnale SIGKILL:
[io@linuxbox io]$ kill -9 2931
Qui si conclude la serie di lezioni di "Learning the Shell". Nella prossima serie, "Writing shell scripts," vedremo come automatizzare l'esecuzione di compiti con la shell.