Ek is eenkeer in 'n onderhoud gevra wat sou jy doen as jy 'n stukkende diens vind as gevolg van die feit dat die skyf nie meer spasie het nie?
Ek het natuurlik geantwoord dat ek sal sien wat hierdie plek doen en, indien moontlik, sal ek die plek skoonmaak.
Toe vra die onderhoudvoerder, wat as daar geen vrye spasie op die partisie is nie, maar jy sien ook nie die lêers wat al die spasie sal opneem nie?
Hierop het ek gesê dat jy altyd na oop lêerbeskrywings kan kyk, byvoorbeeld met die lsof-opdrag en verstaan watter toepassing al die beskikbare spasie in beslag geneem het, en dan kan jy volgens die omstandighede optree, afhangend van of die data benodig word .
Die onderhoudvoerder onderbreek my by die laaste woord en voeg by sy vraag: "Gestel ons het nie die data nodig nie, dit is net 'n debug-log, maar die toepassing is af omdat dit nie die debug kan skryf nie"?
"ok," het ek geantwoord, "ons kan ontfouting in die toepassingsopstelling afskakel en dit herbegin."
Die onderhoudvoerder het beswaar gemaak: "Nee, ons kan nie die toepassing herbegin nie, ons het steeds belangrike data in die geheue, en belangrike kliënte is aan die diens self gekoppel, wat ons nie kan dwing om weer te koppel nie."
“goed,” het ek gesê, “as ons nie die toepassing kan herbegin nie en ons gee nie om oor die data nie, dan kan ons hierdie oop lêer deur die lêerbeskrywing uitvee, selfs al sien ons dit nie in die ls opdrag op die lêerstelsel.”
Die onderhoudvoerder was tevrede, maar ek was nie.
Toe dink ek, hoekom delf die persoon wat my kennis toets nie dieper nie? Maar wat as die data tog belangrik is? Wat as ons nie die proses kan herbegin nie, en terselfdertyd skryf hierdie proses na die lêerstelsel op 'n partisie wat geen vrye spasie het nie? Wat as ons nie net die data wat reeds geskryf is, kan verloor nie, maar ook die data wat hierdie proses skryf of probeer skryf?
Tuzik
Aan die begin van my loopbaan het ek probeer om 'n klein toepassing te skep wat inligting oor gebruikers moes stoor. En toe dink ek, hoe kan ek die gebruiker by sy data pas. Byvoorbeeld, ek het Ivanov Ivan Ivanovich, en hy het 'n paar data, maar hoe om vriende met hulle te maak? Ek kan direk daarop wys dat die hond met die naam "Tuzik" aan hierdie selfde Ivan behoort. Maar wat as hy sy naam verander en in plaas van Ivan byvoorbeeld Olya word? Dan sal dit blyk dat ons Olya Ivanovna Ivanova nie meer 'n hond sal hê nie, en ons Tuzik sal steeds aan die nie-bestaande Ivan behoort. Die databasis het gehelp om hierdie probleem op te los, wat aan elke gebruiker 'n unieke identifiseerder (ID) gegee het, en my Tuzik was aan hierdie ID gekoppel, wat in werklikheid net 'n reeksnommer was. Dus, die eienaar van die tuzik was met ID-nommer 2, en op 'n sekere tydstip was Ivan onder hierdie ID, en toe het Olya onder dieselfde ID geword. Die probleem van die mensdom en veeteelt is prakties opgelos.
Lêerbeskrywing
Die probleem van 'n lêer en 'n program wat met hierdie lêer werk, is omtrent dieselfde as ons hond en mens. Gestel ek het 'n lêer met die naam ivan.txt oopgemaak en die woord tuzik daarin begin skryf, maar het daarin geslaag om net die eerste letter "t" in die lêer te skryf, en hierdie lêer is deur iemand hernoem, byvoorbeeld na olya.txt. Maar die lêer is dieselfde en ek wil steeds my aas daaraan skryf. Elke keer as jy 'n lêer oopmaak met 'n stelseloproep
Op Linux maak die libc-biblioteek 3 beskrywinglêers oop vir elke lopende toepassing (proses), met nommers 0,1,2. Meer inligting kan jy op die skakels kry
- Lêerbeskrywing 0 word STDIN genoem en word geassosieer met toepassinginvoer.
- Lêerbeskrywer 1 word STDOUT genoem en word gebruik deur uitvoertoepassings soos drukopdragte.
- Lêerbeskrywer 2 word STDERR genoem en word deur toepassings gebruik om foutboodskappe uit te voer.
As jy in jou program enige lêer oopmaak vir lees of skryf, dan sal jy heel waarskynlik die eerste gratis ID kry en dit sal nommer 3 wees.
U kan die lys lêerbeskrywers vir enige proses sien as u die PID daarvan ken.
Kom ons maak byvoorbeeld 'n konsole met bash oop en sien die PID van ons proses
[user@localhost ]$ echo $$
15771
In die tweede konsole, hardloop
[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
U kan die lêerbeskrywer met nommer 255 veilig binne die raamwerk van hierdie artikel ignoreer, dit is deur bash self vir u behoeftes oopgemaak en nie deur die gekoppelde biblioteek nie.
Nou word al 3 beskrywerlêers met die pseudo-terminale toestel geassosieer
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
En in die eerste konsole sal ons sien
[user@localhost ]$ hello world
Herlei en pyp
Jy kan hierdie 3 beskrywinglêers maklik in enige proses ignoreer, insluitend in bash, byvoorbeeld, deur 'n pyp (pyp) wat twee prosesse verbind, sien
[user@localhost ]$ cat /dev/zero | sleep 10000
Jy kan hierdie opdrag self uitvoer met spoor -f en kyk wat binne aangaan, maar ek sal dit kort maak.
Ons ouerbash-proses met PID 15771 ontleed ons opdrag en verstaan presies hoeveel opdragte ons wil uitvoer, in ons geval is daar twee van hulle: kat en slaap. Bash weet dat dit twee kinderprosesse moet skep en dit in een pyp moet saamsmelt. In totaal sal bash 2 kinderprosesse en een pyp benodig.
Voordat u kinderprosesse skep, voer bash 'n stelseloproep uit
Vir die ouerproses lyk dit of die pyp reeds daar is, maar daar is nog geen kinderprosesse nie:
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
Gebruik dan die stelseloproep
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
Moenie vergeet dat kloon die proses saam met alle lêerbeskrywers kloon nie, so hulle sal dieselfde wees in die ouerproses en in die kinderproses. Die taak van die ouerproses met PID 15771 is om die kinderprosesse te monitor, so dit wag net vir 'n reaksie van die kinders.
Daarom het hy nie 'n pyp nodig nie, en hy maak die lêerbeskrywers toe met nommers 3 en 4.
In die eerste bash kind proses met PID 9004, die stelsel oproep
In die tweede kind proses met PID 9005, bash dup2s die lêer na STDIN beskrywing nommer 0. Nou sal alles wat ons tweede bash met PID 9005 sal lees uit die pyp lees.
Daarna word lêerbeskrywers met nommers 3 en 4 ook in kinderprosesse gesluit, aangesien dit nie meer gebruik word nie.
Ek ignoreer lêerbeskrywer 255 doelbewus, dit word intern deur bash self gebruik en sal ook in kinderprosesse gesluit word.
Vervolgens, in die eerste kind-proses met PID 9004, begin bash met 'n stelseloproep
In die tweede kinderproses met PID 9005, loop bash die tweede uitvoerbare lêer wat ons gespesifiseer het, in ons geval /usr/bin/sleep.
Die exec-stelseloproep sluit nie lêerbeskrywers nie, tensy hulle met die O_CLOEXEC-vlag oopgemaak is toe die oop oproep uitgevoer is. In ons geval, nadat die uitvoerbare lêers uitgevoer is, sal alle huidige lêerbeskrywings gestoor word.
Kyk na die konsole:
[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
Soos u kan sien, is die unieke nommer van ons pyp dieselfde in beide prosesse. Ons het dus 'n verband tussen twee verskillende prosesse met dieselfde ouer.
Vir diegene wat nie vertroud is met die stelseloproepe wat bash gebruik nie, beveel ek sterk aan om opdragte deur strace te laat loop en kyk wat binne gebeur, byvoorbeeld, soos volg:
strace -s 1024 -f bash -c "ls | grep hello"
Kom ons gaan terug na ons probleem met die opraak van skyfspasie en probeer om data te stoor sonder om die proses te herbegin. Kom ons skryf 'n klein program wat ongeveer 1 megagreep per sekonde na skyf sal skryf. Verder, as ons om een of ander rede nie data na skyf kon skryf nie, sal ons dit eenvoudig ignoreer en probeer om die data binne 'n sekonde weer te skryf. In die voorbeeld wat ek Python gebruik, kan jy enige ander programmeertaal gebruik.
[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
Begin die program en kyk na die lêerbeskrywings
[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
Soos u kan sien, het ons ons 3 standaard lêerbeskrywings en nog een wat ons oopgemaak het. Kom ons kyk na die lêergrootte:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
die data geskryf is, probeer ons om die regte op die lêer te verander:
[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
Ons sien dat die data steeds geskryf word, alhoewel ons gebruiker nie die reg het om na die lêer te skryf nie. Kom ons probeer dit verwyder:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Waar is die data geskryf? En is hulle enigsins geskryf? Ons kontroleer:
[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)
Ja, ons lêerbeskrywing bestaan steeds, en ons kan met hierdie lêerbeskrywing werk soos ons ou lêer, ons kan dit lees, dit skoonmaak en dit kopieer.
Kyk na die lêergrootte:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Die lêergrootte is 19923457. Probeer om die lêer skoon te maak:
[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
Soos u kan sien, neem die lêergrootte net toe en ons stam het nie gewerk nie. Kom ons blaai na die dokumentasie oor die stelseloproep
with open("123.txt", "w") as f:
ons moet sit
with open("123.txt", "a") as f:
Kontroleer met "w" vlag
[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
en met 'n vlag
[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
Programmering van 'n reeds lopende proses
Dikwels, wanneer 'n program geskep en getoets word, gebruik programmeerders ontfouters (byvoorbeeld GDB) of verskeie vlakke van aanteken in die toepassing. Linux bied die vermoë om werklik 'n program wat reeds loop, te skryf en te verander, soos om die waardes van veranderlikes te verander, 'n breekpunt te stel, ensovoorts, ensovoorts.
Om terug te keer na die oorspronklike vraag oor die gebrek aan skyfspasie om 'n lêer te skryf, kom ons probeer om die probleem te simuleer.
Kom ons skep 'n lêer vir ons partisie, wat ons as 'n aparte aandrywer sal monteer:
[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 ~]$
Kom ons skep 'n lêerstelsel:
[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 ~]$
Kom ons monteer die lêerstelsel:
[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
Skep 'n gids met ons eienaar:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Kom ons maak die lêer oop vir skryf slegs in ons program:
with open("/mnt/logs/123.txt", "w") as f:
Begin
[user@localhost ]$ python openforwrite.py
Wag vir 'n paar sekondes
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Dus, ons het die probleem wat aan die begin van hierdie artikel beskryf word. Vrye spasie 0, 100% beset.
Ons onthou dat ons volgens die toestande van die probleem probeer om baie belangrike data op te neem wat nie verlore kan gaan nie. En om dit te doen, moet ons die diens regmaak sonder om die proses te herbegin.
Kom ons sê ons het nog skyfspasie, maar in 'n ander partisie, byvoorbeeld in / tuis.
Kom ons probeer om ons kode "on the fly te herprogrammeer".
Ons kyk na die PID van ons proses, wat al die skyfspasie geëet het:
[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
Koppel aan 'n proses met gdb
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Ons kyk na oop lêerbeskrywings:
(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
Ons kyk na inligting oor die lêerbeskrywer met nommer 3, wat ons interesseer
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
As ons in gedagte hou watter stelseloproep Python doen (sien hierbo waar ons 'n soektog gehardloop het en 'n oop oproep gevind het), terwyl ons ons kode verwerk om 'n lêer oop te maak, doen ons dieselfde self namens ons proses, maar ons benodig die O_WRONLY|O_CREAT| O_TRUNC bisse vervang met 'n numeriese waarde. Om dit te doen, maak byvoorbeeld die kernbronne oop
#definieer O_WRONLY 00000001
#definieer O_CREAT 00000100
#definieer O_TRUNC 00001000
Ons kombineer al die waardes in een, ons kry 00001101
Begin ons oproep vanaf gdb
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
So ons het 'n nuwe lêerbeskrywing met nommer 4 en 'n nuwe oop lêer op 'n ander partisie gekry, kyk:
(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
Ons onthou die voorbeeld met pipe - hoe bash lêerbeskrywings verander, en het reeds die dup2-stelseloproep geleer.
Probeer om een lêerbeskrywer met 'n ander te vervang
(gdb) call dup2(4,3)
$2 = 3
Ons kyk na:
(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
Maak lêerbeskrywing 4 toe, aangesien ons dit nie nodig het nie:
(gdb) call close (4)
$1 = 0
En verlaat 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
Gaan die nuwe lêer na:
[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
Soos u kan sien, word die data na 'n nuwe lêer geskryf, ons kyk na die ou:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Die data gaan nie verlore nie, die toepassing werk, die logs word na 'n nuwe plek geskryf.
Kom ons maak dinge 'n bietjie moeiliker
Stel jou voor dat die data vir ons belangrik is, maar ons het nie skyfspasie in enige van die partisies nie en ons kan nie die skyf koppel nie.
Wat ons kan doen, is om ons data iewers heen te herlei, byvoorbeeld na 'n pyp, en die data van die pyp na die netwerk te herlei deur een of ander program, soos netcat.
Ons kan 'n benoemde pyp skep met die mkfifo-opdrag. Dit sal 'n pseudo-lêer op die lêerstelsel skep, selfs al is daar geen vrye spasie daarop nie.
Herbegin die toepassing en kontroleer:
[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
Daar is geen skyfspasie nie, maar ons skep 'n genoemde pyp suksesvol daar:
[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
Nou moet ons op een of ander manier al die data wat in hierdie pyp kom, na 'n ander bediener deur die netwerk toedraai, dieselfde netkat is geskik hiervoor.
Op die remote-server.example.com-bediener, hardloop
[user@localhost ~]$ nc -l 7777 > 123.txt
Op ons probleembediener, hardloop in 'n aparte terminaal
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Nou sal al die data wat in die pyp kom, outomaties na stdin in netcat gaan, wat dit na die netwerk op poort 7777 sal stuur.
Al wat ons moet doen is om ons data na hierdie benoemde pyp te begin skryf.
Ons het reeds 'n lopende toepassing:
[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
Van al die vlae het ons net O_WRONLY nodig aangesien die lêer reeds bestaan en ons hoef dit nie skoon te maak nie
[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
Kontroleer tans die afgeleë bediener remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Data kom, ons kyk na die probleembediener
[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
Die data word gestoor, die probleem is opgelos.
Ek gebruik hierdie geleentheid om te groet aan my kollegas van Degiro.
Luister na Radio-T-podcasts.
Alles goed.
As 'n huiswerk stel ek voor om te dink oor wat in die lêerbeskrywings van die kat- en slaapproses sal wees as jy die volgende opdrag uitvoer:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Bron: will.com