En gang i et intervju ble jeg spurt om hva du ville gjort hvis du finner en ødelagt tjeneste på grunn av at disken har gått tom for plass?
Jeg svarte selvfølgelig at jeg ville se hva dette stedet gjorde, og om mulig ville jeg rydde stedet.
Så spurte intervjueren, hva om det ikke er ledig plass på partisjonen, men du heller ikke ser filene som vil ta opp all plass?
Til dette sa jeg at du alltid kan se på åpne filbeskrivelser, for eksempel med lsof-kommandoen og forstå hvilken applikasjon som har tatt all tilgjengelig plass, og så kan du handle i henhold til omstendighetene, avhengig av om dataene er nødvendige .
Intervjueren avbrøt meg ved siste ord, og la til spørsmålet sitt: "Anta at vi ikke trenger dataene, det er bare en feilsøkingslogg, men applikasjonen er nede fordi den ikke kan skrive feilsøkingen"?
"ok," svarte jeg, "vi kan slå av feilsøking i applikasjonskonfigurasjonen og starte den på nytt."
Intervjueren innvendte: "Nei, vi kan ikke starte applikasjonen på nytt, vi har fortsatt viktige data i minnet, og viktige klienter er koblet til selve tjenesten, som vi ikke kan tvinge til å koble til på nytt."
"ok," sa jeg, "hvis vi ikke kan starte programmet på nytt og vi ikke bryr oss om dataene, så kan vi bare slette denne åpne filen via filbeskrivelsen, selv om vi ikke ser den i ls kommando på filsystemet."
Intervjueren var fornøyd, men det var jeg ikke.
Da tenkte jeg, hvorfor graver ikke personen som tester kunnskapen min dypere? Men hva om dataene tross alt er viktige? Hva om vi ikke kan starte prosessen på nytt, og samtidig skriver denne prosessen til filsystemet på en partisjon som ikke har ledig plass? Hva om vi ikke bare kan miste dataene som allerede er skrevet, men også dataene som denne prosessen skriver eller prøver å skrive?
Tuzik
I begynnelsen av min karriere prøvde jeg å lage en liten applikasjon som måtte lagre informasjon om brukere. Og så tenkte jeg, hvordan kan jeg matche brukeren til hans data. For eksempel har jeg Ivanov Ivan Ivanovich, og han har noen data, men hvordan blir jeg venner med dem? Jeg kan påpeke direkte at hunden som heter "Tuzik" tilhører denne samme Ivan. Men hva om han endrer navn og i stedet for Ivan blir for eksempel Olya? Da vil det vise seg at vår Olya Ivanovna Ivanova ikke lenger vil ha en hund, og vår Tuzik vil fortsatt tilhøre den ikke-eksisterende Ivan. Databasen hjalp til med å løse dette problemet, som ga hver bruker en unik identifikator (ID), og min Tuzik var knyttet til denne IDen, som faktisk bare var et serienummer. Dermed var eieren av tuziken med ID-nummer 2, og på et tidspunkt var Ivan under denne ID-en, og da ble Olya under samme ID. Problemet med menneskeheten og dyrehold ble praktisk talt løst.
Filbeskrivelse
Problemet med en fil og et program som fungerer med denne filen er omtrent det samme som vår hund og menneske. Anta at jeg åpnet en fil som heter ivan.txt og begynte å skrive ordet tuzik inn i den, men klarte å skrive bare den første bokstaven "t" inn i filen, og denne filen ble omdøpt av noen, for eksempel til olya.txt. Men filen er den samme, og jeg vil fortsatt skrive mitt ess til den. Hver gang du åpner en fil med et systemanrop
På Linux åpner libc-biblioteket 3 deskriptorfiler for hver kjørende applikasjon (prosess), med tallene 0,1,2. Mer informasjon finner du på lenkene
- Filbeskrivelse 0 kalles STDIN og er knyttet til applikasjonsinndata.
- Filbeskrivelse 1 kalles STDOUT og brukes av utdataapplikasjoner som utskriftskommandoer.
- Filbeskrivelse 2 heter STDERR og brukes av applikasjoner til å sende ut feilmeldinger.
Hvis du åpner en fil for lesing eller skriving i programmet ditt, vil du mest sannsynlig få den første gratis ID-en, og denne vil være nummer 3.
Du kan se listen over filbeskrivelser for enhver prosess hvis du kjenner PID-en.
La oss for eksempel åpne en konsoll med bash og se PID-en til prosessen vår
[user@localhost ]$ echo $$
15771
I den andre konsollen, kjør
[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
Du kan trygt ignorere filbeskrivelsen med nummer 255 innenfor rammen av denne artikkelen, den ble åpnet for dine behov av bash selv, og ikke av det koblede biblioteket.
Nå er alle 3 deskriptorfilene assosiert med pseudoterminalenheten
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
Og i den første konsollen vil vi se
[user@localhost ]$ hello world
Redirect og Pipe
Du kan enkelt overstyre disse 3 deskriptorfilene i en hvilken som helst prosess, inkludert i bash, for eksempel gjennom et rør (rør) som forbinder to prosesser, se
[user@localhost ]$ cat /dev/zero | sleep 10000
Du kan kjøre denne kommandoen selv med strace -f og se hva som skjer inni, men jeg skal gjøre det kort.
Vår foreldrebash-prosess med PID 15771 analyserer kommandoen vår og forstår nøyaktig hvor mange kommandoer vi vil kjøre, i vårt tilfelle er det to av dem: katt og søvn. Bash vet at den må lage to underordnede prosesser, og slå dem sammen til ett rør. Totalt vil bash trenge 2 underordnede prosesser og ett rør.
Før du oppretter underordnede prosesser, kjører bash et systemanrop
For overordnet prosessen ser det ut til at røret allerede er der, men det er ingen underordnede prosesser ennå:
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
Deretter bruker du systemanropet
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
Ikke glem at klon kloner prosessen sammen med alle filbeskrivelser, slik at de vil være de samme i overordnet prosessen og i de underordnede. Oppgaven til foreldreprosessen med PID 15771 er å overvåke barneprosessene, så den venter bare på svar fra barna.
Derfor trenger han ikke et rør, og han lukker filbeskrivelsene med nummer 3 og 4.
I den første bash underordnede prosessen med PID 9004 kaller systemet
I den andre underordnede prosessen med PID 9005, dup2ser du filen til STDIN-deskriptor nummer 0. Nå vil alt som vår andre bash med PID 9005 vil lese, lese fra røret.
Etter det lukkes også filbeskrivelser med nummer 3 og 4 i underordnede prosesser, siden de ikke lenger brukes.
Jeg ignorerer fildeskriptor 255 bevisst, den brukes internt av bash selv og vil også bli lukket i underordnede prosesser.
Deretter, i den første underordnede prosessen med PID 9004, starter bash med et systemanrop
I den andre underordnede prosessen med PID 9005 kjører bash den andre kjørbare filen vi spesifiserte, i vårt tilfelle /usr/bin/sleep.
Exec-systemkallet lukker ikke filbeskrivelser med mindre de ble åpnet med O_CLOEXEC-flagget på det tidspunktet det åpne anropet ble utført. I vårt tilfelle, etter å ha kjørt de kjørbare filene, vil alle gjeldende filbeskrivelser bli lagret.
Sjekker i konsollen:
[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
Som du kan se, er det unike nummeret på røret vårt det samme i begge prosessene. Dermed har vi en sammenheng mellom to ulike prosesser med samme forelder.
For de som ikke er kjent med systemkallene som bash bruker, anbefaler jeg på det sterkeste å kjøre kommandoer gjennom strace og se hva som skjer inni, for eksempel slik:
strace -s 1024 -f bash -c "ls | grep hello"
La oss gå tilbake til problemet med å gå tom for diskplass og prøve å lagre data uten å starte prosessen på nytt. La oss skrive et lite program som vil skrive til disken med omtrent 1 megabyte per sekund. Dessuten, hvis vi av en eller annen grunn ikke kunne skrive data til disken, vil vi ganske enkelt ignorere dette og prøve å skrive dataene igjen om et sekund. I eksemplet jeg bruker Python, kan du bruke et hvilket som helst annet programmeringsspråk.
[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
Kjør programmet og se på filbeskrivelsene
[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
Som du kan se, har vi våre 3 standard filbeskrivelser og en annen som vi har åpnet. La oss sjekke filstørrelsen:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
dataene er skrevet, prøver vi å endre rettighetene til filen:
[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
Vi ser at dataene fortsatt skrives, selv om brukeren vår ikke har rett til å skrive til filen. La oss prøve å fjerne det:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Hvor er dataene skrevet? Og er de i det hele tatt skrevet? Vi sjekker:
[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, filbeskrivelsen vår eksisterer fortsatt, og vi kan jobbe med denne filbeskrivelsen som vår gamle fil, vi kan lese den, rydde opp og kopiere den.
Se på filstørrelsen:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Filstørrelsen er 19923457. Prøver å fjerne filen:
[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
Som du kan se, øker filstørrelsen bare og bagasjerommet vårt fungerte ikke. La oss gå til dokumentasjonen på systemsamtalen
with open("123.txt", "w") as f:
vi må sette
with open("123.txt", "a") as f:
Sjekker med "w"-flagget
[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
og med "et" flagg
[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 av en allerede igangværende prosess
Ofte, når de oppretter og tester et program, bruker programmerere debuggere (for eksempel GDB) eller ulike nivåer av logging i applikasjonen. Linux gir muligheten til å faktisk skrive og endre et allerede kjørende program, for eksempel å endre verdiene til variabler, sette et bruddpunkt, og så videre og så videre.
Tilbake til det opprinnelige spørsmålet om mangel på diskplass for å skrive en fil, la oss prøve å simulere problemet.
La oss lage en fil for partisjonen vår, som vi vil montere som en separat stasjon:
[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 ~]$
La oss lage et filsystem:
[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 ~]$
La oss montere filsystemet:
[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
Opprett en katalog med eieren vår:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
La oss bare åpne filen for skriving i programmet vårt:
with open("/mnt/logs/123.txt", "w") as f:
Lansering
[user@localhost ]$ python openforwrite.py
Venter i noen sekunder
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Så vi fikk problemet beskrevet i begynnelsen av denne artikkelen. Ledig plass 0, okkupert 100 %.
Vi husker at i henhold til betingelsene for problemet prøver vi å registrere svært viktige data som ikke kan gå tapt. Og når vi gjør det, må vi fikse tjenesten uten å starte prosessen på nytt.
La oss si at vi fortsatt har diskplass, men i en annen partisjon, for eksempel i / hjemme.
La oss prøve å "omprogrammere i farten" koden vår.
Vi ser på PID-en til prosessen vår, som spiste all diskplass:
[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
Koble til en prosess med gdb
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Vi ser på åpne filbeskrivelser:
(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
Vi ser på informasjon om filbeskrivelsen med nummer 3, som interesserer oss
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Med tanke på hvilket systemkall Python gjør (se ovenfor hvor vi kjørte strace og fant et åpent kall), mens vi behandler koden vår for å åpne en fil, gjør vi det samme selv på vegne av prosessen vår, men vi trenger O_WRONLY|O_CREAT| O_TRUNC-biter erstattes med en numerisk verdi. For å gjøre dette, åpne kjernekildene, for eksempel
#define O_WRONLY 00000001
#define O_CREAT 00000100
#define O_TRUNC 00001000
Vi kombinerer alle verdiene til en, vi får 00001101
Kjører vår samtale fra gdb
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Så vi fikk en ny filbeskrivelse med nummer 4 og en ny åpen fil på en annen partisjon, sjekk:
(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
Vi husker eksempelet med pipe - hvordan bash endrer filbeskrivelser, og har allerede lært dup2-systemkallet.
Prøver å erstatte en filbeskrivelse med en annen
(gdb) call dup2(4,3)
$2 = 3
Vi sjekker:
(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
Lukk filbeskrivelse 4, siden vi ikke trenger den:
(gdb) call close (4)
$1 = 0
Og gå ut av 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
Sjekker den nye filen:
[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
Som du kan se, blir dataene skrevet til en ny fil, vi sjekker den gamle:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Dataene går ikke tapt, applikasjonen fungerer, loggene skrives til et nytt sted.
La oss gjøre ting litt vanskeligere
Tenk deg at dataene er viktige for oss, men vi har ikke diskplass i noen av partisjonene og vi kan ikke koble til disken.
Det vi kan gjøre er å omdirigere dataene våre et sted, for eksempel til et rør, og omdirigere dataene fra røret til nettverket gjennom et eller annet program, for eksempel netcat.
Vi kan lage et navngitt rør med mkfifo-kommandoen. Den vil lage en pseudofil på filsystemet, selv om det ikke er ledig plass på den.
Start applikasjonen på nytt og sjekk:
[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
Det er ingen diskplass, men vi har opprettet en navngitt pipe der:
[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å må vi på en eller annen måte pakke alle dataene som kommer inn i dette røret til en annen server gjennom nettverket, den samme nettkatten er egnet for dette.
Kjør på ekstern-server.example.com-serveren
[user@localhost ~]$ nc -l 7777 > 123.txt
På vår problemserver, kjør i en egen terminal
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Nå vil all data som kommer inn i røret automatisk gå til stdin i netcat, som vil sende den til nettverket på port 7777.
Alt vi trenger å gjøre er å begynne å skrive dataene våre til dette navngitte røret.
Vi har allerede en applikasjon som kjører:
[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
Av alle flaggene trenger vi bare O_WRONLY siden filen allerede eksisterer og vi trenger ikke å slette den
[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
Kontrollerer den eksterne serveren remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Data kommer, vi sjekker problemserveren
[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
Dataene er lagret, problemet er løst.
Jeg benytter anledningen til å hilse på kolleger fra Degiro.
Lytt til Radio-T-podcaster.
Helt fint.
Som en hjemmelekse foreslår jeg å tenke på hva som vil være i filbeskrivelsene til katten og søvnprosessen hvis du kjører følgende kommando:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Kilde: www.habr.com