2009-05-29 4 views
10

J'ai un script qui s'exécute toutes les 15 minutes mais parfois, si la boîte est occupée, elle se bloque et le processus suivant commence avant que la première un effet boule de neige. Comment puis-je ajouter quelques lignes au script bash pour vérifier si quelque chose est en cours d'exécution avant de commencer?Comment vérifier dans un script bash si quelque chose est en cours d'exécution et quitter s'il est

+1

Dupe de 185451. – Rob

+0

Voir [http://stackoverflow.com/questions/185451/quick-and-dirty-way-to-ensure-only-one-instance-of-a-shell-script-is-running-at-a](http : //stackoverflow.com/questions/185451/quick-and-dirty-way-to-ensure-only-one-instance-of-a-shell-script-is-runnin g-at-a). – Rob

+0

duplication possible de [exécution de script shell vérifier si elle est déjà en cours d'exécution ou non] (http://stackoverflow.com/questions/16807876/shell-script-execution-check-if-it-is-already-running-or- – Pureferret

Répondre

3

Au lieu de .pid, tant que votre script a un nom identifiable de manière unique que vous pouvez faire quelque chose comme ceci:

#!/bin/bash 
COMMAND=$0 
# exit if I am already running 
RUNNING=`ps --no-headers -C${COMMAND} | wc -l` 
if [ ${RUNNING} -gt 1 ]; then 
    echo "Previous ${COMMAND} is still running." 
    exit 1 
fi 
... rest of script ... 
+3

Je l'ai fait et Je devais le peaufiner un peu. Tout d'abord, COMMAND inclut le chemin complet, à moins que vous ne l'exécutiez à partir du même répertoire, cela ne fonctionne pas. J'ai codé le nom de toute façon. Deuxièmement, pour une raison quelconque, ps --no-headers -C $ {COMMAND} | wc -l renvoyait toujours 1 sans rien courir et puisque ce script est en cours d'exécution alors qu'il vérifie que c'est un autre 1, il a toujours retourné 2. J'ai dû changer le -gt 1 en -gt 2 et cela a fonctionné. Merci. –

3
pgrep -f yourscript >/dev/null && exit 
+0

pkill -0 yourscript serait probablement mieux – iny

5

Pourquoi ne pas définir un fichier de verrouillage?

Quelque chose comme

yourapp.lock

juste l'enlever lorsque vous traitez est terminé, et vérifier avant de le lancer.

Il pourrait être fait en utilisant

if [ -f yourapp.lock ]; then 
echo "The process is already launched, please wait..." 
fi 
+1

Parce que gérer correctement un fichier de verrouillage, en particulier gérer le cas où un processus s'est terminé de manière incorrecte et n'a pas réussi à effacer son fichier de verrouillage, prend plus de quelques lignes dans bash. – chaos

+1

Si vous utilisez 'flock', les fichiers de verrouillage sont faciles à gérer - mais oui, utiliser' -f' pour tester leur existence est Evil And Wrong. –

13

Vous pouvez utiliser pidof -x si vous connaissez le nom du processus ou kill -0 si vous connaissez le PID.

Exemple:

if pidof -x vim > /dev/null 
then 
    echo "Vim already running" 
    exit 1 
fi 
+1

C'est le meilleur moyen. – olle

+1

Assurez-vous d'utiliser le drapeau -x si vous vérifiez un script, ou vous ne trouverez pas de correspondance, car il cherchera 'bash' – Nathan

+1

si seulement pidof faisait partie de FreeBSD ... –

1

Pour développer ce @bgy dit, la façon dont atomique en toute sécurité pour créer un fichier de verrouillage si elle n'existe pas encore, et échouera si elle n'a pas, est de créer un fichier temporaire, puis reliez-le au fichier de verrouillage standard. Cela protège contre un autre processus créant le fichier entre vous le tester et vous le créer.

Voici le code du fichier de verrouillage de mon script de sauvegarde horaire:

echo $$ > /tmp/lock.$$ 
if ! ln /tmp/lock.$$ /tmp/lock ; then 
     echo "previous backup in process" 
     rm /tmp/lock.$$ 
     exit 
fi 

Ne pas oublier de supprimer le fichier de verrouillage et le fichier temporaire lorsque vous avez terminé, même si vous quittez tôt par un Erreur.

1

Utilisez ce script:

FILE="/tmp/my_file" 
if [ -f "$FILE" ]; then 
    echo "Still running" 
    exit 
fi 
trap EXIT "rm -f $FILE" 
touch $FILE 

...script here... 

Ce script crée un fichier et le retirer à la sortie.

2

J'ai eu récemment la même question et trouvé en haut qui tuent -0 est le mieux pour ma cas:

echo "Starting process..." 
run-process > $OUTPUT & 
pid=$! 
echo "Process started pid=$pid" 
while true; do 
    kill -0 $pid 2> /dev/null || { echo "Process exit detected"; break; } 
    sleep 1 
done 
echo "Done." 
3

Voici comment je le fais dans un de mes emplois Cron

lockfile=~/myproc.lock 
minutes=60 
if [ -f "$lockfile" ] 
then 
    filestr=`find $lockfile -mmin +$minutes -print` 
    if [ "$filestr" = "" ]; then 
    echo "Lockfile is not older than $minutes minutes! Another $0 running. Exiting ..." 
    exit 1 
    else 
    echo "Lockfile is older than $minutes minutes, ignoring it!" 
    rm $lockfile 
    fi 
fi 

echo "Creating lockfile $lockfile" 
touch $lockfile 

et supprimer le fichier de verrouillage à la fin du script

echo "Removing lock $lockfile ..." 
rm $lockfile 
Questions connexes