J'ai un script bash qui exécute une commande en arrière-plan. Après l'avoir exécuté, il affiche à l'utilisateur: Appuyez sur n'importe quelle touche pour continuer (alimenté par read -n1 -r -p 'Appuyez sur n'importe quelle touche pour continuer' valeur ) < / p>
Je voudrais que quelque chose surveille la commande en arrière-plan pour voir quand elle est terminée, et si c'est le cas, je veux que le script continue de toute façon. D'un autre côté, le processus pourrait toujours être en cours, et je voudrais permettre à l'utilisateur d'appuyer sur une touche pour tuer ce processus au lieu d'attendre qu'il se termine.
Je suppose que le moyen le plus simple de le visualiser serait comme ceci:
L'utilisateur peut soit attendre que le minuteur passe à 0 et il s'éteigne automatiquement, soit s'il clique sur le bouton d'arrêt, il s'arrête immédiatement.
3 Réponses :
Quelque chose comme ça pourrait fonctionner pour vous
#!/bin/bash
doStuff() {
local pidOfParent="$1"
for i in $(seq 10); do
echo "stuff ${i}" > /dev/null
sleep 1
done
kill $pidOfParent
}
doStuff $$ &
doStuffPid="$!"
read -n1 -rp 'Press any key to continue' && kill $doStuffPid
Décomposer
doStuff est notre fonction qui contient ce que vous voulez exécuter en arrière-plan, c'est-à-dire la musique.
$$ est le PID du script en cours d'exécution, que nous transmettons à notre fonction pour devenir le pidOfParent dans lequel nous tuons après avoir fini de faire des choses.
Le & après avoir appelé la fonction le met en arrière-plan .
$! obtient le PID de la dernière commande exécutée, nous avons donc maintenant le PID du processus d'arrière-plan que nous venons de démarrer.
Vous avez fourni read -n1 -rp 'Appuyez sur n'importe quelle touche pour continuer' donc je peux supposer que vous savez déjà ce que cela fait, && kill $ doStuffPid va tuer le processus d'arrière-plan lorsque read est sorti (cela fonctionne également si vous terminez le script en utilisant ^C).
Si vous voulez attendre le pid jusqu'à ce que l'utilisateur frappe une clé, vous pouvez le faire comme suit:
./long_command.sh &
waitpid=$!
echo "Hit any key to continue or wait until the command finishes"
while kill -0 ${waitpid} > /dev/null ; do
#if [[ ${#KEY} -gt 0 ]] ; then
if read -n 1 -t 1 KEY ; then
kill ${waitpid}
break
fi
done
Remplacez simplement long_command.sh par votre commander. Ici $! retourne le pid du dernier sous-processus démarré et kill -0 $ {waitpid} vérifie si le processus est toujours existant (il ne tue pas le processus). ps -q $ {waitpid} fonctionne également sous Linux, mais pas sur Mac - merci @leetbacoon de l'avoir mentionné. read -n 1 -t 1 signifie "lire un caractère, mais attendre seulement 1 seconde" (vous pouvez également utiliser des fractions comme 0,5 ici). Le statut de retour de cette commande dépend de, si elle a pu lire un caractère dans le temps spécifié, ou non.
Cela a fonctionné pour moi, merci, mais j'ai dû utiliser kill -0 "$ {waitpid}" au lieu de ps -q $ {waitpid} car la version macOS de ps n'a pas cet indicateur.
Merci pour votre retour. kill -0 n'est même pas documenté dans la page de manuel Linux. Je suppose que cela signifie le signal 0, mais le signal zéro n'est pas répertorié si j'émets kill -l mais cela fonctionne également. bien tu l'as trouvé! Je le mets à jour dans la réponse car il semble plus portable.
Je ne me souviens pas où je l'ai vu mais kill -0 ne tue rien, il vérifie simplement si ce processus est en cours d'exécution. Si tel est le cas, le code de sortie est 0 . Si ce n'est pas le cas, le code de sortie est ≥ 1 (afaik c'est seulement 1 mais pour être sûr, je dirais ≥ 1).
Si vous êtes prêt à utiliser les attentes intégrées, vous pouvez écrire:
expect <(cat <<'EOD'
spawn sleep 10
send_user "Press any key to continue\n"
stty raw -echo
expect {
-i $user_spawn_id -re ".+" {}
-i $spawn_id eof {}
}
EOD
)
où vous remplaceriez sleep 10 par votre processus.
p>