Cambiare stato a una macchina in produzione è una delle poche operazioni in cui un comando digitato male butta fuori tutti gli utenti collegati. Qui contano la sintassi esatta e la famiglia di init: i comandi del mondo SysVinit e quelli del mondo systemd fanno le stesse cose con nomi diversi, e l’esame chiede entrambi.

Il mondo SysVinit: runlevel, inittab e /etc/init.d/

I runlevel vanno da 0 a 6. Solo tre significano ovunque la stessa cosa: 0 arresta il sistema, 1 (indicato anche con s o single) è il monoutente di manutenzione senza rete, 6 riavvia. Da 2 a 5 dipende dalla distribuzione: nella tradizione Red Hat il 3 è multiutente testuale e il 5 aggiunge il login grafico, mentre Debian li rende equivalenti fra loro. Non dare mai per scontato il significato di 2, 3, 4 e 5.

A gestirli è /sbin/init, che legge /etc/inittab. Ogni riga ha la forma id:runlevels:action:process:

id:3:initdefault:
si::sysinit:/etc/init.d/rcS
l3:3:wait:/etc/init.d/rc 3
ca::ctrlaltdel:/sbin/shutdown -r now
1:23:respawn:/sbin/getty tty1 VC linux

La riga initdefault fissa il runlevel predefinito, e quel numero non deve mai essere 0 o 6, altrimenti la macchina si spegne o si riavvia appena finito l’avvio. Le azioni da riconoscere sono sysinit, boot, bootwait, wait, respawn (il processo viene fatto ripartire se muore) e ctrlaltdel. Dopo ogni modifica si esegue telinit q, che fa rileggere il file senza riavviare: saltare questo passo è il modo classico per accorgersi dell’errore solo al riavvio successivo.

Gli script dei servizi stanno in /etc/init.d/, e ogni runlevel ha la sua directory /etc/rc0.d/, /etc/rc1.d/ e così via, piena di link simbolici a quegli script. L’iniziale del nome del link decide il verso: S avvia il servizio entrando nel runlevel, K lo termina. Quindi /etc/rc1.d/K90network ferma la rete quando si passa al monoutente.

Il comando runlevel stampa due valori, il precedente e l’attuale: N 3 significa che è ancora quello dell’avvio. Per cambiarlo si usa telinit: telinit 1, telinit s o telinit S portano al monoutente, telinit 6 riavvia.

Il mondo systemd: unit e target

systemd gestisce risorse e servizi come unit, di sette tipi: service, socket, device, mount, automount, target e snapshot. Il target è ciò che sostituisce il runlevel: multi-user.target corrisponde al 3, graphical.target al 5, rescue.target al monoutente, poweroff.target e reboot.target a 0 e 6. Esistono anche gli alias da runlevel0.target a runlevel6.target, ma /etc/inittab non viene letto.

systemctl start|stop|restart|status sshd.service
systemctl is-active sshd.service
systemctl enable|disable sshd.service
systemctl is-enabled sshd.service
systemctl isolate multi-user.target
systemctl get-default
systemctl set-default multi-user.target

Se non esistono unit omonime di tipo diverso il suffisso si può omettere, quindi systemctl status sshd basta. Attenzione alla coppia più confusa: start e stop agiscono adesso, enable e disable agiscono al prossimo avvio. isolate è l’equivalente di telinit N. Il target predefinito è il link simbolico /etc/systemd/system/default.target, che set-default riscrive; si può anche imporre dal bootloader con systemd.unit=. I file forniti dai pacchetti stanno in /lib/systemd/system/ (su molte distribuzioni /usr/lib/systemd/system/), le personalizzazioni in /etc/systemd/system/, e queste ultime prevalgono.

Per riavviare un servizio, quindi, su SysVinit si scrive service sshd restart oppure /etc/init.d/sshd restart, su systemd systemctl restart sshd.

Avvisare, spegnere, riavviare

shutdown è il comando tradizionale e fa più che togliere corrente: avvisa tutti gli utenti collegati, blocca i nuovi login, invia SIGTERM e poi SIGKILL ai processi, infine delega l’azione al gestore dei servizi in uso. La sintassi è shutdown [opzione] tempo [messaggio] e il tempo è obbligatorio, nei formati hh:mm, +minuti oppure now (equivalente a +0).

shutdown -h now
shutdown -r +10 "Riavvio per aggiornamento del kernel"
shutdown 18:30
shutdown -c

Da ricordare a memoria: -h spegne, -r riavvia, -c annulla uno spegnimento programmato, e senza né -h-r il sistema passa al monoutente. Per un semplice avviso senza cambiare stato c’è wall, che scrive a tutti i terminali: wall "Manutenzione fra cinque minuti", oppure wall messaggio.txt.

Su SysVinit l’opzione -a sulla riga ctrlaltdel di /etc/inittab limita il riavvio da tastiera agli utenti elencati in /etc/shutdown.allow. Con systemd si usano systemctl reboot, systemctl poweroff, systemctl suspend e systemctl hibernate; su molte distribuzioni poweroff e reboot sono link a systemctl. Le reazioni agli eventi di alimentazione, come la chiusura del coperchio, si configurano in /etc/systemd/logind.conf, ma valgono solo se non è attivo un altro gestore: quello classico è il demone acpid, che consente regolazioni più fini.

Terminare i processi come si deve

Terminare un processo significa mandargli un segnale. SIGTERM, numero 15, è il predefinito di kill e chiede al processo di chiudersi ordinatamente salvando il lavoro; SIGKILL, numero 9, lo elimina subito senza dargli alcuna possibilità di reagire e va usato solo dopo che SIGTERM ha fallito; SIGHUP, numero 1, per molti demoni significa «rileggi la configurazione».

kill 2481
kill -15 2481
kill -9 2481
kill -l
killall httpd
pkill -HUP rsyslogd

kill vuole un PID, killall e pkill lavorano sul nome del programma. Ma per un servizio di sistema la via corretta non è kill: si passa dal gestore, con systemctl stop o con service ... stop, altrimenti una voce respawn in /etc/inittab o una unit systemd con riavvio automatico lo faranno ripartire subito.