Executa script / programa quando o arquivo é alterado

6

Existe uma maneira de definir algo como um gatilho em um arquivo, de modo que sempre que o arquivo for alterado, um script ou programa será executado?

Eu só encontrei um mecanismo para isso dentro de um script de shell, mas gostaria de saber se existe um mecanismo para isso na base do sistema operacional (para que eu não precise executar manualmente um programa em segundo plano). Uma solução em base de sistema operacional seria um cron-job executado a cada poucos segundos, mas isso não parece uma solução adequada para mim.

É para o Debian, btw.

Obrigado pela ajuda.

    
por cyphorious 01.12.2011 / 16:55

3 respostas

8

uma de suas opções é o subsistema inotify do kernel do linux:

inotify is a Linux kernel subsystem that acts to extend filesystems to notice changes to the filesystem, and report those changes to applications

mas como inotify é kernel-land, você precisa de algo no espaço do usuário para usá-lo:

  • inchron :

The inotify cron daemon (incrond) is a daemon which monitors filesystem events and executes commands defined in system and user tables. It's use is generally similar to cron(8).

Gamin is a monitoring system for files and directories that independently implements a subset of FAM, the File Alteration Monitor. Running as a service, it allows for the detection of modifications to a file or directory. gam_server functions as a daemon for Gamin.

  • ' levantamento de informações ':

inoticoming - trigger actions when files hit an incoming directory

houve uma resposta para uma pergunta semelhante no askubuntu:

link

    
por 01.12.2011 / 17:03
2

Outra maneira rápida e suja de fazer isso é usar inotifywait do pacote inotify-tools (no fedora).

Eu gosto mais desse método porque você pode fazer tudo a partir de uma única linha de comando bash. Costumo usar isso quando estou escrevendo pequenos programas para ver os resultados do que acabei de salvar.

while [[ 1 ]]; do inotifywait -e modify <filename>; make && ./helloworld; done
    
por 10.06.2014 / 16:15
1

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
    
por 22.07.2016 / 10:26