Arquivo de log excluído acidentalmente do processo em execução python something.py 2>&1 | tee .log
. O script está sendo executado em um painel tmux no zsh. O processo ainda está em execução, mas não registrando. A própria saída estoura o buffer tmux-scrollback. Posso de alguma forma (direitos de admin/sudo) iniciar o processo de log novamente sem reiniciar o processo?
Normalmente minha tentativa funciona sem problemas e o código não é relevante para segurança ou para qualquer tipo de produção, mas simplesmente cálculos matemáticos complexos. Portanto, essa tentativa sempre foi suficiente.
No meu caso atual, seria ótimo se eu pudesse começar a registrar novamente sem reiniciar o processo.
O arquivo continua existindo enquanto o
tee
processo mantiver um descritor de arquivo aberto e tudo ainda estiver sendo registrado lá. Você pode recuperar seu conteúdo atual copiando-o através de /proc:Encontre o PID do processo 'tee'.
Use
lsfd -p <PID>
oulsof -p <PID>
ouls -l /proc/<PID>/fd
para encontrar o número do descritor de arquivo correspondente ao arquivo aberto. (Ele será marcado como "(excluído)" ao lado do nome do arquivo.)Com programas simples como 'tee', o primeiro arquivo aberto quase sempre será o FD #3, então todos os exemplos deste post também serão usados
3
.Copie o conteúdo do arquivo para um novo arquivo através de
/proc
:(Os links simbólicos em /proc/PID/fd são especiais - abri-los ainda resolve para o arquivo correto, mesmo que o link simbólico pareça quebrado ou mesmo que aponte para algo que nem seja um arquivo real.)
Também é possível fazer com que 'tee' comece a gravar em um novo arquivo:
Anexe o
gdb
depurador ao processo:Isto irá pausar 'tee'. O programa Python também pode ser pausado se produzir saída de log suficiente para preencher o buffer do pipe (caso contrário, não notará).
Se você ainda não o fez - use o truque /proc para recuperar o arquivo de log antigo (através de outro shell, não de dentro do gdb):
Ao fazer isso após o gdb ser anexado (ou seja, enquanto 'tee' estiver suspenso), você pode evitar a perda de mensagens durante o intervalo entre o 'cp' e o open().
Agora use gdb para fechar o 'tee' e reabrir o arquivo:
(Os valores
01|0100|02000
são iguais aO_WRONLY|O_CREAT|O_APPEND
from fcntl.h , o que faz com que a chamada open() se comporte como o>>
operador shell.)Para casos simples como 'tee', é extremamente improvável que open() forneça qualquer outro descritor de arquivo que o original #3, pois esse é o menor FD livre. Mas em algumas situações com programas mais complexos (se houver uma lacuna de numeração) pode ser necessário chamar
dup2($2, 3)
eclose($2)
mover manualmente o arquivo recém-aberto para o FD desejado.O arquivo antigo agora terá desaparecido completamente (já que foi removido e o último identificador de arquivo foi fechado), mas 'tee' estará gravando no novo arquivo sem perceber nada.
Nota: em vez de abrir um novo arquivo, pode ser possível usar
linkat()
para trazer o arquivo de log original à existência sem interromper nada, mas ainda não testei isso. (Edit: Infelizmente, de acordo com a documentação do linkat(), isso especificamente não funciona para arquivos que se tornaram totalmente desvinculados.)