Table of Contents

Laborator 05 - Procese; semnale; pipe-uri

Cheat sheet

Comandă Descriere scurtă
su switch user - schimbă utilizatorul în sesiunea curentă
ps afișează informații despre porcesele active în sistem
top afișează informații despre porcese în mod interactiv
pstree ierarhia de procese
| pipe
kill trimite un semnal unui proces identificat prin PID
pkill caută un proces după nume și îi transmite un semnal
fg trece un proces în foreground
& lansează un proces în background running
bg trece un proces din background din stopped în running
mkfifo crează un pipe cu nume
nohup rulează o comandă ce va ignora semnalul SIGHUP

Suport laborator

Arhivă laborator

Introducere

Vizualizarea proceselor din sistem

Pentru a afișa informații despre procesele active, putem utiliza ps. Fără nici un argument, listează procesele deschise din terminalul curent. Apar doar două procese: shell-ul bash și procesul ps:

student@uso:~$ ps
  PID TTY          TIME CMD
 3821 pts/1    00:00:00 bash
 3877 pts/1    00:00:00 ps

Dacă adăugăm argumentele -ef comenzii anterioare se vor afișa toate procesele ce rulează în sistem:

student@uso:~$ ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 19:37 ?        00:00:00 /sbin/init
root         2     0  0 19:37 ?        00:00:00 [kthreadd]
root         3     2  0 19:37 ?        00:00:00 [ksoftirqd/0]
root         6     2  0 19:37 ?        00:00:00 [migration/0]
root         7     2  0 19:37 ?        00:00:00 [watchdog/0]
root         8     2  0 19:37 ?        00:00:00 [migration/1]
root        10     2  0 19:37 ?        00:00:00 [ksoftirqd/1]
root        12     2  0 19:37 ?        00:00:00 [watchdog/1]
root        13     2  0 19:37 ?        00:00:00 [cpuset]
root        14     2  0 19:37 ?        00:00:00 [khelper]
root        15     2  0 19:37 ?        00:00:00 [kdevtmpfs]
root        16     2  0 19:37 ?        00:00:00 [netns]
root        18     2  0 19:37 ?        00:00:00 [sync_supers]
[...]

Consultând man, observăm:

-e              Select all processes. Identical to -A.
-f              Do full-format listing.

Putem folosi man ps împreună cu opțiunea de căutare pentru a găsi descrierea câmpurilor afișate:

uid        UID     see euid. (alias euid).
euid       EUID    effective user ID (alias uid).
pid        PID     process ID number of the process.
ppid       PPID    parent process ID.
c          C       processor utilization. Currently, this is the integer value of the percent usage over the lifetime of the process.
start_time START   starting time or date of the process.
tname      TTY     controlling tty (terminal).
time       TIME    cumulative CPU time, "[DD-]HH:MM:SS" format.
ucmd       CMD     see comm. 
comm       COMMAND command name (only the executable name). 

Informații detaliate despre procesele care ruleaza în sistem pot afișate și folosind argumentele aux. În acest caz argumentele comenzii ps nu sunt prefixate de caracterul -. Este cazul argumentelor date în format BSD.

student@uso:~$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0  24456  2416 ?        Ss   19:37   0:00 /sbin/init
root         2  0.0  0.0      0     0 ?        S    19:37   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    19:37   0:00 [ksoftirqd/0]
root         6  0.0  0.0      0     0 ?        S    19:37   0:00 [migration/0]
root         7  0.0  0.0      0     0 ?        S    19:37   0:00 [watchdog/0]
root         8  0.0  0.0      0     0 ?        S    19:37   0:00 [migration/1]
root        10  0.0  0.0      0     0 ?        S    19:37   0:00 [ksoftirqd/1]
root        12  0.0  0.0      0     0 ?        S    19:37   0:00 [watchdog/1]
root        13  0.0  0.0      0     0 ?        S<   19:37   0:00 [cpuset]
root        14  0.0  0.0      0     0 ?        S<   19:37   0:00 [khelper]
root        15  0.0  0.0      0     0 ?        S    19:37   0:00 [kdevtmpfs]
root        16  0.0  0.0      0     0 ?        S<   19:37   0:00 [netns]
root        18  0.0  0.0      0     0 ?        S    19:37   0:00 [sync_supers]
root        19  0.0  0.0      0     0 ?        S    19:37   0:00 [bdi-default]
root        20  0.0  0.0      0     0 ?        S<   19:37   0:00 [kintegrityd]
root        21  0.0  0.0      0     0 ?        S<   19:37   0:00 [kblockd]
root        22  0.0  0.0      0     0 ?        S<   19:37   0:00 [ata_sff]

