Danasîna pelê di Linux de bi mînakan

Carekê, di dema hevpeyivînekê de, ji min hat pirsîn, ger hûn karûbarek bibînin ku nexebite ji ber ku cîh qediya ye hûn ê çi bikin?

Bê guman, min bersiv da ku ez ê bibînim ku ev der çi ye û heke gengaz be, ez ê cîh paqij bikim.
Dûv re hevpeyivîn pirsî, heke cîhê belaş li ser dabeşkirinê tune be, lê hûn jî pelên ku dê hemî cîh bigire nabînin?

Ji bo vê yekê min got ku hûn her gav dikarin li ravekerên pelê vekirî binêrin, mînakî bi fermana lsof, û fêm bikin ka kîjan serîlêdanê hemî cîhê berdest girtiye, û dûv re hûn dikarin li gorî şert û mercan tevbigerin, li gorî ka dane hewce ne. .

Hevpeyvîn di peyva dawîn de min qut kir û li ser pirsa xwe zêde kir: "Bihesibînin ku em ne hewceyî daneyê ne, ew tenê têketinek debugê ye, lê serîlêdan naxebite ji ber ku nikare xeletiyek binivîse"?

"Baş e," min bersivand, "em dikarin debugkirinê di mîhenga serîlêdanê de vekin û ji nû ve bidin destpêkirin."
Hevpeyvîn îtîraz kir: "Na, em nekarin serîlêdanê ji nû ve bidin destpêkirin, hîn jî daneyên me yên girîng di bîranînê de hatine hilanîn, û xerîdarên girîng bi karûbarê bixwe ve girêdayî ne, ku em nikanin bi zorê ji nû ve ve girêbidin."

"baş e," min got, "heke em nikaribin serîlêdanê ji nû ve bidin destpêkirin û dane ji me re ne girîng in, wê hingê em dikarin bi hêsanî vê pelê vekirî bi navgîniya pelê paqij bikin, her çend em wê di fermana ls de nebînin jî. li ser pergala pelan."

Hevpeyvîn kêfxweş bû, lê ez ne kêfxweş bûm.

Dûv re ez fikirîm, çima kesê ku zanîna min diceribîne kûrtir nakole? Lê çi dibe bila bibe heke daneyan piştî her tiştî girîng e? Ger em nikaribin pêvajoyek ji nû ve bidin destpêkirin, û pêvajo li ser perçeyek ku cîhê belaş tune ye pergala pelan binivîse? Ger em ne tenê daneyên ku berê hatine nivîsandin, lê di heman demê de daneyên ku ev pêvajo dinivîse an hewl dide ku binivîsîne jî winda nekin?

Tuzik

Di destpêka kariyera xwe de, min hewl da ku serîlêdanek piçûk biafirînim ku hewce dike ku agahdariya bikarhêner hilîne. Û dûv re ez fikirîm, ez çawa dikarim bikarhêner bi daneyên wî re li hev bikim. Mînakî, min Ivanov Ivan Ivanovich heye, û hin agahdariya wî heye, lê ez çawa dikarim bi wan re hevaltiyê bikim? Ez rasterast dikarim bibêjim ku kûçikê bi navê "Tûzik" yê vî Îvan e. Lê eger ew navê xwe biguherîne û li şûna Îvan bibe, mînakî, Olya? Wê çaxê dê derkeve holê ku Olya Îvanovna Îvanovaya me êdî kûçikê wê namîne û Tûzikê me jî dê bibe ya Îvanê tune. Databasek ku ji her bikarhênerek nasnameyek yekta (ID) dida, alîkariya çareserkirina vê pirsgirêkê kir, û Tuzikê min bi vê nasnameyê ve girêdayî bû, ku, bi rastî, tenê jimareyek rêzik bû. Bi vî rengî, xwediyê ace xwedan nasnameya 2-yê bû, û di demekê de Ivan di bin vê nasnameyê de bû, û paşê Olya di bin heman nasnameyê de bû. Pirsgirêka mirovahî û sewalkariyê bi pratîkî çareser bû.

Danasîna pelê

