Ame a simplicidade desta resposta. Para sua informação, você poderá adicionar o sinalizador -f ao pgrep e poderá verificar o nome completo do processo, o que é útil se você também deseja inspecionar os argumentos do processo como parte de sua condição.
Craig Sefton
6
Não, você não pode usar o sinalizador -f com pgrep dentro de um cronjob. O motivo é que você comparará com o script de shell usado para executar o cronjob em si.
CpnCrunch
Ao executar um processo da GUI com cron, inclua com export DISPLAY=:0para evitar Could not connect to displayerros. * * * * * export DISPLAY=:0 && pgrep processname > /dev/null || /path/to/processname -args0 -args1
Benjam
9
Execute um script, em vez de diretamente o programa. Existem muitas possibilidades. Por exemplo :
MYPROG="myprog"
RESTART="myprog params"
PGREP="/usr/bin/pgrep"
# find myprog pid
$PGREP ${MYPROG}
# if not running
if [ $? -ne 0 ]
then
$RESTART
fi
Para sua informação, usar variáveis escalares para armazenar listas de argumentos é considerado uma prática ruim. Veja mywiki.wooledge.org/BashFAQ/050 para obter um exemplo de caso em que falha.
Charles Duffy
... da mesma forma, pgrep myprog; if [ $? -ne 0 ]; then ...seria melhor escrito comoif ! pgrep myprog; then ...
Charles Duffy
... esse último estilo não é apenas mais legível, mas também menos propenso a erros: é fácil interromper acidentalmente o valor de $?, por exemplo, adicionando mensagens de log ou tratamento de erros entre linhas.
Charles Duffy
7
Este script não será executado novamente se a instância anterior não tiver sido concluída. Se você não deseja executar algo se outro processo específico estiver em execução, consulte o script do harrymc.
DATE=`date +%c`;
ME=`basename "$0"`;
LCK="./${ME}.LCK";
exec 8>$LCK;
if flock -n -x 8; then
echo ""
echo "Starting your script..."
echo ""
[PUT YOUR STUFF HERE]
echo ""
echo "Script started $DATE";
echo "Script finished `date +%c`";
else
echo "Script NOT started - previous one still running at $DATE";
fi
um bom! agora rsync sobre esta linha lenta pode tomar todo o tempo que ele precisa, disparando dentro de 5 minutos do host cliente que vem em linha sem intervenção manual:*/5 * * * * root flock /run/shm rsync -auhx --numeric-ids -e "ssh -T -c arcfour128 -o Compression=no -x" [source] [user]@[host]:[dest]
eMPee584
1
Isso geralmente é tratado pelo próprio programa e não por cron. Existem duas técnicas padrão para isso:
1) grepa saída de pspara ver se já existe um processo com esse nome em execução
2) Na inicialização, verifique primeiro a existência de um arquivo pid (identificação do processo), geralmente em /var/run/program_name.pide, se existir, leia o pid do arquivo e verifique se esse processo ainda existe; se isso acontecer, recuse-se a começar. Se o arquivo pid não existir ou o pid no arquivo desaparecer, crie um arquivo pid, escreva sua identificação de processo e continue com a inicialização normal.
Embora seja tecnicamente possível escrever pipes bash que os executem diretamente no seu crontab, é melhor adicioná-los ao programa que está sendo iniciado (para que eles sejam aplicados independentemente de como é iniciado) ou gravar um script de wrapper no lidar com isso, como harrymc sugerido.
Reutilizei a resposta acima com uma melhoria na correspondência de padrões. O pgrep sem a opção f não corresponde ao padrão do processo. No entanto, há um problema com o uso da opção f. Com a opção f, o shell que gera o cron sempre é correspondido e retorna seu pid, portanto, o processo nunca é reiniciado.
Adicionar um [] ao redor de um padrão de letras corresponde apenas ao processo e o pid do cron shell não é retornado.
Respostas:
da maneira mais simples, use o pgrep
no crontab:
fonte
export DISPLAY=:0
para evitarCould not connect to display
erros.* * * * * export DISPLAY=:0 && pgrep processname > /dev/null || /path/to/processname -args0 -args1
Execute um script, em vez de diretamente o programa. Existem muitas possibilidades. Por exemplo :
fonte
pgrep myprog; if [ $? -ne 0 ]; then ...
seria melhor escrito comoif ! pgrep myprog; then ...
$?
, por exemplo, adicionando mensagens de log ou tratamento de erros entre linhas.Este script não será executado novamente se a instância anterior não tiver sido concluída. Se você não deseja executar algo se outro processo específico estiver em execução, consulte o script do harrymc.
fonte
Você pode usar um arquivo de bloqueio em seu script, mas consulte Gerenciamento de Processos .
flock
é um utilitário que pode ser usado.fonte
*/5 * * * * root flock /run/shm rsync -auhx --numeric-ids -e "ssh -T -c arcfour128 -o Compression=no -x" [source] [user]@[host]:[dest]
Isso geralmente é tratado pelo próprio programa e não por
cron
. Existem duas técnicas padrão para isso:1)
grep
a saída deps
para ver se já existe um processo com esse nome em execução2) Na inicialização, verifique primeiro a existência de um arquivo pid (identificação do processo), geralmente em
/var/run/program_name.pid
e, se existir, leia o pid do arquivo e verifique se esse processo ainda existe; se isso acontecer, recuse-se a começar. Se o arquivo pid não existir ou o pid no arquivo desaparecer, crie um arquivo pid, escreva sua identificação de processo e continue com a inicialização normal.Embora seja tecnicamente possível escrever pipes bash que os executem diretamente no seu crontab, é melhor adicioná-los ao programa que está sendo iniciado (para que eles sejam aplicados independentemente de como é iniciado) ou gravar um script de wrapper no lidar com isso, como harrymc sugerido.
fonte
* * * * * pgrep -f "[p]attern" > /dev/null || /path/to/processname -args0 -args1
Reutilizei a resposta acima com uma melhoria na correspondência de padrões. O pgrep sem a opção f não corresponde ao padrão do processo. No entanto, há um problema com o uso da opção f. Com a opção f, o shell que gera o cron sempre é correspondido e retorna seu pid, portanto, o processo nunca é reiniciado.
Adicionar um [] ao redor de um padrão de letras corresponde apenas ao processo e o pid do cron shell não é retornado.
fonte