Există 3 formate pentru opțiunile unei comenzi:

Putem vedea semnificația argumentelor mai des folosite pentru ps, în toate cele 3 formate, rulând

ps --help

sau o comandă cu un argument nevalid.

student@uso:~$ ps --help
********* simple selection *********  ********* selection by list *********
-A all processes                      -C by command name
-N negate selection                   -G by real group ID (supports names)
-a all w/ tty except session leaders  -U by real user ID (supports names)
-d all except session leaders         -g by session OR by effective group name
-e all processes                      -p by process ID
T  all processes on this terminal     -s processes in the sessions given
a  all w/ tty, including other users  -t by tty
g  OBSOLETE -- DO NOT USE             -u by effective user ID (supports names)
r  only running processes             U  processes for specified users
x  processes w/o controlling ttys     t  by tty
*********** output format **********  *********** long options ***********
-o,o user-defined  -f full            --Group --User --pid --cols --ppid
-j,j job control   s  signal          --group --user --sid --rows --info
-O,O preloaded -o  v  virtual memory  --cumulative --format --deselect
-l,l long          u  user-oriented   --sort --tty --forest --version
-F   extra full    X  registers       --heading --no-heading --context
                    ********* misc options *********
-V,V  show version      L  list format codes  f  ASCII art forest
-m,m,-L,-T,H  threads   S  children in sum    -y change -l format
-M,Z  security data     c  true command name  -c scheduling class
-w,w  wide output       n  numeric WCHAN,UID  -H process hierarchy

Informațiile oferite de utilitarul ps se pot filtra specificând un set de argumente. Spre exemplu, pentru a afișa doar procesele deținute de utilizatorul student, rulăm comanda:

student@uso:~$ ps -u student
  PID TTY          TIME CMD
 2038 ?        00:00:00 x-session-manag
 2086 ?        00:00:00 ssh-agent
 2089 ?        00:00:00 dbus-launch
 2090 ?        00:00:01 dbus-daemon
 2154 ?        00:00:00 start_kdeinit
 2155 ?        00:00:00 kdeinit4
 2156 ?        00:00:00 klauncher
 2158 ?        00:00:04 kded4
 2163 ?        00:00:00 bluedevil-helpe
 2165 ?        00:00:00 obex-data-serve
 2337 ?        00:00:00 bluedevil-monol
 2339 ?        00:00:00 kglobalaccel

Alternativ putem rula și

student@uso:~$ ps U student
  PID TTY      STAT   TIME COMMAND
 2038 ?        Ss     0:00 /bin/sh /usr/bin/x-session-manager
 2086 ?        Ss     0:00 /usr/bin/ssh-agent /usr/bin/dbus-launch --exit-with-session x-session-manager
 2089 ?        S      0:00 /usr/bin/dbus-launch --exit-with-session x-session-manager
 2090 ?        Ss     0:01 //bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
 2154 ?        S      0:00 /usr/lib/kde4/libexec/start_kdeinit +kcminit_startup
 2155 ?        Ss     0:00 kdeinit4: kdeinit4 Running...                  
 2156 ?        S      0:00 kdeinit4: klauncher [kdeinit] --fd=9           
 2158 ?        Sl     0:04 kdeinit4: kded4 [kdeinit]                      
 2163 ?        S      0:00 /usr/bin/bluedevil-helper
 2165 ?        S      0:00 /usr/bin/obex-data-server --no-daemon 
 2337 ?        S      0:00 /usr/bin/bluedevil-monolithic
 2339 ?        S      0:00 /usr/bin/kglobalaccel
 2341 ?        Sl     0:00 /usr/bin/kwalletd
 2344 ?        S      0:00 /usr/bin/kactivitymanagerd

Se recomandă folosirea argumentelor cu - (în stil GNU). Cu toate acestea, în unele cazuri forma BSD este mai potrivită.

Pipe-uri anonime

Caracterul | (pipe) este folosit pentru a înlănțui 2 comenzi, legând ieșirea standard a primei comenzi la intrarea standard a celeilalte, așa cum arată și figura următoare:

Folosind > și < putem face ca o comandă să scrie într-un fișier sau să citească dintr-un fișier. Folosind | fișierul nu mai este necesar.

Foreground & Background

