Mara moja, wakati wa mahojiano, niliulizwa, utafanya nini ikiwa unapata huduma haifanyi kazi kutokana na ukweli kwamba disk imekwisha nafasi?
Bila shaka, nilijibu kwamba nitaona kilichokaliwa na mahali hapa na, ikiwezekana, ningesafisha mahali hapo.
Kisha mhojiwaji akauliza, je, ikiwa hakuna nafasi ya bure kwenye kizigeu, lakini pia huoni faili zozote ambazo zitachukua nafasi yote?
Kwa hili nilisema kwamba unaweza kutazama maelezo ya faili wazi kila wakati, kwa mfano na lsof amri, na kuelewa ni programu gani imechukua nafasi yote inayopatikana, na kisha unaweza kuchukua hatua kulingana na hali, kulingana na ikiwa data inahitajika. .
Mhojiwa alinizuia kwa neno la mwisho, akiongeza kwa swali lake: "Tuseme hatuhitaji data, ni logi ya utatuzi tu, lakini programu haifanyi kazi kwa sababu haiwezi kuandika utatuzi"?
"Sawa," nilijibu, "tunaweza kuzima utatuzi katika usanidi wa programu na kuianzisha tena."
Mhojiwa alipinga: "Hapana, hatuwezi kuanzisha upya programu, bado tuna data muhimu iliyohifadhiwa kwenye kumbukumbu, na wateja muhimu wameunganishwa kwenye huduma yenyewe, ambayo hatuwezi kulazimisha kuunganisha tena."
"sawa," nilisema, "ikiwa hatuwezi kuanzisha tena programu na data sio muhimu kwetu, basi tunaweza kufuta faili hii wazi kupitia maelezo ya faili, hata ikiwa hatuioni kwenye ls amri. kwenye mfumo wa faili."
Mhojiwa alifurahi, lakini sikufurahi.
Kisha nikafikiria, kwa nini mtu anayejaribu ujuzi wangu asichimbue zaidi? Lakini vipi ikiwa data ni muhimu baada ya yote? Je, ikiwa hatuwezi kuanzisha upya mchakato, na mchakato unaandika kwa mfumo wa faili kwenye kizigeu ambacho hakina nafasi ya bure? Je, ikiwa hatuwezi kupoteza sio tu data ambayo tayari imeandikwa, lakini pia data ambayo mchakato huu unaandika au unajaribu kuandika?
Tuzik
Mapema katika kazi yangu, nilijaribu kuunda programu ndogo ambayo inahitajika kuhifadhi maelezo ya mtumiaji. Na kisha nikafikiria, ninawezaje kulinganisha mtumiaji na data yake. Kwa mfano, nina Ivanov Ivan Ivanovich, na ana habari fulani, lakini ninawezaje kufanya urafiki nao? Ninaweza kusema moja kwa moja kwamba mbwa anayeitwa "Tuzik" ni wa Ivan huyu sana. Lakini vipi ikiwa atabadilisha jina lake na badala ya Ivan inakuwa, kwa mfano, Olya? Kisha itakuwa kwamba Olya Ivanovna Ivanova wetu hatakuwa na mbwa tena, na Tuzik yetu bado itakuwa ya Ivan ambaye hayupo. Hifadhidata ambayo ilimpa kila mtumiaji kitambulisho cha kipekee (Kitambulisho) kilisaidia kutatua tatizo hili, na Tuzik yangu iliunganishwa na kitambulisho hiki, ambacho, kwa kweli, kilikuwa nambari ya serial tu. Kwa hivyo, mmiliki wa ace alikuwa na nambari ya kitambulisho 2, na wakati fulani Ivan alikuwa chini ya kitambulisho hiki, na kisha Olya akawa chini ya kitambulisho sawa. Tatizo la ubinadamu na ufugaji lilitatuliwa kivitendo.
Kifafanuzi cha faili
Tatizo la faili na programu inayofanya kazi na faili hii ni takriban sawa na ile ya mbwa wetu na mwanadamu. Tuseme nilifungua faili inayoitwa ivan.txt na kuanza kuandika neno tuzik ndani yake, lakini niliweza tu kuandika barua ya kwanza "t" kwenye faili, na faili hii iliitwa jina na mtu, kwa mfano, kwa olya.txt. Lakini faili inabakia sawa, na bado nataka kurekodi ace yangu ndani yake. Kila wakati faili inafunguliwa na simu ya mfumo
Katika Linux, maktaba ya libc hufungua faili 3 za maelezo kwa kila programu inayoendesha (mchakato), yenye nambari 0,1,2. Habari zaidi inaweza kupatikana kwenye viungo
- Maelezo ya faili 0 inaitwa STDIN na inahusishwa na uingizaji wa programu
- Kifafanuzi cha faili 1 kinaitwa STDOUT na hutumiwa na programu kutoa data, kama vile maagizo ya kuchapisha
- Kifafanuzi cha faili 2 kinaitwa STDERR na hutumiwa na programu kutoa ujumbe wa makosa.
Ikiwa katika programu yako utafungua faili yoyote ya kusoma au kuandika, basi uwezekano mkubwa utapata kitambulisho cha kwanza cha bure na itakuwa nambari 3.
Orodha ya maelezo ya faili inaweza kutazamwa kwa mchakato wowote ikiwa unajua PID yake.
Kwa mfano, wacha tufungue koni ya bash na tuangalie PID ya mchakato wetu
[user@localhost ]$ echo $$
15771
Katika console ya pili hebu tukimbie
[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
Unaweza kupuuza kwa usalama nambari ya maelezo ya faili 255 kwa madhumuni ya kifungu hiki; ilifunguliwa kwa mahitaji yake na bash yenyewe, na sio na maktaba iliyounganishwa.
Sasa faili zote 3 za maelezo zinahusishwa na kifaa cha mwisho cha pseudo
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
Na katika console ya kwanza tutaona
[user@localhost ]$ hello world
Elekeza upya na Bomba
Unaweza kubatilisha faili hizi 3 za maelezo kwa urahisi katika mchakato wowote, pamoja na bash, kwa mfano kupitia bomba inayounganisha michakato miwili, ona.
[user@localhost ]$ cat /dev/zero | sleep 10000
Unaweza kuendesha amri hii mwenyewe na kamba -f na uone kinachoendelea ndani, lakini nitakuambia kwa ufupi.
Mchakato wetu wa mzazi bash na PID 15771 huchanganua amri yetu na inaelewa ni amri ngapi tunataka kutekeleza, kwa upande wetu kuna mbili kati yao: paka na kulala. Bash anajua kuwa inahitaji kuunda michakato miwili ya watoto, na kuwaunganisha kwenye bomba moja. Kwa jumla, bash itahitaji michakato 2 ya watoto na bomba moja.
Bash huendesha simu ya mfumo kabla ya kuunda michakato ya mtoto
Kwa mchakato wa mzazi, inaonekana kama tayari kuna bomba, lakini hakuna michakato ya mtoto bado:
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
Kisha kutumia simu ya mfumo
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
Usisahau kwamba clone inachukua mchakato pamoja na maelezo yote ya faili, kwa hivyo yatakuwa sawa katika mchakato wa mzazi na kwa watoto. Kazi ya mchakato wa mzazi na PID 15771 ni kufuatilia michakato ya mtoto, kwa hiyo inasubiri tu majibu kutoka kwa watoto.
Kwa hivyo, haiitaji bomba, na inafunga maelezo ya faili yenye nambari 3 na 4.
Katika mchakato wa kwanza wa bash wa mtoto na PID 9004, simu ya mfumo
Katika mchakato wa mtoto wa pili na PID 9005, bash hutumia dup2 kubadilisha maelezo ya faili STDIN nambari 0. Sasa kila kitu ambacho bash yetu ya pili na PID 9005 itasoma itasomwa kutoka kwa bomba.
Baada ya hayo, maelezo ya faili yenye nambari 3 na 4 pia imefungwa katika michakato ya mtoto, kwani haitumiki tena.
Mimi hupuuza kwa makusudi maelezo ya faili 255; inatumika kwa madhumuni ya ndani na bash yenyewe na pia itafungwa katika michakato ya watoto.
Ifuatayo, katika mchakato wa mtoto wa kwanza na PID 9004, bash huanza kutumia simu ya mfumo
Katika mchakato wa pili wa mtoto na PID 9005, bash huendesha utekelezaji wa pili tulioainisha, kwa upande wetu /usr/bin/sleep.
Simu ya mfumo wa utekelezaji haifungi vishikizo vya faili isipokuwa vilifunguliwa na bendera ya O_CLOEXEC wakati simu iliyofunguliwa ilipopigwa. Kwa upande wetu, baada ya kuzindua faili zinazoweza kutekelezwa, maelezo yote ya faili ya sasa yatahifadhiwa.
Angalia kwenye 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
Kama unaweza kuona, nambari ya kipekee ya bomba letu ni sawa katika michakato yote miwili. Kwa hivyo tuna uhusiano kati ya michakato miwili tofauti na mzazi mmoja.
Kwa wale ambao hawajui simu za mfumo ambazo bash hutumia, ninapendekeza sana kutekeleza amri kupitia strace na kuona kile kinachotokea ndani, kwa mfano kama hii:
strace -s 1024 -f bash -c "ls | grep hello"
Hebu turudi kwenye tatizo letu na nafasi ya chini ya diski na kujaribu kuhifadhi data bila kuanzisha upya mchakato. Wacha tuandike programu ndogo ambayo itaandika takriban megabyte 1 kwa sekunde kwa diski. Aidha, ikiwa kwa sababu fulani hatukuweza kuandika data kwenye diski, tutapuuza tu hili na kujaribu kuandika data tena kwa pili. Katika mfano ninaotumia Python, unaweza kutumia lugha nyingine yoyote ya programu.
[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
Wacha tuendeshe programu na tuangalie maelezo ya faili
[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
Kama unavyoona, tuna vifafanuzi vyetu 3 vya kawaida vya faili na moja zaidi ambayo tulifungua. Wacha tuangalie saizi ya faili:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
Data inaandikwa, tunajaribu kubadilisha ruhusa kwenye faili:
[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
Tunaona kwamba data bado inaandikwa, ingawa mtumiaji wetu hana ruhusa ya kuiandikia faili. Wacha tujaribu kuiondoa:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Data imeandikwa wapi? Na zimeandikwa kabisa? Tunaangalia:
[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)
Ndiyo, kifafanuzi cha faili yetu bado kipo na tunaweza kutibu kifafanuzi cha faili hii kama faili yetu ya zamani, tunaweza kuisoma, kuifuta na kuinakili.
Wacha tuangalie saizi ya faili:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Saizi ya faili ni 19923457. Hebu tujaribu kufuta faili:
[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
Kama unaweza kuona, saizi ya faili inaongezeka tu na shina yetu haikufanya kazi. Wacha tuangalie hati za simu za mfumo
with open("123.txt", "w") as f:
inabidi tuweke
with open("123.txt", "a") as f:
Inaangalia na bendera ya "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
na bendera "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
Kupanga mchakato ambao tayari unaendeshwa
Mara nyingi waandaaji programu, wakati wa kuunda na kujaribu programu, hutumia vitatuzi (kwa mfano GDB) au viwango mbalimbali vya kuingia kwenye programu. Linux hutoa uwezo wa kuandika na kubadilisha programu tayari inayoendesha, kwa mfano, kubadilisha maadili ya vigezo, kuweka sehemu ya kuvunja, nk, nk.
Kurudi kwa swali la awali kuhusu nafasi ya kutosha ya disk kuandika faili, hebu tujaribu kuiga tatizo.
Wacha tuunda faili ya kizigeu chetu, ambacho tutaweka kama diski tofauti:
[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 ~]$
Wacha tuunda mfumo wa faili:
[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 ~]$
Weka mfumo wa faili:
[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
Tunaunda saraka na mmiliki wetu:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Wacha tufungue faili kwa kuandika tu katika programu yetu:
with open("/mnt/logs/123.txt", "w") as f:
Uzinduzi
[user@localhost ]$ python openforwrite.py
Tunasubiri sekunde chache
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Kwa hiyo, tuna tatizo lililoelezwa mwanzoni mwa makala hii. Nafasi ya bure 0, 100% ulichukua.
Tunakumbuka kwamba kwa mujibu wa masharti ya kazi, tunajaribu kurekodi data muhimu sana ambayo haiwezi kupotea. Na wakati huo huo, tunahitaji kurekebisha huduma bila kuanzisha upya mchakato.
Wacha tuseme bado tunayo nafasi ya diski, lakini kwa kizigeu tofauti, kwa mfano ndani / nyumbani.
Wacha tujaribu "kupanga upya kwa kuruka" nambari yetu.
Wacha tuangalie PID ya mchakato wetu, ambao umekula nafasi yote ya diski:
[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
Unganisha kwa mchakato kupitia gdb
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Wacha tuangalie maelezo ya faili wazi:
(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
Tunaangalia habari kuhusu nambari ya maelezo ya faili 3, ambayo inatupendeza
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Kwa kuzingatia kile ambacho Python inaita mfumo (tazama hapo juu tulipofuatilia na kupata simu iliyofunguliwa), tunapochakata msimbo wetu ili kufungua faili, tunafanya vivyo hivyo sisi wenyewe kwa niaba ya mchakato wetu, lakini tunahitaji O_WRONLY|O_CREAT| Biti za O_TRUNC hubadilishwa kwa thamani ya nambari. Ili kufanya hivyo, fungua vyanzo vya kernel, kwa mfano
#fafanua O_WRONLY 00000001
#fafanua O_CREAT 00000100
#fafanua O_TRUNC 00001000
Tunachanganya maadili yote kuwa moja, tunapata 00001101
Tunaendesha simu yetu kutoka kwa gdb
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Kwa hivyo tulipata maelezo mapya ya faili na nambari 4 na faili mpya wazi kwenye kizigeu kingine, tunaangalia:
(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
Tunakumbuka mfano na bomba - jinsi bash inavyobadilisha maelezo ya faili, na tayari tumejifunza simu ya mfumo wa dup2.
Tunajaribu kubadilisha maelezo ya faili moja na nyingine
(gdb) call dup2(4,3)
$2 = 3
Tunaangalia:
(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
Tunafunga maelezo ya faili 4, kwani hatuitaji:
(gdb) call close (4)
$1 = 0
Na utoke kwenye 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
Kuangalia faili mpya:
[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
Kama unaweza kuona, data imeandikwa kwa faili mpya, wacha tuangalie ya zamani:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Hakuna data iliyopotea, programu inafanya kazi, kumbukumbu zimeandikwa kwa eneo jipya.
Wacha tufanye kazi ngumu kidogo
Hebu fikiria kwamba data ni muhimu kwetu, lakini hatuna nafasi ya disk katika sehemu yoyote na hatuwezi kuunganisha diski.
Tunachoweza kufanya ni kuelekeza data yetu mahali pengine, kwa mfano kwa bomba, na kuelekeza data kutoka bomba hadi kwa mtandao kupitia programu fulani, kwa mfano netcat.
Tunaweza kuunda bomba iliyopewa jina na amri ya mkfifo. Itaunda faili ya pseudo kwenye mfumo wa faili hata ikiwa hakuna nafasi ya bure juu yake.
Anzisha tena programu na uangalie:
[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
Hakuna nafasi ya diski, lakini tumefanikiwa kuunda bomba lililopewa jina hapo:
[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
Sasa tunahitaji kwa namna fulani kufunika data yote inayoingia kwenye bomba hili kwa seva nyingine kupitia mtandao; netcat sawa inafaa kwa hili.
Kwenye seva ya remote-server.example.com tunazindua
[user@localhost ~]$ nc -l 7777 > 123.txt
Kwenye seva yetu yenye shida tunazindua kwenye terminal tofauti
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Sasa data yote inayoishia kwenye bomba itaenda moja kwa moja kwa stdin in netcat, ambayo itaituma kwa mtandao kwenye bandari 7777.
Tunachotakiwa kufanya ni kuanza kuandika data zetu kwenye bomba hili lililopewa jina.
Tayari tunayo programu inayoendesha:
[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
Kati ya bendera zote, tunahitaji O_WRONLY pekee kwa kuwa faili tayari ipo na hatuhitaji kuifuta.
[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
Inakagua seva ya mbali remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Data inakuja, tunaangalia seva ya tatizo
[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
Data imehifadhiwa, tatizo linatatuliwa.
Nachukua fursa hii kuwasalimu wenzangu kutoka Degiro.
Sikiliza podikasti za Radio-T.
Kila la kheri.
Kama kazi ya nyumbani, ninapendekeza ufikirie juu ya nini kitakuwa kwenye maelezo ya faili ya paka na ulale ikiwa utaendesha amri ifuatayo:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Chanzo: mapenzi.com