Egyszer egy interjúban megkérdezték tőlem, hogy mit tenne, ha megszakadt a szolgáltatás amiatt, hogy a lemezen elfogy a hely?
Természetesen azt válaszoltam, hogy megnézem, mit csinál ez a hely, és ha lehet, kitakarítom a helyet.
Aztán a kérdező megkérdezte, mi van akkor, ha nincs szabad hely a partíción, de nem látod azokat a fájlokat sem, amelyek minden helyet elfoglalnának?
Erre azt mondtam, hogy mindig meg lehet nézni a megnyitott fájlleírókat, például az lsof paranccsal, és megérteni, hogy melyik alkalmazás foglalt el minden rendelkezésre álló helyet, majd a körülményeknek megfelelően lehet cselekedni, attól függően, hogy szükség van-e az adatokra. .
A kérdező az utolsó szónál félbeszakított, kérdéséhez hozzáfűzve: „Tegyük fel, hogy nincs szükségünk az adatokra, ez csak egy hibakeresési napló, de az alkalmazás leállt, mert nem tudja megírni a hibakeresést”?
"Rendben" - válaszoltam - "kikapcsolhatjuk a hibakeresést az alkalmazás konfigurációjában, és újraindíthatjuk."
A kérdező kifogásolta: „Nem, nem tudjuk újraindítani az alkalmazást, még mindig vannak fontos adatok a memóriában, és magához a szolgáltatáshoz csatlakoznak fontos kliensek, amelyeket nem tudunk rákényszeríteni az újracsatlakozásra.”
– Oké – mondtam –, ha nem tudjuk újraindítani az alkalmazást, és nem törődünk az adatokkal, akkor egyszerűen törölhetjük ezt a megnyitott fájlt a fájlleíró segítségével, még akkor is, ha nem látjuk az ls-ben. parancsot a fájlrendszeren.”
A kérdező elégedett volt, én viszont nem.
Aztán arra gondoltam, miért nem ás mélyebbre az, aki teszteli a tudásomat? De mi van akkor, ha az adatok mégis fontosak? Mi van akkor, ha nem tudjuk újraindítani a folyamatot, és ugyanakkor ez a folyamat olyan partíción ír a fájlrendszerbe, amelyen nincs szabad hely? Mi van akkor, ha nem csak a már megírt adatokat nem veszíthetjük el, hanem azokat az adatokat sem, amelyeket ez a folyamat ír vagy próbál írni?
Tuzik
Pályám kezdetén megpróbáltam létrehozni egy kis alkalmazást, amiben információkat kellett tárolni a felhasználókról. És akkor arra gondoltam, hogyan tudnám a felhasználót az adataihoz illeszteni. Például van Ivanov Ivan Ivanovicsom, és van néhány adata, de hogyan lehet velük barátkozni? Közvetlenül kijelenthetem, hogy a "Tuzik" nevű kutya ugyanahhoz az Ivánhoz tartozik. De mi van, ha megváltoztatja a nevét, és Ivan helyett például Olya lesz? Aztán kiderül, hogy Olya Ivanovna Ivanovánknak már nem lesz kutyája, a mi Tuzikunk pedig továbbra is a nem létező Iváné lesz. Az adatbázis segített megoldani ezt a problémát, amely minden felhasználóhoz egyedi azonosítót (ID) adott, és ehhez az azonosítóhoz volt kötve a Tuzikom, ami valójában csak egy sorozatszám volt. Így a tuzik tulajdonosa 2-es azonosítószámú volt, és valamikor Iván is ezen az igazolványon volt, majd Olya is ugyanazon az azonosító alatt állt. Az emberiség és az állattenyésztés problémája gyakorlatilag megoldódott.
Fájlleíró
A fájl és az ezzel a fájllal működő program problémája nagyjából ugyanaz, mint a kutyánknak és az embernek. Tegyük fel, hogy megnyitottam egy ivan.txt nevű fájlt, és elkezdtem beleírni a tuzik szót, de csak az első „t” betűt sikerült beleírnom a fájlba, és ezt a fájlt valaki átnevezte például olya.txt-re. De a fájl ugyanaz, és még mindig rá akarom írni az ászomat. Minden alkalommal, amikor rendszerhívással megnyit egy fájlt
Linuxon a libc könyvtár 3 leíró fájlt nyit meg minden futó alkalmazáshoz (folyamathoz), 0,1,2, XNUMX, XNUMX számokkal. További információkat a linkeken találhat
- A 0 fájlleíró neve STDIN, és az alkalmazás bemenetéhez van társítva.
- Az 1. fájlleíró neve STDOUT, és a kimeneti alkalmazások, például a nyomtatási parancsok használják.
- A 2. fájlleíró neve STDERR, és az alkalmazások hibaüzenetek kiadására használják.
Ha a programjában megnyit egy fájlt olvasásra vagy írásra, akkor valószínűleg megkapja az első ingyenes azonosítót, és ez a 3-as lesz.
Bármely folyamat fájlleíróinak listáját megtekintheti, ha ismeri annak PID-jét.
Például nyissunk meg egy konzolt a bash segítségével, és nézzük meg a folyamatunk PID-jét
[user@localhost ]$ echo $$
15771
A második konzolon futtassa
[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
A cikk keretein belül nyugodtan figyelmen kívül hagyhatja a 255-ös számú fájlleírót, azt maga a bash nyitotta meg, nem a hivatkozott könyvtár.
Most mind a 3 leíró fájl hozzá van rendelve a pszeudoterminál eszközhöz
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
És az első konzolon látni fogjuk
[user@localhost ]$ hello world
Átirányítás és cső
Könnyedén felülírhatja ezt a 3 leíró fájlt bármely folyamatban, beleértve a bash-t is, például két folyamatot összekötő cső (pipe) segítségével, lásd
[user@localhost ]$ cat /dev/zero | sleep 10000
Ezt a parancsot saját maga is futtathatja strace -f és nézd meg, mi történik odabent, de röviden leírom.
A PID 15771-es szülő bash folyamatunk elemzi a parancsunkat, és pontosan megérti, hány parancsot akarunk futtatni, esetünkben kettő van belőlük: cat és sleep. A Bash tudja, hogy két gyermekfolyamatot kell létrehoznia, és egy csőbe kell egyesítenie őket. Összességében a bash-hoz 2 gyermek folyamatra és egy pipere lesz szüksége.
Az utódfolyamatok létrehozása előtt a bash rendszerhívást futtat
A szülőfolyamat esetében úgy tűnik, hogy a cső már megvan, de még nincsenek alárendelt folyamatok:
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
Ezután használja a rendszerhívást
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
Ne felejtsük el, hogy a klón klónozza a folyamatot az összes fájlleíróval együtt, így azok ugyanazok lesznek a szülő folyamatban és a gyermek folyamatban. A PID 15771-es szülőfolyamat feladata a gyermekfolyamatok figyelése, tehát csak a gyerekek válaszára vár.
Ezért nincs szüksége csőre, a fájlleírókat pedig a 3-as és 4-es számmal zárja.
A 9004-es PID-vel rendelkező első bash gyermekfolyamatban a rendszerhívás
A második, PID 9005-ös utódfolyamatban a bash dup2s a fájlt a 0 STDIN-leíró számra írja be. Most minden, amit a 9005-ös PID-vel rendelkező második bash olvasni fog, a csőből fog olvasni.
Ezt követően a 3-as és 4-es számú fájlleírók is bezáródnak a gyermekfolyamatokban, mivel már nem használják őket.
Szándékosan figyelmen kívül hagyom a 255-ös fájlleírót, maga a bash használja belsőleg, és a gyermekfolyamatok is bezárják.
Ezután a 9004-es PID-vel rendelkező első gyermekfolyamatban a bash rendszerhívással indul
A 9005-ös PID-vel rendelkező második gyermekfolyamatban a bash az általunk megadott második végrehajtható fájlt futtatja, esetünkben /usr/bin/sleep.
Az exec rendszerhívás csak akkor zárja be a fájlleírókat, ha azokat az O_CLOEXEC jelzővel nyitották meg a nyitott hívás végrehajtásakor. Esetünkben a futtatható fájlok futtatása után az összes aktuális fájlleíró mentésre kerül.
Ellenőrzés a konzolon:
[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
Mint látható, a csövünk egyedi száma mindkét folyamatban megegyezik. Így két különböző folyamat között van kapcsolatunk ugyanazzal a szülővel.
Azok számára, akik nem ismerik a bash által használt rendszerhívásokat, erősen ajánlom a parancsok futtatását a strace-en keresztül, és nézzék meg, mi történik belül, például így:
strace -s 1024 -f bash -c "ls | grep hello"
Térjünk vissza a problémánkhoz, miszerint kifogyott a lemezterület, és megpróbáljuk elmenteni az adatokat a folyamat újraindítása nélkül. Írjunk egy kis programot, ami körülbelül 1 megabájtot ír a lemezre másodpercenként. Sőt, ha valamilyen oknál fogva nem tudtunk adatokat írni a lemezre, egyszerűen figyelmen kívül hagyjuk ezt, és egy másodperc múlva megpróbáljuk újra írni az adatokat. A Python-t használó példában bármilyen más programozási nyelvet használhat.
[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
Futtassa a programot, és nézze meg a fájlleírókat
[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
Amint látja, van 3 szabványos fájlleírónk, és egy másik, amelyet megnyitottunk. Ellenőrizzük a fájl méretét:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
az adatok írásra kerülnek, megpróbáljuk megváltoztatni a fájl jogait:
[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
Azt látjuk, hogy az adatok írása még folyamatban van, bár felhasználónknak nincs joga írni a fájlba. Próbáljuk meg eltávolítani:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Hol vannak az adatok írva? És egyáltalán meg vannak írva? Ellenőrizzük:
[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)
Igen, a fájlleírónk továbbra is létezik, és ezzel a fájlleíróval is dolgozhatunk, mint a régi fájlunkkal, elolvashatjuk, tisztíthatjuk és másolhatjuk.
Nézze meg a fájl méretét:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
A fájl mérete 19923457. A fájl törlése:
[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
Amint látja, a fájl mérete csak nő, és a törzsünk nem működött. Lapozzuk át a rendszerhívás dokumentációját
with open("123.txt", "w") as f:
tennünk kell
with open("123.txt", "a") as f:
Ellenőrzés "w" zászlóval
[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
és "a" zászlóval
[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
Egy már futó folyamat programozása
Egy program létrehozásakor és tesztelésekor a programozók gyakran hibakeresőket (például GDB) vagy különféle szintű naplózást használnak az alkalmazásban. A Linux lehetővé teszi egy már futó program tényleges megírását és módosítását, például a változók értékeinek megváltoztatását, töréspont beállítását, és így tovább.
Visszatérve a fájl írásához szükséges lemezterület hiányára vonatkozó eredeti kérdéshez, próbáljuk meg szimulálni a problémát.
Hozzon létre egy fájlt a partíciónkhoz, amelyet külön meghajtóként csatolunk:
[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 ~]$
Hozzunk létre egy fájlrendszert:
[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 ~]$
Csatlakoztassuk a fájlrendszert:
[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
Hozzon létre egy könyvtárat tulajdonosunkkal:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Nyissuk meg a fájlt írásra csak a programunkban:
with open("/mnt/logs/123.txt", "w") as f:
Dob
[user@localhost ]$ python openforwrite.py
Várjon néhány másodpercig
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Tehát megkaptuk a cikk elején leírt problémát. Szabad hely 0, 100%-ban foglalt.
Emlékezzünk arra, hogy a probléma körülményeinek megfelelően nagyon fontos adatokat próbálunk rögzíteni, amelyek nem veszhetnek el. Ennek során ki kell javítanunk a szolgáltatást a folyamat újraindítása nélkül.
Tegyük fel, hogy még mindig van lemezterületünk, de egy másik partícióban, például a / home-ban.
Próbáljuk meg "menet közben átprogramozni" a kódunkat.
Megnézzük a folyamatunk PID-jét, amely felemésztette az összes lemezterületet:
[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
Csatlakozás egy folyamathoz a gdb segítségével
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Megnézzük a megnyitott fájlleírókat:
(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
A 3-as számú fájlleíróra vonatkozó információkat nézzük meg, amelyek érdekelnek
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Szem előtt tartva, hogy a Python milyen rendszerhívást végez (lásd fent, ahol a strace-t futtattuk és nyitott hívást találtunk), miközben a kódunkat feldolgozzuk egy fájl megnyitásához, mi magunk is megtesszük ugyanezt a folyamat nevében, de szükségünk van az O_WRONLY|O_CREAT| Az O_TRUNC bitek helyébe numerikus érték lép. Ehhez nyissa meg például a kernelforrásokat
#define O_WRONLY 00000001
#define O_CREAT 00000100
#define O_TRUNC 00001000
Összevonjuk az összes értéket egy, 00001101-et kapunk
A gdb hívása fut
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Tehát kaptunk egy új fájlleírót 4-es számmal és egy új megnyitott fájlt egy másik partíción, ellenőrizze:
(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
Emlékszünk a pipe példára – hogyan változtatja meg a bash a fájlleírókat, és már megtanultuk a dup2 rendszerhívást.
Megpróbál egy fájlleírót lecserélni egy másikra
(gdb) call dup2(4,3)
$2 = 3
Ellenőrizzük:
(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
Zárjuk be a 4-es fájlleírót, mert nincs rá szükségünk:
(gdb) call close (4)
$1 = 0
És kilép a gdb-ből
(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
Az új fájl ellenőrzése:
[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
Amint látja, az adatok egy új fájlba íródnak, ellenőrizzük a régit:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Az adatok nem vesznek el, az alkalmazás működik, a naplók új helyre íródnak.
Nehezítsük meg egy kicsit a dolgokat
Képzeljük el, hogy az adatok fontosak számunkra, de nincs lemezterületünk egyik partícióban sem, és nem tudjuk csatlakoztatni a lemezt.
Annyit tehetünk, hogy átirányítjuk az adatainkat valahova, például egy pipere, és a csőből az adatokat átirányítjuk a hálózatra valamilyen programon, például a netcaten keresztül.
Az mkfifo paranccsal létrehozhatunk egy nevű csövet. Létrehoz egy pszeudofájlt a fájlrendszeren, még akkor is, ha nincs rajta szabad hely.
Indítsa újra az alkalmazást, és ellenőrizze:
[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
Nincs lemezterület, de sikeresen létrehoztunk ott egy nevű csövet:
[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
Most valahogy minden adatot, ami ebbe a csőbe kerül, át kell csomagolnunk egy másik szerverre a hálózaton keresztül, erre ugyanaz a netcat alkalmas.
A remote-server.example.com kiszolgálón futtassa
[user@localhost ~]$ nc -l 7777 > 123.txt
A problémás szerverünkön egy külön terminálon fut
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Mostantól minden adat, amely a csőbe kerül, automatikusan a netcat stdin-jába kerül, amely a 7777-es porton küldi el a hálózatnak.
Nincs más dolgunk, mint elkezdeni az adatainkat írni ebbe a nevezett csőbe.
Már van egy futó alkalmazásunk:
[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
Az összes zászló közül csak az O_WRONLY-ra van szükségünk, mivel a fájl már létezik, és nem kell törölnünk
[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
A távoli szerver ellenőrzése remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Jönnek az adatok, ellenőrizzük a problémás szervert
[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
Az adatok mentésre kerülnek, a probléma megoldódott.
Megragadom az alkalmat, hogy köszöntsem a degirói kollégákat.
Hallgassa meg a Radio-T podcastokat.
Minden rendben.
Házi feladatként azt javaslom, hogy gondolja át, mi lesz a macska és alvás folyamat fájlleíróiban, ha futtatja a következő parancsot:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Forrás: will.com