Dateibeschreiwung am Linux mat Beispiller

Eemol, an engem Interview, gouf ech gefrot wat géift Dir maachen wann Dir e futtis Service fannt wéinst der Tatsaach datt d'Plaz aus dem Disk leeft?

Natierlech hunn ech geäntwert datt ech géif kucken wat dës Plaz mécht a wa méiglech d'Plaz botzen.
Dunn huet den Interviewer gefrot, wat wann et kee fräie Raum op der Partition ass, awer Dir gesitt och net d'Fichier'en déi all Plaz ophuelen?

Zu dësem hunn ech gesot datt Dir ëmmer op oppene Dateideskriptoren kuckt, zum Beispill mam lsof Kommando a verstitt wéi eng Applikatioun all verfügbare Raum geholl huet, an da kënnt Dir no den Ëmstänn handelen, ofhängeg ob d'Donnéeën gebraucht ginn .

Den Interviewer huet mech um leschte Wuert ënnerbrach, a seng Fro bäigefüügt: "Ugeholl datt mir d'Donnéeën net brauchen, et ass just en Debug-Logbuch, awer d'Applikatioun ass erof well et den Debug net kann schreiwen"?

"Ok," hunn ech geäntwert, "mir kënnen Debugging an der Applikatiounskonfiguratioun ausschalten an et nei starten."
Den Interviewer huet dogéint: "Nee, mir kënnen d'Applikatioun net nei starten, mir hunn nach ëmmer wichteg Donnéeën an der Erënnerung, a wichteg Clientë si mam Service selwer verbonnen, wat mir net forcéiere kënnen nei ze konnektéieren."

"Ok," sot ech, "wa mir d'Applikatioun net kënnen nei starten a mir egal vun den Donnéeën, da kënne mir dës oppe Datei einfach iwwer de Dateidescriptor läschen, och wa mir se net an der ls gesinn Kommando am Dateiesystem."

Den Interviewer war zefridden, awer ech war net.

Dunn hunn ech geduecht, firwat gräift déi Persoun déi mäi Wëssen ausprobéiert net méi déif? Awer wat wann d'Donnéeën iwwerhaapt wichteg sinn? Wat wa mir de Prozess net kënnen nei starten, a gläichzäiteg schreift dëse Prozess an de Dateiesystem op enger Partition déi kee fräie Raum huet? Wat wa mir net nëmmen d'Donnéeën déi scho geschriwwe sinn, awer och d'Donnéeën verléieren, déi dëse Prozess schreift oder probéiert ze schreiwen?

Tuzik

Am Ufank vu menger Carrière hunn ech probéiert eng kleng Applikatioun ze kreéieren déi Informatioun iwwer d'Benotzer muss späicheren. An dunn hunn ech geduecht, wéi kann ech dem Benotzer seng Donnéeë passen. Zum Beispill, Ech hunn Ivanov Ivan Ivanovich, an hien huet e puer Donnéeën, mä wéi Frënn mat hinnen ze maachen? Ech kann direkt drop hiweisen datt den Hond mam Numm "Tuzik" dem selwechten Ivan gehéiert. Awer wat wann hien säin Numm ännert an amplaz vum Ivan gëtt, zum Beispill, Olya? Da wäert et erausstellen datt eis Olya Ivanovna Ivanova keen Hond méi wäert hunn, an eis Tuzik wäert nach ëmmer dem net existéierenden Ivan gehéieren. D'Datebank huet gehollef dëse Problem ze léisen, deen all Benotzer en eenzegaartegen Identifizéierer (ID) ginn huet, a meng Tuzik war un dës ID gebonnen, déi tatsächlech just eng Seriennummer war. Sou war de Besëtzer vun der tuzik mat ID Nummer 2, an iergendwann war Ivan ënner dëser ID, an dann Olya gouf ënner der selwechter ID. De Problem vun der Mënschheet an der Déierewirtschaft gouf praktesch geléist.

Datei Beschreiwung

