Mengapa pengalihan output sed ke file input yang sama membuat mesin saya tidak responsif?

13

Saya mencoba sedmengganti beberapa kata kunci dalam file besar (100 MB). Saya tidak mengetahui opsi -i(inplace), jadi upaya pertama saya adalah mengarahkan seperti ini:

sed 's/original/edited/g' file.log >> file.log

apa yang terjadi setelah itu adalah PC saya berhenti, hampir tidak ada input keyboard. Saya mencoba konsol yang berbeda Ctrl+ Alt+ F1tetapi setelah perlahan memasukkan nama pengguna, itu terhenti juga. Tanpa keyboard, satu-satunya pilihan saya adalah mengatur ulang perangkat dengan perangkat keras. Setelah masuk, saya melihat file.log itu sekitar 8 GB.

Saya benar-benar ingin memahami mengapa pelaksanaan perintah itu dapat membuat sistem jadi tidak responsif, dan jika ada mekanisme di tingkat sistem untuk memicu peringatan dan membunuh proses yang menyinggung?

cesarpachon
sumber
7
Apakah ini mesin single core? Tampaknya sangat aneh bahwa ini seharusnya membuat komputer modern bertekuk lutut. Mengisi disk Anda, ya. Digunakan hingga 100% dari salah satu inti Anda, ya. Tapi macet total?
terdon
Apakah ada yang aneh dengan file itu? jika ini bukan masalah, bisakah Anda memposting kontennya ke pastebin?
Sergiy Kolodyazhnyy
Juga, berapa jumlah memori Anda? Bisakah Anda memberi kami hasil free -h ?
Sergiy Kolodyazhnyy
Mengapa menggunakan editor aliran di tempat pertama ketika Anda ingin mengubah file? ex -sc '%s/original/edited/ge|x' file.logharus melakukan apa yang Anda inginkan dengan cara UNIX idiomatik tanpa sed -iefek samping.
David Ongaro
Perhatikan bahwa meskipun Anda melakukannya dengan benar (dengan metode apa pun yang disediakan orang), Anda dapat melakukan hal semacam ini pada file log yang dimiliki proses aktif secara tidak pasti.
Random832

Jawaban:

10

Seperti yang telah dikatakan, >>ditambahkan ke file, jadi sedperintah Anda akan duduk di sana membaca baris yang baru saja dikeluarkan, dan kemudian mengeluarkannya lagi. Jika Anda ingin mengganti file Anda di tempat, >masih tidak akan bekerja, tapi Anda sedang menyadari sed's -ipilihan, yang pasti yang Anda inginkan.

Namun, jika Anda benar-benar yakin bahwa Anda ingin menambahkan file yang sedang Anda baca sebagai streaming, dan hanya ingin melakukan satu pass ini, pertimbangkan untuk menggunakan spongedari moreutilspaket;

sed 's/original/edited/g' file.log | sponge >> file.log

spongemembaca dari stdin ke memori hingga EOF, lalu membuang semua isinya ke stdout, sehingga sedakan mengenai bagian akhir file, berhenti membacanya, menutupnya, dan kemudian spons akan mulai menambahkannya.

ymbirtt
sumber
2
spongeadalah utilitas bagus untuk tahu tentang, tetapi sedsudah memiliki -ipilihan: -i[SUFFIX], --in-place[=SUFFIX], edit files in place (makes backup if SUFFIX supplied).
Joshua Taylor
@ JoshuaTaylor, OP menggunakan >>, yang menambahkan, bukan >yang menggantikan. Memang, OP telah secara khusus disebutkan -idalam pos dan sepertinya kasus penggunaan yang jauh lebih umum daripada yang satu ini, tapi saya pikir itu layak menunjukkan bahwa operasi OP tertentu telah diposting mungkin tanpa terlalu banyak faff, jika Anda benar-benar yakin itu yang ingin kamu lakukan.
ymbirtt
1
Saya menyebutkannya di sini karena itu adalah kunci dalam jawaban yang diterima . Yang mengatakan, saya benar - benar senang belajar tentang spons ; itu adalah alat baru untuk kotak alat saya, dan layak mendapatkan upvote hanya untuk itu.
Joshua Taylor
1
Ah! Saya melihat. Saya akan mengubah jawaban saya untuk membuatnya lebih jelas. Juga, jika Anda menikmati sponge, lihatlah vipe. moreutilshanyalah sebuah paket ajaib yang diisi dengan hal-hal yang Anda tidak pernah tahu Anda butuhkan
ymbirtt
18

