Redirect stderr dari skrip yang sudah berjalan

14

Saya telah menjalankan skrip selama beberapa hari sekarang. Saya mengalihkan stdout ke $HOME/mylog, tetapi tidak mengarahkan stderr karena saya pikir tidak akan ada apa-apa di dalamnya. Tiba-tiba ribuan garis mulai keluar di stderr, jadi saya menunda pekerjaan itu. Apakah ada cara saya dapat mengarahkan stderr ke $HOME/myerrsekarang, tanpa perlu me-restart skrip?

Saya memiliki akses sudo di kotak dan itu OS X.

Mungkin sesuatu yang menggunakan perangkap dtools?

Saya tidak bisa kehilangan pekerjaan yang telah dilakukan skrip sejauh ini dan memulai kembali dari awal. Apakah ada cara untuk "membuang objek dalam memori" pada disk, membekukan program, mengedit variabel (mis. Deskriptor file) dan melanjutkan dengan konteks baru?

Robottinosino
sumber
kemungkinan duplikat Mengarahkan / menerima STDOUT shell yang ada
Gilles 'SO- stop being evil'

Jawaban:

12

Saya pikir itu mungkin jika Anda melampirkan proses penerjemah terkait ke gdb. Saya mencobanya dengan perl one-liner ini

 perl -e 'do { print "x\n"; sleep(1) } while(1)'

dan itu berhasil tetapi sayangnya tidak dengan skrip bash yang serupa.


Pertama-tama Anda harus mencari tahu PID dari proses yang outputnya ingin Anda tangkap. Kemudian mulailah dari gdbterminal lain dan jalankan perintah-perintah gdb berikut

attach PID
call close(2)
call open("/abs/olu/te/path/filename", 65, 384)
detach PID

setelah itu seluruh data yang dituliskan stderrdialihkan ke /abs/olu/te/path/filename, sejak

  • attach PID melampirkan proses ke gdb dan menghentikannya
  • call close(2)menutup proses stderrpengesahan (karena stdoutpengarsipan adalah 1)
  • call open(...) membuka file baru dan mengambil bilangan bulat yang tidak terpakai terendah untuk file yang baru dibuat dan
  • detach PID melanjutkan prosesnya

Setidaknya di mesin saya. Dua baris pertama kompatibel dengan POSIX tetapi bukan yang ketiga.

Argumen kedua dan ketiga opendi baris ketiga didokumentasikan man 2 open. Dalam kasus saya 65 berarti openharus membuat file dan membuka file hanya-menulis yaitu O_WRONLY | O_CREAT(didefinisikan dalam fcntl.h). Argumen ketiga memberitahu terbuka untuk membuat file dengan izin baca dan tulis untuk pengguna yaitu S_IWUSR | S_IRUSR(didefinisikan dalam sys/stat.h). Jadi mungkin Anda harus mencari sendiri nilai yang sesuai pada mesin Anda.

pengguna1146332
sumber
Ini bekerja sangat baik ... topi !!
Robottinosino
8

Ini adalah jawaban yang kasar dan saya harap orang lain melakukan yang lebih baik, tetapi jika tidak ada ide lain yang muncul, pasang gdb dan paksa proses untuk melakukan beberapa syscall:

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c
Alan Curry
sumber
Bagus. Saya tidak sadar gdb bisa melakukan itu. Apakah ada cara untuk memaksanya ke nomor deskriptor file tertentu? Seperti mengatakan jika FD 1 tidak digunakan, dan open()ambil FD 1? Atau Anda hanya perlu menelepon dup()beberapa kali?
Patrick
apakah p open("errfile", O_WRONLY)benar - benar bekerja pada mesin Anda?
user1146332
Anda bisa menempel di p dup2(xxx, 2)dan kemudian di p close(xxx)mana xxxnilai pengembalian open. Ini adalah hal yang rumit, lebih baik tidak menggunakan perintah ini pada proses yang berjalan lama sampai Anda yakin tidak ada pilihan lain.
Alan Curry
@ user1146332 itu ketika saya mencobanya karena saya menggunakan /dev/nullsaya errfilejadi saya tidak perlu O_CREAT. Dan O_WRONLYmenjadi makro, apakah itu meluas atau tidak tergantung pada apakah gdb menghentikan proses pada baris di mana simbol debug tersedia dan makro didefinisikan. Menyuntikkan kode ke dalam proses dengan gdb berbahaya dan tidak ada orang yang seharusnya menyalin perintah ini tanpa memahaminya.
Alan Curry
@AlanCurry Saya tidak berpikir bahwa gdb memperluas makro jika informasi debug umum tersedia. Anda harus mengkompilasi sumber dengan bendera khusus (lihat di sini ). Selain itu sangat jarang bahwa eksekusi sewenang-wenang pada sistem Anda memiliki informasi debugging termasuk (biarkan saja informasi tersebut diperluas dengan informasi makro). Tetapi saya setuju dengan Anda bahwa injeksi kode umumnya tidak disarankan, tetapi mungkin ada kasus di mana Anda mendapat manfaat.
user1146332