Diagrama următoare arată stările în care se poate afla un proces și cum se trece dintr-o stare în alta.

După cum se poate observa din diagramă, pentru a aduce un proces din background în foreground utilizăm comanda fg. Fără nici un parametru, aduce în foreground ultimul proces trimis în background.

Pentru a vedea ce procese se află în fundal utilizăm jobs. Astfel putem afla id-ul unui job și îl putem folosi pentru a aduce în foreground job-ul respectiv.

 fg $jobID 

Unde $jobId se va înlocui cu ID-ul job-ului respectiv.

Pentru a porni un proces direct în background, folosim &. De exemplu, pentru a deschide fișierul beatles utilizând vim direct în background folosim:

 vim beatles &

Atunci când utilizăm & procesul pornește în background și își începe execuția (este în running) iar când utilizăm Ctrl-z acesta este stopped. Pentru a trece din stopped în running utilizăm bg.

procfs

procfs este un sistem de fișiere virtual, adică datele nu se găsesc pe un suport fizic permanent (hard disk). Fiecare fișier oferă informații despre sistem și este stocat fizic în RAM. procfs este montat în /proc.

Informații despre un proces găsim în directorul din /proc care are ca nume PID-ul procesului. Pe scurt, câteva dintre acestea:

Daemon

Un daemon este un tip de proces care rulează în background și se detașează de terminalul de control. Un astfel de proces nu va accepta comenzi de la tastatură.

Putem comunica cu un daemon prin:

De obicei, procesele care sunt daemoni au numele terminat în d (sshd), dar nu este o regulă.

Pachetele ce conțin daemoni de obicei au script-uri de control, localizate în /etc/init.d/. Acestea sunt folosite pentru pornire/oprire și acceptă un argument dintre:

Semnale

Unul din mecanismele prin care se poate comunica între procese sunt semnalele. Un utilizator poate trimite un semnal unui proces folosind comanda kill.

Pentru a vedea toate semnalele care se pot trimite unui proces utilizăm kill -l.

student@uso:~$ kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL       5) SIGTRAP
 6) SIGABRT      7) SIGBUS       8) SIGFPE       9) SIGKILL     10) SIGUSR1
11) SIGSEGV     12) SIGUSR2     13) SIGPIPE     14) SIGALRM     15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD     18) SIGCONT     19) SIGSTOP     20) SIGTSTP
21) SIGTTIN     22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO       30) SIGPWR
31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX

Putem transmite anumite semnale utilizând combinații de taste. De exemplu:

Exerciții

1. ps

Analizați procesele care rulează în sistem folosind ps.

Rezolvare
student@uso:~$ ps 
Rezolvare
student@uso:~$ ps -ef 
student@uso:~$ ps aux 

2. top

Utilitarul ps poate fi folosit pentru a “face o poză” proceselor sistemului la un anumit moment de timp. Pentru a vizualiza informații în timp real, folosim top.

student@uso:~$ top
Rezolvare
student@uso:~$ top -u student

3. Ierarhia de procese

4. Timpul de execuție

Pentru a afla cât timp a rulat un anumit proces, se poate folosi comanda time.

Output-ul comenzii time conține trei valori de timp: real, user, sys.