Pirsgirêka dosya û bernameya ku bi vê pelê re dixebite bi qasî ya kûçik û merivê me ye. Bifikirin ku min dosyayek bi navê ivan.txt vekir û min dest bi nivîsandina peyva tuzik di wê de kir, lê tenê karî ku di pelê de tîpa yekem "t" binivîsim û navê vê pelê ji aliyê kesekî ve hat guherandin, wek nimûne, olya.txt. Lê dosya wek xwe dimîne, û ez dîsa jî dixwazim ace xwe tê de tomar bikim. Her gava ku pelek bi banga pergalê ve tê vekirin vekirî di her zimanekî bernamesaziyê de ez nasnameyek yekta distînim ku min nîşanî pelek dide, ev nasname ravekera pelê ye. Û qet ferq nake ku paşî vê pelê çi û kê bike, ew dikare were jêbirin, dikare bê nav kirin, xwedan dikare were guhertin, an mafên xwendin û nivîsandinê ji dest were girtin, ez ê dîsa jî bigihîjim jê re, ji ber ku di dema vekirina dosyayê de, mafê min hebû ku ez wê bixwînim û/an binivîsim û min karî pê re dest bi xebatê bikim, yanî divê ez vî karî bidomînim.

Di Linuxê de, pirtûkxaneya libc ji bo her serîlêdana (pêvajoya) xebitandinê 3 pelên ravekerê vedike, bi jimareya 0,1,2. Agahiyên bêtir dikarin li ser girêdanan bibînin man stdio и man stdout

  • Danasîna pelê 0 jê re STDIN tê gotin û bi têketina serîlêdanê re têkildar e
  • Danasîna pelê 1 jê re STDOUT tê gotin û ji hêla sepanan ve tê bikar anîn da ku daneyan derxe, wek fermanên çapkirinê.
  • Danasîna pelê 2 jê re STDERR tê gotin û ji hêla serîlêdanan ve tê bikar anîn da ku peyamên xeletiyê derxîne.

Ger hûn di bernameya xwe de pelek ji bo xwendin an nivîsandinê vekin, wê hingê bi îhtîmalek mezin hûn ê yekem nasnameya belaş bistînin û ew ê bibe jimare 3.

Ger hûn PID-a wê zanibin navnîşa ravekerên pelan ji bo her pêvajoyê dikare were dîtin.

Mînakî, em konsolê bash vekin û li PID-a pêvajoya xwe binihêrin

[user@localhost ]$ echo $$
15771

Di konsolê duyemîn de em birevin

