Minsan, sa isang panayam, tinanong ako, ano ang gagawin mo kung makakita ka ng isang serbisyo na hindi gumagana dahil ang disk ay naubusan ng espasyo?
Syempre, sumagot ako na titingnan ko kung ano ang inookupahan ng lugar na ito at, kung maaari, lilinisin ko ang lugar.
Pagkatapos ay nagtanong ang tagapanayam, paano kung walang libreng espasyo sa partisyon, ngunit wala ka ring nakikitang anumang mga file na kukuha ng lahat ng espasyo?
Dito ko sinabi na maaari mong palaging tumingin sa mga open file descriptor, halimbawa sa lsof command, at maunawaan kung aling application ang kumuha ng lahat ng magagamit na espasyo, at pagkatapos ay maaari kang kumilos ayon sa mga pangyayari, depende sa kung ang data ay kinakailangan .
Pinutol ako ng tagapanayam sa huling salita, idinagdag sa kanyang tanong: "Ipagpalagay na hindi namin kailangan ang data, ito ay isang log ng debug lamang, ngunit ang application ay hindi gumagana dahil hindi ito makakasulat ng isang debug"?
"Okay," sagot ko, "maaari naming i-off ang debug sa application config at i-restart ito."
Ang tagapanayam ay tumutol: "Hindi, hindi namin mai-restart ang application, mayroon pa kaming mahalagang data na nakaimbak sa memorya, at ang mga mahahalagang kliyente ay konektado sa serbisyo mismo, na hindi namin mapipilit na muling kumonekta."
"okay," sabi ko, "kung hindi namin ma-restart ang application at ang data ay hindi mahalaga sa amin, pagkatapos ay maaari naming i-clear ang bukas na file na ito sa pamamagitan ng file descriptor, kahit na hindi namin ito nakikita sa ls command sa file system."
Natuwa ang tagapanayam, ngunit ako ay hindi.
Pagkatapos ay naisip ko, bakit hindi mas malalim ang paghuhukay ng taong sumusubok sa aking kaalaman? Ngunit paano kung ang data ay mahalaga pagkatapos ng lahat? Paano kung hindi namin ma-restart ang isang proseso, at ang proseso ay nagsusulat sa file system sa isang partisyon na walang libreng espasyo? Paano kung hindi lamang mawala ang data na naisulat na, kundi pati na rin ang data na isinusulat o sinusubukang isulat ng prosesong ito?
Tuzik
Sa unang bahagi ng aking karera, sinubukan kong lumikha ng isang maliit na application na kailangan upang mag-imbak ng impormasyon ng gumagamit. At pagkatapos ay naisip ko, paano ko maitugma ang gumagamit sa kanyang data. Halimbawa, mayroon akong Ivanov Ivan Ivanovich, at mayroon siyang ilang impormasyon, ngunit paano ako makikipagkaibigan sa kanila? Maaari kong direktang ituro na ang aso na pinangalanang "Tuzik" ay kabilang sa mismong Ivan na ito. Ngunit paano kung binago niya ang kanyang pangalan at sa halip na si Ivan ay naging, halimbawa, si Olya? Pagkatapos ay lalabas na ang aming Olya Ivanovna Ivanova ay hindi na magkakaroon ng aso, at ang aming Tuzik ay mapapabilang pa rin sa hindi umiiral na Ivan. Ang isang database na nagbigay sa bawat user ng natatanging identifier (ID) ay nakatulong sa paglutas ng problemang ito, at ang aking Tuzik ay nakatali sa ID na ito, na, sa katunayan, ay isang serial number lamang. Kaya, ang may-ari ng alas ay may ID number 2, at sa ilang sandali ay nasa ilalim ng ID na ito si Ivan, at pagkatapos ay si Olya ay nasa ilalim ng parehong ID. Ang problema ng sangkatauhan at pag-aalaga ng hayop ay praktikal na nalutas.
Deskriptor ng file
Ang problema ng file at ang program na gumagana sa file na ito ay humigit-kumulang kapareho ng sa aming aso at tao. Ipagpalagay na binuksan ko ang isang file na tinatawag na ivan.txt at sinimulan kong isulat ang salitang tuzik dito, ngunit pinamamahalaang isulat lamang ang unang titik na "t" sa file, at ang file na ito ay pinalitan ng pangalan ng isang tao, halimbawa, sa olya.txt. Ngunit ang file ay nananatiling pareho, at gusto ko pa ring i-record ang aking alas dito. Sa tuwing magbubukas ang isang file sa pamamagitan ng isang system call
Sa Linux, ang libc library ay nagbubukas ng 3 descriptor file para sa bawat tumatakbong application (proseso), na may bilang na 0,1,2. Higit pang impormasyon ay matatagpuan sa mga link
- Ang file descriptor 0 ay tinatawag na STDIN at nauugnay sa input ng application
- Ang file descriptor 1 ay tinatawag na STDOUT at ginagamit ng mga application para mag-output ng data, gaya ng mga print command
- Ang file descriptor 2 ay tinatawag na STDERR at ginagamit ng mga application upang mag-output ng mga mensahe ng error.
Kung sa iyong programa ay nagbukas ka ng anumang file para sa pagbabasa o pagsusulat, malamang na makukuha mo ang unang libreng ID at ito ay magiging numero 3.
Maaaring tingnan ang listahan ng mga deskriptor ng file para sa anumang proseso kung alam mo ang PID nito.
Halimbawa, buksan natin ang bash console at tingnan ang PID ng ating proseso
[user@localhost ]$ echo $$
15771
Sa pangalawang console, tumakbo tayo
[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
Maaari mong ligtas na balewalain ang file descriptor number 255 para sa mga layunin ng artikulong ito; ito ay binuksan para sa mga pangangailangan nito sa pamamagitan ng bash mismo, at hindi ng naka-link na library.
Ngayon lahat ng 3 descriptor file ay nauugnay sa pseudo terminal device
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
At sa unang console makikita natin
[user@localhost ]$ hello world
I-redirect at Pipe
Madali mong ma-override ang 3 descriptor file na ito sa anumang proseso, kasama ang bash, halimbawa sa pamamagitan ng pipe na nagkokonekta sa dalawang proseso, tingnan
[user@localhost ]$ cat /dev/zero | sleep 10000
Maaari mong patakbuhin ang utos na ito sa iyong sarili guhit -f at tingnan kung ano ang nangyayari sa loob, ngunit sasabihin ko sa iyo nang maikli.
Pino-parse ng aming parent bash na proseso sa PID 15771 ang aming command at eksaktong nauunawaan kung gaano karaming mga command ang gusto naming patakbuhin, sa aming kaso, dalawa sa mga ito: pusa at pagtulog. Alam ng Bash na kailangan nitong lumikha ng dalawang proseso ng bata, at pagsamahin ang mga ito sa isang tubo. Sa kabuuan, kakailanganin ng bash ang 2 proseso ng bata at isang pipe.
Ang Bash ay nagpapatakbo ng isang tawag sa system bago gumawa ng mga proseso ng bata
Para sa proseso ng magulang, mukhang mayroon nang pipe, ngunit wala pang mga proseso ng bata:
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
Pagkatapos ay gamit ang system call
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
Huwag kalimutan na clone clone ang proseso kasama ang lahat ng file descriptors, kaya sila ay pareho sa proseso ng magulang at sa mga bata. Ang trabaho ng proseso ng magulang sa PID 15771 ay subaybayan ang mga proseso ng bata, kaya naghihintay lang ito ng tugon mula sa mga bata.
Samakatuwid, hindi nito kailangan ng pipe, at isinasara nito ang mga deskriptor ng file na may bilang na 3 at 4.
Sa unang proseso ng child bash sa PID 9004, ang system call
Sa pangalawang proseso ng bata na may PID 9005, ang bash ay gumagamit ng dup2 para baguhin ang file descriptor STDIN number 0. Ngayon lahat ng mababasa ng aming pangalawang bash na may PID 9005 ay mababasa mula sa pipe.
Pagkatapos nito, ang mga file descriptor na may bilang na 3 at 4 ay sarado din sa mga proseso ng bata, dahil hindi na ginagamit ang mga ito.
Sinadya kong balewalain ang file descriptor 255; ito ay ginagamit para sa mga panloob na layunin ng bash mismo at isasara din sa mga proseso ng bata.
Susunod, sa unang proseso ng bata na may PID 9004, ang bash ay magsisimulang gumamit ng system call
Sa pangalawang proseso ng bata na may PID 9005, pinapatakbo ng bash ang pangalawang executable na tinukoy namin, sa aming kaso /usr/bin/sleep.
Hindi isinasara ng exec system call ang mga file handle maliban kung binuksan ang mga ito gamit ang O_CLOEXEC flag sa oras na ginawa ang bukas na tawag. Sa aming kaso, pagkatapos ilunsad ang mga executable na file, ang lahat ng kasalukuyang file descriptor ay mase-save.
Tingnan sa console:
[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
Tulad ng nakikita mo, ang natatanging bilang ng aming pipe ay pareho sa parehong mga proseso. Kaya mayroon kaming koneksyon sa pagitan ng dalawang magkaibang proseso na may parehong magulang.
Para sa mga hindi pamilyar sa mga tawag sa system na ginagamit ng bash, lubos kong inirerekumenda na patakbuhin ang mga utos sa pamamagitan ng strace at makita kung ano ang nangyayari sa loob, halimbawa tulad nito:
strace -s 1024 -f bash -c "ls | grep hello"
Bumalik tayo sa aming problema sa mababang espasyo sa disk at sinusubukang i-save ang data nang hindi na-restart ang proseso. Sumulat tayo ng isang maliit na programa na magsusulat ng humigit-kumulang 1 megabyte bawat segundo sa disk. Bukod dito, kung sa ilang kadahilanan ay hindi kami nakapagsulat ng data sa disk, babalewalain lang namin ito at susubukan naming isulat muli ang data sa isang segundo. Sa halimbawang ginagamit ko ang Python, maaari kang gumamit ng anumang iba pang programming language.
[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
Patakbuhin natin ang programa at tingnan ang mga deskriptor ng file
[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
Gaya ng nakikita mo, mayroon kaming 3 karaniwang file descriptor at isa pa na binuksan namin. Suriin natin ang laki ng file:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
Sinusulat ang data, sinusubukan naming baguhin ang mga pahintulot sa file:
[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
Nakikita namin na ang data ay isinusulat pa rin, kahit na ang aming user ay walang pahintulot na magsulat sa file. Subukan nating tanggalin ito:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Saan nakasulat ang datos? At nakasulat ba ang mga ito? Sinusuri namin:
[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)
Oo, umiiral pa rin ang aming file descriptor at maaari naming ituring ang file descriptor na ito tulad ng aming lumang file, maaari naming basahin, i-clear at kopyahin ito.
Tingnan natin ang laki ng file:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Ang laki ng file ay 19923457. Subukan nating i-clear ang file:
[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
Tulad ng nakikita mo, ang laki ng file ay tumataas lamang at ang aming trunk ay hindi gumana. Tingnan natin ang dokumentasyon ng system call
with open("123.txt", "w") as f:
kailangan nating ilagay
with open("123.txt", "a") as f:
Pagsusuri gamit ang bandilang "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
at may bandilang "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
Pagprograma ng tumatakbo nang proseso
Kadalasan, ang mga programmer, kapag gumagawa at sumusubok ng mga program, ay gumagamit ng mga debugger (halimbawa, GDB) o iba't ibang antas ng pag-log in sa application. Nagbibigay ang Linux ng kakayahang aktwal na magsulat at magbago ng tumatakbo nang programa, halimbawa, baguhin ang mga halaga ng mga variable, magtakda ng breakpoint, atbp., atbp.
Pagbabalik sa orihinal na tanong tungkol sa hindi sapat na espasyo sa disk para magsulat ng file, subukan nating gayahin ang problema.
Gumawa tayo ng file para sa ating partition, na ilalagay natin bilang hiwalay na disk:
[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 ~]$
Gumawa tayo ng file system:
[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 ~]$
I-mount ang file system:
[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
Lumilikha kami ng isang direktoryo kasama ang aming may-ari:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Buksan natin ang file para sa pagsusulat lamang sa aming programa:
with open("/mnt/logs/123.txt", "w") as f:
Ilunsad
[user@localhost ]$ python openforwrite.py
Naghintay kami ng ilang segundo
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Kaya, mayroon kaming problema na inilarawan sa simula ng artikulong ito. Libreng espasyo 0, 100% occupied.
Naaalala namin na ayon sa mga kondisyon ng gawain, sinusubukan naming i-record ang napakahalagang data na hindi maaaring mawala. At sa parehong oras, kailangan naming ayusin ang serbisyo nang hindi na-restart ang proseso.
Sabihin nating mayroon pa rin tayong espasyo sa disk, ngunit sa ibang partition, halimbawa sa /home.
Subukan nating "reprogram on the fly" ang aming code.
Tingnan natin ang PID ng aming proseso, na kinain ang lahat ng espasyo sa disk:
[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
Kumonekta sa proseso sa pamamagitan ng gdb
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Tingnan natin ang bukas na mga deskriptor ng file:
(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
Tinitingnan namin ang impormasyon tungkol sa file descriptor number 3, na interesado sa amin
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Isinasaisip kung ano ang system call na ginagawa ng Python (tingnan sa itaas kung saan kami nagpatakbo ng strace at natagpuan ang bukas na tawag), kapag pinoproseso ang aming code upang magbukas ng file, ginagawa namin ang parehong sa ngalan ng aming proseso, ngunit kailangan namin ang O_WRONLY|O_CREAT| Ang mga O_TRUNC bit ay pinapalitan ng isang numeric na halaga. Upang gawin ito, buksan ang mga mapagkukunan ng kernel, halimbawa
#define O_WRONLY 00000001
#define O_CREAT 00000100
#define O_TRUNC 00001000
Pinagsasama namin ang lahat ng mga halaga sa isa, nakakakuha kami ng 00001101
Pinapatakbo namin ang aming tawag mula sa gdb
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Kaya nakakuha kami ng bagong file descriptor na may numero 4 at isang bagong bukas na file sa isa pang partition, sinusuri namin:
(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
Naaalala namin ang halimbawa sa pipe - kung paano binabago ng bash ang mga deskriptor ng file, at natutunan na namin ang dup2 system call.
Sinusubukan naming palitan ang isang file descriptor ng isa pa
(gdb) call dup2(4,3)
$2 = 3
Namin suriin:
(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
Isinasara namin ang file descriptor 4, dahil hindi namin ito kailangan:
(gdb) call close (4)
$1 = 0
At lumabas sa 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
Sinusuri ang bagong file:
[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
Tulad ng nakikita mo, ang data ay nakasulat sa isang bagong file, tingnan natin ang luma:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Walang nawala na data, gumagana ang application, isinulat ang mga log sa isang bagong lokasyon.
Medyo gawing kumplikado ang gawain
Isipin natin na ang data ay mahalaga sa amin, ngunit wala kaming puwang sa disk sa alinman sa mga partisyon at hindi namin maikonekta ang disk.
Ang magagawa namin ay i-redirect ang aming data sa isang lugar, halimbawa sa pipe, at sa turn ay i-redirect ang data mula sa pipe patungo sa network sa pamamagitan ng ilang programa, halimbawa netcat.
Maaari tayong lumikha ng pinangalanang pipe na may mkfifo command. Ito ay lilikha ng isang pseudo file sa file system kahit na walang libreng espasyo dito.
I-restart ang application at suriin:
[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
Walang puwang sa disk, ngunit matagumpay kaming lumikha ng pinangalanang pipe doon:
[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
Ngayon kailangan nating ibalot ang lahat ng data na pumapasok sa pipe na ito sa isa pang server sa pamamagitan ng network; ang parehong netcat ay angkop para dito.
Sa server remote-server.example.com kami ay tumatakbo
[user@localhost ~]$ nc -l 7777 > 123.txt
Sa aming may problemang server naglulunsad kami sa isang hiwalay na terminal
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Ngayon ang lahat ng data na nagtatapos sa pipe ay awtomatikong mapupunta sa stdin sa netcat, na magpapadala nito sa network sa port 7777.
Ang kailangan lang nating gawin ay simulan ang pagsulat ng ating data sa pinangalanang pipe na ito.
Mayroon na kaming tumatakbong application:
[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
Sa lahat ng mga flag, O_WRONLY lang ang kailangan namin dahil umiiral na ang file at hindi na namin kailangang i-clear ito
[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
Sinusuri ang remote server remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Darating ang data, sinusuri namin ang server ng problema
[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
Ang data ay nai-save, ang problema ay nalutas.
Sinasamantala ko ang pagkakataong ito para kumustahin ang aking mga kasamahan mula sa Degiro.
Makinig sa mga podcast ng Radio-T.
Mabuti sa lahat.
Bilang araling-bahay, iminumungkahi kong isipin mo kung ano ang magiging proseso ng mga deskriptor ng file na pusa at pagtulog kung patakbuhin mo ang sumusunod na utos:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Pinagmulan: www.habr.com