Reiz intervijas laikÄ man jautÄja, ko jÅ«s darÄ«siet, ja atklÄsiet, ka kÄds pakalpojums nedarbojas, jo diskÄ ir beigusies vieta?
Protams, es atbildÄju, ka paskatÄ«Å”os, ko Ŕī vieta aizÅem, un, ja iespÄjams, uzkopÅ”u vietu.
PÄc tam intervÄtÄjs jautÄja, kÄ bÅ«tu, ja nodalÄ«jumÄ nav brÄ«vas vietas, bet jÅ«s arÄ« neredzat nevienu failu, kas aizÅemtu visu vietu?
Uz to es teicu, ka vienmÄr var apskatÄ«t atvÄrto failu deskriptorus, piemÄram, ar komandu lsof, un saprast, kura lietojumprogramma ir aizÅÄmusi visu pieejamo vietu, un tad var rÄ«koties atbilstoÅ”i apstÄkļiem, atkarÄ«bÄ no tÄ, vai dati ir nepiecieÅ”ami. .
IntervÄtÄjs mani pÄrtrauca uz pÄdÄjo vÄrdu, papildinot savu jautÄjumu: "PieÅemsim, ka mums nav vajadzÄ«gi dati, tas ir tikai atkļūdoÅ”anas žurnÄls, bet lietojumprogramma nedarbojas, jo tÄ nevar uzrakstÄ«t atkļūdoÅ”anu"?
"Labi," es atbildÄju, "mÄs varam izslÄgt atkļūdoÅ”anu lietojumprogrammas konfigurÄcijÄ un restartÄt."
IntervÄtÄjs iebilda: "NÄ, mÄs nevaram restartÄt lietojumprogrammu, mums joprojÄm ir svarÄ«gi dati, kas glabÄjas atmiÅÄ, un svarÄ«gi klienti ir savienoti ar paÅ”u pakalpojumu, kuru mÄs nevaram piespiest atkÄrtoti savienot."
"Labi," es teicu, "ja mÄs nevaram restartÄt lietojumprogrammu un dati mums nav svarÄ«gi, mÄs varam vienkÄrÅ”i notÄ«rÄ«t Å”o atvÄrto failu, izmantojot faila deskriptoru, pat ja mÄs to neredzam komandÄ ls failu sistÄmÄ."
IntervÄtÄjs bija apmierinÄts, bet es nÄ.
Tad es domÄju, kÄpÄc cilvÄks, kurÅ” pÄrbauda manas zinÄÅ”anas, neiedziļinÄs? Bet ko darÄ«t, ja dati tomÄr ir svarÄ«gi? Ko darÄ«t, ja mÄs nevaram restartÄt procesu un process ieraksta failu sistÄmu nodalÄ«jumÄ, kurÄ nav brÄ«vas vietas? Ko darÄ«t, ja mÄs nevaram zaudÄt ne tikai jau ierakstÄ«tos datus, bet arÄ« datus, kurus Å”is process raksta vai mÄÄ£ina rakstÄ«t?
Tuzik
Savas karjeras sÄkumÄ es mÄÄ£inÄju izveidot nelielu lietojumprogrammu, kurÄ bija jÄglabÄ lietotÄja informÄcija. Un tad es domÄju, kÄ es varu saskaÅot lietotÄju ar viÅa datiem. PiemÄram, man ir Ivanovs Ivans IvanoviÄs, un viÅam ir zinÄma informÄcija, bet kÄ es varu ar viÅiem sadraudzÄties? Varu tieÅ”i norÄdÄ«t, ka suns vÄrdÄ āTuzikā pieder tieÅ”i Å”im Ivanam. Bet ja viÅÅ” maina vÄrdu un Ivana vietÄ kļūst, piemÄram, Olja? Tad izrÄdÄ«sies, ka mÅ«su Oļai Ivanovnai Ivanovai vairs nebÅ«s suÅa, un mÅ«su Tuziks joprojÄm piederÄs neesoÅ”ajam Ivanam. DatubÄze, kas katram lietotÄjam pieŔķīra unikÄlu identifikatoru (ID), palÄ«dzÄja atrisinÄt Å”o problÄmu, un mans Tuzik tika piesaistÄ«ts Å”im ID, kas patiesÄ«bÄ bija tikai sÄrijas numurs. TÄdÄjÄdi dūža Ä«paÅ”niekam bija ID numurs 2, un kÄdÄ brÄ«dÄ« Ivans atradÄs ar Å”o ID, un tad Olya kļuva ar to paÅ”u ID. CilvÄces un lopkopÄ«bas problÄma tika praktiski atrisinÄta.
Faila deskriptors
Faila un programmas, kas darbojas ar Å”o failu, problÄma ir aptuveni tÄda pati kÄ mÅ«su sunim un cilvÄkam. PieÅemsim, ka es atvÄru failu ar nosaukumu ivan.txt un sÄku tajÄ rakstÄ«t vÄrdu tuzik, bet failÄ paspÄju ierakstÄ«t tikai pirmo burtu ātā, un kÄds Å”o failu pÄrdÄvÄja, piemÄram, par olya.txt. Bet fails paliek nemainÄ«gs, un es joprojÄm gribu tajÄ ierakstÄ«t savu dÅ«zi. Katru reizi, kad fails tiek atvÄrts ar sistÄmas zvanu
OperÄtÄjsistÄmÄ Linux libc bibliotÄka atver 3 deskriptorus katrai lietojumprogrammai (procesam), kas numurÄtas ar 0,1,2. VairÄk informÄcijas var atrast saitÄs
- Faila deskriptors 0 tiek saukts par STDIN un ir saistīts ar lietojumprogrammas ievadi
- Faila deskriptors 1 tiek saukts par STDOUT, un lietojumprogrammas to izmanto, lai izvadÄ«tu datus, piemÄram, drukÄÅ”anas komandas
- Faila deskriptors 2 tiek saukts par STDERR, un lietojumprogrammas to izmanto kļūdu ziÅojumu izvadÄ«Å”anai.
Ja programmÄ atverat kÄdu failu lasÄ«Å”anai vai rakstÄ«Å”anai, visticamÄk, jÅ«s iegÅ«sit pirmo bezmaksas ID, un tas bÅ«s 3. numurs.
Failu deskriptoru sarakstu var skatÄ«t jebkuram procesam, ja zinÄt tÄ PID.
PiemÄram, atveram bash konsoli un apskatÄ«sim mÅ«su procesa PID
[user@localhost ]$ echo $$
15771
OtrajÄ pultÄ« palaist
[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
Å Ä« raksta vajadzÄ«bÄm varat droÅ”i ignorÄt faila deskriptora numuru 255; to savÄm vajadzÄ«bÄm atvÄra pats bash, nevis saistÄ«tÄ bibliotÄka.
Tagad visi 3 deskriptora faili ir saistÄ«ti ar pseidoterminÄļa ierÄ«ci
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
Un pirmajÄ konsolÄ mÄs redzÄsim
[user@localhost ]$ hello world
Redirect un Pipe
JÅ«s varat viegli ignorÄt Å”os 3 deskriptora failus jebkurÄ procesÄ, ieskaitot bash, piemÄram, caur cauruli, kas savieno divus procesus, sk.
[user@localhost ]$ cat /dev/zero | sleep 10000
Å o komandu var palaist pats ar strace -f un redzÄt, kas notiek iekÅ”Ä, bet es jums pastÄstÄ«Å”u Ä«si.
MÅ«su vecÄku bash process ar PID 15771 parsÄ mÅ«su komandu un precÄ«zi saprot, cik komandu mÄs vÄlamies palaist. MÅ«su gadÄ«jumÄ tÄs ir divas: kaÄ·is un miegs. BaÅ”s zina, ka tam ir jÄizveido divi pakÄrtotie procesi un jÄapvieno tie vienÄ caurulÄ. KopumÄ bash bÅ«s nepiecieÅ”ami 2 bÄrnu procesi un viena caurule.
Pirms pakÄrtoto procesu izveides Bash izpilda sistÄmas izsaukumu
Å Ä·iet, ka vecÄku procesam jau ir caurule, bet vÄl nav neviena pakÄrtota procesa:
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
PÄc tam izmantojiet sistÄmas zvanu
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
Neaizmirstiet, ka klons klonÄ procesu kopÄ ar visiem failu deskriptoriem, tÄpÄc tie bÅ«s vienÄdi vecÄkprocesÄ un pakÄrtotajos procesos. VecÄku procesa uzdevums ar PID 15771 ir uzraudzÄ«t bÄrna procesus, tÄpÄc tas vienkÄrÅ”i gaida atbildi no bÄrniem.
TÄpÄc tai nav nepiecieÅ”ama caurule, un tas aizver failu deskriptorus ar numuru 3 un 4.
PirmajÄ pakÄrtotajÄ bash procesÄ ar PID 9004 sistÄmas izsaukums
OtrajÄ pakÄrtotajÄ procesÄ ar PID 9005 bash izmanto dup2, lai mainÄ«tu faila deskriptora STDIN numuru 0. Tagad viss, ko nolasÄ«s mÅ«su otrais bash ar PID 9005, tiks nolasÄ«ts no caurules.
PÄc tam 3. un 4. failu deskriptori tiek aizvÄrti arÄ« bÄrnprocesos, jo tie vairs netiek izmantoti.
Es apzinÄti ignorÄju faila deskriptoru 255; to iekÅ”Äjiem nolÅ«kiem izmanto pats bash, un tas tiks aizvÄrts arÄ« bÄrnu procesos.
PÄc tam pirmajÄ pakÄrtotajÄ procesÄ ar PID 9004 bash sÄk izmantot sistÄmas zvanu
OtrajÄ pakÄrtotajÄ procesÄ ar PID 9005 bash palaiž otro mÅ«su norÄdÄ«to izpildÄmo failu, mÅ«su gadÄ«jumÄ /usr/bin/sleep.
Exec sistÄmas izsaukums neaizver failu rokturus, ja vien tie nav atvÄrti ar karogu O_CLOEXEC, kad tika veikts atvÄrtais zvans. MÅ«su gadÄ«jumÄ pÄc izpildÄmo failu palaiÅ”anas tiks saglabÄti visi paÅ”reizÄjie failu deskriptori.
PÄrbaudiet konsolÄ:
[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
KÄ redzat, mÅ«su caurules unikÄlais numurs ir vienÄds abos procesos. TÄdÄjÄdi mums ir saikne starp diviem dažÄdiem procesiem ar vienu un to paÅ”u vecÄku.
Tiem, kas nav pazÄ«stami ar sistÄmas izsaukumiem, ko izmanto bash, es ļoti iesaku palaist komandas caur strace un redzÄt, kas notiek iekÅ”Äji, piemÄram, Å”Ädi:
strace -s 1024 -f bash -c "ls | grep hello"
AtgriezÄ«simies pie problÄmas ar maz vietas diskÄ un mÄÄ£inÄjumu saglabÄt datus, nerestartÄjot procesu. UzrakstÄ«sim nelielu programmu, kas diskÄ ierakstÄ«s aptuveni 1 megabaitu sekundÄ. TurklÄt, ja kÄda iemesla dÄļ mÄs nevarÄjÄm ierakstÄ«t datus diskÄ, mÄs to vienkÄrÅ”i ignorÄsim un mÄÄ£inÄsim rakstÄ«t datus vÄlreiz pÄc sekundes. PiemÄrÄ, kurÄ izmantoju Python, varat izmantot jebkuru citu programmÄÅ”anas valodu.
[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
Palaidīsim programmu un apskatīsim failu deskriptorus
[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
KÄ redzat, mums ir 3 standarta failu deskriptori un vÄl viens, ko mÄs atvÄrÄm. PÄrbaudÄ«sim faila lielumu:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
Dati tiek rakstÄ«ti, mÄs cenÅ”amies mainÄ«t faila atļaujas:
[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
MÄs redzam, ka dati joprojÄm tiek rakstÄ«ti, lai gan mÅ«su lietotÄjam nav atļaujas rakstÄ«t failÄ. MÄÄ£inÄsim to noÅemt:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Kur ir rakstÄ«ti dati? Un vai tie vispÄr ir rakstÄ«ti? MÄs pÄrbaudÄm:
[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)
JÄ, mÅ«su faila deskriptors joprojÄm pastÄv, un mÄs varam izturÄties pret Å”o faila deskriptoru kÄ mÅ«su veco failu, mÄs varam to lasÄ«t, notÄ«rÄ«t un kopÄt.
Apskatīsim faila lielumu:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Faila lielums ir 19923457. MÄÄ£inÄsim notÄ«rÄ«t failu:
[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
KÄ redzat, faila lielums tikai palielinÄs, un mÅ«su bagÄžnieks nedarbojÄs. ApskatÄ«sim sistÄmas izsaukuma dokumentÄciju
with open("123.txt", "w") as f:
mums ir jÄliek
with open("123.txt", "a") as f:
PÄrbaude ar āwā karogu
[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
un ar "a" karogu
[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
Jau notiekoÅ”a procesa programmÄÅ”ana
Bieži vien programmÄtÄji, veidojot un testÄjot programmas, lieto atkļūdotÄjus (piemÄram, GDB) vai dažÄdu lÄ«meÅu reÄ£istrÄÅ”anu aplikÄcijÄ. Linux nodroÅ”ina iespÄju faktiski rakstÄ«t un mainÄ«t jau darbojoÅ”os programmu, piemÄram, mainÄ«t mainÄ«go vÄrtÄ«bas, iestatÄ«t pÄrtraukuma punktu utt., utt.
Atgriežoties pie sÄkotnÄjÄ jautÄjuma par diskÄ nepietiek vietas faila rakstÄ«Å”anai, mÄÄ£inÄsim simulÄt problÄmu.
Izveidosim failu savam nodalÄ«jumam, kuru pievienosim kÄ atseviŔķu disku:
[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 ~]$
Izveidosim failu sistÄmu:
[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 ~]$
Pievienojiet failu sistÄmu:
[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
MÄs izveidojam direktoriju ar mÅ«su Ä«paÅ”nieku:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
AtvÄrsim failu rakstÄ«Å”anai tikai mÅ«su programmÄ:
with open("/mnt/logs/123.txt", "w") as f:
Palaist
[user@localhost ]$ python openforwrite.py
MÄs gaidÄm dažas sekundes
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
TÄtad, mums ir Ŕī raksta sÄkumÄ aprakstÄ«tÄ problÄma. BrÄ«vÄ vieta 0, 100% aizÅemta.
MÄs atceramies, ka saskaÅÄ ar uzdevuma nosacÄ«jumiem mÄs cenÅ”amies ierakstÄ«t ļoti svarÄ«gus datus, kurus nevar pazaudÄt. Un tajÄ paÅ”Ä laikÄ mums ir jÄlabo pakalpojums, nerestartÄjot procesu.
PieÅemsim, ka mums joprojÄm ir diska vietas, bet citÄ nodalÄ«jumÄ, piemÄram, /home.
MÄÄ£inÄsim āpÄrprogrammÄt lidojumÄā mÅ«su kodu.
ApskatÄ«sim mÅ«su procesa PID, kas ir paÅÄmis visu diska vietu:
[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
Pievienojieties procesam, izmantojot gdb
[user@localhost ~]$ gdb -p 10078
...
(gdb)
ApskatÄ«sim atvÄrto failu deskriptorus:
(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
MÄs aplÅ«kojam informÄciju par faila deskriptora numuru 3, kas mÅ«s interesÄ
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Paturot prÄtÄ Python sistÄmas izsaukumu (skatiet iepriekÅ”, kur mÄs palaidÄm strace un atradÄm atvÄrto zvanu), apstrÄdÄjot kodu, lai atvÄrtu failu, mÄs paÅ”i darÄm to paÅ”u sava procesa vÄrdÄ, taÄu mums ir nepiecieÅ”ams O_WRONLY|O_CREAT| O_TRUNC biti tiek aizstÄti ar skaitlisku vÄrtÄ«bu. Lai to izdarÄ«tu, atveriet, piemÄram, kodola avotus
#define O_WRONLY 00000001
#define O_CREAT 00000100
#define O_TRUNC 00001000
MÄs apvienojam visas vÄrtÄ«bas vienÄ, iegÅ«stam 00001101
MÄs veicam zvanu no gdb
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
TÄtad mÄs saÅÄmÄm jaunu faila deskriptoru ar numuru 4 un jaunu atvÄrtu failu citÄ nodalÄ«jumÄ, mÄs pÄrbaudÄm:
(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
MÄs atceramies piemÄru ar pipe - kÄ bash maina failu deskriptorus, un mÄs jau esam iemÄcÄ«juÅ”ies dup2 sistÄmas zvanu.
MÄs cenÅ”amies aizstÄt vienu faila deskriptoru ar citu
(gdb) call dup2(4,3)
$2 = 3
PÄrbaude:
(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
MÄs aizveram faila deskriptoru 4, jo mums tas nav nepiecieÅ”ams:
(gdb) call close (4)
$1 = 0
Un iziet no 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
JaunÄ faila pÄrbaude:
[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
KÄ redzat, dati tiek ierakstÄ«ti jaunÄ failÄ, pÄrbaudÄ«sim veco:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Dati netiek zaudÄti, aplikÄcija darbojas, žurnÄli tiek rakstÄ«ti uz jaunu vietu.
Nedaudz sarežģīsim uzdevumu
IedomÄsimies, ka dati mums ir svarÄ«gi, bet mums nav diska vietas nevienÄ no nodalÄ«jumiem un mÄs nevaram pieslÄgt disku.
Tas, ko mÄs varam darÄ«t, ir novirzÄ«t savus datus kaut kur, piemÄram, uz cauruli, un savukÄrt pÄradresÄt datus no caurules uz tÄ«klu, izmantojot kÄdu programmu, piemÄram, netcat.
MÄs varam izveidot nosauktu cauruli ar komandu mkfifo. Tas failu sistÄmÄ izveidos pseido failu pat tad, ja tajÄ nav brÄ«vas vietas.
RestartÄjiet lietojumprogrammu un pÄrbaudiet:
[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
DiskÄ nav vietas, taÄu mÄs tur veiksmÄ«gi izveidojam nosauktu cauruli:
[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
Tagad mums ir kaut kÄ jÄiesaiÅo visi dati, kas nonÄk Å”ajÄ caurulÄ, citÄ serverÄ«, izmantojot tÄ«klu; tam ir piemÄrots tas pats netcat.
MÄs palaižam serverÄ« remote-server.example.com
[user@localhost ~]$ nc -l 7777 > 123.txt
MÅ«su problemÄtiskajÄ serverÄ« mÄs palaižam to atseviÅ”Ä·Ä terminÄlÄ
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Tagad visi dati, kas nonÄk caurulÄ, automÄtiski tiks novirzÄ«ti uz stdin in netcat, kas tos nosÅ«tÄ«s uz tÄ«klu portÄ 7777.
Viss, kas mums jÄdara, ir sÄkt rakstÄ«t savus datus Å”ajÄ nosauktajÄ caurulÄ.
Mums jau darbojas lietojumprogramma:
[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
No visiem karodziÅiem mums ir nepiecieÅ”ams tikai O_WRONLY, jo fails jau pastÄv un mums tas nav jÄdzÄÅ”.
[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
PÄrbauda attÄlo serveri remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Dati nÄk, mÄs pÄrbaudÄm problÄmas serveri
[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
Dati ir saglabÄti, problÄma ir atrisinÄta.
Es izmantoju Å”o iespÄju, lai sveiktu savus kolÄÄ£us no Degiro.
Klausieties Radio-T aplÄdes.
Labi visiem.
KÄ mÄjasdarbu iesaku padomÄt par to, kas bÅ«s procesa faila deskriptoros cat and sleep, ja izpildÄ«siet Å”Ädu komandu:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Avots: www.habr.com