Je veux commencer le processus (par exemple. MyCommand) et obtenir son pid (pour permettre de le tuer plus tard).
J'ai essayé ps et filtrer par nom, mais je ne peux pas distinguer processus par noms
myCommand
ps ux | awk '/<myCommand>/ {print $2}'
Parce que les noms de processus ne sont pas uniques.
Je peux exécuter le processus par:
myCommand &
J'ai trouvé que je pouvais obtenir ce PID en:
echo $!
Y a-t-il une solution plus simple?
Je serais heureux d'exécuter myCommand et d'obtenir son PID à la suite d'une commande d'une ligne.
myprogram
aurait été génial&
la ligne précédente, sinon, l'écho renvoie un blanc.command & echo $!
gèle l'exécution à cette étape :(Envelopper la commande dans un petit script
la source
Vous pouvez utiliser
sh -c
etexec
pour obtenir le PID de la commande avant même son exécution.Pour commencer
myCommand
, afin que son PID soit imprimé avant son exécution, vous pouvez utiliser:Comment ça fonctionne:
Cela démarre un nouveau shell, affiche le PID de ce shell, puis utilise la commande
exec
intégrée pour remplacer le shell par votre commande, en veillant à ce qu'il ait le même PID. Lorsque votre shell exécute une commande avec laexec
commande intégrée, votre shell est en fait de plus cette commande , plutôt que le comportement plus fréquent de bifurquer une nouvelle copie de lui - même, qui a son propre PID séparé et qui devient alors la commande.Je trouve cela beaucoup plus simple que des alternatives impliquant une exécution asynchrone (avec
&
), un contrôle des travaux ou une recherche avecps
. Ces approches sont acceptables, mais à moins que vous n'ayez une raison spécifique de les utiliser - par exemple, la commande est peut-être déjà en cours d'exécution. Dans ce cas, il serait logique de rechercher son PID ou d'utiliser le contrôle des tâches - je suggère de commencer par cette méthode. (Et je n’envisagerais certainement pas d’écrire un script complexe ou un autre programme pour y parvenir).Cette réponse comprend un exemple de cette technique.
Des parties de cette commande peuvent parfois être omises, mais pas habituellement.
Même si le shell que vous utilisez est de type Bourne et prend donc en charge les fonctions
exec
intégrées avec ces sémantiques, vous ne devriez généralement pas éviter d'utilisersh -c
(ou l'équivalent) pour créer un nouveau processus de shell distinct à cette fin, car:myCommand
, il n'y a plus de shell en attente pour exécuter les commandes suivantes.sh -c 'echo $$; exec myCommand; foo
ne serait pas en mesure d'essayer de courirfoo
après s'être remplacé avecmyCommand
. Sauf si vous écrivez un script qui l'exécute en tant que dernière commande, vous ne pouvez pas l'utiliser uniquementecho $$; exec myCommand
dans un shell où vous exécutez d'autres commandes.(echo $$; exec myCommand)
Peut être syntaxiquement plus beau quesh -c 'echo $$; exec myCommand'
, mais quand vous courez$$
dedans(
)
, ça donne le PID du shell parent, pas du sous-shell lui-même. Mais c'est le PID du sous-shell qui sera le PID de la nouvelle commande. Certains shells fournissent leurs propres mécanismes non portables pour trouver le PID du sous-shell, que vous pouvez utiliser pour cela. En particulier, dans Bash 4 ,(echo $BASHPID; exec myCommand)
fonctionne.Enfin, notez que certains shells effectuent une optimisation en exécutant une commande comme si
exec
(c’est-à-dire qu’ils renonçaient au premier abord) quand on sait que le shell n’aura plus rien à faire par la suite. Certains shells essaient de le faire chaque fois que c'est la dernière commande à être exécutée, tandis que d'autres ne le feront que lorsqu'il n'y a pas d'autres commandes avant ou après la commande, et d'autres ne le feront pas du tout. L'effet est que si vous oubliez d'écrireexec
et utilisez simplement,sh -c 'echo $$; myCommand'
vous obtiendrez parfois le bon PID sur certains systèmes avec certains shells. Je recommande de ne jamais compter sur un tel comportement , mais de toujours inclureexec
quand c'est ce dont vous avez besoin.la source
myCommand
mon travail, je dois définir un certain nombre de variables d’environnement dans mon script bash. Celles-ci seront-elles transférées à l'environnement dans lequel laexec
commande est exécutée?exec
commande. Cependant, cette approche ne fonctionne pas aumyCommand
démarrage d'autres processus, ceux avec lesquels vous devez travailler. lorsque je produis un akill -INT <pid>
où apid
été obtenu de cette manière, le signal n'atteint pas les sous-processus démarrés parmyCommand
, alors que si je coursmyCommand
dans la session en cours et en Ctrl + C, les signaux se propagent correctement.sh -c 'echo $$; exec /usr/local/bin/mbdyn -f "input.file" -o "/path/to/outputdir" > "command_output.txt" 2>&1 &'
Je ne connais pas de solution plus simple, mais je n’utilise pas $! assez bien? Vous pouvez toujours affecter la valeur à une autre variable si vous en avez besoin ultérieurement, comme d'autres l'ont dit.
En guise d’accompagnement, vous pouvez utiliser
pgrep
oupidof
.la source
utilisez exec depuis un script bash après avoir enregistré le pid dans un fichier:
exemple:
supposons que vous ayez un script nommé "forever.sh" que vous voulez exécuter avec les arguments p1, p2, p3
code source de forever.sh:
créer un reaper.sh:
exécutez forever.sh via reaper.sh:
forever.sh ne fait rien de plus que consigner une ligne dans syslog toutes les 5 secondes
vous avez maintenant le pid dans /var/run/forever.sh.pid
et forever.sh exécute aok. syslog grep:
vous pouvez le voir dans la table de processus:
la source
exec "$@"
place deexec $*
. Techniquement, vous ne devez pas conserver les espaces, mais les occurrences des caractères dans le paramètre du shell IFS (qui utilise par défaut les espaces, les tabulations et les retours à la ligne).Dans le shell bash, une alternative à
$!
pourrait être l'jobs -p
intégré. Dans certains cas ,!
en$!
est interprété par la coquille avant (ou au lieu de) l'expansion variable conduisant à des résultats inattendus.Ceci, par exemple, ne fonctionnera pas:
alors que cela va:
la source
Vous pouvez utiliser quelque chose comme:
Ou
Les deux commandes peuvent être des joints utilisant
;
ou&&
. Dans le second cas, le pid ne sera défini que si la première commande réussit. Vous pouvez obtenir l'identifiant du processus à partir de$pid
.la source
$!
après&&
ou;
ne vous donnera jamais le PID du processus démarré pour le côté gauche du séparateur de commandes.$!
n'est défini que pour les processus lancés de manière asynchrone (par exemple, généralement avec,&
mais certains shells utilisent aussi d'autres méthodes).Ceci est un peu une réponse bidouille et ne fonctionnera probablement pas pour la plupart des gens. C’est également un risque énorme pour la sécurité, alors ne le faites pas à moins d’être sûr que vous serez en sécurité et que les entrées sont désinfectées et… eh bien, vous avez l’idée.
Compilez le petit programme C ici dans un binaire appelé
start
(ou ce que vous voulez), puis lancez votre programme en tant que./start your-program-here arg0 arg1 arg2 ...
En résumé, ceci imprimera le PID dans
stdout
, puis chargera votre programme dans le processus. Il devrait toujours avoir le même PID.la source
stdout
semble pas claire, ne semble pas être enregistré dans cet exemple:RESULT="$(./start_and_get_pid.out echo yo)"; echo "$RESULT"
sleep 10 & PID_IS=$!; echo $PID_IS