Unwaith, yn ystod cyfweliad, gofynnwyd i mi, beth fyddwch chi'n ei wneud os gwelwch wasanaeth nad yw'n gweithio oherwydd bod y ddisg wedi rhedeg allan o le?
Wrth gwrs, atebais y byddwn yn gweld beth oedd yn cael ei feddiannu gan y lle hwn ac, os yn bosibl, byddwn yn glanhau'r lle.
Yna gofynnodd y cyfwelydd, beth os nad oes lle am ddim ar y rhaniad, ond hefyd nad ydych chi'n gweld unrhyw ffeiliau a fyddai'n cymryd yr holl le?
I hyn dywedais y gallwch chi bob amser edrych ar ddisgrifyddion ffeiliau agored, er enghraifft gyda'r gorchymyn lsof, a deall pa raglen sydd wedi cymryd yr holl le sydd ar gael, ac yna gallwch chi weithredu yn ôl yr amgylchiadau, yn dibynnu a oes angen y data .
Fe wnaeth y cyfwelydd dorri ar draws fi ar y gair olaf, gan ychwanegu at ei gwestiwn: “Tybiwch nad oes angen y data arnom, dim ond log dadfygio ydyw, ond nid yw'r cais yn gweithio oherwydd ni all ysgrifennu dadfyg”?
“Iawn,” atebais, “gallwn ddiffodd y dadfygio yng nghyfluniad y cymhwysiad a'i ailgychwyn.”
Gwrthwynebodd y cyfwelydd: “Na, ni allwn ailgychwyn y cais, mae gennym ni ddata pwysig wedi’i storio yn y cof o hyd, ac mae cleientiaid pwysig wedi’u cysylltu â’r gwasanaeth ei hun, na allwn orfodi i ailgysylltu eto.”
“iawn,” dywedais, “os na allwn ailgychwyn y rhaglen ac nad yw'r data'n bwysig i ni, yna gallwn glirio'r ffeil agored hon trwy'r disgrifydd ffeil, hyd yn oed os nad ydym yn ei weld yn y gorchymyn ls ar y system ffeiliau.”
Roedd y cyfwelydd yn falch, ond doeddwn i ddim.
Yna meddyliais, pam nad yw'r person sy'n profi fy ngwybodaeth yn cloddio'n ddyfnach? Ond beth os yw'r data'n bwysig wedi'r cyfan? Beth os na allwn ailgychwyn proses, a bod y broses yn ysgrifennu at y system ffeiliau ar raniad sydd heb le am ddim? Beth os na allwn golli nid yn unig y data sydd eisoes wedi'i ysgrifennu, ond hefyd y data y mae'r broses hon yn ei ysgrifennu neu'n ceisio ei ysgrifennu?
Tuzik
Yn gynnar yn fy ngyrfa, ceisiais greu cymhwysiad bach a oedd angen storio gwybodaeth defnyddwyr. Ac yna meddyliais, sut alla i baru'r defnyddiwr â'i ddata. Er enghraifft, mae gen i Ivanov Ivan Ivanovich, ac mae ganddo rywfaint o wybodaeth, ond sut alla i wneud ffrindiau gyda nhw? Gallaf nodi'n uniongyrchol bod y ci o'r enw “Tuzik” yn perthyn i'r union Ivan hwn. Ond beth os bydd yn newid ei enw ac yn lle Ivan yn dod, er enghraifft, Olya? Yna bydd yn troi allan na fydd gan ein Olya Ivanovna Ivanova gi mwyach, a bydd ein Tuzik yn dal i fod yn perthyn i'r Ivan nad yw'n bodoli. Fe wnaeth cronfa ddata a roddodd ddynodwr unigryw (ID) i bob defnyddiwr helpu i ddatrys y broblem hon, ac roedd fy Tuzik ynghlwm wrth yr ID hwn, a oedd, mewn gwirionedd, yn rhif cyfresol yn unig. Felly, roedd gan berchennog yr ace ID rhif 2, ac ar ryw adeg roedd Ivan o dan yr ID hwn, ac yna daeth Olya o dan yr un ID. Cafodd problem dynoliaeth a hwsmonaeth anifeiliaid ei datrys yn ymarferol.
Disgrifydd ffeil
Mae problem y ffeil a'r rhaglen sy'n gweithio gyda'r ffeil hon tua'r un peth â phroblem ein ci a'n dyn. Tybiwch imi agor ffeil o'r enw ivan.txt a dechrau ysgrifennu'r gair tuzik i mewn iddo, ond dim ond llwyddo i ysgrifennu'r llythyren gyntaf “t” yn y ffeil, ac ailenwyd y ffeil hon gan rywun, er enghraifft, i olya.txt. Ond mae'r ffeil yn aros yr un fath, a dwi dal eisiau cofnodi fy ace ynddo. Bob tro mae ffeil yn cael ei hagor gan alwad system
Yn Linux, mae'r llyfrgell libc yn agor 3 ffeil disgrifydd ar gyfer pob rhaglen redeg (proses), wedi'i rhifo 0,1,2. Ceir rhagor o wybodaeth ar y dolenni
- Gelwir disgrifydd ffeil 0 yn STDIN ac mae'n gysylltiedig â mewnbwn cymhwysiad
- Gelwir disgrifydd ffeil 1 yn STDOUT ac fe'i defnyddir gan gymwysiadau i allbynnu data, megis gorchmynion argraffu
- Gelwir disgrifydd ffeil 2 yn STDERR ac fe'i defnyddir gan gymwysiadau i allbynnu negeseuon gwall.
Os byddwch chi'n agor unrhyw ffeil ar gyfer darllen neu ysgrifennu yn eich rhaglen, yna mae'n fwyaf tebygol y byddwch chi'n cael yr ID cyntaf am ddim a dyma fydd rhif 3.
Gellir gweld y rhestr o ddisgrifyddion ffeil ar gyfer unrhyw broses os ydych yn gwybod ei DCP.
Er enghraifft, gadewch i ni agor y consol bash ac edrych ar PID ein proses
[user@localhost ]$ echo $$
15771
Yn yr ail gonsol gadewch i ni redeg
[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
Gallwch anwybyddu disgrifydd ffeil rhif 255 yn ddiogel at ddibenion yr erthygl hon; fe'i hagorwyd ar gyfer ei anghenion gan bash ei hun, ac nid gan y llyfrgell gysylltiedig.
Nawr mae pob un o'r 3 ffeil disgrifydd yn gysylltiedig â'r ddyfais derfynell ffug
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
Ac yn y consol cyntaf byddwn yn gweld
[user@localhost ]$ hello world
Ailgyfeirio a Pipe
Gallwch chi ddiystyru'r 3 ffeil disgrifydd hyn yn hawdd mewn unrhyw broses, gan gynnwys mewn bash, er enghraifft trwy bibell sy'n cysylltu dwy broses, gweler
[user@localhost ]$ cat /dev/zero | sleep 10000
Gallwch chi redeg y gorchymyn hwn eich hun gyda strap -f a gweld beth sy'n digwydd y tu mewn, ond byddaf yn dweud wrthych yn fyr.
Mae ein proses bash rhiant gyda PID 15771 yn dosrannu ein gorchymyn ac yn deall yn union faint o orchmynion yr ydym am eu rhedeg, yn ein hachos ni mae dau ohonyn nhw: cath a chysgu. Mae Bash yn gwybod bod angen iddo greu prosesau dau blentyn, a'u huno yn un bibell. Yn gyfan gwbl, bydd angen 2 broses plentyn ac un bibell ar bash.
Mae Bash yn rhedeg galwad system cyn creu prosesau plentyn
Ar gyfer y broses rhiant, mae'n edrych fel bod pibell eisoes, ond nid oes prosesau plentyn eto:
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
Yna defnyddio'r alwad system
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
Peidiwch ag anghofio bod clôn yn clonio'r broses ynghyd â'r holl ddisgrifyddion ffeil, felly byddant yr un peth yn y broses rhiant ac yn y rhai plentyn. Gwaith y broses rhiant gyda PID 15771 yw monitro prosesau'r plentyn, felly mae'n aros am ymateb gan y plant.
Felly, nid oes angen pibell arno, ac mae'n cau disgrifyddion ffeiliau rhif 3 a 4.
Yn y broses bash plentyn cyntaf gyda PID 9004, y system alwad
Yn y broses ail blentyn gyda PID 9005, mae bash yn defnyddio dup2 i newid y disgrifydd ffeil rhif STDIN 0. Nawr bydd popeth y bydd ein hail bash gyda PID 9005 yn ei ddarllen yn cael ei ddarllen o'r bibell.
Ar ôl hyn, mae disgrifyddion ffeiliau rhif 3 a 4 hefyd ar gau yn y prosesau plentyn, gan nad ydynt yn cael eu defnyddio mwyach.
Rwy’n anwybyddu disgrifydd ffeil 255 yn fwriadol; caiff ei ddefnyddio at ddibenion mewnol gan bash ei hun a bydd hefyd yn cael ei gau mewn prosesau plant.
Nesaf, yn y broses plentyn cyntaf gyda PID 9004, mae bash yn dechrau defnyddio galwad system
Yn y broses ail blentyn gyda PID 9005, mae bash yn rhedeg yr ail weithredadwy a nodwyd gennym, yn ein hachos ni /usr/bin/cwsg.
Nid yw'r alwad system exec yn cau dolenni ffeiliau oni bai eu bod wedi'u hagor gyda'r faner O_CLOEXEC ar yr adeg y gwnaed yr alwad agored. Yn ein hachos ni, ar ôl lansio'r ffeiliau gweithredadwy, bydd yr holl ddisgrifyddion ffeil cyfredol yn cael eu cadw.
Gwiriwch yn y consol:
[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
Fel y gwelwch, mae nifer unigryw ein pibell yr un peth yn y ddwy broses. Felly mae gennym gysylltiad rhwng dwy broses wahanol gyda'r un rhiant.
I'r rhai nad ydynt yn gyfarwydd â'r galwadau system y mae bash yn eu defnyddio, rwy'n argymell yn fawr rhedeg y gorchmynion trwy strace a gweld beth sy'n digwydd yn fewnol, er enghraifft fel hyn:
strace -s 1024 -f bash -c "ls | grep hello"
Gadewch i ni ddychwelyd at ein problem gyda gofod disg isel a cheisio arbed data heb ailgychwyn y broses. Gadewch i ni ysgrifennu rhaglen fach a fydd yn ysgrifennu tua 1 megabeit yr eiliad i ddisg. Ar ben hynny, os nad oeddem yn gallu ysgrifennu data i'r ddisg am ryw reswm, byddwn yn anwybyddu hyn ac yn ceisio ysgrifennu'r data eto mewn eiliad. Yn yr enghraifft rydw i'n defnyddio Python, gallwch chi ddefnyddio unrhyw iaith raglennu arall.
[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
Gadewch i ni redeg y rhaglen ac edrych ar y disgrifyddion ffeil
[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
Fel y gallwch weld, mae gennym ein 3 disgrifydd ffeil safonol ac un arall a agorwyd gennym. Gadewch i ni wirio maint y ffeil:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
Mae'r data yn cael ei ysgrifennu, rydym yn ceisio newid y caniatâd ar y ffeil:
[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
Gwelwn fod y data yn dal i gael ei ysgrifennu, er nad oes gan ein defnyddiwr ganiatâd i ysgrifennu at y ffeil. Gadewch i ni geisio cael gwared arno:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Ble mae'r data wedi'i ysgrifennu? Ac a ydynt yn ysgrifenedig o gwbl? Rydym yn gwirio:
[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)
Ydy, mae ein disgrifydd ffeil yn dal i fodoli a gallwn drin y disgrifydd ffeil hwn fel ein hen ffeil, gallwn ei darllen, ei chlirio a'i chopïo.
Edrychwn ar faint y ffeil:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Maint y ffeil yw 19923457. Gadewch i ni geisio clirio'r ffeil:
[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
Fel y gallwch weld, dim ond cynyddu maint y ffeil ac ni weithiodd ein boncyff. Edrychwn ar ddogfennaeth galwadau'r system
with open("123.txt", "w") as f:
mae'n rhaid i ni roi
with open("123.txt", "a") as f:
Gwirio gyda'r faner “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
a chyda baner "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
Rhaglennu proses sydd eisoes yn rhedeg
Yn aml, mae rhaglenwyr, wrth greu a phrofi rhaglenni, yn defnyddio dadfygwyr (er enghraifft GDB) neu lefelau amrywiol o fewngofnodi yn y rhaglen. Mae Linux yn darparu'r gallu i ysgrifennu a newid rhaglen sydd eisoes yn rhedeg, er enghraifft, newid gwerthoedd newidynnau, gosod torbwynt, ac ati, ac ati.
Gan ddychwelyd at y cwestiwn gwreiddiol am ddim digon o le ar ddisg i ysgrifennu ffeil, gadewch i ni geisio efelychu'r broblem.
Gadewch i ni greu ffeil ar gyfer ein rhaniad, y byddwn yn ei osod fel disg ar wahân:
[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 ~]$
Gadewch i ni greu system ffeiliau:
[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 ~]$
Gosodwch y system ffeiliau:
[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
Rydym yn creu cyfeiriadur gyda'n perchennog:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Gadewch i ni agor y ffeil i'w hysgrifennu yn ein rhaglen yn unig:
with open("/mnt/logs/123.txt", "w") as f:
Lansio
[user@localhost ]$ python openforwrite.py
Rydym yn aros ychydig eiliadau
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Felly, mae gennym y broblem a ddisgrifir ar ddechrau'r erthygl hon. Lle am ddim 0, 100% wedi'i feddiannu.
Cofiwn, yn ôl amodau’r dasg, ein bod yn ceisio cofnodi data pwysig iawn na ellir ei golli. Ac ar yr un pryd, mae angen i ni drwsio'r gwasanaeth heb ailgychwyn y broses.
Gadewch i ni ddweud bod gennym le ar ddisg o hyd, ond mewn rhaniad gwahanol, er enghraifft yn / cartref.
Gadewch i ni geisio “ailraglennu ar y hedfan” ein cod.
Edrychwn ar PID ein proses, sydd wedi bwyta'r holl le ar y ddisg:
[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
Cysylltwch â'r broses trwy gdb
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Edrychwn ar y disgrifyddion ffeil agored:
(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
Edrychwn ar y wybodaeth am ddisgrifydd ffeil rhif 3, sydd o ddiddordeb i ni
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Gan gadw mewn cof pa alwad system y mae Python yn ei gwneud (gweler uchod lle rhedon ni'n ddirybudd a dod o hyd i'r alwad agored), wrth brosesu ein cod i agor ffeil, rydyn ni'n gwneud yr un peth ein hunain ar ran ein proses, ond mae angen yr O_WRONLY|O_CREAT| Mae didau O_TRUNC yn disodli gyda gwerth rhifol. I wneud hyn, agorwch y ffynonellau cnewyllyn, er enghraifft
#diffinio O_WRONLY 00000001
#diffinio O_CREAT 00000100
#diffinio O_TRUNC 00001000
Rydym yn cyfuno'r holl werthoedd yn un, rydym yn cael 00001101
Rydym yn rhedeg ein galwad o gdb
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Felly cawsom ddisgrifydd ffeil newydd gyda rhif 4 a ffeil agored newydd ar raniad arall, rydym yn gwirio:
(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
Rydyn ni'n cofio'r enghraifft gyda phibell - sut mae bash yn newid disgrifyddion ffeil, ac rydyn ni eisoes wedi dysgu'r alwad system dup2.
Rydym yn ceisio disodli un disgrifydd ffeil am un arall
(gdb) call dup2(4,3)
$2 = 3
Rydym yn gwirio:
(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
Rydym yn cau disgrifydd ffeil 4, gan nad oes ei angen arnom:
(gdb) call close (4)
$1 = 0
Ac ymadael 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
Wrthi'n gwirio'r ffeil newydd:
[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
Fel y gallwch weld, mae'r data wedi'i ysgrifennu i ffeil newydd, gadewch i ni wirio'r hen un:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Nid oes unrhyw ddata yn cael ei golli, mae'r rhaglen yn gweithio, mae logiau'n cael eu hysgrifennu i leoliad newydd.
Gadewch i ni gymhlethu'r dasg ychydig
Dychmygwn fod y data yn bwysig i ni, ond nid oes gennym le ar ddisg yn unrhyw un o'r rhaniadau ac ni allwn gysylltu'r ddisg.
Yr hyn y gallwn ei wneud yw ailgyfeirio ein data yn rhywle, er enghraifft i bibell, ac yn ei dro ailgyfeirio data o bibell i'r rhwydwaith drwy ryw raglen, er enghraifft netcat.
Gallwn greu pibell a enwir gyda'r gorchymyn mkfifo. Bydd yn creu ffeil ffug ar y system ffeiliau hyd yn oed os nad oes lle am ddim arno.
Ailgychwyn y cais a gwirio:
[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
Nid oes lle ar y ddisg, ond rydym yn llwyddo i greu pibell a enwir yno:
[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
Nawr mae angen i ni rywsut lapio'r holl ddata sy'n mynd i'r bibell hon i weinydd arall trwy'r rhwydwaith; mae'r un netcat yn addas ar gyfer hyn.
Ar y gweinydd pell-server.example.com rydym yn rhedeg
[user@localhost ~]$ nc -l 7777 > 123.txt
Ar ein gweinydd problemus rydym yn lansio mewn terfynell ar wahân
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Nawr bydd yr holl ddata sy'n dod i ben yn y bibell yn mynd yn awtomatig i stdin yn netcat, a fydd yn ei anfon i'r rhwydwaith ar borthladd 7777.
Y cyfan sy'n rhaid i ni ei wneud yw dechrau ysgrifennu ein data i'r bibell hon a enwir.
Mae gennym y cais yn rhedeg yn barod:
[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
O'r holl fflagiau, dim ond O_WRONLY sydd ei angen arnom gan fod y ffeil eisoes yn bodoli ac nid oes angen i ni ei chlirio
[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
Gwirio'r gweinydd pell remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Mae'r data yn dod, rydym yn gwirio'r gweinydd problem
[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
Mae'r data yn cael ei arbed, mae'r broblem yn cael ei datrys.
Manteisiaf ar y cyfle hwn i ddweud helo wrth fy nghydweithwyr o Degiro.
Gwrandewch ar bodlediadau Radio-T.
Pob peth yn dda.
Fel gwaith cartref, rwy'n awgrymu eich bod chi'n meddwl beth fydd yn y disgrifiadau ffeil proses cath a chysgu os ydych chi'n rhedeg y gorchymyn canlynol:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Ffynhonnell: hab.com