Stderr'i zaten çalışan bir komut dosyasından yönlendir


14

Birkaç gündür senaryo yazıyorum. Stdout'u yönlendirdim $HOME/mylog, ancak üzerinde hiçbir şey olmayacağını düşündüğümden stderr'i yönlendirmedim. Aniden stderr'de binlerce satır ortaya çıkmaya başladı, bu yüzden işi askıya aldım. $HOME/myerrKomut dosyasını yeniden başlatmaya gerek kalmadan stderr'ı bundan sonra yeniden yönlendirebileceğim bir yol var mı ?

Kutuda sudo erişimim var ve OS X.

Belki dtools yakalama kullanan bir şey?

Betiğin şimdiye kadar yaptığı işi kaybedemiyorum ve sıfırdan yeniden başlatamıyorum. Diskteki "bellek içi nesneleri boşaltmak", programı dondurmak, değişkenleri düzenlemek (örneğin dosya tanımlayıcıları) ve yeni bağlamla devam etmek için bir yol var mı?


Yanıtlar:


12

İlgili tercüman sürecini gdb'ye eklemeniz mümkün. Bu perl tek katmanlı ile denedim

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

ve maalesef benzer bir bash betiği ile çalışmıyor.


Her şeyden önce, çıktısını yakalamak istediğiniz o sürecin PID'sini bulmalısınız. Sonra gdbbaşka bir terminalde başlayın ve aşağıdaki gdb komutlarını yürütün

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

bundan sonra yazılır bütün veriler stderryönlendirilir /abs/olu/te/path/filename, çünkü

  • attach PID işlemi gdb'ye ekler ve durdurur
  • call close(2)stderrişlemin dosyalama tanımlayıcısını kapatır ( stdoutdosyalama tanımlayıcı 1'dir)
  • call open(...) yeni bir dosya açar ve yeni oluşturulan dosya tanımlayıcı için kullanılmayan en düşük tamsayıyı alır ve
  • detach PID sürece devam ediyor

En azından makinemde. İlk iki satır POSIX uyumlu ancak üçüncü satır değil.

openÜçüncü satırdaki ikinci ve üçüncü argüman belgelenir man 2 open. Benim durumumda 65 openbu dosyayı oluşturmak ve sadece yazma yani O_WRONLY | O_CREAT(içinde tanımlanmış fcntl.h) dosyayı açmak anlamına gelir . Üçüncü argüman, open'a kullanıcı için okuma ve yazma izniyle S_IWUSR | S_IRUSR( yani içinde tanımlanmış sys/stat.h) oluşturmayı açıklar . Bu yüzden belki de makinenizde uygun değerleri kendiniz bulmalısınız.


Bu çok iyi çalıştı ... şapka kapalı !!
Robottinosino

8

Bu kaba bir cevaptır ve umarım başka biri daha iyisini yapar, ancak başka bir fikir ortaya çıkmazsa, gdb'yi ekleyin ve işlemi birkaç sistem çağrısı yapmaya zorlayın:

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c

Şık. GDB'nin bunu yapabileceğinin farkında değildim. Belirli bir dosya tanımlayıcı numarasına zorlamanın herhangi bir yolu var mı? Diyelim ki FD 1 kullanılmıyorsa ve open()FD 1'i alıyor mu? Yoksa sadece dup()birkaç kez mi aramak zorundasınız ?
Patrick

yok p open("errfile", O_WRONLY)gerçekten makinenizde çalışır?
user1146332

Bir p dup2(xxx, 2)ve sonra sopa dönüş değeri p close(xxx)nerede yapışabilir . Bu zor şeyler, başka bir seçenek olmadığından emin olana kadar uzun süren bir işlemde bu komutları kullanmayın. xxxopen
Alan Curry

@ user1146332 denedim zaman yaptım çünkü benim gibi kullandım /dev/null, bu errfileyüzden ihtiyacım yoktu O_CREAT. Ve O_WRONLYbir makro olması, genişletilip genişletilmeyeceği, gdb'nin işlemi, hata ayıklama simgelerinin bulunduğu ve makro tanımlı bir satırda durdurup durdurmadığına bağlıdır. Gdb ile bir sürece kod eklemek tehlikelidir ve hiç kimse bu komutları anlamadan kopyalamamalıdır.
Alan Curry

@AlanCurry Genel hata ayıklama bilgileri varsa gdb'nin makroları genişlettiğini sanmıyorum. Kaynakları özel bayraklarla derlemelisiniz ( buraya bakınız ). Ayrıca, sisteminizdeki rasgele bir yürütülebilir dosyanın hata ayıklama bilgisine sahip olması çok nadirdir (bilginin makro bilgilerle genişletilmesine izin verin). Ancak, kod enjeksiyonunun genellikle tavsiye edilmediğini kabul ediyorum, ancak fayda sağlayabileceğiniz durumlar olabilir.
user1146332
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.