Una volta, durante una entrevista, mi sò dumandatu, chì fate si truvate un serviziu chì ùn funziona micca per via di u fattu chì u discu hà scappatu di u spaziu?
Di sicuru, aghju rispostu ch'e aghju vistu ciò chì era occupatu da stu locu è, s'ellu hè pussibule, aghju pulitu u locu.
Allora l'entrevistadore dumandò, chì s'ellu ùn ci hè micca spaziu liberu nantu à a partizione, ma ùn vede micca ancu i schedari chì piglianu tuttu u spaziu?
À questu aghju dettu chì pudete sempre guardà i descriptori di u schedariu aperti, per esempiu cù u cumandamentu lsof, è capisce quale applicazione hà pigliatu tuttu u spaziu dispunibule, è poi pudete agisce secondu e circustanze, secondu chì a dati hè necessariu. .
L'intervistatore m'hà interrottu nantu à l'ultima parola, aghjunghjendu à a so quistione: "Suppone chì ùn avemu micca bisognu di e dati, hè solu un log di debug, ma l'applicazione ùn funziona micca perchè ùn pò micca scrive un debug"?
"Va bè", aghju rispostu, "pudemu disattivà u debug in a cunfigurazione di l'applicazione è riavvia".
L'entrevistadore hà oppostu: "No, ùn pudemu micca riavvia l'applicazione, avemu sempre dati impurtanti almacenati in memoria, è i clienti impurtanti sò cunnessi à u serviziu stessu, chì ùn pudemu micca forza à ricunnisce micca di novu".
"Va bè", aghju dettu, "se ùn pudemu micca riavvia l'applicazione è i dati ùn sò micca impurtanti per noi, allora pudemu simpricimenti sguassate stu schedariu apertu attraversu u descrittore di u schedariu, ancu s'ellu ùn vedemu micca in u cumandimu ls. nantu à u sistema di fugliale ".
L'entrevistadore era cuntentu, ma ùn era micca.
Allora aghju pensatu, perchè a persona chì prova a mo cunniscenza ùn scava più profonda? Ma chì si i dati sò impurtanti dopu à tuttu? E se ùn pudemu micca riavvià un prucessu, è u prucessu scrive à u sistema di schedari nantu à una partizione chì ùn hà micca spaziu liberu? E se ùn pudemu micca perde micca solu i dati chì sò digià scritti, ma ancu i dati chì stu prucessu scrive o prova di scrive?
Tuzik
A principiu di a mo carriera, aghju pruvatu à creà una piccula applicazione chì avia bisognu di almacenà l'infurmazioni di l'utilizatori. E poi aghju pensatu, cumu possu currisponde à l'utilizatori cù i so dati. Per esempiu, aghju Ivanov Ivan Ivanovich, è hà qualchì infurmazione, ma cumu possu fà amici cù elli? Puderaghju direttamente chì u cane chjamatu "Tuzik" appartene à questu Ivan. Ma chì si cambia u so nome è invece di Ivan diventa, per esempiu, Olya? Allora vi sarà chì a nostra Olya Ivanovna Ivanova ùn avarà più un cane, è u nostru Tuzik appartene ancu à l'Ivan inesistente. Una basa di dati chì dete à ogni utilizatore un identificatore unicu (ID) hà aiutatu à risolve stu prublema, è u mo Tuzik era ligatu à questu ID, chì, in fattu, era solu un numeru di serie. Cusì, u pruprietariu di l'as hà avutu u numeru ID 2, è in un certu puntu in u tempu Ivan era sottu à questu ID, è dopu Olya diventò sottu à u listessu ID. U prublema di l'umanità è l'allevamentu di l'animali hè stata praticamente risolta.
Descrizzione di u schedariu
U prublema di u schedariu è u prugramma chì travaglia cù stu schedariu hè apprussimatamente u listessu cum'è quellu di u nostru cane è omu. Eppo supponi chì aghju apertu un schedariu chjamatu ivan.txt è hà cuminciatu à scrive a parolla tuzik in questu, ma solu riesciutu à scrive a prima lettera "t" in u schedariu, è questu schedariu hè statu rinominatu da qualchissia, per esempiu, olya.txt. Ma u schedariu ferma u listessu, è vogliu sempre registrà u mo zitellu in questu. Ogni volta chì un schedariu hè apertu da una chjama di sistema
In Linux, a libreria libc apre 3 file descriptori per ogni applicazione in esecuzione (processu), numerata 0,1,2. Più infurmazione pò esse truvata nantu à i ligami
- U descrittore di u schedariu 0 hè chjamatu STDIN è hè assuciatu cù l'input di l'applicazione
- U descriptor d'archiviu 1 hè chjamatu STDOUT è hè utilizatu da l'applicazioni per pruduce dati, cum'è cumandamenti di stampa
- U descriptor d'archiviu 2 hè chjamatu STDERR è hè utilizatu da l'applicazioni per pruduce missaghji d'errore.
Se in u vostru prugramma avete apertu un schedariu per leghje o scrive, allora u più prubabile uttene u primu ID gratuitu è serà u numeru 3.
A lista di descriptori di u schedariu pò esse vistu per qualsiasi prucessu se cunnosci u so PID.
Per esempiu, apremu a cunsola bash è fighjemu u PID di u nostru prucessu
[user@localhost ]$ echo $$
15771
In a seconda cunsola corremu
[user@localhost ]$ ls -lah /proc/15771/fd/
total 0
dr-x------ 2 user user 0 Oct 7 15:42 .
dr-xr-xr-x 9 user user 0 Oct 7 15:42 ..
lrwx------ 1 user user 64 Oct 7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 255 -> /dev/pts/21
Pudete ignurà in modu sicuru u descrittore di u schedariu 255 per i scopi di questu articulu; hè statu apertu per i so bisogni da bash stessu, è micca da a biblioteca ligata.
Avà tutti i schedarii descriptori 3 sò assuciati cù u pseudo-dispositivu terminal
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
È in a prima cunsola videremu
[user@localhost ]$ hello world
Redirect è Pipe
Pudete facilmente rimpiazzà questi file descriptori 3 in ogni prucessu, cumpresu in bash, per esempiu attraversu una pipa chì cunnetta dui prucessi, vede
[user@localhost ]$ cat /dev/zero | sleep 10000
Pudete eseguisce stu cumandamentu sè stessu strace -f è vedi ciò chì si passa ind'è, ma ti dicu brevemente.
U nostru prucessu parent bash cù PID 15771 analizà u nostru cumandamentu è capisce esattamente quanti cumandamenti vulemu eseguisce, in u nostru casu ci sò dui: cat è dorme. Bash sà chì ci vole à creà dui prucessi di u zitellu, è unisce in una pipa. In totale, bash hà bisognu di 2 prucessi di u zitellu è una pipa.
Bash esegue una chjama di sistema prima di creà prucessi di u zitellu
Per u prucessu parent, pare chì ci hè digià una pipa, ma ùn ci hè ancu micca prucessi di u zitellu:
PID command
15771 bash
lrwx------ 1 user user 64 Oct 7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:42 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:42 255 -> /dev/pts/21
Dopu aduprà a chjama di u sistema
PID command
15771 bash
lrwx------ 1 user user 64 Oct 7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:42 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:42 255 -> /dev/pts/21
PID command
9004 bash
lrwx------ 1 user user 64 Oct 7 15:57 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 255 -> /dev/pts/21
PID command
9005 bash
lrwx------ 1 user user 64 Oct 7 15:57 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 3 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 4 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 255 -> /dev/pts/21
Ùn vi scurdate micca chì u clone clone u prucessu inseme cù tutti i descrittori di u schedariu, cusì seranu listessi in u prucessu parent è in i zitelli. U travagliu di u prucessu parentale cù PID 15771 hè di monitorà i prucessi di u zitellu, cusì aspetta solu una risposta da i zitelli.
Dunque, ùn hà micca bisognu di pipa, è chjude i descrittori di u schedariu numerati 3 è 4.
In u primu prucessu di bash di u zitellu cù PID 9004, a chjama di u sistema
In u sicondu prucessu di u zitellu cù PID 9005, bash usa dup2 per cambià u descriptor d'archivi STDIN numeru 0. Avà tuttu ciò chì a nostra seconda bash cù PID 9005 leghjite serà lettu da a pipa.
Dopu questu, i descriptori di fugliale numerati 3 è 4 sò ancu chjusi in i prucessi di u zitellu, postu chì ùn sò più usati.
Ignoru deliberatamente u descrittore di u schedariu 255; hè adupratu per scopi interni da bash stessu è serà ancu chjusu in i prucessi di u zitellu.
In seguitu, in u primu prucessu di u zitellu cù PID 9004, bash principia cù una chjama di sistema
In u sicondu prucessu di u zitellu cù PID 9005, bash corre u secondu eseguibile chì avemu specificatu, in u nostru casu /usr/bin/sleep.
A chjama di u sistema execu ùn chjude micca i manichi di i schedari, salvu ch'elli sò stati aperti cù a bandiera O_CLOEXEC à u mumentu chì a chjama aperta hè stata fatta. In u nostru casu, dopu avè lanciatu i fugliali eseguibili, tutti i descriptori di u schedariu attuale seranu salvati.
Verificate in a cunsola:
[user@localhost ]$ pgrep -P 15771
9004
9005
[user@localhost ]$ ls -lah /proc/15771/fd/
total 0
dr-x------ 2 user user 0 Oct 7 15:42 .
dr-xr-xr-x 9 user user 0 Oct 7 15:42 ..
lrwx------ 1 user user 64 Oct 7 15:42 0 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 2 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:42 255 -> /dev/pts/21
[user@localhost ]$ ls -lah /proc/9004/fd
total 0
dr-x------ 2 user user 0 Oct 7 15:57 .
dr-xr-xr-x 9 user user 0 Oct 7 15:57 ..
lrwx------ 1 user user 64 Oct 7 15:57 0 -> /dev/pts/21
l-wx------ 1 user user 64 Oct 7 15:57 1 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 2 -> /dev/pts/21
lr-x------ 1 user user 64 Oct 7 15:57 3 -> /dev/zero
[user@localhost ]$ ls -lah /proc/9005/fd
total 0
dr-x------ 2 user user 0 Oct 7 15:57 .
dr-xr-xr-x 9 user user 0 Oct 7 15:57 ..
lr-x------ 1 user user 64 Oct 7 15:57 0 -> pipe:[253543032]
lrwx------ 1 user user 64 Oct 7 15:57 1 -> /dev/pts/21
lrwx------ 1 user user 64 Oct 7 15:57 2 -> /dev/pts/21
[user@localhost ]$ ps -up 9004
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
user 9004 0.0 0.0 107972 620 pts/21 S+ 15:57 0:00 cat /dev/zero
[user@localhost ]$ ps -up 9005
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
user 9005 0.0 0.0 107952 360 pts/21 S+ 15:57 0:00 sleep 10000
Comu pudete vede, u numeru unicu di a nostra pipa hè u listessu in i dui prucessi. Cusì avemu una cunnessione trà dui prucessi diffirenti cù u stessu parente.
Per quelli chì ùn sò micca familiarizati cù e chjama di u sistema chì bash usa, vi cunsigliu assai di eseguisce i cumandamenti attraversu strace è vede ciò chì succede internamente, per esempiu cusì:
strace -s 1024 -f bash -c "ls | grep hello"
Andemu à u nostru prublemu di scappari fora di u spaziu discu è circannu à salvà dati senza ripigliate u prucessu. Scrivemu un picculu prugramma chì scriverà circa 1 megabyte per seconda à u discu. Inoltre, se per una certa ragione ùn pudemu micca scrive dati à u discu, simpricimenti ignurà questu è pruvate à scrive i dati di novu in un secondu. In l'esempiu chì aghju utilizatu Python, pudete aduprà qualsiasi altra lingua di prugrammazione.
[user@localhost ]$ cat openforwrite.py
import datetime
import time
mystr="a"*1024*1024+"n"
with open("123.txt", "w") as f:
while True:
try:
f.write(str(datetime.datetime.now()))
f.write(mystr)
f.flush()
time.sleep(1)
except:
pass
Eseguimu u prugramma è fighjemu i descrittori di u schedariu
[user@localhost ]$ python openforwrite.py &
[1] 3762
[user@localhost ]$ ps axuf | grep [o]penforwrite
user 3762 0.0 0.0 128600 5744 pts/22 S+ 16:28 0:00 | _ python openforwrite.py
[user@localhost ]$ ls -la /proc/3762/fd
total 0
dr-x------ 2 user user 0 Oct 7 16:29 .
dr-xr-xr-x 9 user user 0 Oct 7 16:29 ..
lrwx------ 1 user user 64 Oct 7 16:29 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 7 16:29 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 7 16:29 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 7 16:29 3 -> /home/user/123.txt
Comu pudete vede, avemu i nostri 3 descriptori di file standard è un altru chì avemu apertu. Cuntrollamu a dimensione di u schedariu:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
I dati sò scritti, pruvemu di cambià i permessi nantu à u schedariu:
[user@localhost ]$ sudo chown root: 123.txt
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 root root 168M Oct 7 16:31 123.txt
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 root root 172M Oct 7 16:31 123.txt
Avemu vistu chì i dati sò sempre scritti, ancu s'è u nostru utilizatore ùn hà micca permessu di scrive à u schedariu. Pruvemu di sguassà:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Induve sò scritti i dati? È sò scritti à tutti ? Avemu verificatu:
[user@localhost ]$ ls -la /proc/3762/fd
total 0
dr-x------ 2 user user 0 Oct 7 16:29 .
dr-xr-xr-x 9 user user 0 Oct 7 16:29 ..
lrwx------ 1 user user 64 Oct 7 16:29 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 7 16:29 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 7 16:29 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 7 16:29 3 -> /home/user/123.txt (deleted)
Iè, u nostru descriptore di u schedariu esiste sempre è pudemu trattà stu descrittore di u schedariu cum'è u nostru vechju schedariu, pudemu leghje, sbulicà è copià.
Fighjemu a dimensione di u schedariu:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
A dimensione di u schedariu hè 19923457. Pruvemu di sguassà u schedariu:
[user@localhost ]$ truncate -s 0 /proc/31083/fd/3
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 136318390 2621522 /home/user/123.txt
Comu pudete vede, a dimensione di u schedariu hè solu crescente è u nostru troncu ùn hà micca travagliatu. Fighjemu a documentazione di a chjama di u sistema
with open("123.txt", "w") as f:
avemu da mette
with open("123.txt", "a") as f:
Verificate cù a bandiera "w".
[user@localhost ]$ strace -e trace=open python openforwrite.py 2>&1| grep 123.txt
open("123.txt", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
è cù a bandiera "a".
[user@localhost ]$ strace -e trace=open python openforwrite.py 2>&1| grep 123.txt
open("123.txt", O_WRONLY|O_CREAT|O_APPEND, 0666) = 3
Prugrammazione di un prucessu digià in esecuzione
Spessu i programatori, quandu creanu è teste prugrammi, utilizanu debuggers (per esempiu GDB) o diversi livelli di logging in l'applicazione. Linux furnisce l'abilità di scrive veramente è cambià un prugramma digià in esecuzione, per esempiu, cambià i valori di variabili, stabilisce un puntu di ruptura, etc., etc.
Riturnendu à a quistione originale chì ùn hè micca abbastanza spaziu di discu per scrive un schedariu, pruvemu à simule u prublema.
Creemu un schedariu per a nostra partizione, chì monteremu cum'è un discu separatu:
[user@localhost ~]$ dd if=/dev/zero of=~/tempfile_for_article.dd bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 0.00525929 s, 2.0 GB/s
[user@localhost ~]$
Creemu un sistema di schedari:
[user@localhost ~]$ mkfs.ext4 ~/tempfile_for_article.dd
mke2fs 1.42.9 (28-Dec-2013)
/home/user/tempfile_for_article.dd is not a block special device.
Proceed anyway? (y,n) y
...
Writing superblocks and filesystem accounting information: done
[user@localhost ~]$
Muntà u sistema di schedari:
[user@localhost ~]$ sudo mount ~/tempfile_for_article.dd /mnt/
[sudo] password for user:
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 172K 7.9M 3% /mnt
Creemu un annuariu cù u nostru pruprietariu:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Aprimu u schedariu per scrive solu in u nostru prugramma:
with open("/mnt/logs/123.txt", "w") as f:
Lanciari
[user@localhost ]$ python openforwrite.py
Aspittemu uni pochi seconde
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Dunque, avemu u prublema discritta à u principiu di stu articulu. Spaziu liberu 0, 100% occupatu.
Ricurdamu chì secondu e cundizioni di u compitu, avemu a prova di arregistrà dati assai impurtanti chì ùn ponu micca persu. È à u listessu tempu, avemu bisognu di riparà u serviziu senza ripiglià u prucessu.
Diciamu chì avemu sempre spaziu di discu, ma in una partizione diversa, per esempiu in /home.
Pruvemu di "riprogrammà nantu à a mosca" u nostru codice.
Fighjemu u PID di u nostru prucessu, chì hà manghjatu tuttu u spaziu di discu:
[user@localhost ~]$ ps axuf | grep [o]penfor
user 10078 27.2 0.0 128600 5744 pts/22 R+ 11:06 0:02 | _ python openforwrite.py
Cunnette vi u prucessu via gdb
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Fighjemu i descrittori di u schedariu aperti:
(gdb) shell ls -lah /proc/10078/fd/
total 0
dr-x------ 2 user user 0 Oct 8 11:06 .
dr-xr-xr-x 9 user user 0 Oct 8 11:06 ..
lrwx------ 1 user user 64 Oct 8 11:09 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:09 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:06 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:09 3 -> /mnt/logs/123.txt
Fighjemu l'infurmazioni nantu à u descriptore di u schedariu numeru 3, chì ci interessa
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Tenendu in mente ciò chì u sistema chjamatu Python face (vede sopra induve curriamu strace è truvamu a chjama aperta), quandu trasfurmava u nostru codice per apre un schedariu, facemu u stessu in nome di u nostru prucessu, ma avemu bisognu di u O_WRONLY|O_CREAT| I bits O_TRUNC rimpiazzanu cù un valore numericu. Per fà questu, apre i fonti di u kernel, per esempiu
#define O_WRONLY 00000001
#define O_CREAT 00000100
#define O_TRUNC 00001000
Cumbinemu tutti i valori in unu, avemu 00001101
Eseguimu a nostra chjama da gdb
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Allora avemu un novu descriptore di schedariu cù u numeru 4 è un novu schedariu apertu nantu à una altra partizione, cuntrollemu:
(gdb) shell ls -lah /proc/10078/fd/
total 0
dr-x------ 2 user user 0 Oct 8 11:06 .
dr-xr-xr-x 9 user user 0 Oct 8 11:06 ..
lrwx------ 1 user user 64 Oct 8 11:09 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:09 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:06 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:09 3 -> /mnt/logs/123.txt
l-wx------ 1 user user 64 Oct 8 11:15 4 -> /home/user/123.txt
Ricurdamu l'esempiu cù pipe - cumu bash cambia i descrittori di u schedariu, è avemu digià amparatu a chjama di u sistema dup2.
Pruvemu di rimpiazzà un descrittore di fugliale cù un altru
(gdb) call dup2(4,3)
$2 = 3
Verificate:
(gdb) shell ls -lah /proc/10078/fd/
total 0
dr-x------ 2 user user 0 Oct 8 11:06 .
dr-xr-xr-x 9 user user 0 Oct 8 11:06 ..
lrwx------ 1 user user 64 Oct 8 11:09 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:09 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:06 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:09 3 -> /home/user/123.txt
l-wx------ 1 user user 64 Oct 8 11:15 4 -> /home/user/123.txt
Chiudemu u descriptore di u schedariu 4, postu chì ùn ne avemu micca bisognu:
(gdb) call close (4)
$1 = 0
È esce da gdb
(gdb) quit
A debugging session is active.
Inferior 1 [process 10078] will be detached.
Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2.7, process 10078
Verificate u novu schedariu:
[user@localhost ~]$ ls -lah /home/user/123.txt
-rw-rw-r-- 1 user user 5.1M Oct 8 11:18 /home/user/123.txt
[user@localhost ~]$ ls -lah /home/user/123.txt
-rw-rw-r-- 1 user user 7.1M Oct 8 11:18 /home/user/123.txt
Comu pudete vede, i dati sò scritti in un novu schedariu, cuntrollemu u vechju:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Nisuna dati hè persu, l'applicazione funziona, i logs sò scritti in un novu locu.
Cumplichemu un pocu u compitu
Imaginemu chì i dati sò impurtanti per noi, ma ùn avemu micca spaziu di discu in alcuna partizioni è ùn pudemu micca cunnette u discu.
Ciò chì pudemu fà hè di ridirezzione di i nostri dati in un locu, per esempiu à pipa, è in turnu redirezzione di dati da a pipa à a reta per un prugramma, per esempiu netcat.
Pudemu creà una pipa chjamata cù u cumandimu mkfifo. Ci hà da creà un pseudo schedariu nant'à u sistema di schedari ancu s'ellu ùn ci hè micca spaziu liberu nantu à ellu.
Riavvia l'applicazione è verificate:
[user@localhost ]$ python openforwrite.py
[user@localhost ~]$ ps axuf | grep [o]pen
user 5946 72.9 0.0 128600 5744 pts/22 R+ 11:27 0:20 | _ python openforwrite.py
[user@localhost ~]$ ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/123.txt
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Ùn ci hè micca spaziu di discu, ma avemu criatu bè una pipa chjamata quì:
[user@localhost ~]$ mkfifo /mnt/logs/megapipe
[user@localhost ~]$ ls -lah /mnt/logs/megapipe
prw-rw-r-- 1 user user 0 Oct 8 11:28 /mnt/logs/megapipe
Avà avemu bisognu d'incarcerà tutte e dati chì entranu in questa pipa à un altru servitore via a reta; u stessu netcat hè adattatu per questu.
Nant'à u servitore remote-server.example.com curriamu
[user@localhost ~]$ nc -l 7777 > 123.txt
In u nostru servitore problematicu lanciamu in un terminal separatu
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Avà tutti i dati chì finiscinu in u pipe andaranu automaticamente à stdin in netcat, chì u mandarà à a reta in u portu 7777.
Tuttu ciò chì avemu da fà hè di cumincià à scrive i nostri dati in questa pipa chjamata.
Avemu digià l'applicazione in esecuzione:
[user@localhost ~]$ ps axuf | grep [o]pen
user 5946 99.8 0.0 128600 5744 pts/22 R+ 11:27 169:27 | _ python openforwrite.py
[user@localhost ~]$ ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/123.txt
Di tutti i bandieri, avemu solu bisognu di O_WRONLY postu chì u schedariu esiste digià è ùn avemu micca bisognu di sguassà
[user@localhost ~]$ gdb -p 5946
...
(gdb) call open("/mnt/logs/megapipe", 00000001,0666)
$1 = 4
(gdb) shell ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/123.txt
l-wx------ 1 user user 64 Oct 8 14:20 4 -> /mnt/logs/megapipe
(gdb) call dup2(4,3)
$2 = 3
(gdb) shell ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/megapipe
l-wx------ 1 user user 64 Oct 8 14:20 4 -> /mnt/logs/megapipe
(gdb) call close(4)
$3 = 0
(gdb) shell ls -lah /proc/5946/fd
total 0
dr-x------ 2 user user 0 Oct 8 11:27 .
dr-xr-xr-x 9 user user 0 Oct 8 11:27 ..
lrwx------ 1 user user 64 Oct 8 11:28 0 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:28 1 -> /dev/pts/22
lrwx------ 1 user user 64 Oct 8 11:27 2 -> /dev/pts/22
l-wx------ 1 user user 64 Oct 8 11:28 3 -> /mnt/logs/megapipe
(gdb) quit
A debugging session is active.
Inferior 1 [process 5946] will be detached.
Quit anyway? (y or n) y
Detaching from program: /usr/bin/python2.7, process 5946
Verificate u servitore remoto remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
I dati venenu, cuntrollemu u servitore prublema
[user@localhost ~]$ ls -lah /mnt/logs/
total 7.9M
drwxr-xr-x 2 user user 1.0K Oct 8 11:28 .
drwxr-xr-x 4 root root 1.0K Oct 8 10:55 ..
-rw-rw-r-- 1 user user 7.9M Oct 8 14:17 123.txt
prw-rw-r-- 1 user user 0 Oct 8 14:22 megapipe
I dati sò salvati, u prublema hè risolta.
Approfittu di sta occasione per salutà i mo culleghi di Degiro.
Ascolta i podcast di Radio-T.
Bon à tutti.
Cum'è i travaglii di casa, vi suggerenu di pensà à ciò chì serà in i descrittori di u schedariu di prucessu cat and sleep si eseguite u cumandimu seguente:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Source: www.habr.com