In soldoni un processo è un programma, i processi possono esistere in diversi stati, e possono comunicare tra loro attraverso i cosiddetti "segnali", che non sono altro che notifiche asincrone mandate ad un processo. Gli strumenti principali per visualizzare i processi attivi su una macchina sono:
- Top (Programma interattivo e dinamico)
- Ps (Programma statico)
N.B.: Esiste una categoria particolare di processi chiamata " demoni" (Su altri sistemi operativi possono essere chiamati servizi), sono processi che vengono lanciati in background automaticamente e non sono interattivi, non hanno un terminale di controllo. I demoni effettuano determinate azioni in determinati tempi o in risposta a determinati eventi. Nei sistemi GNU/Linux e derivati da Unix i nomi dei processi demone finiscono in "d" o in 'd[0,x]' come ksyslogd, kswapd0 o kthreadd.
It is complicated: pid is process identifier; tid is thread identifier.
But as it happens, the kernel doesn't make a real distinction between them: threads are just like processes but they share some things (memory, file descriptors and so on...) with other instances of the same group.
So, a tid is actually the identifier of the schedulable object in the kernel (thread), while the pid is the identifier of the group of schedulable objects that share memory and fds (process).
But to make things more interesting, when a process has only one thread (the initial situation and in the good old times the only one) the pid and the tid are always the same. So any function that works with a tid will automatically work with a pid.
It is worth noting that many functions/system calls/command line utilities documented to work with pid actually use tids. But if the effect is process-wide you will simply not notice the difference.
Top è un programma interattivo e dinamico per la gestione dei processi. Per avviarlo basta scrivere in un terminale "top", a questo punto comparirà una schermata in cui:
- "Load average" tiene conto della media di utilizzo della CPU, il primo numero è al minuto, il secondo ogni 5 minuti e il terzo ogni 15 minuti, possiamo fare delle considerazioni su questi, ad esempio se il primo è molto alto e l'ultimo basso, allora c'è stato un picco nell'ultimo minuto di risorse richieste e viceversa, inoltre è da tenere a mente che possono essere un buono strumento per valutare se un server è troppo debole o troppo forte per il suo lavoro, ad esempio su una macchina con 4 processori ho una media costante molto più bassa rispetto al numero 4 allora, tutti quei processori sono sprecati per il mio sistema
- Con "Shift+P" ordina i processi per utilizzo cpu
- Con "Shift+M" ordina i processi per utilizzo della memoria RAM
- La colonna "NI" rappresenta la priorità di un processo: più è basso il numero più è alta la priorità assegnata al processo.
- Le priorità vanno da -20 a +19; -20 costituisce la priorità più alta che un processo possa avere, viceversa +19 è la più bassa.
- Con "r" posso cambiare la priorità di un processo, mi basta inserire il PID (Process ID) da ri-prioritarizzare e schiacciando invio posso inserire la nuova priorità.
- Con "k" termino un processo, anche in questo caso mi basta
inserire il PID e il segnale con cui terminarlo.
- Segnale 15 chiusura normale
- Segnale -9 chiusura forzata
- Con "q" esce dal programma
- Con "m" mostra o nasconde informazioni sulla memoria
- Con "s" cambia il tempo di aggiornamento della schemata di top (di default questo tempo è 3 secondi)
La schermata di top si aggiorna automaticamente ogni 3 secondi, ad ogni modo esistono altre modalità con cui lanciarlo per poter cambiare questa impostazione o richiedere feature specifiche:
top -d 1
# aggiorna lo stato dei processi ogni secondo
top -p 1
# si ottiene una versione di top con focus sul
# processo avento PID = 1
top -p 1,2,3
# come il caso precedente, ma ora il focus è sui
# processi 1, 2 and 3
top -b
# avvio top in modalità "batch", in questa modalità
# visualizzo solo i processi senza informazioni aggiuntive
Possiamo vedere una descrizione dettagliata del significato dei campi visualizzati da top, nella pagina di man di top, nella sezione "DESCRIPTIONS". Una variante molto comoda e più avanzata a "top" è "htop".
Con htop, possiamo abilitare/disabilitare la visualizzazione dei diversi thread associati allo stesso processo con "Shift+H", a common suggestion is, enabling "Display threads in a different color" and "Show custom thread names" under F2 / Display.
Ps è un programma statico per la gestione dei processi, viene molto utilizzato nella stesura di programmi o script che devono in qualche modo interagire con i processi, ps mi fornisce una fotografia al tempo in cui viene lanciato dei processi attivi sulla macchina. Lanciando il programma con "ps" mi mostrerà solo i processi attivi all'interno del mio terminale, dovremo quindi aggiungere dei parametri per effettuare operazioni più complesse. I'll have many columns, and terminals are identified by TTY (Teletype code), identifies the terminal that the process is running on. Other cases are:
ps -e
# mostra i processi in running sul sistema
ps -x
# mostra tutti i processi in running dell'utente che ha
# lanciato il comando
ps -U username
# mostra tutti i processi in running dell'utente
# username
ps -aux
# mostra tutti i processi in running mostrando anche
# informazioni aggiuntive come uso CPU, uso memoria, è la più
# comune applicazione di ps
ps w > alldata.txt
# scrive i risultati sul file alldata.txt
ps -ef --forest | less
# this willl explore and see which are
# the parents of the processes, this is useful in order to see
# who generated certain processes
ps -U root --forest
# mostra l'albero gerarchico di tutti i
# processi
ps -l
# mostra informazioni dettagliate sui processi, ad
# esempio qui possiamo visualizzare con VSZ quanto occupano in
# memoria (totale) (in kiB), mentre con RSS quanto stanno
# attualmente occupando in RAM (in KiB), nota che queste due
# possono essere diverse in quanto un processo può avere una
# parte in memoria e l'altra sull'area di swap
E' possibile reperire altre informazioni sui processi attraverso altri programmi; ad esempio:
pwdx processID
# mi fornisce la directory in cui sta lavorando
# il processo con PID processID
pidof processName
# mi fornisce il PID del processo con nome "
# processName"
pgrep processName
# mi fornisce il PID o i PID del processo con
# nome "processName"
un sommario sull'utilizzo dei processi è dato da:
procinfo
# mostra sommari e statistiche sui processi, vedere il
# "man procinfo" per la spiegazione di ogni singola stringa e per
# varie opzioni
E' possibile lanciare programmi specificando il grado di priorità attraverso il comando "nice", ad esempio:
nice programName
# in questo modo lanceremo il programma con
# una priorità default che è uguale a 10
nice -n 10 programName
# = al caso precedente
nice -10 programName
# = al caso precedente
Molto utile è anche il comando "renice" che ci permette di cambiare la priorità di un processo già in running, alcuni esempi applicativi possono essere:
renice -n -20 -p processID
# cambia la priorità del processo
# associato al PID processID ad un valore di -20
renice -n -20 -u root
# cambia la priorità di tutti i processi
# attivi dall'utente root ad un valore di -20
I programmi attivi che stiamo utilizzando interattivamente davanti al terminale si dicono in "foreground", mentre quelli attivi nascosti vengono detti in "background", può essere utile mandare processi in background nel momento in cui vogliamo effettuare operazioni lunghe con cui non c'è bisogno di interagire molto.
E' possibile mandare processi in background attraverso la combinazione di tasti "Ctrl+z". Ad esempio possiamo provare ad avviare da terminale il programma "nano", lanciandolo con "nano nomeFile", in questo momento nano è in foreground, nel momento in cui vogliamo passare ad un altra operazione, lo possiamo mettere in background attraverso la combinazione "Ctrl+z", alcuni comandi per gestire i processi in background/foreground sono:
jobs
# mi mostra tutti i programmi in background del terminale
# corrente
fg processCode
# mi riporta il programma associato al PID
# processCode in foreground, per poter visualizzare il PID del
# programma interessato, mi basta avviare prima "jobs"
E' possibile anche avviare direttamente un programma inserendolo in background:
./myProgram &
# avvia myProgram direttamente in background,
# possiamo quindi continuare ad utilizzare il terminale per
# effettuare altre operazioni
oppure è possibile portare un comando in background anche con:
bg processCode
# dove processCode è il PID del processo
# visualizzabile con "jobs"
N.B.: E' bene tenere a mente che tutti i processi del terminale vengono terminati con nel momento in cui usciamo dal terminale, nel caso volessimo far sopravvivere i nostri processi anche una volta usciti dal terminale dobbiamo effettuare un'operazione di "nohup".
E' possibile uccidere un processo mandandogli dei segnali, esistono tre tipi di segnali utili per la terminazione di un processo:
- 1 - sigup termina il programma e chiede al demone di rileggere i file di configurazione, solitamente questo è utilizzato con i demoni, visto che la loro particolarità è quella di riavviarsi una volta uccisi
- 9 - sigterm forza l'uscita
- 15 - quit with shutdown chiude prima tutti i file aperti dal processo, è una terminazione meno brusca rispetto al segnale 9
Esempi di utilizzo possono essere:
kill -s 9 processID
# uccide il processo con PID processID
# utilizzando il signale 9, è equivalente a "kill -9 processID",
# il comando "kill" ha bisogno del PID del processo
pidof nomeProcess
# visualizza il PID del processo chiamato "
# nomeProcesso"
pkill nomeProcesso
# uccide il processo chiamato "nomeProcesso"
xkill
# uccide il processo legato ad una determinata finestra
# grafica, dopo averlo lanciato, ci basta clickare sulla finestra
# del processo da terminare, potrebbe essere utile associarlo ad
# una determinata combinazione di tasti da tastiera+
Possiamo anche interrompere processi per farli procedere in un secondo momento con:
kill -STOP processID
# interrompi il processo attraverso il
# segnale "STOP"
kill -CONT processID
# continua il processo interrotto con "
# -STOP" attraverso il segnale "CONT"
Questa procedura torna molto utile con processi che durano giorni o in genere molto tempo. possiamo mostrare i processi stoppati (attraverso l'opzione -STOP con:
ps -e -j | grep 'T'
Alcune distro hanno il comando "killall", ad esempio:
killall -9 apache2
# manda il segnale 9 a tutti i processi
# associati ad apache2, è da notare che al comando "killall"
# possiamo anche passare il nome del processo a differenza del
# comando "kill"
Nel caso volessi chiudere tutti i programmi legati al mio terminale, mi basta lanciare il comando "exit".
Inoltre spesso capita di lanciare in background processi ad esempio con:
programma1 arg1 arg2 &> /dev/null &
programma2 arg1 arg2 &> /dev/null &
si ricorda che questi processi possono essere visualizzati col comando:
jobs
# visualizza i processi in background
e possiamo eliminarli attraverso l'identificativo mostrato da jobs
con kill
utilizzando il simbolo percentuale, ad esempio:
kill %1
# questo terminera' il processo in background identificato come `1` da jobs
Possiamo controllare il consumo di memoria RAM di un processo in diversi modi,
utilizzando top/htop oppure tramite il PID utilizzando pmap
, un altro
tool comune per sistemi POSIX.
Possiamo quindi ad esempio controllare il consumo di memoria del process
i3
eseguendo:
ps -aux | grep -i "i3"
pmap <PID>
# oppure
pmap $(pidof i3)
E poi andando a visualizzare la voce "total" in fondo all'output.
Possiamo anche visualizzare direttamente solo il totale eseguendo:
sudo pmap 917 | tail -n 1
# oppure
sudo pmap 917 | tail -n 1 | awk '/[0-9]K/{print $2}'
Possiamo controllare la percentuale di memoria utilizzata anche con:
ps -o pid,user,%mem,command ax | sort -b -k3 -r
Nel caso volessimo lanciare un programma e assicurarci che continui la sua esecuzione anche nel caso in cui il nostro sistema ci forza l'uscita, o veniamo sloggati o accidentalmente chiudiamo il nostro terminale, allora in questi casi si rivela utile l'utilizzo del comando "nohup":
nohup commandName
# lancia il comando in modalità "nohup", il
# programma continua a essere in "running", possiamo comunque
# concludere la sua esecuzione con un'operazione di kill come ad
# esempio: kill -9 processID
E' da tenere a mente che nohup creerà un file chiamato nohup.out che conterrà il contenuto dello standard output e dello standard error prodotto
nohup commandName >/dev/null 2>&1
# in questo caso redirigo
# stdout e stderr in /dev/null
Per lanciare un processo in background, in modalità "nohup" possiamo effettuare:
nohup programName &
# lancia programName in background in
# modalità "nohup"
nohup perl myscript.pl > out.txt 2>err.txt &
# esegue lo script in perl e redirege l'output
# sul file out.txt e lo standard error sul file
# err.txt inoltre lo script parte in background
# quindi intanto possiamo fare altro e anche effettuare
# logout dalla macchina, tanto lo script continuera'
# la sua esecuzione
Un altro comando utile può essere:
disown -a && exit
# in questo caso tutti i processi attivi
# nella shell verranno lasciati in runnning e la shell verrà
# chiusa
La differenza tra nohup e disown, è che nohup è utilizzato all'avvio di un processo, mentre se un processo è già in running (ed è stato lanciato senza nohup) e vogliamo assicurarci che continui a runnare anche dopo la chiusura del terminale, allora possiamo sganciarlo dal terminale con "disown".
# disown -h [job-spec] where [job-spec] is the job number (like
# %1 for the first running job; find about your number with the
# jobs command) so that the job isn't killed when the terminal
# closes.
Suppose for some reason Ctrl+Z is also not working, go to another terminal, find the process id (using ps) and run:
kill -20 PID && kill -18 PID
# kill -20 (SIGTSTP) will suspend
# the process and kill -18 (SIGCONT) will resume the process, in
# background. So now, closing both your terminals won't stop your
# process.
Il programma lsof permette di capire quali file sono aperti dai vari processi, infatti lsof sta per "list opened files", vediamo alcuni esempi applicativi:
lsof
# elenca i file aperti col relativo proprietario e PID
lsof -u cindy | wc -l
# mostra il numero di file aperti dall'utente "cindy"
lsof -u^cindy | wc -l
# mostra il numero di file aperti da tutti eccetto l'utente "cindy"
# nota che il carattere '^' e' usato per la negazione
lsof -cpython | head -15
# mostra tutti i file aperti dai processi che iniziano per "python"
# in questo caso con "head -15" mostriamo i primi 15 file
lsof -cpython -c^python2.7
# mostra tutti i file aperti dai processi che iniziano per "python"
# ma che non iniziano per python2.7
lsof +d /usr/bin
# mostra tutti i file aperti nella directory e nelle sue top level
# directory
lsof -p 1839
# mostra tutti i file aperti dal processo 1839
lsof -iUDP
# mostra tutte le connessioni UDP attive
lsof -i 6
# mostra tutte le connessioni IPv6 attive
lsof -t /var/log/dummy_svc.log
# mostra solo i PID dei processi che tengono aperto il file menzionato
# questo e' utile soprattutto quando bisogna usare kill o chiudere i processi
# che operano (o tengono aperto) su un file
lsof /percorso/nomeFile
# mostra il programma che tiene aperto
# il file indicato nel comando con relative informazioni, utile
# quando vogliamo smontare device ad esempio e non ci riusciamo,
# in quanto bloccati da qualche processo
lsof -p 2589
# mostra informazioni relative ai file aperti dal
# processo con PID 2589
lsof -i
# mostra informazioni su tutti i processi attivi su
# tutte le porte, utile alternativa veloce a netstat/ss, se al
# posto di numeri di porta vediamo nomi relativi a servizi, ad
# esempio "nomeServizio" o "rtsp", allora cerchiamo questa
# stringa all'interno del file "/etc/services", ad esempio con un
# comodo grep oppure vedere il comando successivo
lsof -i -n -P
# mostra informazioni su tutti i processi attivi
# su tutte le porte, utile alternativa veloce a netstat/ss, in
# questo caso ci viene mostrato il nome della porta senza
# eventuale associazione del servizio basata sul file
# /etc/services
lsof -i :80
# mostra tutti i processi attivi sulla porta "80"
lsof -i :80 | grep LISTEN
# mostra tutti i processi attivi
# sulla porta "80" nello stato "LISTEN"
lsof -i -P -n :80
# visualizza quali processi stanno
# ascoltandando sulla porta 80
lsof -i@172.16.12.5
# mostra connessioni aperte con l'indirizzo
# ip specificato
lsof -i@172.16.12.5:22
# mostra connessioni aperte con
# l'indirizzo ip e la porta specificati
lsof -iTCP
# mostra solo le connessioni TCP
lsof -iUDP
# mostra solo le connessioni UDP
lsof -i 6
# mostra solo il traffico ipv6
lsof -i | grep -i LISTEN
# mostra porte in ascolto che
# aspettanno connessioni
lsof -i | grep -i ESTABLISHED
# mostra connessioni stabilite
lsof -u daniel
# mostra i file aperti dall'utente "daniel"
lsof -u ^daniel
# mostra i file aperti da tutti gli utenti
# eccetto l'utente "daniel"
kill -9 `lsof -t -u daniel`
# killiamo tutti i processi aperti
# dall'utente "daniel"
lsof -c nomeprogramma
# vediamo l'elenco dei file e delle
# connessioni aperte dal programma specificato
lsof +D /directory/
# mostra per ogni file aperto della
# directory indicata il processo che lo sta utilizzando con le
# relative informazioni
lsof -u nomeUtente
# mostra tutti i file aperti dall'utente "
# nomeUtente"
kill -9 `lsof -t -u nomeUtente`
# il flag "-t" permette di
# mostrare solo il PID relativo ai processi richiesti in questo
# modo riusciamo ad eseguire comandi sui processi, come in questo
# caso che viene usato kill per uccidere tutti i processi
# appartenenti all'utente "nomeUtente"
lsof -n -P -c nomeComando
# elenca tutti i file aperti dal
# comando "nomeComando"
lsof -n -P -u nomeUtente
# elenca tutti i file aperti
# dall'utente menzionato
sudo lsof -iTCP:631 -sTCP:LISTEN
# guarda chi è in ascolto
# sulla porta TCP 631, citando il process name
un'alternativa ad lsof è "fuser", vediamo alcuni esempi:
fuser -v /mnt/myUsb
# visualizza tutti i processi aperti (PID)
# relativi alla directory menzionata
fuser -v -k /mnt/myDir
# termina tutti i processi utilizzanti
# una determinata directory/file
fuser -v -k -i /mnt/usb
# termina tutti i processi utilizzanti
# una determinata directory/file interattivamente
nelle tabelle presentate da fuser, la simbologia è:
c
current directorye
executable being runf
open file. f is omitted in default display modeF
open file for writing. F is omitted in default display moder
root directorym
mmap’ed file or shared library
Storicamente (e ancora su alcune distro) il gestore di inizializzazione dei servizi su GNU/Linux è stato "sysVinit", che prevedeva un processo iniziale con PID=1 chiamato init, padre di tutti i processi e un insieme di 6 runlevel (stati del sistema) tra cui switchare. Oggigiorno la maggior parte delle distro più famose usa un gestore di inizializzazione dei servizi chiamato " systemd", che ha una gestione dei processi e dei demoni molto più complessa. Per capire quale systema di inizializzazione dei processi utilizza il nostro sistema possiamo effettuare:
cat /proc/1/comm
# stampa sullo standard output il comando
# relativo al processo con PID=1
Possiamo capire quale gestore dei demoni abbiamo anche attraverso questa strategia:
Before proceeding, you need to determine your system’s version of init. If you’re not sure, check your system as follows:
- If your system has /usr/lib/systemd and /etc/systemd directories, you have systemd. Go to 6.4 systemd.
- If you have an /etc/init directory that contains several .conf files, you’re probably running Upstart (unless you’re running Debian 7, in which case you probably have System V init). Go to 6.5 Upstart.
- If neither of the above is true, but you have an /etc/inittab file, you’re probably running System V init. Go to 6.6 System V init. If your system has manual pages installed, viewing the init(8) manual page should help identify your version.
Il sistema di gestione servizi sysVinit è molto semplice, in pratica è basato su 6 runlevel del sistema, ad ogni runlevel possiamo associare degli script. In pratica la totalità degli script vive nella directory "/etc/init.d/" questa directory contiene gli script che si occupano di lanciare o terminare i processi; in pratica l'inizio, il riavvio o la terminazione di un processo possono coinvolgere tutta una serie di passi da seguire, da qui la necessità di associare degli script ai processi. Però uno script associato ad un servizio che viene messo in questa directory non combinerà nulla, infatti se vogliamo runnare un determinato servizio, allora dovremmo creare un link simbolico in una delle directory "/etc/rc.x/" (dove "x" rappresenta il runlevel).
Systemd permette all'utente di creare diversi "stati" che forniscono all'utente un meccanismo flessibile per creare diverse configurazioni in cui effettuare "boot", questi stati sono composti da più "unit file" che messi assieme formano i cosiddetti "target", i target hanno nomi significativi al posto di semplici numeri come avveniva in sysVinit, e gli "unit file" gestiscono servizi, socket, e mount. Gli "unit file" sono collocati in due directory:
/etc/systemd/sytem/
# directory delegata a contenere gli unit
# file creati dall'utente e ha priorità sulla seconda
/usr/lib/systemd/system/
# directory delegata a contenere gli
# unit file non creati dall'utente
/lib/systemd/system/
# directory delegata a contenere gli unit
# file non creati dall'utente
Al boot systemd attiva di default il runlevel inteso dal file " default.target".
I classici 6 runlevel di "sysVinit" sono sostituiti generalmente dai cosiddetti "target", vediamo i principali:
systemd.unit=rescue.target
# è un runlevel special per
# impostare le configurazioni di base o effettuare un recovery
# del sistema
systemd.unit=emergency.target
# è una bash shell, con la
# possibilità di avviare l'intero sistema
systemd.unit=multi-user.target
# avvia un sistema multi utente
# non grafico;
systemd.unit=graphical.target
# avvia un sistema multi utente
# grafico;
Per ulteriori dettagli su questi target e su altri target è consigliato eseguire un:
man systemd.special
# visualizza un man con la descrizione dei
# vari target possibili
Lo strumento principale per gestire i servizi con systemd è costituito dal programma "systemctl", vediamone alcuni esempi:
systemctl
# visualizza lo stato ed una breve descrizione di
# tutti i servizi presenti, è utilie se utilizzato in
# combinazione con "systemd-analyze blame" per capire cosa parte
# all'avvio
systemctl start foo
# avvia il servizio foo
systemctl stop foo
# ferma il servizio foo
systemctl restart foo
# riavvia il servizio foo
systemctl status foo
# visualizza lo stato del servizio foo
systemctl enable foo
# abilita il servizio foo, in questo modo,
# anche se riavvio il sistema, il servizio foo si avvia in
# automatico
systemctl disable foo
# disabilita il servizio foo, in questo
# modo, non si avvierà in automatico per i prossimi riavvi di
# sistema
systemctl reload foo
# ricarica i file di configurazione del
# servizio foo, utile quando cambiamo qualche configurazione
systemctl daemon-reload
# riavvia tutti i servizi e ricrea
# tutto l'albero di dipendenze dei servizi
systemctl mask foo
# nasconde un servizio, prevenendo quindi
# l'avvio automatico dinamico o anche manuale
systemctl list-dependencies foo
# elenca le dipendenze del
# servizio foo
systemctl is-enabled foo
# controlla se il servizio foo è
# attivo
E' da notare che systemd è compatibile con sysVinit, quindi i servizi possono anche essere gestiti attraverso i comandi start, stop, restart ecc... ad esempio:
service NetworkManager stop
# ferma il servizio chiamato "
# NetworkManager"
può essere usato al posto di:
systemctl stop NetworkManager
# ferma il servizio chiamato "
# NetworkManager"
Possiamo passare dinamicamente da un target all'altro durante una sessione attraverso:
systemctl isolate multi-user.target
# entra nel target
# multi-user, che è simile al classico runlevel 3 di sysVinit
systemctl isolate graphical.target
# entra nel target
# graphical, che è simile al classico runlevel 5 di sysVinit
per cambiare il target default possiamo invece effettuare:
systemctl set-default <nome del target>.target
# cambia il
# target di default a "nome del target", è l'operazione analoga
# al cambio del runlevel di default su sysVinit
E' da notare che quello che viene effettuato in realtà quando viene lanciato questo comando è:
ln -sf /lib/systemd/system/<nome del target>.target /etc/systemd/system/default.target
Altre istruzioni utili sono:
systemctl get-default
# mostra il target presente
Mentre un'altra directory utile in alcune distro è /etc/init.d/, questa directory viene dal sistema sysVinit e contiene gli script che si occupano di lanciare o terminare i processi; in pratica l'inizio, il riavvio o la terminazione di un processo possono coinvolgere tutta una serie di passi da seguire, da qui la necessità di associare degli script ai processi. Vediamo ora alcuni altri comandi che utilizzano systemd:
systemd-analyze
# analizza i tempi di boot, nel caso in cui non
# si usi systemd, questo comando può essere sostituito attraverso
# il programma "bootchart" o programmi che raccolgono e
# analizzano dati dal processo di boot
ATTENZIONE: su sistemi con firmware BIOS systemd non può ottenere come dato il tempo che questo ci ha messo ad inizializzarsi e a fare le sue cose, mentre con sistemi con firmware UEFI, il firmware fornisce dati al kernel come il tempo di avvio, vedremo infatti sui sistemi UEFI una voce aggiuntiva chiamata "firmware" questa si riferisce proprio al tempo di caricamento del firmware UEFI, un'altra voce aggiuntiva che incontriamo sui sistemi UEFI è "loader" questo è il tempo impiegato dal bootloader.
systemd-analyze blame
# visualizza i tempi di boot per ogni
# servizio al boot
systemd-analyze plot > graph.svg
# mi salva un'immagine con un
# grafico dei tempi di boot
systemd-analyze crotical-chain
# mi mostra il collo di
# bottiglia del sistema, visualizzando i target di systemd più
# esosi
journalctl -u nomeServizio
# visualizza il log relativo al
# servizio indicato
possiamo anche visualizzare i messaggi di journalctl in tempo reale con:
journalctl -f
# visualizza i messaggi di journalctl in tempo reale
oppure possiamo visualizzare solo quelli relativi al kernel con:
journalctl -k
# visualizza solo i messaggi di journalctl relativi al kernel
systemctl status nomeServizio
# fornisce informazioni sul
# servizio, come il file che lo avvia, il PID, eccetera
systemctl list-dependencies --reverse nomeServizio
# mostra in
# quale target è avviato il servizio indicato nel comando
sudo systemctl show NetworkManager|grep FragmentPath
# mostra
# il nome dello script che avvia il servizio
Attraverso i comandi sopracitati, possiamo quindi tenere sotto controllo il sistema, sapendo cosa viene avviato, quando viene avviato e da cosa (quale script, programma) viene avviato.
Possiamo avere una panoramica generale dei servizi presenti sul sistema con:
systemctl list-units
Oppure andare nello specifico visualizzando tutte le unita' installate sul sistema:
systemctl list-unit-files
Possiamo visualizzare la lista di servizi in enabled con:
systemctl list-units --type=service --state=active
Possiamo visualizzare la lista di servizi in running con:
systemctl list-units --type=service --state=running
systemctl list-units --type=service --state=failed
Possiamo anche applicare filtri con grep, ad esempio:
systemctl list-units | grep -E 'service.*running'
Possiamo visualizzare anche quali sono i servizi che si devono avviare prima di un altro servizio con:
systemctl list-dependencies --reverse NetworkManager-wait-online.service
# mostra i servizi che aspettano NetworkManager sia avviato prima di avviarsi
Oppure possiamo capire di quali unita' o servizi ha bisogno un servizio prima di avviarsi con:
systemctl list-dependencies NetworkManager-wait-online.service
# mostra i servizi che si devono avviare prima di NetworkManager-wait-online
Per creare un servizio, dobbiamo creare uno "unit file", uno unit file molto minimale potrebbe essere:
[Unit]
Description=Possiamo inserire una breve descrizione del servizio qui
After=default.target
[Install]
WantedBy=default.target
[Service]
Type=forking
ExecStart=/usr/local/bin/myScript
Dove:
- nella sezione [Unit] indichiamo quando deve essere avviato rispetto a default.target
- nella sezione [Install] indichiamo che è richiesto quando viene lanciato default.target
- nella sezione [Service] il Type=forking è necessario, in quanto nel nostro esempio stiamo eseguendo uno script di shell, in caso contrario dobbiamo eliminarlo, mentre in ExecStart indichiamo il programma da eseguire
Per installarlo spostiamo (o creiamo un link) il file all'interno della directory "/etc/systemd/system" ed eseguiamo:
systemctl --system enable nomeServizio
# dove nomeServizio è il
# nome del file
Possiamo verificare al prossimo riavvio se il modulo è stato caricato, col comando:
systemctl --failed
# visualizza i moduli che non sono stati
# caricati correttamente
Se il nostro modulo è presente in questa lista, allora non è stato caricato correttamente e possiamo ispezionare il problema con:
systemctl status nomeModulo
# visualizza lo status del modulo
Nei sistemi GNU/Linux esistono anche demoni particolari detti "superdemoni", questi superdemoni non sono altro che demoni il cui scopo è gestire altri demoni, uno dei più famosi è "xinet.d", che ha sostituito l'ormai obsoleto "inet.d", ma esistono anche altri pacchetti software che ci permettono di installare superdemoni.