É possível “rolar” um link simbólico para um novo arquivo sem afetar nenhum identificador de arquivo aberto?

7

Um aplicativo que estou desenvolvendo localmente registra sua saída em arquivos formatados com o timestamp atual, como app-%Y%m%d.log .

Para simplificar o registro do dia atual em uma janela de terminal, tenho um link simbólico denominado current.log , que aponta para o log de hoje.

No início do trabalho todos os dias, preciso matar o processo final, apontar o link simbólico para o arquivo atual e, em seguida, executar novamente o comando para tail -f current.log .

É possível alterar o alvo do symlink sem ter que reiniciar tail - alterando o alvo do manipulador de arquivo sem que tail seja mais sábio?

Para automatizar essa tarefa de "início de um novo dia de trabalho", seria fácil configurar um script cron para apontar o link simbólico para o arquivo atual, mas parece que o processo tail existente não teria ideia de que o destino mudou.

    
por matt b 01.04.2011 / 16:35

6 respostas

7

Eu não acho que isso seja possível, a menos que você possa começar a fechar e reabrir o arquivo periodicamente. Uma cauda (ou qualquer outro programa) abre um arquivo, ele recebe um identificador para o inode desse arquivo. Nesse ponto, nomes de arquivos e links não são mais consultados. É por isso que você pode excluir um arquivo do sistema de arquivos e qualquer programa que tenha esse arquivo aberto continuará funcionando. É somente quando o programa ast fecha o arquivo que é removido do disco.

Atualização: Pelo menos a versão no OS X tem uma opção -F, que reabrirá o arquivo se ele foi movido.

    
por 01.04.2011 / 16:55
2

Se você está em um linux moderno, você pode usar o inotifywait , um dos programas de linha de comando do pacote inotify-tools . Eu não fiz isso, mas parece que inotifywait poderia ser usado em um script de shell para redefinir o symlink e parar e reiniciar tail -f no symlink. Você pode até ser capaz de descartar o link simbólico e apenas seguir o arquivo de log atual.

Sem o uso de inotify, é possível escrever seu próprio programa que verifica se o número de inode do nome do arquivo que ele leu foi alterado. Nesse ponto, o programa semelhante a uma cauda pode fechar seu descritor de arquivo antigo e obter um novo descritor de arquivo para o nome de arquivo agora diferente. Este é um programa difícil de escrever e é propenso a condições de corrida.

    
por 01.04.2011 / 17:46
1

A partir da sua descrição, parece que sua circunstância específica poderia ser resolvida fazendo um cron job que também matou / reiniciou o processo final. Mas, em geral, (o Mac OS sendo a exceção) a cauda lembrará onde você está no arquivo (ou seja, o deslocamento de byte). Além disso, o identificador de arquivo aberto aponta para o arquivo de destino, não para o link simbólico. O link simbólico se torna irrelevante para o processo de leitura depois que o arquivo é aberto. Embora seja possível ter recursos que reabram o arquivo com base no caminho original quando algo muda, a maioria das implementações não faz isso.

    
por 01.04.2011 / 17:12
1

Por que não logar em um arquivo, current.log, que você pode alterar para o conteúdo do seu coração, e então usar algo como / usr / sbin / logrotate para rotacionar esse arquivo. Você pode especificar na configuração que você gostaria de fazer alguns comandos postrotate para renomear o arquivo antigo com a data anexada, etc. Ele remove a necessidade de links simbólicos completamente e também pode simplificar o seu código de registro.

É claro que o logrotate pode não estar instalado no sistema para o qual você está desenvolvendo.

    
por 01.04.2011 / 19:55
1

Quando um programa abre o arquivo, ele continua acessando o mesmo arquivo, mesmo que o arquivo seja movido ou até excluído. (Remover um arquivo aberto apenas remove seu nome; o arquivo - inode - é realmente excluído quando nenhum processo o abre. )

Alguns programas observam se algo acontece com o arquivo que eles abriram. Por exemplo, o programa clássico tail -f mantém as linhas de impressão anexadas ao mesmo arquivo; algumas implementações modernas (GNU, FreeBSD, NetBSD, OSX) têm tail -F , que detecta se um novo arquivo com o mesmo nome é colocado no lugar e começa a ler o novo arquivo. O Multitail também pode fazer isso (executá-lo como multitail --retry ).

Você pode usar a interface Inotify no Linux, ou seu equivalente em outros unices, para detectar se um arquivo foi alterado . No Linux, use o comando inotifywait .

    
por 01.04.2011 / 22:16
0

Eu prefiro usar um script perl curto em vez de /usr/bin/tail -f para esse propósito.

Veja link para dicas.

    
por 24.03.2012 / 00:11