Behin, elkarrizketa batean, zer egingo zenuke diskoa lekurik gabe geratu delako hondatutako zerbitzu bat aurkituko baduzu zer egingo zenuke?
Noski, toki hau zertan ari zen ikusiko nuela erantzun nion eta, ahal izanez gero, lekua garbituko nuela.
Orduan elkarrizketatzaileak galdetu zuen: zer gertatzen da partizioan leku librerik ez badago, baina espazio guztia hartuko luketen fitxategiak ere ez badituzu ikusten?
Honi, esan nion beti begiratu dezakezula fitxategi irekien deskribatzaileak, adibidez, lsof komandoarekin eta ulertu zein aplikaziok hartu duen espazio guztia, eta gero egoeraren arabera jokatu dezakezula, datuak behar diren ala ez kontuan hartuta. .
Elkarrizketatzaileak eten egin ninduen azken hitzean, bere galderari gehituz: βDemagun ez dugula daturik behar, arazketa-erregistro bat besterik ez dela, baina aplikazioa hutsik dago arazketa idatzi ezin duelakoβ?
"Ados", erantzun nion, "aplikazioaren konfigurazioan arazketa desaktibatu eta berrabiarazi dezakegu".
Elkarrizketatzaileak aurka egin zuen: "Ez, ezin dugu aplikazioa berrabiarazi, oraindik datu garrantzitsuak ditugu memorian, eta bezero garrantzitsuak zerbitzura konektatuta daude, ezin dugu berriro konektatzera behartu".
"Ongi", esan nion, "Aplikazioa berrabiarazi ezin badugu eta datuei buruz ez badigugu axola, orduan irekitako fitxategi hau fitxategi deskribatzailearen bidez garbitu dezakegu, ls-en ikusten ez badugu ere. komandoa fitxategi-sisteman."
Elkarrizketatzailea pozik zegoen, baina ni ez.
Orduan pentsatu nuen, zergatik ez du sakontzen nire ezagutza probatzen ari denak? Baina, azken finean, datuak garrantzitsuak badira? Zer gertatzen da prozesua berrabiarazi eta, aldi berean, prozesu honek fitxategi-sisteman leku librerik ez duen partizio batean idazten badu? Zer gertatzen da dagoeneko idatzitako datuak ez ezik, prozesu hau idazten edo idazten saiatzen ari den datuak ere galdu ezin baditugu?
Tuzik
Nire karreraren hasieran, erabiltzaileei buruzko informazioa gordetzeko behar zuen aplikazio txiki bat sortzen saiatzen ari nintzen. Eta orduan pentsatu nuen, nola lotu dezaket erabiltzailea bere datuekin. Esaterako, Ivanov Ivan Ivanovich dut, eta datu batzuk ditu, baina nola egin haiekin lagun? Zuzenean adierazi dezaket "Tuzik" izeneko txakurra Ivan honena dela. Baina zer gertatzen da izena aldatu eta Ivanen ordez, adibidez, Olya bihurtzen bada? Orduan, gure Olya Ivanovna Ivanovak ez duela gehiago txakurrik izango eta gure Tuzik oraindik existitzen ez den Ivanarena izango da. Datu-baseak arazo hau konpontzen lagundu zuen, erabiltzaile bakoitzari identifikatzaile bakarra (ID) ematen zion, eta nire Tuzik ID horri lotuta zegoen, hau da, serie-zenbaki bat besterik ez zena. Horrela, tuzik jabea 2 NAN zenbakia zuen, eta noizbait Ivan ID horren pean zegoen, eta orduan Olya ID beraren pean geratu zen. Gizadiaren eta abeltzaintzaren arazoa ia konpondu zen.
Fitxategiaren deskribatzailea
Fitxategi batekin eta fitxategi honekin lan egiten duen programa baten arazoa gure txakurra eta gizakiaren berdina da. Demagun ivan.txt izeneko fitxategi bat ireki eta tuzik hitza idazten hasi naizela, baina fitxategian lehen letra "t" bakarrik idaztea lortu dudala, eta fitxategi honi norbaitek izena aldatu diola, adibidez, olya.txt. Baina fitxategia berdina da eta oraindik nire batekoa idatzi nahi diot. Sistema-dei batekin fitxategi bat irekitzen duzun bakoitzean
Linux-en, libc liburutegiak 3 fitxategi deskribatzaile irekitzen ditu martxan dagoen aplikazio bakoitzeko (prozesua), 0,1,2 zenbakiekin. Informazio gehiago esteketan aurki dezakezu
- 0 fitxategi deskribatzailea STDIN deitzen da eta aplikazioaren sarrerarekin lotuta dago.
- Fitxategiaren deskribatzailea 1 STDOUT deitzen da eta irteerako aplikazioek erabiltzen dute, esate baterako, inprimatzeko komandoak.
- 2. fitxategi-deskribatzaileak STDERR izena du eta aplikazioek erabiltzen dute errore-mezuak ateratzeko.
Zure programan irakurtzeko edo idazteko fitxategiren bat irekitzen baduzu, ziurrenik doako lehen IDa lortuko duzu eta 3. zenbakia izango da.
Edozein prozesuren fitxategi deskribatzaileen zerrenda ikus dezakezu bere PID ezagutzen baduzu.
Adibidez, ireki dezagun bash-ekin kontsola bat eta ikus dezagun gure prozesuaren PID-a
[user@localhost ]$ echo $$
15771
Bigarren kontsolan, exekutatu
[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
Artikulu honen barruan 255 zenbakia duen fitxategi deskribatzaileari segurtasunez ez ikusi egin dezakezu, zure beharretarako ireki da bash-ek berak, eta ez estekatutako liburutegiak.
Orain 3 deskribatzaile fitxategiak sasi-terminal gailuarekin lotuta daude
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
Eta lehenengo kontsolan ikusiko dugu
[user@localhost ]$ hello world
Birbideratu eta kanalizatu
3 deskribatzaile fitxategi hauek erraz gainidatzi ditzakezu edozein prozesutan, bash-en barne, adibidez, bi prozesu lotzen dituen kanalizazio baten (hodiaren) bidez, ikus
[user@localhost ]$ cat /dev/zero | sleep 10000
Komando hau zuk zeuk exekutatu dezakezu traza -f eta ikusi zer gertatzen den barruan, baina labur egingo dut.
Gure guraso bash-prozesuak PID 15771-rekin gure komandoa analizatzen du eta zehatz-mehatz ulertzen du zenbat komando exekutatu nahi ditugun, gure kasuan bi daude: cat eta sleep. Bashek badaki bi prozesu seme-alaba sortu behar dituela eta kanalizazio batean batu. Guztira, bash-ek 2 haur-prozesu eta kanalizazio bat beharko ditu.
Haur-prozesuak sortu aurretik, bash-ek sistema-dei bat exekutatzen du
Prozesu nagusirako, badirudi kanalizazioa dagoeneko hor dagoela, baina oraindik ez dago prozesu seme-alabarik:
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
Ondoren, sistema-deia erabiliz
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
Ez ahaztu klonak prozesua klonatzen duela fitxategi deskribatzaile guztiekin batera, beraz, berdinak izango dira prozesu nagusietan eta umeetan. PID 15771 duen guraso-prozesuaren zeregina haurraren prozesuak kontrolatzea da, beraz, haurren erantzunaren zain geratzen da.
Horregatik, ez du kanalizaziorik behar, eta fitxategien deskribatzaileak 3 eta 4 zenbakiekin ixten ditu.
PID 9004 duen lehen bash haur-prozesuan, sistema deia
PID 9005 duen bigarren haur-prozesuan, bash dup2 fitxategia STDIN deskribatzaile zenbakira 0. Orain PID 9005 duen bigarren bash-ek irakurriko duen guztia kanaletik irakurriko da.
Horren ostean, 3. eta 4. zenbakiak dituzten fitxategi-deskribatzaileak ere itxi egiten dira prozesu umeetan, jada ez baitira erabiltzen.
Nahita ez dut jaramonik egiten 255 fitxategi-deskribatzailea, bash-ek barnean erabiltzen du eta ume-prozesuetan ere itxiko da.
Ondoren, PID 9004 duen lehen haur-prozesuan, bash sistema dei batekin hasten da
PID 9005 duen bigarren haur-prozesuan, bash-ek zehaztu dugun bigarren exekutagarria exekutatzen du, gure kasuan /usr/bin/sleep.
Exec sistema-deiak ez ditu fitxategi-deskribatzaileak ixten, deia exekutatu zenean O_CLOEXEC banderarekin ireki ezean. Gure kasuan, fitxategi exekutagarriak exekutatu ondoren, uneko fitxategi deskribatzaile guztiak gordeko dira.
Kontsolan egiaztatzea:
[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
Ikus dezakezunez, gure hodiaren zenbaki bakarra berdina da bi prozesuetan. Horrela, guraso bera duten bi prozesu ezberdinen arteko lotura dugu.
Bashek erabiltzen dituen sistema-deiak ezagutzen ez dituztenentzat, gomendatzen dut strace bidez komandoak exekutatu eta ikustea zer gertatzen den barruan, adibidez, honela:
strace -s 1024 -f bash -c "ls | grep hello"
Itzul gaitezen gure arazora diskoko lekurik gabe geratu eta datuak gordetzen saiatzean prozesua berrabiarazi gabe. Idatz dezagun diskoan segundoko 1 megabyte inguru idatziko duen programa txiki bat. Gainera, arrazoiren batengatik ezin izan bagenu datuak diskoan idatzi, hau baztertu eta segundo batean datuak berriro idazten saiatuko gara. Python erabiltzen ari naizen adibidean, beste edozein programazio-lengoaia erabil dezakezu.
[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
Exekutatu programa eta begiratu fitxategien deskribatzaileak
[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
Ikus dezakezunez, gure 3 fitxategi deskribatzaile estandarrak ditugu eta ireki dugun beste bat. Ikus dezagun fitxategiaren tamaina:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
datuak idatzita daude, fitxategiaren eskubideak aldatzen saiatzen gara:
[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
Datuak oraindik idazten ari direla ikusten dugu, nahiz eta gure erabiltzaileak fitxategian idazteko eskubiderik ez duen. Saia gaitezen kentzen:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Non daude idatzita datuak? Eta idatzita daude? Egiaztatzen dugu:
[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)
Bai, gure fitxategi-deskribatzailea oraindik existitzen da, eta fitxategi-deskribatzaile honekin lan egin dezakegu gure fitxategi zaharra bezala, irakurri, garbitu eta kopiatu.
Begiratu fitxategiaren tamaina:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Fitxategiaren tamaina 19923457 da. Fitxategia garbitu nahian:
[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
Ikus dezakezunez, fitxategiaren tamaina handitzen da soilik eta gure enborrak ez zuen funtzionatu. Goazen sistema-deiari buruzko dokumentaziora
with open("123.txt", "w") as f:
jarri behar dugu
with open("123.txt", "a") as f:
"w" banderarekin egiaztatzen
[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
eta "a" banderarekin
[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
Dagoeneko martxan dagoen prozesu bat programatzea
Askotan, programa bat sortu eta probatzerakoan, programatzaileek araztaileak (adibidez, GDB) edo aplikazioan saioaren hainbat maila erabiltzen dituzte. Linux-ek dagoeneko martxan dagoen programa bat idazteko eta aldatzeko gaitasuna eskaintzen du, hala nola aldagaien balioak aldatzea, eten puntu bat ezartzea, eta abar.
Fitxategi bat idazteko diskoko leku faltari buruzko jatorrizko galderara itzuliz, saia gaitezen arazoa simulatzen.
Sortu dezagun fitxategi bat gure partiziorako, disko bereizi gisa muntatuko duguna:
[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 ~]$
Sortu dezagun fitxategi-sistema bat:
[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 ~]$
Munta dezagun fitxategi-sistema:
[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
Sortu direktorio bat gure jabearekin:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Ireki dezagun fitxategia gure programan soilik idazteko:
with open("/mnt/logs/123.txt", "w") as f:
korrika
[user@localhost ]$ python openforwrite.py
Segundo batzuk zain
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Beraz, artikulu honen hasieran deskribatutako arazoa lortu dugu. Espazio librea 0, %100 okupatua.
Gogoratzen dugu arazoaren baldintzen arabera, galdu ezin diren datu oso garrantzitsuak erregistratzen saiatzen ari garela. Eta horrela, zerbitzua konpondu behar dugu prozesua berrabiarazi gabe.
Demagun oraindik diskoan tokia dugula, baina beste partizio batean, adibidez, / homen.
Saia gaitezen gure kodea "berrantoan birprogramatzen".
Gure prozesuaren PID-a ikusten dugu, diskoko espazio guztia jan zuen:
[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
gdb-rekin prozesu batera konektatzen
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Fitxategi irekien deskribatzaileak aztertuko ditugu:
(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
Interesatzen zaigun 3. zenbakia duen fitxategi deskribatzaileari buruzko informazioa ikusten dugu
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Python-ek sistema-deiak zer egiten duen kontuan izanda (ikusi gorago non exekutatu dugun strace eta dei ireki bat aurkitu dugun), fitxategi bat irekitzeko gure kodea prozesatzen dugun bitartean, guk ere gauza bera egiten dugu gure prozesuaren izenean, baina O_WRONLY|O_CREAT| behar dugu. O_TRUNC bitek zenbakizko balio batekin ordezkatzen dute. Horretarako, ireki nukleoaren iturriak, adibidez
#defini O_WRONLY 00000001
#defini O_CREAT 00000100
#defini O_TRUNC 00001000
Balio guztiak bakar batean konbinatzen ditugu, 00001101 lortzen dugu
Gdb-tik gure deia exekutatzen
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Beraz, 4. zenbakia duen fitxategi deskribatzaile berri bat eta beste partizio batean irekitako fitxategi berri bat lortu dugu, egiaztatu:
(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
Pipe-rekin duen adibidea gogoratzen dugu: bash-ek fitxategien deskribatzaileak nola aldatzen dituen eta dagoeneko ikasi dugu dup2 sistema-deia.
Fitxategi deskribatzaile bat beste batekin ordezkatzen saiatzen
(gdb) call dup2(4,3)
$2 = 3
Egiaztatzen dugu:
(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
Itxi fitxategi deskribatzailea 4, ez dugulako behar:
(gdb) call close (4)
$1 = 0
Eta gdb irten
(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
Fitxategi berria egiaztatzen:
[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
Ikus dezakezunez, datuak fitxategi berri batean idazten dira, zaharra egiaztatuko dugu:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Datuak ez dira galtzen, aplikazioak funtzionatzen du, erregistroak kokapen berri batean idazten dira.
Egin ditzagun gauzak pixka bat zailago
Imajinatu datuak garrantzitsuak direla guretzat, baina ez daukagu ββdiskoko lekurik edozein partiziotan eta ezin dugu diskoa konektatu.
Egin dezakeguna gure datuak nonbaitera birbideratzea da, adibidez, kanalizazio batera, eta datuak kanaletik sarera birbideratzea programa batzuen bidez, netcat adibidez.
Izeneko kanalizazio bat sor dezakegu mkfifo komandoarekin. Fitxategi-sisteman sasi-fitxategi bat sortuko du, leku librerik ez badago ere.
Berrabiarazi aplikazioa eta egiaztatu:
[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
Ez dago diskoko lekurik, baina izendun kanalizazio bat sortuko dugu bertan:
[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
Orain hodi honetan sartzen diren datu guztiak sarearen bidez beste zerbitzari batera bildu behar ditugu nolabait, netcat bera egokia da horretarako.
remote-server.example.com zerbitzarian, exekutatu
[user@localhost ~]$ nc -l 7777 > 123.txt
Gure arazo-zerbitzarian, exekutatu beste terminal batean
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Orain kanalizazioan sartzen diren datu guztiak netcat-en stdin-era joango dira automatikoki, eta 7777 atakako sarera bidaliko ditu.
Egin behar duguna da gure datuak idazten hastea izendun hodi honetan.
Dagoeneko badugu aplikazio bat martxan:
[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
Bandera guztien artean, O_WRONLY baino ez dugu behar, fitxategia jada existitzen baita eta ez dugulako garbitu behar
[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
Urruneko zerbitzaria egiaztatzea remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Datuak iristen ari dira, arazoaren zerbitzaria egiaztatzen dugu
[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
Datuak gordetzen dira, arazoa konpondu da.
Aukera hau aprobetxatzen dut Degiroko lankideei agurtzeko.
Entzun Radio-T podcastak.
Ongi dena.
Etxeko lan gisa, katu eta lo prozesuaren fitxategi-deskribatzaileetan zer egongo den pentsatzea proposatzen dut komando hau exekutatzen baduzu:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Iturria: www.habr.com