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 redirecionei o stderr, pois achei que não haveria nada nele. De repente, milhares de linhas começaram a aparecer no stderr, então eu suspendi o trabalho. Existe uma maneira de redirecionar o stderr para $HOME/myerr a partir de agora, sem precisar reiniciar o script?

Eu tenho acesso sudo na caixa e é o OS X.

Talvez algo usando o trapping do dtools?

Eu 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 currículo com o novo contexto?

    
por Robottinosino 15.08.2012 / 00:09

2 respostas

12

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

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

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

Primeiro de tudo você tem que descobrir o PID desse processo cuja saída você deseja capturar. Então inicie gdb em 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 gravados em stderr serão redirecionados para /abs/olu/te/path/filename , pois

  • attach PID anexa o processo ao gdb e o interrompe
  • call close(2) fecha o stderr filedescriptor do processo (para stdout o filedescriptor é 1)
  • call open(...) abre um novo arquivo e usa o menor inteiro não utilizado para o filedescriptor recém-criado 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 open na terceira linha estão documentados em man 2 open . No meu caso, 65 significa que open deve criar o arquivo e abrir o arquivo somente gravação, ou seja, O_WRONLY | O_CREAT (definido em fcntl.h ). O terceiro argumento diz open para criar o arquivo com permissão de leitura e gravação para o usuário, por exemplo, S_IWUSR | S_IRUSR (definido em sys/stat.h ). Então talvez você tenha que descobrir os valores apropriados em sua máquina sozinho.

    
por 15.08.2012 / 02:02
8

Esta é uma resposta grosseira e espero que outra pessoa faça melhor, mas se nenhuma outra idéia aparecer, 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
    
por 15.08.2012 / 01:32