Pernah, dalam temu bual, saya ditanya apa yang anda akan lakukan jika anda mendapati perkhidmatan yang rosak kerana fakta bahawa cakera telah kehabisan ruang?
Sudah tentu, saya menjawab bahawa saya akan melihat apa yang dilakukan oleh tempat ini dan, jika boleh, saya akan membersihkan tempat itu.
Kemudian penemuduga bertanya, bagaimana jika tiada ruang kosong pada partition, tetapi anda juga tidak melihat fail yang akan mengambil semua ruang?
Untuk ini, saya berkata bahawa anda sentiasa boleh melihat deskriptor fail terbuka, sebagai contoh, dengan perintah lsof dan memahami aplikasi mana yang telah mengambil semua ruang yang ada, dan kemudian anda boleh bertindak mengikut keadaan, bergantung pada sama ada data diperlukan .
Pewawancara mengganggu saya pada perkataan terakhir, sambil menambah soalannya: "Katakanlah kami tidak memerlukan data, ia hanya log nyahpepijat, tetapi aplikasi tidak berfungsi kerana ia tidak dapat menulis nyahpepijat"?
"ok," saya menjawab, "kita boleh mematikan penyahpepijatan dalam konfigurasi aplikasi dan memulakannya semula."
Penemuduga membantah: "Tidak, kami tidak boleh memulakan semula aplikasi, kami masih mempunyai data penting dalam ingatan, dan pelanggan penting disambungkan ke perkhidmatan itu sendiri, yang tidak boleh kami paksa untuk menyambung semula."
βokay,β saya berkata, βjika kami tidak boleh memulakan semula aplikasi dan kami tidak mengambil berat tentang data, maka kami boleh mengosongkan fail terbuka ini melalui deskriptor fail, walaupun kami tidak melihatnya dalam ls arahan pada sistem fail."
Penemuduga berpuas hati, tetapi saya tidak.
Kemudian saya berfikir, mengapa orang yang menguji pengetahuan saya tidak menggali lebih dalam? Tetapi bagaimana jika data itu penting? Bagaimana jika kita tidak boleh memulakan semula proses, dan pada masa yang sama proses ini menulis ke sistem fail pada partition yang tidak mempunyai ruang kosong? Bagaimana jika kita tidak boleh kehilangan bukan sahaja data yang telah ditulis, tetapi juga data yang sedang ditulis atau cuba ditulis oleh proses ini?
Tuzik
Pada awal kerjaya saya, saya cuba mencipta aplikasi kecil yang diperlukan untuk menyimpan maklumat tentang pengguna. Dan kemudian saya berfikir, bagaimana saya boleh memadankan pengguna dengan datanya. Sebagai contoh, saya mempunyai Ivanov Ivan Ivanovich, dan dia mempunyai beberapa data, tetapi bagaimana untuk berkawan dengan mereka? Saya boleh menunjukkan secara langsung bahawa anjing bernama "Tuzik" adalah milik Ivan yang sama ini. Tetapi bagaimana jika dia menukar namanya dan bukannya Ivan menjadi, sebagai contoh, Olya? Kemudian ternyata Olya Ivanovna Ivanova kami tidak akan mempunyai anjing lagi, dan Tuzik kami akan tetap menjadi milik Ivan yang tidak wujud. Pangkalan data membantu menyelesaikan masalah ini, yang memberikan setiap pengguna pengecam unik (ID), dan Tuzik saya terikat dengan ID ini, yang sebenarnya, hanyalah nombor siri. Oleh itu, pemilik tuzik mempunyai ID nombor 2, dan pada satu ketika Ivan berada di bawah ID ini, dan kemudian Olya menjadi di bawah ID yang sama. Masalah manusia dan penternakan telah diselesaikan secara praktikal.
Deskriptor fail
Masalah fail dan program yang berfungsi dengan fail ini hampir sama dengan anjing dan manusia kita. Katakan saya membuka fail bernama ivan.txt dan mula menulis perkataan tuzik ke dalamnya, tetapi berjaya menulis hanya huruf pertama "t" ke dalam fail, dan fail ini telah dinamakan semula oleh seseorang, sebagai contoh, kepada olya.txt. Tetapi fail itu sama dan saya masih mahu menulis ace saya kepadanya. Setiap kali anda membuka fail dengan panggilan sistem
Di Linux, perpustakaan libc membuka 3 fail deskriptor untuk setiap aplikasi yang sedang berjalan (proses), dengan nombor 0,1,2. Maklumat lanjut anda boleh dapatkan pada pautan
- Deskriptor fail 0 dipanggil STDIN dan dikaitkan dengan input aplikasi.
- Deskriptor fail 1 dipanggil STDOUT dan digunakan oleh aplikasi output seperti arahan cetak.
- Deskriptor fail 2 dinamakan STDERR dan digunakan oleh aplikasi untuk mengeluarkan mesej ralat.
Jika dalam program anda anda membuka sebarang fail untuk membaca atau menulis, kemungkinan besar anda akan mendapat ID percuma pertama dan ia akan menjadi nombor 3.
Anda boleh melihat senarai deskriptor fail untuk sebarang proses jika anda mengetahui PIDnya.
Sebagai contoh, mari buka konsol dengan bash dan lihat PID proses kami
[user@localhost ]$ echo $$
15771
Dalam konsol kedua, jalankan
[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
Anda boleh mengabaikan deskriptor fail dengan nombor 255 dengan selamat dalam rangka artikel ini, ia dibuka untuk keperluan anda oleh bash itu sendiri, dan bukan oleh perpustakaan yang dipautkan.
Kini kesemua 3 fail deskriptor dikaitkan dengan peranti pseudo-terminal
[user@localhost ]$ echo "hello world" > /proc/15771/fd/0
Dan dalam konsol pertama kita akan lihat
[user@localhost ]$ hello world
Ubah hala dan Paip
Anda boleh mengatasi 3 fail deskriptor ini dengan mudah dalam sebarang proses, termasuk dalam bash, contohnya, melalui paip (paip) yang menyambungkan dua proses, lihat
[user@localhost ]$ cat /dev/zero | sleep 10000
Anda boleh menjalankan arahan ini sendiri dengan strace -f dan lihat apa yang berlaku di dalam, tetapi saya akan pendekkan.
Proses bash induk kami dengan PID 15771 menghuraikan perintah kami dan memahami dengan tepat berapa banyak perintah yang ingin kami jalankan, dalam kes kami terdapat dua daripadanya: kucing dan tidur. Bash tahu bahawa ia perlu mencipta dua proses kanak-kanak, dan menggabungkannya ke dalam satu paip. Secara keseluruhan, bash memerlukan 2 proses kanak-kanak dan satu paip.
Sebelum membuat proses anak, bash menjalankan panggilan sistem
Untuk proses induk, nampaknya paip sudah ada, tetapi belum ada proses anak lagi:
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
Kemudian menggunakan panggilan sistem
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
Jangan lupa bahawa klon mengklon proses bersama-sama dengan semua deskriptor fail, jadi mereka akan sama dalam proses induk dan dalam proses kanak-kanak. Tugas proses induk dengan PID 15771 adalah untuk memantau proses kanak-kanak, jadi ia hanya menunggu respons daripada kanak-kanak.
Oleh itu, dia tidak memerlukan paip, dan dia menutup deskriptor fail dengan nombor 3 dan 4.
Dalam proses anak bash pertama dengan PID 9004, panggilan sistem
Dalam proses anak kedua dengan PID 9005, bash dup2s fail ke nombor deskriptor STDIN 0. Sekarang semua yang akan dibaca oleh bash kedua kami dengan PID 9005 akan dibaca dari paip.
Selepas itu, deskriptor fail dengan nombor 3 dan 4 juga ditutup dalam proses anak, kerana ia tidak lagi digunakan.
Saya sengaja mengabaikan deskriptor fail 255, ia digunakan secara dalaman oleh bash itu sendiri dan juga akan ditutup dalam proses anak.
Seterusnya, dalam proses anak pertama dengan PID 9004, bash bermula dengan panggilan sistem
Dalam proses anak kedua dengan PID 9005, bash menjalankan boleh laku kedua yang kami tentukan, dalam kes kami /usr/bin/sleep.
Panggilan sistem exec tidak menutup deskriptor fail melainkan ia dibuka dengan bendera O_CLOEXEC pada masa panggilan terbuka dilaksanakan. Dalam kes kami, selepas menjalankan fail boleh laku, semua deskriptor fail semasa akan disimpan.
Menyemak dalam konsol:
[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
Seperti yang anda lihat, nombor unik paip kami adalah sama dalam kedua-dua proses. Oleh itu, kami mempunyai hubungan antara dua proses berbeza dengan induk yang sama.
Bagi mereka yang tidak biasa dengan panggilan sistem yang digunakan oleh bash, saya sangat mengesyorkan menjalankan arahan melalui strace dan lihat apa yang berlaku di dalam, contohnya, seperti ini:
strace -s 1024 -f bash -c "ls | grep hello"
Mari kita kembali kepada masalah kita kehabisan ruang cakera dan cuba menyimpan data tanpa memulakan semula proses. Mari kita tulis program kecil yang akan menulis ke cakera kira-kira 1 megabait sesaat. Selain itu, jika atas sebab tertentu kami tidak dapat menulis data ke cakera, kami hanya akan mengabaikan ini dan cuba menulis data sekali lagi dalam satu saat. Dalam contoh yang saya gunakan Python, anda boleh menggunakan mana-mana bahasa pengaturcaraan lain.
[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
Jalankan program dan lihat deskriptor fail
[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
Seperti yang anda lihat, kami mempunyai 3 deskriptor fail standard kami dan satu lagi yang telah kami buka. Mari semak saiz fail:
[user@localhost ]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 117M Oct 7 16:30 123.txt
data ditulis, kami cuba menukar hak kepada fail:
[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
Kami melihat bahawa data masih sedang ditulis, walaupun pengguna kami tidak mempunyai hak untuk menulis ke fail. Mari cuba keluarkan:
[user@localhost ]$ sudo rm 123.txt
[user@localhost ]$ ls 123.txt
ls: cannot access 123.txt: No such file or directory
Di manakah data ditulis? Dan adakah mereka ditulis sama sekali? Kami menyemak:
[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)
Ya, deskriptor fail kami masih wujud dan kami boleh bekerja dengan deskriptor fail ini seperti fail lama kami, kami boleh membacanya, membersihkannya dan menyalinnya.
Lihat saiz fail:
[user@localhost ]$ lsof | grep 123.txt
python 31083 user 3w REG 8,5 19923457 2621522 /home/user/123.txt
Saiz fail ialah 19923457. Cuba mengosongkan fail:
[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
Seperti yang anda lihat, saiz fail hanya bertambah dan batang kami tidak berfungsi. Mari kita beralih kepada dokumentasi pada panggilan sistem
with open("123.txt", "w") as f:
kita kena letak
with open("123.txt", "a") as f:
Menyemak dengan bendera "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
dan dengan bendera "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
Memprogramkan proses yang sudah berjalan
Selalunya, semasa membuat dan menguji program, pengaturcara menggunakan penyahpepijat (contohnya, GDB) atau pelbagai peringkat pengelogan dalam aplikasi. Linux menyediakan keupayaan untuk benar-benar menulis dan menukar program yang sudah berjalan, seperti menukar nilai pembolehubah, menetapkan titik putus, dan sebagainya dan sebagainya.
Kembali kepada soalan asal tentang kekurangan ruang cakera untuk menulis fail, mari cuba meniru masalah tersebut.
Mari buat fail untuk partition kami, yang akan kami lekapkan sebagai pemacu berasingan:
[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 ~]$
Mari buat sistem fail:
[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 ~]$
Mari pasang sistem fail:
[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
Buat direktori dengan pemilik kami:
[user@localhost ~]$ sudo mkdir /mnt/logs
[user@localhost ~]$ sudo chown user: /mnt/logs
Mari buka fail untuk menulis hanya dalam program kami:
with open("/mnt/logs/123.txt", "w") as f:
Kami melancarkan
[user@localhost ]$ python openforwrite.py
Menunggu beberapa saat
[user@localhost ~]$ df -h | grep mnt
/dev/loop0 8.7M 8.0M 0 100% /mnt
Jadi, kami mendapat masalah yang diterangkan pada permulaan artikel ini. Ruang kosong 0, diduduki 100%.
Kami ingat bahawa mengikut keadaan masalah, kami cuba merekodkan data yang sangat penting yang tidak boleh hilang. Dan dengan berbuat demikian, kami perlu membetulkan perkhidmatan tanpa memulakan semula proses.
Katakan kita masih mempunyai ruang cakera, tetapi dalam partition yang berbeza, sebagai contoh, dalam / rumah.
Mari cuba "program semula dengan cepat" kod kami.
Kami melihat PID proses kami, yang memakan semua ruang cakera:
[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
Menyambung ke proses dengan gdb
[user@localhost ~]$ gdb -p 10078
...
(gdb)
Kami melihat deskriptor fail terbuka:
(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
Kami melihat maklumat tentang deskriptor fail dengan nombor 3, yang menarik minat kami
(gdb) shell cat /proc/10078/fdinfo/3
pos: 8189952
flags: 0100001
mnt_id: 482
Mengingat apa yang dilakukan oleh panggilan sistem Python (lihat di atas tempat kami menjalankan strace dan menemui panggilan terbuka), semasa memproses kod kami untuk membuka fail, kami melakukan perkara yang sama sendiri bagi pihak proses kami, tetapi kami memerlukan O_WRONLY|O_CREAT| Bit O_TRUNC digantikan dengan nilai angka. Untuk melakukan ini, buka sumber kernel, sebagai contoh
#define O_WRONLY 00000001
#define O_CREAT 00000100
#define O_TRUNC 00001000
Kami menggabungkan semua nilai menjadi satu, kami mendapat 00001101
Menjalankan panggilan kami daripada gdb
(gdb) call open("/home/user/123.txt", 00001101,0666)
$1 = 4
Jadi kami mendapat deskriptor fail baharu dengan nombor 4 dan fail terbuka baharu pada partition lain, semak:
(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
Kami masih ingat contoh dengan paip - bagaimana bash menukar deskriptor fail, dan telah mempelajari panggilan sistem dup2.
Cuba menggantikan satu deskriptor fail dengan yang lain
(gdb) call dup2(4,3)
$2 = 3
Kami menyemak:
(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
Tutup deskriptor fail 4, kerana kami tidak memerlukannya:
(gdb) call close (4)
$1 = 0
Dan keluar dari 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
Menyemak fail baharu:
[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
Seperti yang anda lihat, data ditulis ke fail baru, kami menyemak yang lama:
[user@localhost ~]$ ls -lah /mnt/logs/123.txt
-rw-rw-r-- 1 user user 7.9M Oct 8 11:08 /mnt/logs/123.txt
Data tidak hilang, aplikasi berfungsi, log ditulis ke lokasi baru.
Mari kita membuat perkara lebih sukar
Bayangkan bahawa data itu penting kepada kami, tetapi kami tidak mempunyai ruang cakera dalam mana-mana partition dan kami tidak boleh menyambung cakera.
Apa yang boleh kami lakukan ialah mengubah hala data kami ke suatu tempat, contohnya, ke paip, dan ubah hala data daripada paip ke rangkaian melalui beberapa program, seperti netcat.
Kita boleh mencipta paip bernama dengan arahan mkfifo. Ia akan mencipta fail pseudo pada sistem fail, walaupun tiada ruang kosong padanya.
Mulakan semula aplikasi dan semak:
[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
Tiada ruang cakera, tetapi kami berjaya mencipta paip bernama di sana:
[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
Sekarang kita perlu membungkus semua data yang masuk ke dalam paip ini ke pelayan lain melalui rangkaian, netcat yang sama sesuai untuk ini.
Pada pelayan remote-server.example.com, jalankan
[user@localhost ~]$ nc -l 7777 > 123.txt
Pada pelayan masalah kami, jalankan dalam terminal yang berasingan
[user@localhost ~]$ nc remote-server.example.com 7777 < /mnt/logs/megapipe
Sekarang semua data yang masuk ke dalam paip secara automatik akan pergi ke stdin dalam netcat, yang akan menghantarnya ke rangkaian pada port 7777.
Apa yang perlu kita lakukan ialah mula menulis data kita ke paip bernama ini.
Kami sudah mempunyai aplikasi yang sedang berjalan:
[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
Daripada semua bendera, kami hanya memerlukan O_WRONLY kerana fail itu sudah wujud dan kami tidak perlu mengosongkannya
[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
Menyemak pelayan jauh remote-server.example.com
[user@localhost ~]$ ls -lah 123.txt
-rw-rw-r-- 1 user user 38M Oct 8 14:21 123.txt
Data akan datang, kami menyemak pelayan masalah
[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
Data disimpan, masalah diselesaikan.
Saya mengambil kesempatan ini untuk bertanya khabar kepada rakan sekerja dari Degiro.
Dengar podcast Radio-T.
Selamat untuk semua.
Sebagai kerja rumah, saya bercadang untuk memikirkan apa yang akan ada dalam deskriptor fail proses kucing dan tidur jika anda menjalankan arahan berikut:
[user@localhost ~]$ cat /dev/zero 2>/dev/null| sleep 10000
Sumber: www.habr.com