existe uma maneira de recuperar std redirecionado para /dev/null? Eu tentei tail -f /proc/{PID}/fd/1
, parece que só funciona, exceto redireciona para /dev/null
.
ou seja
tail -f /proc/${cmd_pid}/fd/1
funciona cmd > log.txt
mas nãocmd > /dev/null
------------atualizar------------
na verdade, meu problema será log.txt
muito grande se sempre registrar o stdout. seria melhor se eu pudesse controlar quando registrar ou interromper o registro (sem interromper o cmd
processo em si).
então se é possível redirecionar o stdout para algum tmp
sistema de arquivos que não ocupa nenhum recurso, e quando eu precisar posso recuperar o stdout?
Não, você não pode alterar o identificador do arquivo.
Não, você não pode armazenar os dados sem armazená-los em algum lugar .
Alguém provavelmente escreveu um buffer circular - o que permitiria que você visse (digamos) os últimos 100k de dados. Alternativamente, se o programa estiver rodando normalmente sem comando, você pode enviar a saída para a tela e executá-la via
screen
.Isso pode ser feito canalizando a saída para um script de shell, como o seguinte:
Observe que o redirecionamento é feito dentro do loop, especificamente para que o arquivo de saída seja aberto novamente a cada iteração. Então, para começar:
Então, quando você quiser os logs:
E a próxima iteração do loop começará a gravar
/some/log/file
em vez de em/dev/null
.Se o seu comando registra muito, isso pode resultar em uma penalidade severa de desempenho.
Quando você faz
cmd > /dev/null
, o shell, em um novo processo filho, abre fd 1/dev/null
e executacmd
.cmd
faz algunswrite(1, "output"...)
para gravar dados em stdout (ou possivelmente em outras chamadas de sistema de gravação, comosend
,sendmsg
oupwrite
), independentemente do que esse fd está aberto.No Linux,
/proc/$pid_of_cmd/fd/1
será apenas um link simbólico mágico para/dev/null
, o arquivo fd 1 está aberto, entãotail -f that
será o mesmo quetail -f /dev/null
.Você pode interceptar essas
write()
chamadas do sistemastrace
e decodificar o resultado:Ou:
Para apenas os
write()
s para stdout (fd 1). Ou:Somente para
write()
s para stdout (fd 1) e somente quando stdout estiver aberto em/dev/null
.Observe que, se você redirecionar a saída de
perl
para algo diferente de um dispositivo tty, ele começará a armazenar em buffer por blocos em vez de por linha, portanto, você verá apenas a saída em lotes de alguns kibibytes. Você pode desativar esse buffer definindo a$|
variável como1
:Como alternativa, em vez de fazer
cmd > /dev/null
, façacmd | cat > /dev/null
.Então
cmd
o stdout do 's será um pipe, e no Linux,/proc/$pid_of_cmd/fd/1
se comportará como um pipe nomeado, então se você fizer:Na verdade, você redirecionará o pipe para seu novo
cat
comando.Se você terminar aquele novo
cat
, você vai querer retomar o outro (kill -s CONT "$pid_of_cat"
) para reabrir a torneira/dev/null
naquele cano.Para realmente alterar para onde vai o stdout do processo, você pode anexar um depurador:
Então no gdb:
(0x241 para O_WRONLY|O_TRUNC|O_CREAT)
Verifique se
open()
retorna fd 1. Caso contrário, você pode precisar de alguma chamada paradup2()
e um arquivoclose()
.