GNU bash, version 1.14.7 (1)
J'ai un script qui s'appelle "abc.sh
" Je dois vérifier ceci à partir du script abc.sh
uniquement ... À l'intérieur, j'ai écrit la déclaration suivante.
status=`ps -efww | grep -w "abc.sh" | grep -v grep | grep -v $$ | awk '{ print $2 }'`
if [ ! -z "$status" ]; then
echo "[`date`] : abc.sh : Process is already running"
exit 1;
fi
Je sais que c'est faux, car chaque fois qu'il se termine car il trouve son propre processus dans 'ps' Comment le résoudre? Comment puis-je vérifier que le script est déjà en cours d'exécution ou pas uniquement from that script
?
Un moyen plus facile de vérifier si un processus est déjà en cours d'exécution est la commande pidof
.
if pidof -x "abc.sh" >/dev/null; then
echo "Process already running"
fi
Vous pouvez également demander à votre script de créer un fichier PID lors de son exécution. C'est ensuite un simple exercice de vérification de la présence du fichier PID pour déterminer si le processus est déjà en cours d'exécution.
#!/bin/bash
# abc.sh
mypidfile=/var/run/abc.sh.pid
# Could add check for existence of mypidfile here if interlock is
# needed in the Shell script itself.
# Ensure PID file is removed on program exit.
trap "rm -f -- '$mypidfile'" EXIT
# Create a file with current PID to indicate that process is running.
echo $$ > "$mypidfile"
...
Mise à jour: La question a maintenant changé pour vérifier à partir du script lui-même. Dans ce cas, nous nous attendons à toujours voir au moins un abc.sh
en cours d'exécution. S'il existe plus d'un abc.sh
, nous savons que ce processus est toujours en cours d'exécution. Je suggérerais quand même d'utiliser la commande pidof
qui renverrait 2 PID si le processus était déjà en cours d'exécution. Vous pouvez utiliser grep
pour filtrer le PID actuel, la boucle dans le shell ou même revenir au comptage des PID avec wc
pour détecter plusieurs processus.
Voici un exemple:
#!/bin/bash
for pid in $(pidof -x abc.sh); do
if [ $pid != $$ ]; then
echo "[$(date)] : abc.sh : Process is already running with PID $pid"
exit 1
fi
done
Si vous voulez la méthode "pidof", voici le truc:
if pidof -o %PPID -x "abc.sh">/dev/null; then
echo "Process already running"
fi
Où le paramètre -o %PPID
indique d'omettre le pid du shell ou du script shell appelant. Plus d'informations dans la page de manuel pidof
.
Voici un truc que vous verrez à différents endroits:
status=`ps -efww | grep -w "[a]bc.sh" | awk -vpid=$$ '$2 != pid { print $2 }'`
if [ ! -z "$status" ]; then
echo "[`date`] : abc.sh : Process is already running"
exit 1;
fi
Les crochets entourant le [a]
(ou choisissez une lettre différente) empêchent grep
de se retrouver. Cela rend le bit grep -v grep
inutile. J'ai également supprimé le grep -v $$
et corrigé la partie awk
pour accomplir la même chose.
Quelqu'un s'il vous plaît abattez-moi si je me trompe ici
Je comprends que l’opération mkdir
est atomique, vous pouvez donc créer un verrou répertoire
#!/bin/sh
lockdir=/tmp/AXgqg0lsoeykp9L9NZjIuaqvu7ANILL4foeqzpJcTs3YkwtiJ0
mkdir $lockdir || {
echo "lock directory exists. exiting"
exit 1
}
# take pains to remove lock directory when script terminates
trap "rmdir $lockdir" EXIT INT KILL TERM
# rest of script here
Utilisez la commande PS de manière légèrement différente pour ignorer également le processus enfant:
ps -eaf | grep -v grep | grep $PROCESS | grep -v $$
pidof
ne fonctionnait pas pour moi, alors j'ai cherché un peu plus et je suis tombé sur pgrep
for pid in $(pgrep -f my_script.sh); do
if [ $pid != $$ ]; then
echo "[$(date)] : my_script.sh : Process is already running with PID $pid"
exit 1
else
echo "Running with PID $pid"
fi
done
Extrait des réponses ci-dessus et/ https://askubuntu.com/a/803106/802276
Je crée un fichier temporaire en cours d'exécution.
Voici comment je le fais:
#!/bin/sh
# check if lock file exists
if [ -e /tmp/script.lock ]; then
echo "script is already running"
else
# create a lock file
touch /tmp/script.lock
echo "run script..."
#remove lock file
rm /tmp/script.lock
fi
Je ne voulais pas coder en dur abc.sh
dans la vérification, alors j'ai utilisé ce qui suit:
MY_SCRIPT_NAME=`basename "$0"`
if pidof -o %PPID -x $MY_SCRIPT_NAME > /dev/null; then
echo "$MY_SCRIPT_NAME already running; exiting"
exit 1
fi
Voici comment je le fais dans un script bash:
if ps ax | grep $0 | grep -v $$ | grep bash | grep -v grep
then
echo "The script is already running."
exit 1
fi
Cela me permet d’utiliser cet extrait pour n’importe quel script bash. J'avais besoin de grep bash, car lors de son utilisation avec cron, il crée un autre processus qui l'exécute avec/bin/sh.
J'ai constaté qu'en utilisant des pseudonymes pour capturer le résultat d'une commande dans une variable, il en résulte un nombre trop élevé de ps aux results, par exemple pour une seule instance en cours d'exécution de abc.sh :
ps aux | grep -w "abc.sh" | grep -v grep | wc -l
renvoie "1". cependant,
count=`ps aux | grep -w "abc.sh" | grep -v grep | wc -l`
echo $count
renvoie "2"
On dirait que l'utilisation de la construction backtick crée temporairement un autre processus. Cela pourrait être la raison pour laquelle le sujet ne pourrait pas faire ce travail. Juste besoin de décrémenter le $ count var.
Je trouve que la réponse de @Austin Phillips est parfaite. Une petite amélioration que je ferais est d'ajouter -o (pour ignorer le pid du script lui-même) et de faire correspondre le script avec le nom de base (c'est-à-dire que le même code peut être placé dans n'importe quel script):
if pidof -x "`basename $0`" -o $$ >/dev/null; then
echo "Process already running"
fi