Redirecionar stderr de um script já em execução

14

Estou executando um script há vários dias. Eu redirecionei o stdout para $HOME/mylog, mas não o redirecionei, pois pensei que não haveria nada nele. De repente, milhares de linhas começaram a sair no stderr, então eu suspendi o trabalho. Existe uma maneira de redirecionar o stderr $HOME/myerrde agora em diante, sem a necessidade de reiniciar o script?

Eu tenho acesso sudo na caixa e é OS X.

Talvez algo usando dtools trapping?

Não posso perder o trabalho que o script fez até agora e reiniciá-lo do zero. Existe uma maneira de "despejar os objetos na memória" no disco, congelar o programa, editar as variáveis ​​(por exemplo, os descritores de arquivo) e continuar com o novo contexto?

Robottinosino
fonte
possível duplicata de Redirecionando / grep'ing STDOUT de um shell existente
Gilles 'SO parada sendo mal'

Respostas:

12

Eu acho que é possível se você anexar o processo do intérprete relacionado ao gdb. Eu tentei com este one-liner perl

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

e funciona, mas infelizmente não com um script bash semelhante.


Primeiro, você precisa descobrir o PID desse processo cuja saída você deseja capturar. Então comece gdbem outro terminal e execute os seguintes comandos gdb

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

depois disso, todos os dados que são gravados stderrsão redirecionados /abs/olu/te/path/filename, pois

  • attach PID anexa o processo ao gdb e o interrompe
  • call close(2)fecha o stderreditor de arquivos do processo (para stdouto editor de arquivos é 1)
  • call open(...) abre um novo arquivo e pega o menor número inteiro não utilizado para o recém-criado editor de arquivos e
  • detach PID continua o processo

Pelo menos na minha máquina. As duas primeiras linhas são compatíveis com POSIX, mas não a terceira.

O segundo e o terceiro argumento de openna terceira linha estão documentados em man 2 open. No meu caso, 65 significa que opendeve criar o arquivo e abrir o arquivo somente para gravação, ou seja, O_WRONLY | O_CREAT(definido em fcntl.h). O terceiro argumento diz aberto para criar o arquivo com permissão de leitura e gravação para o usuário, ou seja S_IWUSR | S_IRUSR(definido em sys/stat.h). Então, talvez você precise descobrir os valores apropriados em sua máquina.

user1146332
fonte
Isso funcionou tão estupendamente bem ... tiramos o chapéu !!
Robottinosino 19/08/2012
8

Esta é uma resposta grosseira e espero que alguém faça melhor, mas se nenhuma outra idéia surgir, anexe o gdb e force o processo a fazer alguns syscalls:

(gdb) attach 12345 # target PID
(gdb) p close(2)
(gdb) p open("errfile", O_WRONLY)
(gdb) c
Alan Curry
fonte
Bacana. Eu não sabia que o gdb poderia fazer isso. Existe alguma maneira de forçá-lo a um número específico de descritor de arquivo? Como, digamos, se o FD 1 não for utilizado, e o open()FD 1 é garantido? Ou você só precisa ligar dup()algumas vezes?
Patrick
que p open("errfile", O_WRONLY)realmente funciona na sua máquina?
precisa saber é o seguinte
Você pode colocar um p dup2(xxx, 2)e então p close(xxx)onde xxxestá o valor de retorno do open. Isso é complicado, é melhor não usar esses comandos em um processo de longa execução até ter certeza de que não há outra opção.
21712 Alan
@ user1146332 quando tentei, porque usei /dev/nullcomo meu errfilee não precisei O_CREAT. E O_WRONLYsendo uma macro, se ela se expande ou não, depende se o gdb interrompeu o processo em uma linha em que os símbolos de depuração estão disponíveis e a macro está definida. Injetar código em um processo com o gdb é perigoso e ninguém deve copiar esses comandos sem entendê-los.
27612 Alan
@ AlanCurry Não acho que o gdb expanda macros se houver informações gerais sobre depuração. Você precisa compilar as fontes com sinalizadores especiais (veja aqui ). Além disso, é muito incomum que um executável arbitrário em seu sistema tenha informações de depuração incluídas (deixe que as informações sejam estendidas com informações de macro). Mas concordo com você que a injeção de código geralmente não é aconselhável, mas pode haver casos em que você se beneficia.
user1146332