Terminer un script shell bash s'exécutant en arrière-plan

16

J'utilise souvent bashdes scripts shell pour exécuter des commandes simples pour de nombreux fichiers différents. Par exemple, supposons que j'ai le suivant bashscript shell, appelé script.sh, qui exécute le programme / commande foosur trois fichiers texte "a.txt", "b.txt", "c.txt":

#!/bin/bash

for strname in "a" "b" "c"
do
foo $strname".txt"
done

Supposons également que cela foo $strname".txt"soit lent, de sorte que l'exécution du script prendra beaucoup de temps (heures ou jours, par exemple). Pour cette raison, je voudrais utiliser nohuppour que l'exécution continue même si le terminal est fermé ou déconnecté. J'aimerais également que le script passe immédiatement en arrière-plan, je vais donc utiliser l' &opérateur. J'utiliserai donc la commande suivante pour appeler script.sh:

nohup bash script.sh &

Cela fonctionne très bien pour exécuter le script en arrière-plan et sans raccrocher, mais supposons maintenant que je souhaite terminer l'exécution à un moment donné pour une raison quelconque. Comment puis-je faire ceci?

Le problème que j'ai rencontré est qu'en regardant top, je ne vois que le foocorrespondant à "a.txt". Je peux mettre fin à cet fooappel, mais le foocorrespondant à "b.txt"est appelé et je dois également terminer celui-ci, etc. Pour des dizaines ou des centaines de fichiers texte spécifiés dans la forboucle, il devient difficile de terminer chaque foo, un par un! Donc, d'une manière ou d'une autre, j'ai besoin de mettre fin au script shell lui - même , pas aux appels particuliers émis à partir du script shell.

Quand je tape la commande

ps -u myusername

myusernameest mon nom d'utilisateur, j'obtiens une liste des processus que j'exécute. Mais je vois deux ID de processus différents appelés bash. Comment savoir lequel de ces processus, le cas échéant, correspond à mon appel d'origine nohup bash script.sh &?

Andrew
la source
@Andrew, les deux processus montrent-ils que rien n'est mentionné dans la commande? .... vous pouvez également essayer ps -aWu Andrew et vérifier si vous obtenez une seule entrée longue avec nohup .... est-ce que cela aide?
nitin
2
En passant, votre citation est loufoque. for s in a b c; do foo "$s".txt; done
tripleee
1
@NSD: Non, il y nohupaura longtemps que vous n'aurez plus de liste de processus pour voir le travail que vous avez commencé. Vous pouvez regarder la colonne "gentillesse" dans la pssortie mais les réponses ici sont plus utiles.
tripleee

Réponses:

9

Par défaut, psn'affichera pas les paramètres avec lesquels le programme a été appelé. Les options -fet les -ldeux afficheront l'appel complet.

ps -fu username

entraînera une sortie qui ressemble à:

username 23464 66.7  0.0  11400   628 pts/5    R    15:28   1:40 bash script.sh
j883376
la source
2
C'est modérément utile, mais cela ne supprime pas l'ambiguïté de plusieurs processus avec les mêmes arguments.
tripleee
11

Vous avez plusieurs options. Puisque votre processus s'exécute en arrière-plan, vous pouvez utiliser jobspour le trouver:

nohup bash script.sh &
...
jobs
[1]+ Running    nohup bash script.sh &
kill %1
jobs
[1]+ Terminated nohup bash script.sh &

Vous pouvez également utiliser pkillpour rechercher dans la table de processus une correspondance de ligne de commande; à savoir:

pkill -f script.sh
JRFerguson
la source
1

La pssortie (avec par exempleps aux ) inclut l'ID de processus du parent. Tuez le parent bashet ses enfants seront également supprimés.

Pour une visualisation ASCII de l'arborescence des processus, essayez pstree -pavec quelques processus d'arrière-plan en cours d'exécution.

tripleee
la source