Kord küsiti minult intervjuu ajal, et mida teete, kui leiate, et teenus ei tööta, kuna kettal on ruum otsa saanud?
Muidugi vastasin, et vaatan, mis see koht hõivab ja võimalusel koristan selle koha ära.
Seejärel küsis intervjueerija, et mis siis, kui partitsioonil pole vaba ruumi, kuid te ei näe ka ühtegi faili, mis kogu ruumi võtaks?
Selle peale ütlesin, et alati saab vaadata avatud failideskriptoreid, näiteks käsuga lsof ja aru saada, milline rakendus on kogu vaba ruumi enda alla võtnud ja siis saab vastavalt oludele tegutseda, olenevalt kas andmeid on vaja .
Intervjueerija katkestas mind viimase sõna peale, lisades oma küsimusele: "Oletame, et me ei vaja andmeid, see on lihtsalt silumislogi, kuid rakendus ei tööta, kuna see ei saa silumist kirjutada"?
"Olgu," vastasin, "saame rakenduse konfiguratsioonis silumise välja lülitada ja selle taaskäivitada."
Intervjueerija vaidles vastu: "Ei, me ei saa rakendust taaskäivitada, olulised andmed on endiselt mällu salvestatud ja olulised kliendid on ühendatud teenuse endaga, mida me ei saa sundida uuesti ühendama."
"Olgu," ütlesin ma, "kui me ei saa rakendust taaskäivitada ja andmed pole meile olulised, siis saame selle avatud faili lihtsalt failideskriptori kaudu kustutada, isegi kui me seda käsus ls ei näe failisüsteemis."
Intervjueerija oli rahul, aga mina mitte.
Siis mõtlesin, et miks see inimene, kes minu teadmisi proovile paneb, ei süvene? Aga mis siis, kui andmed on siiski olulised? Mis siis, kui me ei saa protsessi taaskäivitada ja protsess kirjutab failisüsteemi partitsioonile, millel pole vaba ruumi? Mis siis, kui me ei saa kaotada mitte ainult juba kirjutatud andmeid, vaid ka andmeid, mida see protsess kirjutab või üritab kirjutada?
Tuzik
Oma karjääri alguses püüdsin luua väikest rakendust, mis vajas kasutajateabe salvestamist. Ja siis ma mõtlesin, et kuidas ma saan kasutaja tema andmetega kokku sobitada. Näiteks on mul Ivanov Ivan Ivanovitš ja tal on natuke teavet, aga kuidas ma saan nendega sõbraks saada? Võin otse välja tuua, et koer nimega “Tuzik” kuulub just sellele Ivanile. Aga mis siis, kui ta muudab nime ja saab Ivani asemel näiteks Olya? Siis selgub, et meie Olja Ivanovna Ivanoval pole enam koera ja meie Tuzik jääb ikkagi olematule Ivanile. Andmebaas, mis andis igale kasutajale kordumatu identifikaatori (ID), aitas seda probleemi lahendada ja minu Tuzik oli seotud selle ID-ga, mis tegelikult oli vaid seerianumber. Seega oli tuziku omanikul ID-number 2 ja mingil ajal oli selle ID all Ivan ja siis sai selle ID all ka Olya. Inimkonna ja loomakasvatuse probleem sai praktiliselt lahendatud.
Faili deskriptor
Faili ja selle failiga töötava programmi probleem on ligikaudu sama, mis meie koeral ja inimesel. Oletame, et avasin faili nimega ivan.txt ja hakkasin sinna kirjutama sõna tuzik, kuid jõudsin failis kirjutada ainult esimese tähe “t” ja keegi nimetas selle faili ümber, näiteks nimeks olya.txt. Kuid fail jääb samaks ja ma tahan ikka oma ässa sinna salvestada. Iga kord, kui fail avatakse süsteemikõnega
Linuxis avab libc teek iga töötava rakenduse (protsessi) jaoks 3 deskriptorifaili, mis on nummerdatud 0,1,2. Rohkem infot leiab linkidelt
- Failideskriptorit 0 nimetatakse STDIN-iks ja see on seotud rakenduse sisendiga
- Faili deskriptorit 1 nimetatakse STDOUT ja rakendused kasutavad seda andmete, näiteks printimiskäskude, väljastamiseks
- Failideskriptorit 2 nimetatakse STDERR-iks ja rakendused kasutavad seda veateadete väljastamiseks.
Kui avate oma programmis lugemiseks või kirjutamiseks mis tahes faili, saate suure tõenäosusega esimese tasuta ID ja see on number 3.
Failideskriptorite loendit saab vaadata mis tahes protsessi jaoks, kui teate selle PID-d.
Näiteks avame bash-konsooli ja vaatame oma protsessi PID-d
[user@localhost ]$ echo $$
15771
Teises konsoolis jookseme
[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
Selle artikli puhul võite failideskriptorit number 255 julgelt ignoreerida; selle avas oma vajadusteks bash ise, mitte lingitud teek.
Nüüd on kõik 3 deskriptorifaili seotud pseudoterminali seadmega
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
Ja esimeses konsoolis näeme
[user@localhost ]$ hello world
Ümbersuunamine ja toru
Neid 3 deskriptorifaili saate hõlpsasti alistada mis tahes protsessis, sealhulgas bashis, näiteks kahte protsessi ühendava toru kaudu, vt
[user@localhost ]$ cat /dev/zero | sleep 10000
Saate selle käsu ise käivitada joon -f ja vaata, mis seal sees toimub, aga ma räägin sulle lühidalt.
Meie vanem bash protsess PID 15771-ga parsib meie käsku ja mõistab täpselt, kui palju käske tahame käivitada, meie puhul on neid kaks: kass ja uni. Bash teab, et ta peab looma kaks alamprotsessi ja liitma need üheks toruks. Kokku vajab bash 2 alamprotsessi ja ühte toru.
Bash käivitab enne alamprotsesside loomist süsteemikutse
Vanemprotsessi jaoks näib, et toru on juba olemas, kuid alamprotsesse pole veel:
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
Seejärel kasutage süsteemikõnet
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
Ärge unustage, et kloon kloonib protsessi koos kõigi failideskriptoritega, nii et need on põhiprotsessis ja alamprotsessis samad. PID 15771-ga vanemprotsessi ülesanne on jälgida alamprotsesse, nii et see lihtsalt ootab lastelt vastust.
Seetõttu ei vaja see toru ja see sulgeb failideskriptorid numbritega 3 ja 4.
Esimeses alam-bash-protsessis PID 9004-ga kutsub süsteem välja
Teises PID 9005 alamprotsessis kasutab bash failideskriptori STDIN numbri 2 muutmiseks dup0. Nüüd loetakse torust kõik, mida meie teine bash PID 9005-ga loeb.
Pärast seda suletakse alamprotsessides ka failideskriptorid numbritega 3 ja 4, kuna neid enam ei kasutata.
Ignoreerin meelega failideskriptorit 255; seda kasutab sisemistel eesmärkidel bash ise ja see suletakse ka alamprotsessides.
Järgmisena hakkab bash PID 9004-ga esimeses alamprotsessis kasutama süsteemikutset
Teises PID 9005 alamprotsessis käivitab bash teist meie määratud käivitatavat faili, meie puhul /usr/bin/sleep.
Exec-süsteemikutse ei sulge failikäepidemeid, välja arvatud juhul, kui need avati avatud kõne tegemise ajal lipuga O_CLOEXEC. Meie puhul salvestatakse pärast käivitatavate failide käivitamist kõik praegused failideskriptorid.
Kontrollige konsoolis:
[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
Nagu näete, on meie toru kordumatu number mõlemas protsessis sama. Seega on meil seos kahe erineva protsessi vahel sama vanemaga.
Neile, kes pole bashi kasutatavate süsteemikutsega tuttavad, soovitan tungivalt käivitada käsud läbi strace ja vaadata, mis toimub sisemiselt, näiteks järgmiselt:
strace -s 1024 -f bash -c "ls | grep hello"
Pöördume tagasi probleemi juurde, mis puudutab vähest kettaruumi ja andmete salvestamist ilma protsessi taaskäivitamata. Kirjutame väikese programmi, mis kirjutab kettale umbes 1 megabaidi sekundis. Veelgi enam, kui me mingil põhjusel ei saanud andmeid kettale kirjutada, siis me lihtsalt ignoreerime seda ja proovime andmed sekundi pärast uuesti kirjutada. Näites, kus ma kasutan Pythoni, saate kasutada mis tahes muud programmeerimiskeelt.
[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
Käivitame programmi ja vaatame failide kirjeldusi
[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
Nagu näete, on meil kolm standardset failideskriptorit ja veel üks, mille avasime. Kontrollime faili suurust:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
Andmeid kirjutatakse, proovime faili õigusi muuta:
[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
Näeme, et andmeid alles kirjutatakse, kuigi meie kasutajal puudub luba faili kirjutamiseks. Proovime selle eemaldada:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Kuhu andmed kirjas on? Ja kas need on üldse kirjutatud? Kontrollime:
[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)
Jah, meie failideskriptor on endiselt olemas ja me saame seda failideskriptorit käsitleda nagu meie vana faili, saame seda lugeda, kustutada ja kopeerida.
Vaatame faili suurust:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Faili suurus on 19923457. Proovime faili tühjendada:
[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
Nagu näete, faili suurus ainult suureneb ja meie pagasiruumi ei töötanud. Vaatame süsteemikõnede dokumentatsiooni
with open("123.txt", "w") as f:
peame panema
with open("123.txt", "a") as f:
Kontrollimine "w" lipuga
[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
ja "a" lipuga
[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
Juba käimasoleva protsessi programmeerimine
Sageli kasutavad programmeerijad programmide loomisel ja testimisel silujaid (näiteks GDB) või rakenduses erinevaid logimise tasemeid. Linux annab võimaluse kirjutada ja muuta juba töötavat programmi, näiteks muuta muutujate väärtusi, määrata katkestuspunkti jne jne.
Tulles tagasi algse küsimuse juurde, et faili kirjutamiseks pole piisavalt kettaruumi, proovime probleemi simuleerida.
Loome oma partitsiooni jaoks faili, mille ühendame eraldi kettana:
[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 ~]$
Loome failisüsteemi:
[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 ~]$
Paigaldage failisüsteem:
[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
Koostame oma omanikuga kataloogi:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Avame faili ainult meie programmis kirjutamiseks:
with open("/mnt/logs/123.txt", "w") as f:
Käivitamine
[user@localhost ]$ python openforwrite.py
Ootame paar sekundit
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Niisiis, meil on selle artikli alguses kirjeldatud probleem. Vaba ruum 0, 100% hõivatud.
Peame meeles, et vastavalt ülesande tingimustele püüame salvestada väga olulisi andmeid, mis ei saa kaduda. Ja samal ajal peame teenuse parandama ilma protsessi taaskäivitamata.
Oletame, et meil on veel kettaruumi, kuid teises partitsioonis, näiteks /home.
Proovime oma koodi "lennult ümber programmeerida".
Vaatame meie protsessi PID-d, mis on ära söönud kogu kettaruumi:
[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
Ühendage protsessiga gdb kaudu
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Vaatame avatud faili kirjeldusi:
(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
Vaatame teavet failideskriptori number 3 kohta, mis meid huvitab
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Pidades meeles, millist süsteemikutset Python teeb (vt ülalt, kus käivitasime strace ja leidsime avatud kutse), teeme faili avamiseks koodi töötlemisel sama protsessi nimel, kuid vajame O_WRONLY|O_CREAT| O_TRUNC bitid asendatakse arvväärtusega. Selleks ava näiteks kerneli allikad
#define O_WRONLY 00000001
#define O_CREAT 00000100
#define O_TRUNC 00001000
Ühendame kõik väärtused üheks, saame 00001101
Teeme oma kõne gdb-st
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Nii saime uue failideskriptori numbriga 4 ja uue avatud faili teisel partitsioonil, kontrollime:
(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
Meenub näide toruga - kuidas bash muudab failideskriptoreid ja oleme juba õppinud dup2 süsteemikutset.
Püüame asendada ühe failikirjelduse teisega
(gdb) call dup2(4,3)
$2 = 3
Kontrollime:
(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
Sulgeme failideskriptori 4, kuna me ei vaja seda:
(gdb) call close (4)
$1 = 0
Ja välju gdb-st
(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
Uue faili kontrollimine:
[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
Nagu näete, kirjutatakse andmed uude faili, kontrollime vana:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Andmed ei lähe kaduma, rakendus töötab, logid kirjutatakse uude asukohta.
Teeme ülesande pisut keerulisemaks
Kujutagem ette, et andmed on meile olulised, kuid meil pole üheski partitsioonis kettaruumi ja me ei saa ketast ühendada.
Mida me saame teha, on suunata oma andmed kuhugi, näiteks torusse, ja omakorda suunata andmed torust võrku läbi mõne programmi, näiteks netcat.
Nimega toru saame luua käsuga mkfifo. See loob failisüsteemis pseudofaili isegi siis, kui sellel pole vaba ruumi.
Taaskäivitage rakendus ja kontrollige:
[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
Kettaruumi pole, kuid loome seal edukalt nimega toru:
[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
Nüüd peame kõik sellesse torusse minevad andmed kuidagi võrgu kaudu teise serverisse pakkima, selleks sobib sama netcat.
Töötame serveris remote-server.example.com
[user@localhost ~]$ nc -l 7777 > 123.txt
Meie probleemse serveri käivitame eraldi terminalis
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Nüüd lähevad kõik torusse sattunud andmed automaatselt netcati stdini, mis saadab need pordi 7777 kaudu võrku.
Peame vaid hakkama oma andmeid sellesse nimega torusse kirjutama.
Rakendus meil juba töötab:
[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
Kõigist lippudest vajame ainult O_WRONLY, kuna fail on juba olemas ja me ei pea seda kustutama
[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
Kaugserveri remote-server.example.com kontrollimine
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Andmed tulevad, kontrollime probleemset serverit
[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
Andmed salvestatakse, probleem on lahendatud.
Kasutan võimalust ja tervitan oma kolleege Degirost.
Kuulake Radio-T taskuhäälingusaateid.
Hea kõigile.
Kodutööna soovitan teil mõelda, mis on protsessi failikirjeldustes cat and sleep, kui käivitate järgmise käsu:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Allikas: www.habr.com