sedPerintah Anda sedang mencoba membaca file yang ditambahkannya. Ini tidak akan pernah mencapai End-Of-File, tetapi akan memakan banyak waktu CPU mencoba. Itu sebabnya ^ C (interrupt current process) ditemukan.

waltinator
sumber
Saya tidak berpikir ^ C adalah pilihan di sana ... ia pergi ke HALT, yaitu tidak ada kursor berkedip, macet!
EKons
18

Menambahkan kembali ke file yang Anda baca bukan ide yang baik, karena Anda akan berakhir dengan file yang terus bertambah. Jika Anda benar-benar ingin menulis kembali ke file Anda harus menggunakan -iflag:

sed -i 's/original/edited/g' file.log

atau jika Anda ingin membuat cadangan sebelum melakukan perubahan Anda dapat menambahkan akhiran file ke -ibendera:

sed -i.bak 's/original/edited/g' file.log

Ini akan membuat file bernama file.log.bakdan kemudian melakukan perubahan, apa yang Anda lakukan di sana dengan mencoba menambahkan ke file yang Anda baca dari kami memanggil programmer gaul perlombaan data, di mana proses yang berbeda berlomba untuk sumber data yang sama baik itu input atau output . Ini juga mengapa mesin Anda berhenti.

Videonauth
sumber
1
Saya terkejut ini adalah jawaban yang diterima, karena bahkan tidak menjawab pertanyaan OP"I really would like to understand why the execution of that command was able to make the system so unresponsive, and if mechanisms exist at the system level to trigger alerts and kill the offending process?"
Steve
@ Seve Mengapa berhenti, saya berbicara, tetapi untuk bagian kedua Anda benar. Saya tidak mengatasinya karena saya tidak tahu jawaban untuk ini. Kami menguji perintah setelah diskusi obrolan secara luas dan sampai pada hasil yang sangat berbeda pada mesin dan sistem operasi yang berbeda. Contoh: Pada mesin dengan lengkungan itu hanya memungkinkan file tumbuh selamanya, tetapi tidak membuat mesin tidak responsif. Di mesin Ubuntu saya, saya mendapatkan hasil yang sama sebagai penanya tanpa kesempatan untuk mematikan proses. Mesin kedua menguji yang sama di Ubuntu VM berhenti sama.
Videonauth
Sebuah straceseluruh proses di didtn sisi lain mereproduksi hasil dan ini pada mesin saya dan pada mesin dari pengguna lain. Tentu ada mekanisme yang dapat Anda gunakan untuk mematikan aplikasi yang tidak responsif, tetapi jika mesin Anda dianggap tidak responsif, Anda hanya memiliki satu opsi, mengatur ulang. Saya masih menguji ini dan sebelum saya tidak mengerti sepenuhnya apa yang menyebabkan perilaku yang dijelaskan, saya tidak dapat membahas bagian dari pertanyaan ini.
Videonauth
Mungkin perbedaan dalam konfigurasi kernel, seperti scheduler berbeda yang memprioritaskan IO, atau perbedaan dalam driver disk / sistem file antara sistem. Senang melihat investigasi yang kalian lakukan, itu informasi yang bagus.
Steve
Jika Anda tertarik pada titik data lain; Saya mencoba ini pada mesin CentOS dengan file yang cukup kecil, dan itu melakukan hal yang persis sama dengan solusi spons saya di bawah ini. Saya membayangkan bahwa untuk file kecil sedakan buffering semuanya ke dalam memori dan kemudian menutupnya, daripada tetap memegang pegangannya. Dengan file ~ 100MB, seperti pada OP, itu tumbuh tanpa batas tetapi tidak merusak mesin.
ymbirtt