De Problem vun engem Dossier an engem Programm, dee mat dësem Fichier funktionnéiert, ass ongeféier d'selwecht wéi eisen Hond a Mënsch. Ugeholl datt ech e Fichier mam Numm ivan.txt opgemaach hunn an ugefaang d'Wuert tuzik an et ze schreiwen, awer et fäerdeg bruecht nëmmen den éischte Bréif "t" an d'Datei ze schreiwen, an dës Datei gouf vun engem ëmbenannt, zum Beispill op olya.txt. Mä de Fichier ass déi selwecht an ech wëll nach meng Ace ze schreiwen. All Kéier wann Dir eng Datei mat engem Systemruff opmaacht Open an all Programméierungssprooch kréien ech eng eenzegaarteg ID déi mech op eng Datei weist, dës ID ass den Dateideskriptor. An et ass iwwerhaapt egal wat a wien duerno mat dësem Fichier mécht, et kann geläscht ginn, et kann ëmbenannt ginn, et kann säi Besëtzer änneren oder d'Rechter fir ze liesen a ze schreiwen ewechhuelen, ech wäert nach ëmmer Zougang dozou hunn, well ech beim Opmaache vun der Datei d'Rechter hat et ze liesen an/oder ze schreiwen an ech hunn et fäerdeg bruecht domat unzefänken, dat heescht datt ech weider muss maachen.

Op Linux mécht d'libc-Bibliothéik 3 Deskriptordateien fir all lafend Applikatioun (Prozess) op, mat Zuelen 0,1,2. Méi Informatioun fannt Dir op de Linken man stdio и man stdout

  • Datei Descriptor 0 gëtt STDIN genannt an ass mat der Uwendungsinput assoziéiert.
  • Dateibeschreiwung 1 gëtt STDOUT genannt a gëtt vun Ausgangsapplikatiounen wéi Dréckbefehle benotzt.
  • Datei Descriptor 2 gëtt STDERR genannt a gëtt vun Uwendungen benotzt fir Fehlermeldungen auszeginn.

Wann Dir an Ärem Programm all Datei opmaacht fir ze liesen oder ze schreiwen, da kritt Dir héchstwahrscheinlech déi éischt gratis ID an et wäert d'Nummer 3 sinn.

Dir kënnt d'Lëscht vun Dateideskriptoren fir all Prozess gesinn wann Dir seng PID kennt.

Zum Beispill, loosst eis eng Konsole mat Bash opmaachen an de PID vun eisem Prozess gesinn

[user@localhost ]$ echo $$
15771

An der zweeter Konsole lafen

