Estou entrando no unix de outro mundo e queria saber se
while true
do
/someperlscript.pl
done
O próprio script perl possui internamente um observador de pastas / arquivos que é executado quando os arquivos são alterados no local de destino.
Isso é ( while true
) uma boa ideia? Caso contrário, qual é a abordagem robusta preferida?
TIA
Edição: Como isso parece ter gerado um pouco de interesse, aqui está o cenário completo. O próprio script perl observa um diretório usando um observador de arquivos. Ao receber novos arquivos (eles chegam via rsync), ele pega o novo e o processa. Agora, os arquivos recebidos podem estar corrompidos (não pergunte .. provenientes de um raspberry pi) e, às vezes, o processo pode não ser capaz de lidar com isso. Não sei exatamente por que, porque ainda não estamos cientes de todos os cenários.
MAS - se o processo falhar por algum motivo, queremos que ele esteja em funcionamento e lide com o próximo arquivo, porque o próximo arquivo não tem nenhuma relação com o arquivo anterior que pode ter causado o erro.
Normalmente, eu usaria algum tipo de catch all e envolvia todo o código em torno dele para que NUNCA travasse. Mas não tinha certeza do perl.
Pelo que entendi, usar algo como supervisord é uma boa abordagem para isso.
inotify
API para evitar um loop ocupado aguardando a alteração dos arquivos no diretório de destino.Respostas:
Isso depende da rapidez com que o script perl retorna. Se retornar rapidamente, convém inserir uma pequena pausa entre as execuções para evitar a carga da CPU, por exemplo:
Isso também evitará um problema de CPU se o script não for encontrado ou travar imediatamente.
O loop também pode ser melhor implementado no próprio script perl para evitar esses problemas.
Editar:
Como você escreveu o loop, o único objetivo é reiniciar o script perl, caso ocorra uma falha, uma abordagem melhor seria implementá-lo como um serviço monitorado, mas a maneira precisa de fazer isso depende do sistema operacional. Por exemplo: Solaris smf, Linux systemd ou um cronômetro baseado em cron.
fonte
while sleep 1; do ...
para salvar a chamada verdadeira.until ! sleep 1; do ...; done
ainda salvará a chamada interna ao iniciar o script imediatamente.sleep 1& /someperlscript.pl; wait
.until
instrução, confundi-a com umdo/until
loop hipotético que não existe no shell.As outras respostas, sobre o uso
inotify
, estão corretas, mas não são uma resposta para esta pergunta.Um supervisor de processo, como
supervisord
,upstart
, ourunit
, é projetado para exatamente o problema de assistir e reiniciar um serviço se ele falhar.Sua distribuição provavelmente vem com um supervisor de processo incorporado.
fonte
while true
é bom como uma construção geral de "loop para sempre". Como outras respostas dizem, o corpo do loop não deve estar vazio ou ficar vazio em virtude do comando dentro do loop não funcionar.Se você estiver usando Linux, convém usar um comando como o
inotifywait
que torna owhile
loop muito mais simples:Aqui, o
inotifywait
comando aguardará a ocorrência de um evento do sistema de arquivos (neste exemplo, quando os arquivos no diretório forem gravados). Nesse ponto, ele sai com sucesso e o corpo do loop é executado. Em seguida, volta a esperar novamente. Como oinotifywait
comando aguarda que algo aconteça no diretório, é muito mais eficiente do que pesquisar continuamente o diretório.fonte
Mova o while 1 para o script perl (seguindo a sugestão do @roaima)
fonte
Quando seu script perl se destina a continuar em execução o tempo todo, por que usar a construção while? Quando o perl falha devido a algum problema sério, o novo script perl iniciado por enquanto pode travar com a mesma força. De novo e de novo e assim por diante.
se você realmente deseja que seu perl seja reiniciado, considere o crontab e um script que primeiro verifique se há instâncias em execução. Dessa forma, seu script será iniciado após uma reinicialização.
fonte
Em geral, não há nenhum problema em usar,
while true
pois é um teste minúsculo que só é executado após o término do script perl. Lembre-se de que, dependendo da variante do Linux / Unix que você está usando, o script pode ser encerrado no logoff. Nesse caso, considere usar o loop em um script e chamá-lonohup
e colocá-lo em segundo plano, ou seja,nohup myscript &
Se o script perl terminar com muita frequência e causar carga na CPU, essa carga será responsável pelo script perl e não pelo
while true
.Veja também
man nohup
para detalhes.fonte
Se você deseja gerenciar um processo, consulte um gerente de processo para fazê-lo.
Com muitos sistemas recentes, você pode usar o systemd para monitorar seus processos (que é um dos benefícios do systemd sobre os scripts de inicialização clássicos). Se a sua distro de escolha não utiliza systemd, você poderia usar daemontools ou monit .
fonte
mon
é uma alternativa simples, se a imensidão da monit e do sistema incomodá-lo tanto quanto eles.O
while
loop não é realmente uma boa ideia. Não há como escapar lá - apenas corre para sempre - estaticamente . Muitas coisas podem mudar no ambiente e não serão afetadas - e isso pode ser ruim.Por exemplo, se o executável do shell responsável por esse
while
loop for atualizado, o kernel não poderá liberar espaço em disco para a versão antiga até que o script seja encerrado porque ele precisa manter o descritor enquanto for executado. E isso é verdade para qualquer arquivo que o shell possa ter aberto por qualquer motivo para executar o loop - todos eles serão mantidos abertos por essewhile
loop pelo tempo que for executado - para sempre.E se, pro céu, haja um vazamento de memória em qualquer lugar do shell executando esse loop - mesmo o mais minucioso - ele simplesmente continuará vazando - estaticamente . Ele será construído sem controle e o único recurso é matá-lo à força, e iniciá-lo novamente para fazer o mesmo mais tarde.
Realmente não é assim que você deve configurar um processo em segundo plano - pelo menos não na minha opinião. Em vez disso, como penso, deve haver um ponto de redefinição - uma atualização do script e seu estado. A maneira mais fácil de fazer isso é com
exec
. Você pode substituir o processo atual por um novo - mantendo o mesmo PID - mas ainda executando um novo processo.Por exemplo, se seu
perl
script retornar true depois de ter tratado com êxito uma modificação de arquivo em algum diretório monitorado:...ou algo assim. Algo que permite que o mecanismo básico por trás do loop seja atualizado de vez em quando.
fonte
Votei algumas dessas respostas, mas instintivamente tenho o maior carinho pela resposta da @ WalterA. Bem, fiz até criar minha própria resposta ...
Pessoalmente, eu tenderia a atualizar o script Perl para que ele escreva uma entrada de log descritiva sobre a falha e envie um alerta para um administrador.
Se o script Perl deve continuar em execução, aguardando eventos de alteração no sistema de arquivos, por que está falhando?
Se não estiver falhando, por que você está preocupado em envolvê-lo em um script para reiniciá-lo infinitamente?
Se houver um problema de configuração ou alguma dependência interrompida que faça com que o script Perl seja interrompido, simplesmente reiniciá-lo repetidamente não fará com que ele repentinamente comece a funcionar.
Você conhece a definição de insanidade, certo? (fazendo a mesma coisa repetidamente, esperando um resultado diferente). Apenas dizendo. ;-)
fonte