Перенаправить stderr из уже запущенного скрипта

14

Я запускаю сценарий уже несколько дней. Я перенаправил stdout на $HOME/mylog, но не перенаправил stderr, так как думал, что на нем ничего не будет. Внезапно на stderr стали выходить тысячи строк, поэтому я приостановил работу. Есть ли способ, с помощью которого я теперь могу перенаправлять stderr $HOME/myerr, без необходимости перезапускать скрипт?

У меня есть доступ sudo на коробке, и это OS X.

Возможно, что-то с использованием dtools trapping?

Я не могу потерять работу, которую до сих пор выполнял скрипт, и перезапустить его с нуля. Есть ли способ «сбросить объекты в памяти» на диск, заморозить программу, отредактировать переменные (например, дескрипторы файлов) и продолжить работу с новым контекстом?

Robottinosino
источник
возможный дубликат перенаправления / grep'а STDOUT существующей оболочки
Gilles 'SO- перестань быть злым'

Ответы:

12

Я думаю, что это возможно, если вы присоедините процесс соответствующего интерпретатора к GDB. Я пробовал с этим perl one-liner

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

и это работает, но, к сожалению, не с похожим сценарием Bash.


Прежде всего вы должны выяснить PID того процесса, чей вывод вы хотите записать. Затем запустите gdbв другом терминале и выполните следующие команды gdb

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

после этого все данные, которые записываются, stderrперенаправляются /abs/olu/te/path/filename, так как

  • attach PID присоединяет процесс к GDB и останавливает его
  • call close(2)закрывает stderrфайловый дескриптор процесса (для stdoutфайлового дескриптора 1)
  • call open(...) открывает новый файл и берет самое низкое неиспользуемое целое число для вновь созданного дескриптора файла и
  • detach PID продолжает процесс

По крайней мере, на моей машине. Первые две строки совместимы с POSIX, но не третья.

Второй и третий аргумент openв третьей строке описаны в man 2 open. В моем случае 65 означает, что openследует создать файл и открыть файл только для записи, т. Е. O_WRONLY | O_CREAT(Определено в fcntl.h). Третий аргумент говорит open, чтобы создать файл с разрешением на чтение и запись для пользователя, т.е. S_IWUSR | S_IRUSR(определено в sys/stat.h). Поэтому, возможно, вам придется самостоятельно найти подходящие значения на вашей машине.

user1146332
источник
Это сработало так здорово ... снимаю шляпу !!
Robottinosino
8

Это грубый ответ, и я надеюсь, что кто-то еще добьется большего успеха, но если не появятся другие идеи, присоедините gdb и заставьте процесс сделать несколько системных вызовов:

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c
Алан Карри
источник
Острота. Я не знал, что GDB может сделать это. Есть ли способ заставить его к определенному номеру дескриптора файла? Как сказать, если FD 1 не используется, и open()захватывает FD 1? Или вам просто нужно позвонить dup()несколько раз?
Патрик
это p open("errfile", O_WRONLY)действительно работает на вашей машине?
user1146332
Вы можете вставить в, p dup2(xxx, 2)а затем, p close(xxx)где xxxэто возвращаемое значение open. Это сложная штука, лучше не использовать эти команды в длительном процессе, пока вы не уверены, что другого выбора нет.
Алан Карри
@ user1146332 это сделал, когда я попробовал, потому что я использовал /dev/nullкак свой, errfileтак что мне не нужно O_CREAT. И O_WRONLYто, является ли макрос макросом, расширяется он или нет, зависит от того, остановил ли GDB процесс в строке, где доступны символы отладки и макрос определен. Внедрение кода в процесс с помощью gdb опасно, и никто не должен просто копировать эти команды, не понимая их.
Алан Карри
@AlanCurry Я не думаю, что GDB расширяет макросы, если доступна общая информация для отладки. Вы должны скомпилировать исходники со специальными флагами (см. Здесь ). Кроме того, очень редко случается так, что произвольный исполняемый файл в вашей системе содержит отладочную информацию (пусть любая информация дополняется макроинформацией). Но я согласен с вами, что внедрение кода, как правило, не рекомендуется, но могут быть случаи, когда вы выиграете.
user1146332