To run the command `ls -Fs' and show just the user, system, and total time:
            time -f "%E real,%U user,%S sys" ls -Fs
[...]
E      Elapsed real (wall clock) time used by the process, in [hours:]minutes:seconds.
U      Total number of CPU-seconds that the process used directly (in user mode), in seconds.
S      Total number of CPU-seconds used by the system on behalf of the process (in kernel mode), in seconds.

5. Sistemul de fișiere procfs

6. uptime

student@uso:~$ man uptime
[...]
uptime  gives  a  one line display of the following information.  The current time, how long the system has been running, how many users are currently logged on, and the system load averages for the past 1, 5, and 15 minutes.

Faceți fișierul uptime_ex din arhiva de laborator executabil și rulațil astfel:

student@uso:~/Downloads/lab05$ chmod +x uptime_ex
student@uso:~/Downloads/lab05$ ./uptime_ex

Cum variază valorile numerice de load? Ce credeți că face programul?

7. Pipe-uri anonime

student@uso:~/1960s$ touch Ticket-to-Ride_TheBeatles.txt Yesterday_TheBeatles.txt Penny-Lane_TheBeatles.txt
student@uso:~/1960s$ touch Satisfaction_RollingStones Brown-Sugar_RollingStones Wild-Horses_RollingStones Play-With-Fire_RollingStones
student@uso:~/1960s$ touch Hey-Jude_TheBeatles
student@uso:~/1960s$ touch Rainy-Day-Women_BobDylan

Comanda grep citește fișierul primit ca parametru și afișează doar liniile ce se potrivesc cu un anumit șablon. Mai multe detalii într-un laborator ulterior.

Rezolvare
student@uso:~/1960s$ ls -l | grep TheBeatles

8. Semnale

Utilizați kill -l pentru a vedea toate semnalele care se pot trimite unui proces.

Faceți programul signal_test din arhiva de laborator executabil și rulați-l:

student@uso:~$ chmod +x signal_test
student@uso:~$ ./signal_test

La final, pentru a opri procesul signal_test, rulați comanda:

student@uso:~$ kill -9 $(pidof signal_test)

Observați că semnalul 9 (SIGKILL) nu poate fi tratat de nici o aplicație.

9. xkill

Pentru a forța închiderea unei aplicații grafice se poate folosi comanda xkill.

În terminal a apărut mesajul:

Select the window whose client you wish to kill with button 1

Ce formă are mouse-ul?

Dați click undeva în interiorul ferestrei gedit.

10. fg. Operatorul &.

vim TheBeatles
vim &

11. bg. Variabila $!

Rulați comanda

student@uso:~$ cat /dev/random

Nu intrați în panică, rolul fișierului /dev/random este acela de a genera octeți aleatori. Este normal să vedeți caractere ciudate.

Pe ecran vor fi afișate caractere random. Trimiteți procesul în fundal utilizând semnalul SIGSTOP (Ctrl-Z).

$! este PID-ul ultimului proces aflat în background.

Rezolvare
student@uso:~$ kill -9 $!

12. htop

Instalați pachetul htop folosind apt-get (aduceți-vă aminte din laboratorul 2 cum instalați pachete). Deschideți o instanță de vim.

Într-un alt terminal, rulați comanda

student@uso:~$ htop

Observați că informațiile afișate sunt cele din top dar interfața este mult mai ușor de folosit.

Afișați detalii despre procesul vim, detalii referitoare la fișierele deschise și la zonele de memorie folosite (folosiți tasta l)

Rezolvare
Selectăm procesul și tastăm l

13. less. more

Folosind ps și listarea tuturor proceselor, determinați PID-ul procesului gnome-panel.

NU folosiți scroll sau parametrul -C. Folosiți less sau more pentru a prelucra outputul ps. Apăsați q pentru a părăsi less.

Observați că less permite operații mai avansate decât more. Se spune frecvent că ”less is more

Rezolvare
student@uso:~$ ps -e | less

14. Pipe-uri cu nume

Un tip special de fișiere unix sunt pipe-urile cu nume. Acestea au o reprezentare fizică pe disc.

Creați un pipe cu numele twitter:

student@uso:~$ mkfifo twitter

Listați în format lung informații despre acest fișier. Ce observați?

Scrieți mesajul “USO rU1z” în fișierul twitter, folosind echo.

Deschideți un alt terminal și afișați conținutul fișierului twitter folosind cat. Ce observați?

Încercați să afișați din nou conținutul fișierului.

Ce se întâmplă dacă revenim în primul terminal și încercăm să scriem un nou mesaj în fișier?

Rezolvare
Terminal 1 Terminal 2
ls -l twitter
echo “USO rU1z” > twitter
cat twitter
cat twitter
echo “It works!” > twitter

15. Find out PIDs

Folosiți ps și grep pentru a afla PID-ul terminalului curent.

Ce se întâmplă dacă aveți mai multe sesiuni deschise?

$$ este o variabilă de mediu specială care conține PID-ul procesului curent.

Determinați PID-ul terminalului curent.

Determinați PID-ul procesului părinte. (folosiți variabila de mediu $PPID)

Aflați numele procesului părinte. (ps și grep)

Rezolvare
student@uso:~$ ps -e | grep bash
student@uso:~$ echo $$
student@uso:~$ echo $PPID
student@uso:~$ ps -e | grep $PID #replace $PID cu cel obținut anterior

16. pgrep

Deschideți editorul vi.

Într-un alt terminal, folosiți comanda pgrep pentru a afișa numele și pid-ul tuturor proceselor vi din sistem.

Căutați parametrul -l în man pgrep și folosiți-l pentru a completa lista de PID-uri obținută anterior cu date despre numele proceselor.

Cum ați putea afișa doar procesele vi, fără a afișa și procesele ale căror nume conțin grupul de litere vi? Căutați în man după “exactly”.

17. Daemon

Rulați programul signal_test din arhivă astfel:

student@uso:~$ ./signal_test 42
Rezolvare
student@uso:~$ pgrep signal_test

Singura modalitate de a interacționa cu acesta, o dată ce a fost pornit, o reprezintă semnalele.

Rezolvare
student@uso:~$ cd /proc/$(pgrep signal_test)
student@uso:/proc/<pid>$ ls -l fd

Instalați pachetul apache2.

Verificați că există un proces apache2 care rulează. Acesta este un exemplu de daemon al unui server web. Ce utilizator deține procesul apache?

apache2 se instalează împreună cu un script care permite interacțiunea facila cu acesta. Folosind /etc/init.d/apache2 împreună cu argumentul stop opriți procesul apache. Acest script trimite un semnal daemonului Apache. Ca rezultat, daemonul se va închide. Din contul cărui utilizator trebuie trimis semnalul?

Rezolvare
student@uso:~$ sudo apt-get install apache2
student@uso:~$ ps -e | grep apache2
student@uso:~$ sudo /etc/init.d/apache2 stop

18. Nohup

Porniți un proces folosind comanda ping -c 10000 google.com într-un terminal.

Închideți acest terminal și verificați (folosind ps și htop) dacă procesul ping mai există.

Rezolvare
student@uso:~$ ping -c 10000 google.com
#Alt-F4 (Enter)
student@uso:~$ ps -e | grep ping
student@uso:~$ htop # căutam ping în output

Încercați același lucru și trimițând procesul ping în background prin folosirea &.

Rezolvare
student@uso:~$ ping -c 10000 google.com &
# Alt-F4 (Enter)
student@uso:~$ ps -e | grep ping
student@uso:~$ htop # căutam ping în output și nu-l găsim

Încercați și folosind nohup, trimițând procesul în background prin & (nohup ping -c 10000 google.com &)

Rezolvare
student@uso:~$ nohup ping -c 10000 google.com &
# Alt-F4 (Enter)
student@uso:~$ ps -e | grep ping
student@uso:~$ htop # căutam ping în output și îl găsim

Folosirea nohup împreună cu & permite pornirea de procese ce nu vor fi terminate în momentul încheierii sesiunii curente.

19. disown

Rulați comanda ping 8.8.8.8 > /dev/null &. Procesul este rulat în background.

Închideți acest terminal și verificați (folosind ps și htop) dacă procesul mai există.

Rezolvare
student@uso:~$ ping 8.8.8.8 > /dev/null &
# close terminal
student@uso:~$ ps -e | grep ping

Deschideți un alt terminal și rulați din nou ping 8.8.8.8 > /dev/null &. Procesul rulează în background.

Aflati pid-ul procesului ping și folosiți disown împreună cu pid-ul descoperit anterior, apoi închideți terminal-ul.

Ce se întâmplă cu procesul?

Rezolvare
student@uso:~$ ping 8.8.8.8 > /dev/null &
disown $(pidof ping)
# close terminal
student@uso:~$ ps -e | grep ping

disown este o comandă built-in a shell-ului care face ca un proces să nu se termine în momentul încheierii sesiunii curente.

20. Procese orfan

Demonstrați, pornind procese și trimițând semnalele corespunzătoare, că dacă terminăm părintele unui proces, atunci copii lui sunt preluați de procesul init.

Hint: porniți un xterm din interiorul altui xterm pornit din terminal și terminați primul xterm pornit.

Puteți folosi pstree pentru vizualizare rapidă sau ps afișând și PPID.

Rezolvare
0$ xterm
1$ xterm

Se închide primul xterm pornit.

2$ ps -eo cmd,pid,ppid | grep xterm

21. Screen

Instalați pachetul screen. Folosiți-l pentru a rula, în paralel, pagina de manual a programului screen, o instanță de vim și procesul corespunzător comenzii ping google.com.

Utilizând pagina de manual, determinați combinația de taste necesară pentru a părăsi screen fără a opri procesele care rulează.

Pentru a verifica, conectați-vă la sesiunea anterioară de screen.

Rezolvare
Control-A Control-C creează o fereastră nouă

Control-A număr navighează la fereastra număr

Control-A Control-D detașează screen

Resume la o sesiune se face cu screen -r