Eu diria que um mecanismo para isso dentro de um shell script é uma solução perfeitamente adequada e que um mecanismo para isso em base ao sistema operacional (para que eu não precise manualmente executar um programa em segundo plano) significa apenas colocar essa solução em um gerenciador de processos como s6 , runit , um unidade systemd , ou até mesmo uma entrada inittab se você estiver em um sysvinit sistema.
Independentemente do mecanismo para mantê-lo em execução, eu gosto de
entrar para assistir a arquivos. Simples, ao ponto, composable (por exemplo, trivial para colocar em um gerenciador de processos).
Aqui está um script para assistir /path/to/file e executar /usr/local/bin/do_stuff quando for alterado:
#!/bin/bash
exec entr /usr/local/bin/do_stuff < <(echo /path/to/file)
Isso é tudo que existe para isso. Coloque isso no arquivo run de runit ou s6, coloque-o na linha ExecStart de uma unidade systemd ou chame esse script de uma linha em inittab . Embora se você colocá-lo em inittab você provavelmente deseja adicionar um sleep em algum lugar, já que o sysvinit não processa o limite de taxa que falham imediatamente devido a erros ortográficos, falta de arquivos ou algo assim.
Por que não apenas echo /path/to/file | entr /usr/local/bin/do_stuff ? Ao executar o gerenciamento de processos, é importante que o processo gerenciado esteja diretamente sob o supervisor, para que ele se comporte corretamente sob, por exemplo, desligar. Se o shell for executado sob o supervisor, o shell detectará os sinais TERM , INT ou KILL em vez do processo em execução e não os transmitirá. Ou, ele sairá e deixará o processo órfão. exec remove o shell da cadeia de processo. ( exec no lado direito do | não faz diferença)
Ou use um shell que nunca se coloca no meio, execline :
#!/bin/execlineb
pipeline -d {
echo /path/to/file
} entr /usr/local/bin/do_stuff