[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

Dir kënnt sécher de Fichier Descriptor mat Nummer 255 am Kader vun dësem Artikel ignoréieren, et gouf fir Är Bedierfnesser vum Bash selwer opgemaach, an net vun der verlinkter Bibliothéik.

Elo sinn all 3 Deskriptordateien mat dem Pseudo-Terminalapparat assoziéiert /dev/pts, mee mir kënnen se nach manipuléieren, zum Beispill, lafen an der zweeter Konsol

[user@localhost ]$ echo "hello world" > /proc/15771/fd/0

An an der éischter Konsole wäerte mir gesinn

[user@localhost ]$ hello world

Redirect a Pipe

Dir kënnt dës 3 Deskriptordateien einfach an all Prozess iwwerschreiden, och am Bash, zum Beispill, duerch e Päif (Päif) déi zwee Prozesser verbënnt, kuckt

[user@localhost ]$ cat /dev/zero | sleep 10000

Dir kënnt dëst Kommando selwer lafen mat streck -f a kucke wat dobannen lass ass, mee ech maachen et kuerz.

Eis Elterebash-Prozess mat PID 15771 parséiert eise Kommando a versteet genau wéi vill Kommandoe mir wëllen ausféieren, an eisem Fall sinn et zwee vun hinnen: Kaz a Schlof. Bash weess datt et muss zwee Kannerprozesser erstellen an se an eng Päif fusionéieren. Am Ganzen brauch Bash 2 Kannerprozesser an eng Päif.

Ier Dir Kannerprozesser erstellt, leeft bash e Systemruff Päif ugeet a kritt nei Dateideskriptoren op engem temporäre Päifbuffer, awer dëse Puffer verbënnt eis zwee Kannerprozesser nach net op iergendeng Manéier.

Fir den Elterenprozess gesäit et aus wéi wann d'Päif schonn do ass, awer et gi nach keng Kannerprozesser:

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

Da benotzt de System Uruff Klon bash erstellt zwee Kannerprozesser, an eis dräi Prozesser wäerten esou ausgesinn:

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

Vergiesst net datt Klonen de Prozess zesumme mat all Dateideskriptoren klonen, sou datt se d'selwecht sinn am Elterenprozess an an de Kanner. D'Aufgab vum Elterendeel mam PID 15771 ass d'Kandprozesser ze iwwerwaachen, also waart et just op eng Äntwert vun de Kanner.

Dofir brauch hien net e Päif, an hie mécht d'Dateibeschreiwunge mat den Zuelen 3 a 4 zou.

Am éischte Bash Kand Prozess mat PID 9004, de System Opruff dup 2, ännert eisen STDOUT-Dateibeschreibung Nummer 1 op e Dateideskriptor, deen op eng Päif weist, an eisem Fall ass et d'Nummer 3. Also fällt alles wat den éischte Kandprozess mam PID 9004 op STDOUT schreift automatesch an de Päifbuffer.

Am zweete Kand Prozess mat PID 9005, bash dup2s der Datei ze STDIN Descriptor Nummer 0. Elo alles wat eis zweet Bash mat PID 9005 liesen wäert aus der Päif liesen.

Duerno ginn och Dateidescriptoren mat den Zuelen 3 a 4 a Kannerprozesser zougemaach, well se net méi benotzt ginn.

Ech ignoréieren bewosst Fichier Descriptor 255, et gëtt intern vun Bash selwer benotzt a wäert och an Kand Prozesser zougemaach ginn.

Als nächst, am éischte Kand Prozess mat PID 9004, fänkt bash mat engem System Opruff exec déi ausführbar Datei déi mir op der Kommandozeil uginn hunn, an eisem Fall ass et /usr/bin/cat.

Am zweete Kannerprozess mat PID 9005 leeft bash den zweeten Ausführbar, dee mir spezifizéiert hunn, an eisem Fall /usr/bin/sleep.

Den Exec System Uruff schléisst keng Dateideskriptoren zou, ausser se goufen mam O_CLOEXEC Fändel opgemaach an der Zäit wou den oppene Ruff ausgefouert gouf. An eisem Fall, nodeems Dir déi ausführbar Dateien ausgeführt hutt, ginn all aktuell Dateideskriptoren gespäichert.

Iwwerpréift an der 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

Wéi Dir kënnt gesinn, ass déi eenzegaarteg Zuel vun eisem Päif déiselwecht a béide Prozesser. Also hu mir eng Verbindung tëscht zwee verschiddene Prozesser mam selwechten Elterendeel.

Fir déi, déi net vertraut sinn mat de System Uriff, déi de Bash benotzt, ech recommandéieren d'Befehle duerch Strace ze lafen a kuckt wat dobannen geschitt, zum Beispill, sou:

strace -s 1024 -f bash -c "ls | grep hello"

Loosst eis zréck op eise Problem mam Lafen aus dem Disk Space a probéieren Daten ze späicheren ouni de Prozess nei ze starten. Loosst eis e klenge Programm schreiwen, deen ongeféier 1 Megabyte pro Sekonn op Disk schreift. Ausserdeem, wa mir aus irgendege Grënn keng Daten op Disk schreiwen konnten, ignoréiere mir dëst einfach a probéieren d'Donnéeën an enger Sekonn erëm ze schreiwen. Am Beispill benotzen ech Python, Dir kënnt all aner Programméierungssprooch benotzen.

[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

Run de Programm a kuckt op d'Datei Descriptoren

[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

Wéi Dir gesitt, hu mir eis 3 Standard Dateideskriptoren an en aneren deen mir opgemaach hunn. Loosst eis d'Dateigréisst kontrolléieren:

[user@localhost ]$ ls -lah 123.txt 
-rw-rw-r-- 1 user user 117M Oct  7 16:30 123.txt

d'Donnéeën geschriwwe ginn, mir probéieren d'Rechter op d'Datei z'änneren:

[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

Mir gesinn datt d'Donnéeën nach ëmmer geschriwwe ginn, obwuel eise Benotzer net d'Recht huet fir de Fichier ze schreiwen. Loosst eis probéieren et ze läschen:

[user@localhost ]$ sudo rm 123.txt 
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory

Wou sinn d'Donnéeë geschriwwen? A si se iwwerhaapt geschriwwen? Mir kontrolléieren:

[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)

Jo, eise Fichier Descriptor existéiert nach ëmmer, a mir kënne mat dësem Fichier Descriptor schaffen wéi eis al Datei, mir kënnen et liesen, botzen a kopéieren.

Kuckt d'Dateigréisst:

[user@localhost ]$ lsof | grep 123.txt
python    31083             user    3w      REG                8,5   19923457   2621522 /home/user/123.txt

D'Dateigréisst ass 19923457. Probéiert de Fichier ze läschen:

[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

Wéi Dir gesitt, geet d'Dateigréisst nëmmen erop an eise Trunk huet net geschafft. Loosst eis op d'Dokumentatioun iwwer de Systemruff goen Open. Wa mir den O_APPEND Fändel benotzen wann Dir eng Datei opmaacht, da mat all Schreiwen, kontrolléiert de Betribssystem d'Dateigréisst a schreift Daten bis zum Enn vun der Datei, a mécht et atomesch. Dëst erlaabt verschidde Threads oder Prozesser op déiselwecht Datei ze schreiwen. Awer an eisem Code benotze mir dëse Fändel net. Mir kënnen eng aner Dateigréisst am lsof nom Trunk gesinn nëmme wa mir d'Datei opmaachen fir ze schreiwen, dat heescht datt an eisem Code, amplaz

with open("123.txt", "w") as f:

mir mussen setzen

with open("123.txt", "a") as f:

Iwwerpréift mat "w" Fändel

[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

a mat "e" Fändel

[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

Programméiere vun engem scho lafende Prozess

Dacks, wann Dir e Programm erstellt an testen, benotzen d'Programméierer Debugger (zum Beispill GDB) oder verschidde Niveaue vum Logbuch an der Applikatioun. Linux bitt d'Fäegkeet fir e scho lafende Programm tatsächlech ze schreiwen an z'änneren, sou wéi d'Wäerter vun de Variablen z'änneren, e Breakpoint astellen, asw.

Zréck op déi ursprénglech Fro iwwer de Mangel u Plaatz fir eng Datei ze schreiwen, loosst eis probéieren de Problem ze simuléieren.

Loosst eis eng Datei fir eis Partition erstellen, déi mir als separat Drive montéieren:

[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 ~]$

Loosst eis e Dateiesystem erstellen:

[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 ~]$

Loosst eis de Dateisystem montéieren:

[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

Erstellt e Verzeechnes mat eisem Besëtzer:

[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs

Loosst eis d'Datei opmaachen fir nëmmen an eisem Programm ze schreiwen:

with open("/mnt/logs/123.txt", "w") as f:

Lancéiere

[user@localhost ]$ python openforwrite.py 

Waarde fir e puer Sekonnen

[user@localhost ~]$ df -h | grep mnt
/dev/loop0      8.7M  8.0M     0 100% /mnt

Also hu mir de Problem am Ufank vun dësem Artikel beschriwwen. Fräi Plaz 0, besat 100%.

Mir erënneren, datt laut de Konditioune vum Problem, mir probéieren ganz wichteg Donnéeën opzehuelen, déi net verluer kënne ginn. An dofir musse mir de Service fixéieren ouni de Prozess nei ze starten.

Loosst eis soen datt mir nach ëmmer Disk Space hunn, awer an enger anerer Partition, zum Beispill an / doheem.

Loosst eis probéieren eise Code "op der Flucht ze reprogramméieren".

Mir kucken de PID vun eisem Prozess, deen all Disk Space giess huet:

[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

Verbindung mat engem Prozess mat gdb

[user@localhost ~]$ gdb -p 10078
...
(gdb) 

Mir kucken op oppene Dateideskriptoren:

(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

Mir kucken d'Informatiounen iwwer de Fichier Descriptor mat Nummer 3, déi eis interesséiert

(gdb) shell cat /proc/10078/fdinfo/3
pos:    8189952
flags:  0100001
mnt_id: 482

Bedenkt wat de System Uruff Python mécht (kuckt hei uewen wou mir Strace lafen an en oppenen Uruff fonnt hunn), wärend eise Code veraarbecht fir eng Datei opzemaachen, maache mir datselwecht selwer am Numm vun eisem Prozess, awer mir brauchen den O_WRONLY|O_CREAT| O_TRUNC Bits ersetzen mat engem numeresche Wäert. Fir dëst ze maachen, öffnen zum Beispill d'Kernelquellen hei a kucke wéi eng Fändelen fir wat verantwortlech sinn

#definéieren O_WRONLY 00000001
#definéieren O_CREAT 00000100
#definéieren O_TRUNC 00001000

Mir kombinéieren all Wäerter an een, mir kréien 00001101

Lafen eisen Uruff vun gdb

(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4

Also hu mir en neien Dateideskriptor mat Nummer 4 an eng nei oppene Datei op enger anerer Partition, kontrolléiert:

(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

Mir erënnere mech un d'Beispill mat Päif - wéi Bash Dateideskriptoren ännert, an hu schonn den dup2 System Uruff geléiert.

Probéiert een Dateideskriptor mat engem aneren ze ersetzen

(gdb) call dup2(4,3)
$2 = 3

Mir iwwerpréiwen:

(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

Zoumaachen Datei Descriptor 4, well mir et net brauchen:

(gdb) call close (4)
$1 = 0

An erausgoen 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

Iwwerpréift déi nei Datei:

[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

Wéi Dir gesitt, sinn d'Donnéeën an eng nei Datei geschriwwe ginn, mir kontrolléieren déi al:

[user@localhost ~]$ ls -lah /mnt/logs/123.txt 
-rw-rw-r-- 1 user user 7.9M Oct  8 11:08 /mnt/logs/123.txt

D'Donnéeë ginn net verluer, d'Applikatioun funktionnéiert, d'Logbicher ginn op eng nei Plaz geschriwwe.

Loosst eis d'Saache e bësse méi schwéier maachen

Stellt Iech vir datt d'Donnéeën fir eis wichteg sinn, awer mir hunn keen Disk Space an enger vun de Partitionen a mir kënnen d'Disk net verbannen.

Wat mir maache kënnen ass eis Donnéeën iergendwou viruleeden, zum Beispill op eng Päif, an d'Daten aus der Päif an d'Netzwierk duerch e puer Programm, wéi netcat, viruleeden.
Mir kënnen e genannte Päif mam mkfifo Kommando erstellen. Et wäert eng Pseudo-Datei am Dateiesystem erstellen, och wann et kee fräie Raum drop ass.

Restart d'Applikatioun a kontrolléiert:

[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

Et gëtt keen Disk Space, awer mir erstellen erfollegräich e genannte Pipe do:

[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

Elo musse mir iergendwéi all d'Donnéeën, déi an dësem Päif op en anere Server duerch d'Netz kommen, wéckelen, dee selwechte Netcat ass fir dëst gëeegent.

Um Remote-server.example.com Server, lafen

[user@localhost ~]$ nc -l 7777 > 123.txt 

Op eisem Problem Server, lafen an engem separaten Terminal

[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe 

Elo ginn all d'Donnéeën, déi an d'Päif kommen, automatesch op stdin an netcat goen, wat se an d'Netzwierk um Port 7777 schéckt.

Alles wat mir maache mussen ass eis Donnéeën un dës genannt Päif ze schreiwen.

Mir hu schonn eng lafend Applikatioun:

[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

Vun all de Fändelen brauche mir nëmmen O_WRONLY well de Fichier schonn existéiert a mir brauche se net ze läschen

[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

Kontrolléiert de Remote Server Remote-server.example.com

[user@localhost ~]$ ls -lah 123.txt 
-rw-rw-r-- 1 user user 38M Oct  8 14:21 123.txt

Daten kommen, mir kontrolléieren de Problem Server

[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

D'Donnéeë ginn gespäichert, de Problem ass geléist.

Ech profitéieren vun dëser Geleeënheet fir de Kollege vum Degiro ze soen.
Lauschtert Radio-T Podcasts.

Gutt un all.

Als Hausaufgaben proposéieren ech ze denken iwwer wat an de Dateibeschreiwunge vum Kaz a Schlofprozess wäert sinn wann Dir de folgende Kommando ausféiert:

[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000

Source: will.com

Setzt e Commentaire