Бир жолу интервью учурунда менден дискте орун калбай калгандыктан, кызмат иштебей калса эмне кыласыз?
Албетте, мен бул жерди эмнелер ээлегенин көрөм, мүмкүн болсо ошол жерди тазалайм деп жооп бердим.
Андан кийин интервьючу сурады, эгерде бөлүмдө бош орун жок болсо, бирок сиз бардык мейкиндикти ээлей турган файлдарды көрбөй жатсаңызчы?
Буга мен айттым, сиз ар дайым ачык файл дескрипторлорун, мисалы lsof буйругу менен карап, кайсы колдонмо бардык жеткиликтүү мейкиндикти ээлегенин түшүнсөңүз болот, андан кийин маалымат керекпи же жокпу, ошого жараша жагдайга жараша иш-аракет кыла аласыз. .
Интервьючу менин сөзүмдү токтотуп, анын суроосуна: "Бизге маалымат кереги жок дейли, бул жөн гана мүчүлүштүктөрдү оңдоо журналы, бирок колдонмо иштебейт, анткени ал мүчүлүштүктөрдү жаза албайт"?
"Макул" деп жооп бердим мен, "колдонмонун конфигурациясында мүчүлүштүктөрдү оңдоону өчүрүп, кайра иштетсек болот."
Интервьючу каршы чыкты: "Жок, биз тиркемени кайра иштете албайбыз, бизде дагы эле эстутумда сакталган маанилүү маалыматтар бар жана маанилүү кардарлар кызматтын өзүнө туташкан, биз аны кайра туташууга мажбурлай албайбыз."
"Макул" дедим мен, "эгер биз тиркемени кайра иштете албасак жана маалыматтар биз үчүн маанилүү болбосо, анда биз бул ачык файлды ls буйругунда көрбөсөк да, файлдын дескриптору аркылуу тазалай алабыз. файл системасында."
Маектешкен адам ыраазы болду, бирок мен жактырган жокмун.
Анан мен ойлодум, эмне үчүн менин билимимди сынап жаткан адам тереңирээк казбайт? Бирок, эгер маалыматтар маанилүү болсочу? Эгерде биз процессти кайра иштете албасак, жана процесс файл тутумуна бош орун жок бөлүмгө жазсачы? Эгер биз буга чейин жазылган маалыматтарды гана эмес, бул процесс жазган же жазууга аракет кылган маалыматтарды да жоготуп албасакчы?
Тузик
Карьерамдын башында мен колдонуучу маалыматын сактоо үчүн зарыл болгон кичинекей тиркемени түзүүгө аракет кылдым. Анан мен кантип колдонуучуну анын маалыматтарына дал келтирсем болот деп ойлодум. Маселен, менде Иванов Иван Иванович бар, анын бир аз маалыматы бар, бирок мен алар менен кантип достошо алам? Түз эле айта алам: “Тузик” деген ит дал ушул Иванга таандык. Ал эми атын өзгөртүп, Ивандын ордуна, мисалы, Оля болуп калсачы? Ошондо биздин Оля Ивановна Иванованын ити жок болуп калат, биздин Тузик дагы жок Ивандыкы болуп калат. Ар бир колдонуучуга уникалдуу идентификатор (ID) берген маалымат базасы бул көйгөйдү чечүүгө жардам берди жана менин Тузикем бул ID менен байланышкан, ал чындыгында жөн гана сериялык номер болчу. Ошентип, тузуктун ээсинин ID номери 2 болгон жана кайсы бир убакта Иван бул ID астында болгон, андан кийин Оля да дал ушул ID менен болгон. Адамзаттын жана мал чарбасынын проблемасы иш жузунде чечилди.
Файлдын дескриптору
Файлдын жана бул файл менен иштеген программанын көйгөйү болжол менен биздин ит менен адамдыкындай. Мен ivan.txt деген файлды ачып, ага tuzik деген сөздү жаза баштадым дейли, бирок файлга биринчи “t” тамгасын гана жаза алдым жана бул файлдын атын кимдир бирөө, мисалы, olya.txt деп өзгөрттү. Бирок файл ошол эле бойдон калууда, мен дагы ага өзүмдү жазгым келет. Файл системалык чакыруу аркылуу ачылган сайын
Linuxда libc китепканасы ар бир иштеп жаткан тиркеме (процесс) үчүн 3 номерлүү 0,1,2 дескриптор файлын ачат. Кененирээк маалыматты шилтемелерден тапса болот
- Файлдын дескриптору 0 STDIN деп аталат жана колдонмо киргизүү менен байланышкан
- Файлдын дескриптору 1 STDOUT деп аталат жана тиркемелер тарабынан басып чыгаруу буйруктары сыяктуу маалыматтарды чыгаруу үчүн колдонулат
- Файлдын дескриптору 2 STDERR деп аталат жана ката билдирүүлөрүн чыгаруу үчүн колдонмолор тарабынан колдонулат.
Эгер программаңызда окуу же жазуу үчүн кандайдыр бир файлды ачсаңыз, анда сиз биринчи акысыз ID аласыз жана ал 3-сан болот.
Файлдын дескрипторлорунун тизмесин, эгер сиз анын PIDди билсеңиз, каалаган процесс үчүн көрүүгө болот.
Мисалы, келгиле, bash консолун ачып, процессибиздин PIDди карап көрөлү
[user@localhost ]$ echo $$
15771
Экинчи консолдо чуркайлы
[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
Бул макаланын максаттары үчүн №255 файл дескрипторун этибарга албай койсоңуз болот; ал шилтемеленген китепкана тарабынан эмес, bash тарабынан өзүнүн муктаждыктары үчүн ачылган.
Эми бардык 3 дескриптор файлы псевдо терминалдык түзүлүш менен байланышкан
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
Ал эми биринчи консолдо биз көрөбүз
[user@localhost ]$ hello world
Багыттоо жана түтүк
Сиз бул 3 дескриптор файлын каалаган процессте, анын ичинде bashда, мисалы, эки процессти бириктирген түтүк аркылуу оңой эле жокко чыгара аласыз, караңыз
[user@localhost ]$ cat /dev/zero | sleep 10000
Бул буйрукту өзүңүз менен иштетсеңиз болот strace -f жана ичинде эмне болуп жатканын көр, бирок мен сага кыскача айтып берейин.
PID 15771 менен биздин ата-эне bash процессибиз биздин буйрукту талдап, канча команданы иштеткибиз келгенин так түшүнөт, биздин учурда алардын экөөсү бар: мышык жана уйку. Bash эки бала процессин түзүп, аларды бир түтүккө бириктирүү керек экенин билет. Жалпысынан, bash үчүн 2 бала процесси жана бир түтүк керек болот.
Bash бала процесстерин түзүүдөн мурун тутумдук чакырууну иштетет
Ата-эне процесси үчүн, мурунтан эле түтүк бар окшойт, бирок азырынча эч кандай бала процесстери жок:
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
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
Клон процессти бардык файлдын дескрипторлору менен бирге клондаштырарын унутпаңыз, андыктан алар ата-эне процессинде да, балада да бирдей болот. PID 15771 менен ата-эне процессинин милдети баланын процесстерин көзөмөлдөө болуп саналат, ошондуктан ал жөн гана балдардан жооп күтөт.
Ошондуктан, ал түтүктүн кереги жок, ал 3 жана 4 номерлүү файл дескрипторлорун жабат.
PID 9004 менен биринчи бала баш процессинде системалык чалуу
PID 9005 менен экинчи бала процессинде, bash STDIN саны 2 файл дескрипторун өзгөртүү үчүн dup0 колдонот. Эми PID 9005 менен экинчи башыбыз окуй турган нерселердин баары түтүктөн окулат.
Андан кийин 3 жана 4 номерлүү файл дескрипторлору дагы колдонулбай калгандыктан, бала процесстеринде жабылат.
Мен 255 файл дескрипторун атайылап этибарга албайм; ал bash тарабынан ички максаттар үчүн колдонулат жана ошондой эле бала процесстеринде жабылат.
Андан кийин, PID 9004 менен биринчи бала процессинде, bash тутумдук чакырууну колдоно баштайт
PID 9005 менен экинчи бала процессинде bash биз белгилеген экинчи аткарылуучу файлды иштетет, биздин учурда /usr/bin/sleep.
Exec тутумдук чакыруусу ачык чалуу жасалган учурда O_CLOEXEC желеги менен ачылбаса, файл туткаларын жаппайт. Биздин учурда, аткарылуучу файлдарды ишке киргизгенден кийин, бардык учурдагы файл дескрипторлору сакталат.
Консолдо текшерүү:
[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
Көрүнүп тургандай, биздин түтүктүн уникалдуу саны эки процессте бирдей. Ошентип, бир эле ата-эне менен эки башка процесстин ортосунда байланыш бар.
Bash колдонгон тутумдук чалууларды жакшы билбегендер үчүн мен буйруктарды strace аркылуу иштетүүнү жана ички ичинде эмне болуп жатканын көрүүнү сунуштайм, мисалы:
strace -s 1024 -f bash -c "ls | grep hello"
Дисктеги мейкиндиктин аздыгы жана процессти кайра баштабастан маалыматтарды сактоого аракет кылуу менен биздин көйгөйгө кайрылып көрөлү. Келгиле, дискке болжол менен секундасына 1 мегабайт жаза турган кичинекей программа жазалы. Анын үстүнө, кандайдыр бир себептерден улам биз дискке маалыматтарды жаза албай калсак, биз буга көңүл бурбай, бир секунданын ичинде кайра жазууга аракет кылабыз. Мен Python колдонуп жаткан мисалда, сиз каалаган башка программалоо тилин колдоно аласыз.
[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
Келгиле, программаны иштетип, файлдын дескрипторлорун карап көрөлү
[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
Көрүнүп тургандай, бизде 3 стандарттуу файл дескриптору жана биз ачкан дагы бирөө бар. Келгиле, файлдын өлчөмүн текшерип көрөлү:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
Маалыматтар жазылып жатат, биз файлдагы уруксаттарды өзгөртүүгө аракет кылабыз:
[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
Биздин колдонуучунун файлга жазууга уруксаты жок болсо да, маалыматтар дагы эле жазылып жатканын көрүп жатабыз. Аны алып салууга аракет кылалы:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Маалымат кайда жазылган? Жана алар дегеле жазылганбы? Биз текшеребиз:
[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)
Ооба, биздин файл дескрипторубуз дагы эле бар жана биз бул файл дескрипторуна эски файлыбыздай мамиле кыла алабыз, аны окуп, тазалап жана көчүрө алабыз.
Келгиле, файлдын өлчөмүн карап көрөлү:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Файлдын өлчөмү 19923457. Келгиле, файлды тазалап көрөлү:
[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
Көрүнүп тургандай, файлдын көлөмү көбөйүп баратат жана биздин trunk иштебей калды. Келгиле, системалык чакыруу документтерин карап көрөлү
with open("123.txt", "w") as f:
коюшубуз керек
with open("123.txt", "a") as f:
"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
жана «а» желеги менен
[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
Иштеп жаткан процессти программалоо
Көбүнчө программисттер программаларды түзүүдө жана сынап жатканда мүчүлүштүктөрдү оңдоочуларды (мисалы, GDB) же тиркемеде каттоонун ар кандай деңгээлдеринде колдонушат. Linux иштеп жаткан программаны иш жүзүндө жазуу жана өзгөртүү мүмкүнчүлүгүн берет, мисалы, өзгөрмөлөрдүн маанилерин өзгөртүү, үзгүлтүккө учуроо чекин коюу ж.б.у.с.
Файлды жазуу үчүн диск мейкиндиги жетишсиз деген баштапкы суроого кайрылып, маселени окшоштурууга аракет кылалы.
Бөлүмүбүз үчүн файл түзөлү, аны өзүнчө диск катары орнотобуз:
[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 ~]$
Келгиле, файл тутумун түзөлү:
[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 ~]$
Файл системасын орнотуу:
[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
Ээсибиз менен каталог түзөбүз:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Биздин программада гана жазуу үчүн файлды ачалы:
with open("/mnt/logs/123.txt", "w") as f:
Ишке киргизүү
[user@localhost ]$ python openforwrite.py
Биз бир нече секунд күтөбүз
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Ошентип, бизде ушул макаланын башында айтылган көйгөй бар. Бош орун 0, 100% ээлеген.
Биз тапшырманын шарттарына ылайык, биз жоголбой турган абдан маанилүү маалыматтарды жазууга аракет кылып жатканыбызды эстейбиз. Ошол эле учурда биз процессти кайра баштабастан кызматты оңдообуз керек.
Бизде дагы эле диск мейкиндиги бар дейли, бирок башка бөлүмдө, мисалы, /үйдө.
Келгиле, кодубузду "учуп жатканда кайра программалоого" аракет кылалы.
Бардык диск мейкиндигин жеп кеткен процессибиздин PIDди карап көрөлү:
[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
gdb аркылуу процесске туташыңыз
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Келгиле, ачык файлдын дескрипторлорун карап көрөлү:
(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
Бизди кызыктырган №3 файл дескриптору жөнүндө маалыматты карайбыз
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Python кандай тутумдук чалуу жасаганын эстеп (жогоруда караңыз, биз strace иштетип, ачык чалууну таптык), файлды ачуу үчүн кодубузду иштетип жатканда, процессибиздин атынан өзүбүз да ушундай кылабыз, бирок бизге O_WRONLY|O_CREAT| O_TRUNC биттери сандык мааниге алмаштырылат. Бул үчүн, мисалы, ядро булактарын ачыңыз
#00000001 дегенди туура эмес аныктагыла
#O_CREAT 00000100 аныктаңыз
#O_TRUNC 00001000 аныктаңыз
Биз бардык баалуулуктарды бирге бириктирип, 00001101 алабыз
Биз чалууну gdbден аткарабыз
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Ошентип, биз 4 саны менен жаңы файл дескрипторун жана башка бөлүмдө жаңы ачык файлды алдык, биз текшеребиз:
(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
Биз түтүк менен мисалды эстейбиз - bash файлдын дескрипторлорун кантип өзгөртөт жана биз dup2 тутумунун чакырыгын үйрөнгөнбүз.
Биз бир файл дескрипторун башкасына алмаштырууга аракет кылабыз
(gdb) call dup2(4,3)
$2 = 3
текшерүү:
(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
Биз 4-файл дескрипторун жабабыз, анткени бизге кереги жок:
(gdb) call close (4)
$1 = 0
Жана 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
Жаңы файл текшерилүүдө:
[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
Көрүнүп тургандай, маалыматтар жаңы файлга жазылган, эскисин карап көрөлү:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Эч кандай маалымат жоголбойт, колдонмо иштейт, журналдар жаңы жерге жазылат.
Келгиле, тапшырманы бир аз татаалдаштыралы
Келгиле, маалыматтар биз үчүн маанилүү экенин элестетип көрөлү, бирок бизде дискте мейкиндик жок жана дискти туташтыра албайбыз.
Биз жасай турган нерсе, биздин берилиштерибизди кандайдыр бир жерге, мисалы, түтүккө багыттоо жана өз кезегинде кандайдыр бир программа, мисалы, netcat аркылуу маалыматтарды түтүктөн тармакка багыттоо.
Биз mkfifo буйругу менен аталган түтүк түзө алабыз. Ал файл тутумунда бош орун жок болсо да, псевдо файлды түзөт.
Колдонмону кайра иштетип, текшериңиз:
[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
Дискте мейкиндик жок, бирок биз ал жерде ийгиликтүү аталган түтүктү түзөбүз:
[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
Эми биз кандайдыр бир жол менен бул түтүккө кирген бардык маалыматтарды тармак аркылуу башка серверге орошубуз керек; ошол эле netcat бул үчүн ылайыктуу.
remote-server.example.com серверинде биз иштетебиз
[user@localhost ~]$ nc -l 7777 > 123.txt
Биздин көйгөйлүү серверде биз өзүнчө терминалда ишке киргизебиз
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Эми түтүктө аяктаган бардык маалыматтар автоматтык түрдө netcat ичиндеги stdin'ге өтөт, ал аны 7777 портундагы тармакка жөнөтөт.
Болгону, бул аталган түтүккө маалыматтарыбызды жаза башташыбыз керек.
Бизде мурунтан эле иштеп жаткан колдонмо бар:
[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_WRONLY гана керек, анткени файл мурунтан эле бар жана аны тазалоонун кереги жок
[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
Алыскы сервер remote-server.example.com текшерилүүдө
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Берилиштер келип жатат, биз көйгөй серверин текшеребиз
[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
Маалыматтар сакталат, маселе чечилет.
Учурдан пайдаланып, Дегиродогу кесиптештериме салам айтам.
Radio-T подкасттарын угуңуз.
Баарына жакшылык.
Үй тапшырмасы катары, мен сизге төмөнкү буйрукту аткарсаңыз, кош жана уйку процессинин дескрипторлорунда эмне болору жөнүндө ойлонууну сунуштайм:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Source: www.habr.com