Fins ara tot el que has manejat estava quiet: fitxers, permisos, text. Aquesta lliçó canvia d'objecte i s'ocupa del que està viu. Un procés és un programa en execució, amb la seva pròpia memòria, els seus descriptors de fitxer oberts, la seva identitat i el seu lloc en un arbre genealògic que arrenca a systemd. Entendre'ls és el que et permet respondre la pregunta que tard o d'hora et farà la Marta: «per què va lent, el servidor?».
A la lliçó anterior vas descobrir que el 65 % dels errors d'acces.log es concentren a la franja de les 03:00, i que tot apunta que alguna cosa competeix per les connexions de la base de dades durant la finestra nocturna. Aquí tens les eines per esbrinar què és aquesta cosa, i per actuar-hi sense tirar el servei a terra.
Contingut
- Què és un procés
- L'arbre de processos
- Cicle de vida: fork, exec, wait, exit
- Zombis i orfes
- Estats de procés
psde debòtopihtop: llegir la capçalerapgrepipkill- Senyals
- Prioritats:
nice,reniceiionice - Control de treballs a la sessió interactiva
lsofifuser- Cas Tramontana: l'app penjada de matinada
- Què és un procés
Cada procés té una fitxa al nucli amb, entre altres coses:
| Atribut | Què és |
|---|---|
| PID | identificador únic |
| PPID | PID del procés pare |
| UID/GID efectius | identitat amb què es comproven els permisos |
| Estat | R, S, D, T o Z (apartat 5) |
Prioritat (PRI) i nice (NI) |
quanta CPU li toca |
| VSZ / RSS | memòria virtual reservada / memòria física realment utilitzada |
| Directori de treball | el cwd amb què resol rutes relatives |
| Descriptors oberts | els que vas veure a /proc/<pid>/fd a 03-04 |
La distinció VSZ enfront de RSS és la que més malentesos causa: VSZ inclou memòria reservada però mai tocada i biblioteques compartides, així que sumar els VSZ de tots els processos dona un número molt superior a la RAM instal·lada sense que això signifiqui res. El número que importa és RSS.
- L'arbre de processos
Tot procés descendeix d'un altre. L'arrel és systemd, amb PID 1, el primer procés que arrenca el nucli.
operador@srv-tramontana:~$ pstree -p | head -8
systemd(1)─┬─cron(742)
├─dbus-daemon(701)
├─executable(1284)─┬─{executable}(1285)
│ ├─{executable}(1286)
│ └─{executable}(1287)
├─sshd(889)───sshd(1502)───sshd(1508)───bash(1509)───pstree(1620)
└─systemd-journald(412)Es llegeix molt. executable(1284) és l'aplicació de Tramontana amb tres fils (entre claus, no són processos independents). La cadena de sshd mostra la teva pròpia connexió: el dimoni principal, el procés de la connexió, el de la sessió ja autenticada, el teu bash i el pstree que acabes de llançar com a fill seu. Aquí hi ha l'herència de l'entorn de 03-01, feta diagrama.
pstree -ps 1284 mostra els avantpassats d'un PID concret i retorna systemd(1)───executable(1284): l'app penja directament de systemd, no d'una sessió d'usuari. Això significa que sobreviu al fet que tanquis l'SSH, i és la diferència entre un servei i un programa llançat a mà.
- Cicle de vida: fork, exec, wait, exit
flowchart LR
P["Pare (bash)"] -->|"fork()"| C["Fill: còpia del pare<br/>PID nou, mateix codi"]
C -->|"exec()"| N["El fill es reemplaça<br/>pel programa nou"]
N -->|"exit(codi)"| Z["Zombi: només queda<br/>el codi de sortida"]
P -->|"wait()"| Z
Z --> F["Alliberat de la taula<br/>de processos"]
Quan escrius ls a Bash passa això: Bash fa fork(), que crea un fill idèntic a ell; el fill crida exec(), que substitueix el seu contingut pel binari d'ls conservant el PID i els descriptors oberts —aquí és on encaixen les redireccions que Bash va preparar abans—; ls acaba cridant exit(0); i Bash, que era a wait(), recull aquell codi de sortida, que és el que després llegeixes a $?.
Aquesta separació entre fork i exec és la que fa possible la redirecció tal com la vas estudiar: hi ha un moment, entre les dues crides, en què el fill ja existeix i encara no és el programa nou, i és allà on el shell reconfigura els descriptors.
- Zombis i orfes
Són dues situacions oposades i convé no confondre-les.
Un zombi (estat Z) és un procés que ja ha acabat però el pare del qual no ha cridat wait(). No consumeix CPU ni memòria: només ocupa una entrada a la taula de processos amb el seu codi de sortida, esperant que algú el reculli.
Un zombi no es pot matar. Ja és mort; kill -9 sobre ell no fa res, perquè els senyals els reben processos vius. L'única manera d'eliminar-lo és que el seu pare el reculli o que el pare mori. Un grapat de zombis és irrellevant; milers indiquen un pare mal programat, i l'acció correcta és reiniciar el pare.
Per buscar-los: ps -eo stat,ppid,pid,comm | awk '$1 ~ /^Z/'. A srv-tramontana no retorna res.
Un orfe és el contrari: un procés viu el pare del qual ha mort. No és cap problema. El nucli el reassigna a systemd (el PPID passa a 1), que sí que crida wait() correctament. És el mecanisme en què es recolzen nohup i els dimonis.
- Estats de procés
| Estat | Nom | Significa |
|---|---|---|
R |
Running / runnable | executant-se o a punt per fer-ho |
S |
Interruptible sleep | esperant alguna cosa (E/S, xarxa, un temporitzador); la majoria |
D |
Uninterruptible sleep | esperant E/S de disc, no accepta senyals |
T |
Stopped | aturat per Ctrl+Z o SIGSTOP |
Z |
Zombie | acabat, pendent de recollir |
Modificadors que veuràs enganxats: s líder de sessió, l multifil, + en primer pla, < prioritat alta, N prioritat baixa.
Per què un procés en D no es pot matar. Està bloquejat dins del nucli esperant que es completi una operació de disc o de xarxa, i el nucli no li lliura senyals fins que aquella operació acabi. kill -9 es queda encuat: el senyal s'entregarà quan el procés torni a l'estat S o R. Si un procés porta minuts en D, el problema no és el procés: és l'emmagatzematge —un disc que falla, un muntatge NFS caigut— i és allà on cal mirar.
ps de debò
ps de debòps té dues sintaxis històriques que conviuen: BSD (sense guionet) i UNIX (amb guionet). Les dues combinacions que es fan servir:
operador@srv-tramontana:~$ ps aux | head -3
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.4 168404 12856 ? Ss 08:31 0:03 /sbin/init
svc-tram+ 1284 2.1 12.4 982340 483920 ? Ssl 08:32 1:47 /opt/tramontana/app/executable| Columna | Significa |
|---|---|
USER |
propietari efectiu (truncat a 8 caràcters: svc-tram+) |
%CPU |
percentatge de CPU promitjat des que va arrencar, no instantani |
%MEM |
percentatge de RAM física |
VSZ / RSS |
memòria virtual / resident, en KiB |
TTY |
terminal associat; ? significa que no en té, típic d'un servei |
STAT |
estat més modificadors |
START / TIME |
hora d'arrencada / CPU total consumida |
Compte amb %CPU: és una mitjana des de l'arrencada del procés. Un procés que va devorar la CPU fa vuit hores i ara dorm pot continuar mostrant un percentatge alt. Per saber què consumeix ara, fes servir top.
ps -ef dona la vista UNIX, amb PPID explícit, que és el que vols per seguir relacions pare-fill. I ps -o construeix la sortida a mida:
operador@srv-tramontana:~$ ps -eo pid,ppid,user,ni,stat,rss,etime,cmd --sort=-rss | head -4
PID PPID USER NI STAT RSS ELAPSED CMD
1284 1 svc-tram 0 Ssl 483920 04:12:33 /opt/tramontana/app/executable
889 1 root 0 Ss 12404 04:13:05 sshd: /usr/sbin/sshd -D
412 1 root 0 Ss 11208 04:13:11 systemd-journald--sort=-rss ordena per memòria resident descendent (el - inverteix). etime dona el temps transcorregut des de l'arrencada, molt més útil que l'hora absoluta quan estàs diagnosticant.
Filtres: -u operador per usuari, -C executable per nom d'ordre, -p 1284 per PID, --forest per veure la jerarquia a la mateixa sortida de ps.
top i htop: llegir la capçalera
top i htop: llegir la capçaleratop - 12:44:18 up 4:13, 2 users, load average: 3.42, 1.87, 0.94 Tasks: 132 total, 2 running, 130 sleeping, 0 stopped, 0 zombie %Cpu(s): 12.3 us, 4.1 sy, 0.0 ni, 18.2 id, 64.8 wa, 0.3 hi, 0.3 si, 0.0 st MiB Mem : 3844.0 total, 198.4 free, 2914.2 used, 731.4 buff/cache MiB Swap: 2048.0 total, 1620.0 free, 428.0 used. 612.8 avail Mem
La càrrega mitjana
Els tres números són la mitjana de processos en estat R o D durant 1, 5 i 15 minuts. Dues conseqüències que gairebé ningú té clares:
- No és un percentatge. Cal comparar-lo amb el nombre de nuclis: a la VM de
srv-tramontana, amb 2 vCPU, una càrrega de 2,00 és plena ocupació i 3,42 significa que hi ha més feina de la que la màquina pot atendre. - Inclou els processos en
D, és a dir, els que esperen disc. Una càrrega de 3,42 amb la CPU gairebé ociosa no indica manca de CPU: indica que hi ha processos encallats esperant E/S.
I la comparació entre els tres números dona la tendència: 3.42, 1.87, 0.94 és una corba ascendent. El problema està empitjorant ara mateix, no remetent.
El desglossament de CPU
| Sigla | Significa |
|---|---|
us |
temps en codi d'usuari |
sy |
temps al nucli |
ni |
processos amb el nice modificat |
id |
ociós |
wa |
esperant E/S: la CPU està lliure però no pot avançar |
hi / si |
interrupcions de maquinari / de programari |
st |
steal: CPU que l'hipervisor va donar a una altra VM |
Aquest 64.8 wa és la dada de la capçalera de dalt. La CPU no està saturada: està esperant el disc o la base de dades. Perseguir un procés que consumeix CPU seria buscar al lloc equivocat. I un st alt en una màquina virtual significa que el problema no és a la teva VM sinó a l'amfitrió, cosa que convé saber abans d'optimitzar codi.
Sobre la memòria: buff/cache no és memòria perduda, és memòria cau de disc que el nucli allibera tan bon punt algú la necessita. La xifra que importa és avail Mem. Veure poca memòria lliure a Linux és normal i desitjable.
Tecles útils a top: M ordena per memòria, P per CPU, 1 desglossa per nucli, k envia un senyal, u filtra per usuari, c mostra la línia d'ordres completa. htop fa el mateix amb colors, ratolí i arbre amb F5; s'instal·la a part però val la pena.
pgrep i pkill
pgrep i pkilloperador@srv-tramontana:~$ pgrep -a executable
1284 /opt/tramontana/app/executable --config /etc/tramontana/app.conf-a mostra la línia d'ordres, -c compta, -u filtra per usuari, -f coincideix contra la línia completa i no només amb el nom, -x exigeix coincidència exacta, -n/-o el més nou / el més antic.
Per què són millors que ps | grep | awk | kill: aquesta canonada té dos defectes. El primer és que el mateix grep apareix a la llista i pots acabar matant un PID que ja no existeix o, pitjor, un de reciclat. El segon és que una coincidència parcial s'emporta per davant processos que no volies. pgrep consulta directament /proc i no s'hi inclou a si mateix.
Abans de pkill, executa sempre el pgrep equivalent. És la mateixa convenció que ls abans de rm:
operador@srv-tramontana:~$ pgrep -a -f 'executable --config'
1284 /opt/tramontana/app/executable --config /etc/tramontana/app.conf
operador@srv-tramontana:~$ pkill -f 'executable --config'
- Senyals
Un senyal és una notificació asíncrona que el nucli lliura a un procés.
| Núm. | Nom | Efecte per defecte | Es pot capturar? |
|---|---|---|---|
| 1 | SIGHUP | acabar; per convenció, recarregar la configuració | sí |
| 2 | SIGINT | interrompre (Ctrl+C) |
sí |
| 3 | SIGQUIT | acabar i abocar el core (Ctrl+\) |
sí |
| 9 | SIGKILL | matar immediatament | no |
| 15 | SIGTERM | acabar ordenadament (per defecte) | sí |
| 18/19 | SIGCONT / SIGSTOP | reprendre / aturar | CONT sí, STOP no |
| 10/12 | SIGUSR1 / SIGUSR2 | lliures, definides per l'aplicació | sí |
kill -l llista els 64 senyals del sistema. kill 1284 envia SIGTERM. Per a un altre: kill -TERM 1284, kill -15 1284 o kill -s SIGTERM 1284, totes equivalents. killall nom actua per nom en comptes de per PID —amb el risc evident d'abastar més del que preteníes.
La regla professional: SIGTERM, esperar, i només llavors SIGKILL
SIGTERM és una petició: el procés la rep, executa la seva rutina de tancament i acaba quan ha enllestit. SIGKILL és una execució sumària: el nucli destrueix el procés sense avisar-lo. El procés no se n'assabenta i per tant no pot fer res.
Què es perd amb -9:
- Les dades a memòries intermèdies que encara no s'havien escrit al disc.
- Les transaccions obertes a la base de dades, que queden sense confirmar i bloquejant files fins que expirin.
- Les peticions HTTP en curs, que es tallen en sec: el client veu un error.
- Els fitxers temporals i els fitxers de bloqueig, que queden orfes i poden impedir l'arrencada següent.
- L'oportunitat que el procés escrigui al registre per què es va tancar.
El procediment correcte:
operador@srv-tramontana:~$ kill -TERM 1284
operador@srv-tramontana:~$ sleep 10; pgrep -c executable
0Deu segons és un marge raonable per a una aplicació web; si el procés ja no hi és, hem acabat bé. Només si continua viu passat aquest termini es recorre a kill -9, i aleshores es documenta com a incident, perquè significa que la rutina de tancament de l'aplicació no funciona i això és una fallada que cal corregir.
SIGHUP mereix una menció: per convenció, molts dimonis l'interpreten com a «rellegeix la teva configuració sense reiniciar». Quan funciona, és la manera d'aplicar un canvi a app.conf sense tallar ni una petició.
- Prioritats:
nice, renice i ionice
nice, renice i ioniceEl valor nice va de -20 (prioritat màxima) a 19 (mínima). El nom ve de «ser amable»: com més alt, més cedeix el procés davant dels altres. Un usuari normal només el pot pujar —baixar la seva pròpia prioritat—; reduir-lo exigeix root.
operador@srv-tramontana:~$ nice -n 15 tar -czf /srv/tramontana/backups/enviaments/dades.tar.gz /home/operador/dades
operador@srv-tramontana:~$ sudo renice -n 5 -p 1284
1284 (process ID) old priority 0, new priority 5
operador@srv-tramontana:~$ ionice -c 3 tar -czf /srv/tramontana/backups/enviaments/dades.tar.gz /home/operador/dadesnice llança una ordre amb la prioritat modificada; renice canvia la d'un procés ja en marxa, també per usuari (-u) o per grup. I per a l'E/S, que en el nostre cas és el recurs escàs, hi ha ionice. La seva classe 3 és idle: la còpia només llegeix del disc quan ningú més no el necessita. Amb un wa del 64,8 %, ionice resol més que nice: baixar la prioritat de CPU d'un procés que no fa servir CPU no serveix de res. Diagnosticar abans d'actuar també significa triar la palanca correcta.
- Control de treballs a la sessió interactiva
| Acció | Com |
|---|---|
| Llançar en segon pla | ordre & |
| Llistar els treballs de la sessió | jobs -l |
| Portar al primer pla | fg %1 |
| Continuar en segon pla | bg %1 |
| Suspendre l'actual | Ctrl+Z (envia SIGSTOP) |
| Deslligar de la sessió | disown -h %1 |
| Immune al tancament de sessió | nohup ordre & |
operador@srv-tramontana:~$ tar -czf /tmp/copia.tar.gz /opt/tramontana/releases/3.1.0 &
[1] 2041
operador@srv-tramontana:~$ jobs -l
[1]+ 2041 Running tar -czf /tmp/copia.tar.gz /opt/tramontana/releases/3.1.0 &En tancar la sessió, el shell envia SIGHUP als seus treballs. nohup els immunitza i redirigeix la sortida a nohup.out; disown -h aconsegueix el mateix amb un treball ja llançat.
I ara l'advertiment important: res d'això no serveix per a un servei de debò. Un nohup ./executable & no es reinicia si el procés mor, no arrenca en encendre el servidor, no té control de recursos, no gestiona els seus registres i no pot aturar-se de manera ordenada per ningú que no siguis tu. El control de treballs és per a tasques llargues de la teva sessió —una còpia, una compilació—, no per a producció. Els serveis es gestionen amb systemd, i això és la lliçó 05-05.
lsof i fuser
lsof i fuserlsof («list open files») respon la pregunta «qui té això obert?». Com que a Linux gairebé tot és un fitxer, serveix també per a sòcols i ports.
Cas «no puc desmuntar».
operador@srv-tramontana:~$ sudo umount /srv/tramontana/backups
umount: /srv/tramontana/backups: target is busy.
operador@srv-tramontana:~$ sudo lsof +D /srv/tramontana/backups
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 1509 opera cwd DIR 8,1 4096 262148 /srv/tramontana/backups/enviaments
tar 2041 opera 3w REG 8,1 10485760 262203 /srv/tramontana/backups/enviaments/dades.tar.gzDos culpables: un bash el directori de treball del qual (cwd) és a dins —n'hi ha prou amb un cd a fora— i un tar escrivint (3w, descriptor 3 en mode escriptura). Amb això ja saps què esperar i a qui avisar, en comptes de forçar el desmuntatge.
Cas «el port 8080 està ocupat».
operador@srv-tramontana:~$ sudo lsof -i :8080
COMMAND PID USER FD TYPE DEVICE NODE NAME
executable 1284 svc-tramontana 7u IPv4 1284091 TCP *:http-alt (LISTEN)El PID 1284 té el port a l'escolta. És la resposta directa a «no puc arrencar l'aplicació nova perquè el port està en ús»: la vella continua viva.
fuser és més escarit i molt pràctic per actuar: fuser -v /ruta llista els processos, fuser -k /ruta els mata (amb compte) i fuser -k -TERM 8080/tcp envia SIGTERM a qui ocupi aquell port.
/proc/<pid>/ és la font de veritat de la qual beuen totes aquestes eines: cmdline l'ordre exacta, environ l'entorn amb què va arrencar, cwd i exe com a enllaços simbòlics, fd/ els descriptors, status un resum llegible, limits els límits de recursos. Quan una eina et doni una dada dubtosa, ves al fitxer.
- Cas Tramontana: l'app penjada de matinada
03:05. L'aplicació no respon. La Marta t'escriu. Procediment, amb la conclusió de 03-05 com a hipòtesi de partida.
Pas 1: és viva i en quin estat?
operador@srv-tramontana:~$ ps -o pid,stat,ni,rss,etime,pcpu -p $(pgrep -x executable)
PID STAT NI RSS ELAPSED %CPU
1284 Dsl 0 483920 04:12:33 2.1Estat D: no està penjada en un bucle, està bloquejada esperant E/S. Amb només un 2,1 % de CPU, no és un problema de càlcul. Un kill -9 aquí ni tan sols tindria efecte immediat.
Pas 2: què diu la càrrega? El load average: 3.42, 1.87, 0.94 amb 64.8 wa de la capçalera de l'apartat 7 confirma el mateix des d'un altre angle: cua creixent i espera d'E/S, no manca de CPU.
Pas 3: qui hi competeix?
operador@srv-tramontana:~$ ps -eo pid,user,stat,pcpu,etime,cmd --sort=-pcpu | head -4
PID USER STAT %CPU ELAPSED CMD
2210 operador D 38.4 05:12 tar -czf /srv/tramontana/backups/enviaments/nocturna.tar.gz /opt/tramontana
1284 svc-tram Dsl 2.1 04:12:33 /opt/tramontana/app/executableAquí està. Una còpia de seguretat nocturna porta cinc minuts llegint /opt/tramontana sencer —inclosos els quatre releases amb els seus executable de 48 MB— i satura el disc de la VM. L'aplicació, que necessita el disc per atendre consultes, es queda esperant.
Pas 4: alleujar sense matar res. La còpia és legítima; el que està malament és la seva prioritat.
operador@srv-tramontana:~$ sudo ionice -c 3 -p 2210
operador@srv-tramontana:~$ sudo renice -n 19 -p 2210
2210 (process ID) old priority 0, new priority 19Tots dos canvis s'apliquen al procés en marxa, sense interrompre'l. Dos minuts després el wa baixa i l'aplicació torna a respondre.
Pas 5: si hagués calgut reiniciar l'app, el procediment hauria estat kill -TERM $(pgrep -x executable), esperar que les peticions en curs acabin, verificar amb pgrep que ja no hi és i només llavors arrencar-la de nou. Mai kill -9 d'entrada: tallaria les reserves que s'estiguessin confirmant en aquell moment, i una reserva a mitges és un problema amb el client al davant.
Informe per a la Marta. La caiguda no va ser una fallada de l'aplicació sinó una competència pel disc: la còpia de seguretat nocturna s'executava amb la mateixa prioritat que el servei i el deixava sense accés a l'emmagatzematge. La mesura aplicada —donar a la còpia la prioritat d'E/S més baixa— protegeix que torni a bloquejar el servei, i no protegeix davant d'un augment general de la càrrega: si creix el nombre de reserves, caldran més recursos o separar la base de dades. A més, la còpia inclou els quatre releases sencers quan n'hi hauria prou amb l'actiu, cosa que la fa innecessàriament pesada. Pendent: ajustar l'abast de la còpia i el seu horari, que és exactament el que veurem a la lliçó següent.
Errors Comuns i Consells
- Fer servir
kill -9com a primera opció. És l'última. SIGTERM, esperar, verificar. - Intentar matar un zombi. Ja és mort. Actua sobre el pare.
- Insistir amb un procés en
D. No rebrà el senyal fins que l'E/S acabi. Investiga l'emmagatzematge. - Llegir el
%CPUdepscom a valor instantani. És una mitjana des de l'arrencada. Fes servirtop. - Alarmar-se per poca memòria lliure.
buff/cacheés memòria cau reutilitzable. Miraavail Mem. - Comparar la càrrega mitjana amb 100. Compara-la amb el nombre de nuclis, i recorda que inclou l'espera d'E/S.
ps | grep | killsobre un nom curt. El mateixgrepsurt a la llista i una coincidència parcial mata de més. Fes servirpgrep -ai despréspkill.- Deixar un servei amb
nohup &. No sobreviu a un reinici ni es recupera sol. - Consell: davant d'un «el servidor va lent», mira sempre primer el
wadetop. Si és alt, el coll d'ampolla és el disc i la meitat de les hipòtesis es descarten de cop. - Consell:
ps -eoaccepta qualsevol combinació de columnes; guarda't un àlies amb les teves a~/.bashrc, com vas aprendre a 03-01.
Exercicis
Exercici 1. Esbrina amb quina línia d'ordres exacta, amb quin directori de treball i amb quines variables d'entorn va arrencar el procés de Tramontana, sense fer servir ps. Explica què et diu cada dada.
Exercici 2. Llança una tasca llarga en segon pla, suspèn-la, reprèn-la en segon pla, baixa-li la prioritat de CPU i d'E/S, i deslliga-la de la teva sessió perquè sobrevisqui a un tancament d'SSH. Mostra la comprovació de cada pas.
Exercici 3. Simula el diagnòstic de «el port 8080 no accepta la versió nova»: identifica quin procés l'ocupa, de qui és, des de quan, i atura aquell procés de manera ordenada verificant que ha acabat abans de donar el pas per bo.
Solucions
Solució 1.
operador@srv-tramontana:~$ PID=$(pgrep -x executable)
operador@srv-tramontana:~$ tr '\0' ' ' < /proc/$PID/cmdline; echo
/opt/tramontana/app/executable --config /etc/tramontana/app.conf
operador@srv-tramontana:~$ sudo ls -l /proc/$PID/cwd /proc/$PID/exe
lrwxrwxrwx 1 svc-tramontana tramontana 0 Aug 18 12:52 /proc/1284/cwd -> /opt/tramontana/app
lrwxrwxrwx 1 svc-tramontana tramontana 0 Aug 18 12:52 /proc/1284/exe -> /opt/tramontana/releases/3.2.1/executable
operador@srv-tramontana:~$ sudo tr '\0' '\n' < /proc/$PID/environ | grep -E 'PATH|LANG'
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LANG=C.UTF-8cmdline guarda els arguments separats per bytes nuls, d'aquí el tr. Confirma que l'app llegeix /etc/tramontana/app.conf, així que un canvi allà l'afecta. El cwd és /opt/tramontana/app, l'enllaç simbòlic: significa que les seves rutes relatives es resolen a través d'ell.
La dada reveladora és exe, que apunta a /opt/tramontana/releases/3.2.1/executable, la ruta ja resolta. És la prova que el desplegament atòmic funciona com esperàvem: el nucli va fixar el binari real en arrencar, de manera que canviar l'enllaç app a un altre release no afecta el procés en marxa. Saps quina versió està servint de debò, no quina diu l'enllaç ara mateix. I environ mostra un PATH mínim i LANG=C.UTF-8: el servei no hereta el teu entorn interactiu, cosa que ja sabies des de 03-01 i que tornarà a aparèixer a la lliçó següent.
Solució 2.
operador@srv-tramontana:~$ tar -czf /tmp/rel.tar.gz /opt/tramontana/releases &
[1] 2311
operador@srv-tramontana:~$ fg %1
tar -czf /tmp/rel.tar.gz /opt/tramontana/releases
^Z
[1]+ Stopped tar -czf /tmp/rel.tar.gz /opt/tramontana/releases
operador@srv-tramontana:~$ ps -o pid,stat -p 2311
PID STAT
2311 T
operador@srv-tramontana:~$ bg %1
[1]+ tar -czf /tmp/rel.tar.gz /opt/tramontana/releases &
operador@srv-tramontana:~$ renice -n 15 -p 2311 && ionice -c 3 -p 2311
2311 (process ID) old priority 0, new priority 15
operador@srv-tramontana:~$ disown -h %1
operador@srv-tramontana:~$ ps -o pid,ni,stat -p 2311
PID NI STAT
2311 15 SNCada comprovació aporta alguna cosa: STAT en T confirma que Ctrl+Z el va aturar de debò (SIGSTOP), i després de bg i dels ajustos, SN indica que dorm amb prioritat baixa (N) i NI és 15. renice a 15 no ha necessitat sudo perquè pujar el nice propi està permès a qualsevol usuari; baixar-lo requeriria privilegis. disown -h no el treu de la llista de treballs, però marca que no ha de rebre SIGHUP en tancar la sessió. Si haguéssim sabut per endavant que la tasca és llarga, el que hauria estat net és nohup ... & des del principi.
Solució 3.
operador@srv-tramontana:~$ sudo lsof -i :8080 -sTCP:LISTEN
COMMAND PID USER FD TYPE DEVICE NODE NAME
executable 1284 svc-tramontana 7u IPv4 1284091 TCP *:http-alt (LISTEN)
operador@srv-tramontana:~$ ps -o pid,user,etime,cmd -p 1284
PID USER ELAPSED CMD
1284 svc-tram 04:31:12 /opt/tramontana/app/executable --config /etc/tramontana/app.confJa tenim les tres respostes: l'ocupa executable, pertany a svc-tramontana i porta quatre hores i mitja en marxa. -sTCP:LISTEN filtra els sòcols a l'escolta i descarta les connexions establertes, que serien soroll.
operador@srv-tramontana:~$ sudo kill -TERM 1284
operador@srv-tramontana:~$ sleep 10; pgrep -x executable || echo 'ha acabat correctament'
ha acabat correctament
operador@srv-tramontana:~$ sudo lsof -i :8080
operador@srv-tramontana:~$ echo "port lliure: $?"
port lliure: 1Dues verificacions diferents i totes dues necessàries. pgrep confirma que el procés ja no existeix; lsof sense sortida confirma que el port està lliure, que no és exactament el mateix: un sòcol pot quedar uns segons en TIME_WAIT després de tancar-se el procés, i intentar arrencar la versió nova en aquell forat fallaria per un motiu diferent i desconcertant. Comprovar el recurs que de debò necessites, i no només el procés, és el que evita aquest diagnòstic erroni. L'estat TIME_WAIT i la resta d'estats TCP els veuràs a 03-08.
Conclusió
Has deixat de mirar fitxers per mirar el que s'està executant, i amb això has resolt una incidència real de principi a fi.
- Saps què guarda el nucli de cada procés —PID, PPID, UID efectiu, estat, prioritat, VSZ i RSS— i que el número de memòria que importa és RSS.
- Recorres l'arbre de processos amb
pstreedes desystemd(PID 1) i entens el cicle fork / exec / wait / exit, que és on encaixa la redirecció de 03-04. - Distingeixes zombi d'orfe: el zombi no es pot matar i s'actua sobre el pare; l'orfe l'adopta
systemdi no és cap problema. - Coneixes els estats R, S, D, T, Z i per què un procés en
Dno respon a cap senyal, ni tan sols a-9. - Llegeixes
ps auxips -efcolumna a columna, construeixes vistes ambps -eo ... --sort=, i saps que el%CPUdepsés una mitjana des de l'arrencada. - Interpretes la capçalera de
top: la càrrega mitjana enfront del nombre de nuclis i la seva tendència, el desglossamentus/sy/ni/id/wa/hi/si/st—ambwacom el senyal que el coll d'ampolla és el disc— i quebuff/cacheno és memòria perduda. - Fas servir
pgrep/pkillen comptes deps | grep | kill, comprovant sempre abans de matar, i apliques la regla professional dels senyals: SIGTERM, esperar, verificar i només llavors SIGKILL, sabent què es perd amb-9. - Ajustes prioritats amb
nice,reniceiionice, triant la palanca segons on sigui el coll d'ampolla. - Controles treballs amb
&,jobs,fg,bg,Ctrl+Z,disowninohup, i tens clar que res d'això no val per a un servei de producció. - Respons amb
lsofifusera «qui té això obert?» i «qui ocupa aquest port?», i vas a/proc/<pid>/quan vols la veritat sense intermediaris.
El diagnòstic ha deixat una tasca pendent molt concreta: la còpia nocturna s'executa a l'hora equivocada, amb la prioritat equivocada i sobre més dades de les necessàries. Arreglar-la és el tema de la lliçó següent. Programació de Tasques amb Cron t'ensenyarà la sintaxi dels cinc camps fins als seus casos més recargolats, les tres fallades clàssiques que causen el 90 % de les incidències —el PATH mínim, el correu de sortida que ningú llegeix i la zona horària—, com depurar una tasca que «funciona a mà i a cron no», i com evitar amb flock que dues execucions se solapin, que és precisament el que pot haver passat aquesta matinada.
Curs de Linux: De Principiant a Administrador de Sistemes
Mòdul 1: Introducció a Linux
- Què és Linux?
- Història de Linux
- Distribucions de Linux
- Instal·lant Linux
- Primer Contacte amb el Sistema
- Estructura del Sistema de Fitxers de Linux
Mòdul 2: Comandes Bàsiques de Linux
- Introducció a la Línia de Comandes
- Obtenir Ajuda i Documentació del Sistema
- Navegant pel Sistema de Fitxers
- Operacions amb Fitxers i Directoris
- Visualització i Edició de Fitxers
- Enllaços Durs i Simbòlics
- Permisos i Propietat dels Fitxers
Mòdul 3: Habilitats Avançades en la Línia de Comandes
- L'Entorn del Shell: Variables, Àlies i Historial
- Ús de Comodins i Expressions Regulars
- Cerca de Fitxers i Contingut: find, locate i grep
- Canonades i Redirecció
- Processament de Text: cut, sort, uniq, sed i awk
- Gestió de Processos
- Programació de Tasques amb Cron
- Comandes de Xarxa
Mòdul 4: Scripting en Shell
- Introducció al Scripting en Shell
- Variables i Tipus de Dades
- Entrada, Sortida i Arguments d'un Script
- Estructures de Control
- Funcions i Biblioteques
- Depuració i Gestió d'Errors
- Scripts de Producció: Bones Pràctiques
Mòdul 5: Administració del Sistema
- Gestió d'Usuaris i Grups
- sudo i Permisos Especials
- Gestió de Paquets
- Gestió de Discs
- systemd i la Gestió de Serveis
- Registres del Sistema: journald i syslog
- Monitoratge del Sistema i Optimització del Rendiment
- Còpies de Seguretat i Restauració
Mòdul 6: Xarxes i Seguretat
- Configuració de Xarxes
- SSH i Accés Remot
- Tallafocs i Seguretat Perimetral
- Sistemes de Detecció d'Intrusions
- Gestió de Secrets i Certificats TLS
- Assegurant Sistemes Linux
Mòdul 7: Temes Avançats
- El Procés d'Arrencada i la Recuperació del Sistema
- Diagnòstic Avançat: strace, perf i eBPF
- Optimització del Nucli de Linux
- Virtualització amb Linux
- Contenidors de Linux i Docker
- Automatització amb Ansible
- Alta Disponibilitat i Balanceig de Càrrega