[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

Ji bo mebestên vê gotarê hûn dikarin bi ewlehî ravekera pelê 255 ji bîr nekin; ew ji bo hewcedariyên wê ji hêla bash-ê ve hatî vekirin, ne ji hêla pirtûkxaneya girêdayî ve.

Naha her 3 pelên danasînê bi cîhaza termînala pseudo ve girêdayî ne /dev/pts, lê dîsa jî em dikarin wan manîpule bikin, mînakî, wan di konsolek duyemîn de bimeşînin

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

Û di konsolê yekem de em ê bibînin

[user@localhost ]$ hello world

Beralîkirin û Pipe

Hûn dikarin bi hêsanî van 3 pelên ravekerê di her pêvajoyê de, di nav de bash, ji holê rakin, mînakî bi boriyek ku du pêvajoyan bi hev ve girêdide, binêre

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

Hûn dikarin bi xwe re vê fermanê bimeşînin strace -f û binêre ka li hundur çi diqewime, lê ez ê bi kurtî ji we re bibêjim.

Pêvajoya bash-a me ya bi PID 15771 emrê me pars dike û tam fam dike ka em çend fermanan dixwazin bimeşînin, di doza me de du ji wan hene: pisîk û xew. Bash dizane ku ew hewce dike ku du pêvajoyên zarokan biafirîne, û wan di yek boriyekê de bike yek. Bi tevahî, bash dê 2 pêvajoyên zarokan û yek boriyek hewce bike.

Bash berî ku pêvajoyên zarokan biafirîne bangek pergalê dimeşîne lûle û ravekerên pelê yên nû li ser tampona boriyê ya demkî distîne, lê ev tampon hîn du pêvajoyên me yên zarokî bi hev ve girê nade.

Ji bo pêvajoya dêûbav, wusa dixuye ku jixwe boriyek heye, lê hîna pêvajoyên zarokan tune ne:

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

Dûv re banga pergalê bikar tînin clone bash du pêvajoyên zarokan diafirîne, û sê pêvajoyên me dê bi vî rengî xuya bikin:

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

Ji bîr nekin ku klon bi hemî ravekerên pelan re pêvajoyê klon dike, ji ber vê yekê ew ê di pêvajoya dêûbav û ya zarokan de heman bin. Karê pêvajoya dêûbav bi PID 15771 çavdêriya pêvajoyên zarokan e, ji ber vê yekê ew tenê li benda bersivek zarokan e.

Ji ber vê yekê, ew ne hewceyê boriyê ye, û ew ravekerên pelê yên bi jimare 3 û 4 digire.

Di yekem pêvajoya bash a zarokê de bi PID 9004, banga pergalê dup2, ravekera pelê STDOUT jimare 1 diguhezîne ravekerek pelê ku boriyê nîşan dide, di rewşa me de ew hejmar 3 ye. Bi vî rengî, her tiştê ku pêvajoya zaroka yekem a bi PID 9004 li STDOUT dinivîse dê bixweber di nav tampona boriyê de biqede.

Di pêvajoya zaroka duyemîn a bi PID 9005-ê de, bash dup2 bikar tîne da ku ravekera pelê STDIN-jimar 0 biguhezîne. Naha her tiştê ku bash-a meya duyemîn a bi PID 9005-ê wê bixwîne dê ji boriyê were xwendin.

Piştî vê yekê, ravekerên pelê yên bi jimare 3 û 4 jî di pêvajoyên zarokan de têne girtin, ji ber ku ew êdî nayên bikar anîn.

Ez bi qestî ravekera pelê 255 paşguh dikim; ew ji hêla bash-ê ve ji bo armancên hundurîn tê bikar anîn û dê di pêvajoyên zarokan de jî were girtin.

Dûv re, di yekem pêvajoya zarokê de bi PID 9004, bash dest bi karanîna bangek pergalê dike exec pelê îcrakar ku me li ser rêzika fermanê diyar kiriye, di rewşa me de ew /usr/bin/cat e.

Di pêvajoya zarokê ya duyemîn de bi PID 9005, bash di doza me de /usr/bin/sleep de cîbicîkirina duyemîn a ku me diyar kiriye dimeşîne.

Banga pergala exec destikên pelan nagire heya ku di dema banga vekirî de bi ala O_CLOEXEC venebin. Di rewşa me de, piştî destpêkirina pelên darvekirî, dê hemî ravekerên pelê yên heyî werin tomarkirin.

Di konsolê de kontrol bikin:

[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

Wekî ku hûn dibînin, hejmara yekta ya boriyê me di her du pêvajoyan de yek e. Ji ber vê yekê di navbera du pêvajoyên cûda de bi dêûbav re têkiliyek me heye.

Ji bo kesên ku bi bangên pergalê yên ku bash bikar tîne nizanin, ez bi tundî pêşniyar dikim ku fermanan bi riya strace bimeşînin û bibînin ka çi di hundurê de diqewime, mînakî bi vî rengî:

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

Ka em vegerin ser pirsgirêka xwe ya bi cîhê dîskê kêm û hewl didin ku daneyan hilînin bêyî destpêkirina pêvajoyê. Ka em bernameyek piçûk binivîsin ku dê bi qasî 1 megabyte serê saniyeyê li ser dîskê binivîsîne. Wekî din, heke ji ber hin sedeman me nikarîbû daneyan li ser dîskê binivîsin, em ê tenê vê yekê paşguh bikin û hewl bidin ku di saniyeyekê de dîsa daneyan binivîsin. Di mînaka ku ez Python bikar tînim, hûn dikarin her zimanek bernamenûsê din bikar bînin.

[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

Ka em bernameyê bimeşînin û li ravekerên pelan binêrin

[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

Wekî ku hûn dibînin, me 3 ravekerên pelê standard û yeka ku me vekir heye. Ka em mezinahiya pelê kontrol bikin:

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

Daneyên têne nivîsandin, em hewl didin ku destûrên li ser pelê biguherînin:

[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

Em dibînin ku dane hîn jî têne nivîsandin, her çend bikarhênerê me destûr nîne ku li pelê binivîsîne. Ka em hewl bidin ku wê jêbirin:

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

Daneyên li ku têne nivîsandin? Û ew bi tevahî têne nivîsandin? Em kontrol dikin:

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

Erê, ravekerê pelê me hîn jî heye û em dikarin vê ravekera pelê wekî pelê xweya kevn bişopînin, em dikarin wê bixwînin, paqij bikin û kopî bikin.

Ka em li mezinahiya pelê binêrin:

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

Mezinahiya pelê 19923457 e. Ka em hewl bidin ku pelê paqij bikin:

[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

Wekî ku hûn dibînin, mezinahiya pelê tenê zêde dibe û qurmê me nexebitî. Ka em li belgeya banga pergalê binêrin vekirî. Ger em ala O_APPEND dema vekirina pelek bikar bînin, wê hingê bi her nivîsandinê re, pergala xebitandinê mezinahiya pelê kontrol dike û daneyan heya dawiya pelê dinivîse, û vê yekê bi atomî dike. Ev dihêle ku gelek mijar an pêvajoyên li heman pelê binivîsin. Lê di koda xwe de em vê alê bikar naynin. Tenê heke em pelê ji bo nivîsandina zêde vekin, ku di şûna koda me de tê vê wateyê, em dikarin mezinahiya pelê ya cihêreng di lsof-ê de piştî qurmê bibînin.

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

divê em deynin

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

Kontrolkirina bi ala "w".

[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

û bi ala "a".

[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

Bernamekirin pêvajoyek jixwe dimeşe

Pir caran bernamenûs, dema ku bernameyan diafirînin û ceribandinê, debuggeran (mînak GDB) an astên cihêreng ên têketinê di serîlêdanê de bikar tînin. Linux îmkana nivîsandinê û guheztina bi rastî bernameyek ku jixwe tê xebitandin peyda dike, mînakî, guheztina nirxên guhêrbaran, danîna xalek veqetandinê, hwd., hwd.

Em vegerin ser pirsa orîjînal a di derbarê ne cîhê dîskê de ji bo nivîsandina pelê, em hewl bidin ku pirsgirêkê simule bikin.

Ka em ji bo dabeşkirina xwe pelek biafirînin, ku em ê wekî dîskek veqetandî hilînin:

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

Ka em pergalek pelan biafirînin:

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

Pergala pelan saz bikin:

[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

Em bi xwediyê xwe re pelrêçek çêdikin:

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

Ka em pelê tenê di bernameya xwe de ji bo nivîsandinê vekin:

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

Destpêkirin

[user@localhost ]$ python openforwrite.py 

Em çend saniyan bisekinin

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

Ji ber vê yekê, me pirsgirêka ku di destpêka vê gotarê de hatî destnîşan kirin heye. Cihê belaş 0, 100% dagirkirî.

Em bi bîr tînin ku li gorî şert û mercên peywirê, em hewl didin daneyên pir girîng ên ku neyên windakirin tomar bikin. Û di heman demê de, pêdivî ye ku em karûbarê bêyî destpêkirina pêvajoyê rast bikin.

Ka em bibêjin hîn cîhê dîskê me heye, lê di dabeşek cûda de, mînakî li /home.

Werin em hewl bidin ku koda xwe "ji nû ve bername" bikin.

Ka em li PID-a pêvajoya xwe binêrin, ku hemî cîhê dîskê xwariye:

[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

Bi pêvajoya gdb ve girêdayî ye

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

Ka em li ravekerên pelê vekirî binêrin:

(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

Em li agahdariya di derheqê pelê jimare 3 de, ku me eleqedar dike, dinêre

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

Dema ku em koda xwe ji bo vekirina pelê vedikin, ji bîr mekin ku navê Python kîjan pergalê dike (li jor binêre ku me li ku derê rêve kir û banga vekirî dît), em bi xwe jî li ser navê pêvajoya xwe heman tiştî dikin, lê em hewceyê O_WRONLY|O_CREAT| Bîtên O_TRUNC bi nirxek jimareyî diguhezînin. Ji bo vê yekê, ji bo nimûne, çavkaniyên kernel vekin vir û binerin kîjan al ji çi berpirsiyar in

#define O_WRONLY 00000001
# define O_CREAT 00000100
# define O_TRUNC 00001000

Em hemî nirxan di yek yek de berhev dikin, em 00001101 distînin

Em banga xwe ji gdb dimeşînin

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

Ji ber vê yekê me ravekerek pelê ya nû ya bi hejmara 4 û pelek nû ya vekirî li ser dabeşek din peyda kir, em kontrol dikin:

(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

Em mînaka bi boriyê bi bîr tînin - ka bash çawa ravekerên pelan diguhezîne, û em berê fêrî banga pergala dup2 bûne.

Em hewl didin ku ravekerek pelê bi yekî din veguherînin

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

Em kontrol dikin:

(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

Em şirovekara pelê 4 digirin, ji ber ku em ne hewce ne:

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

Û ji gdb derkeve

(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

Kontrolkirina pelê nû:

[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

Wekî ku hûn dikarin bibînin, dane li pelek nû hatî nivîsandin, ka em ya kevin kontrol bikin:

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

Ti dane winda nabe, serîlêdan dixebite, têketin li cîhek nû têne nivîsandin.

Werin em kar hinekî tevlihev bikin

Ka em bifikirin ku dane ji me re girîng in, lê cîhê me yê dîskê di yek ji dabeşan de tune ye û em nikanin dîskê girêbidin.

Tiştê ku em dikarin bikin ev e ku daneyên xwe li cîhek beralî bikin, mînakî boriyê, û di encamê de daneyan ji boriyê ber bi torê ve bi hin bernameyekê verast bikin, mînakî netcat.
Em dikarin bi fermana mkfifo boriyek binavkirî biafirînin. Ew ê li ser pergala pelê pelek pseudo biafirîne heya ku cîhê belaş li ser tune be.

Serlêdanê ji nû ve bidin destpêkirin û kontrol bikin:

[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

Cihê dîskê tune ye, lê em bi serfirazî boriyek bi navê li wir diafirînin:

[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

Naha pêdivî ye ku em bi rengekî hemî daneyên ku di vê boriyê de diçin ser serverek din bi navgîniya torê ve bipêçin; heman netcat ji bo vê yekê maqûl e.

Li ser server remote-server.example.com em dimeşînin

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

Li ser servera meya pirsgirêkê em di termînalek cûda de dest pê dikin

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

Naha hemî daneyên ku di boriyê de diqedin dê bixweber biçin stdin di netcat de, ku dê wê bişîne torê li porta 7777.

Tiştê ku divê em bikin ev e ku dest bi nivîsandina daneyên xwe di vê boriya bi nav de bikin.

Jixwe serlêdana me heye:

[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

Ji hemî alayan, em tenê O_WRONLY hewce dikin ji ber ku pel jixwe heye û ne hewce ye ku em wê paqij bikin

[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

Kontrolkirina servera dûr a remote-server.example.com

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

Daneyên tê, em servera pirsgirêkê kontrol dikin

[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

Daneyên xilas kirin, pirsgirêk çareser kirin.

Ez vê firsendê bi kar tînim û silavan ji hevkarên xwe yên Degiro re bêjim.
Li podcastên Radio-T guhdarî bikin.

Hemî xweş.

Wekî karê malê, ez ji we re pêşniyar dikim ku hûn bifikirin ka dê di pêvajoyê de ravekerên pelê pisîk û xewê de çi be heke hûn fermana jêrîn bimeşînin:

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

Source: www.habr.com

Add a comment