Comment puis-je détacher un processus d'un script bash?


18

J'essaie de détacher un processus d'un script bash afin que SIGINT ne soit pas transmis au processus lorsque je quitte le script.

J'ai utilisé la disowncommande directement dans le terminal, mais dans bash, cela disownn'empêche pas le transfert de SIGINT. Le but de ce script est de démarrer openocd puis gdb avec une seule invocation. Étant donné que le script ne se ferme jamais (il exécute gdb), SIGINT est toujours transmis de gdb à openocd, ce qui est un problème car SIGINT est utilisé comme commande d'arrêt dans gdb.

Dans le terminal, cela ressemblerait à ceci:

$ openocd &    # run openocd demonized
$ disown $!    # disown last pid
$ gdb          # invoke GDB

lorsqu'il est invoqué sur le terminal dans cet ordre, le SIGINT n'est pas passé de gdb à openocd. Cependant, si cette même invocation était dans un script bash, le SIGINT est passé.

Toute aide serait grandement appréciée.

ps ce problème est sous OS X mais j'essaie d'utiliser des outils qui sont également portables pour tous les outils Unix.


nohupn'est pas tout à fait la bonne réponse. Vous devez ajouter un pseudocode ou un exemple de code pour montrer plus précisément ce que vous voulez.
Bruce Ediger

1
Êtes-vous prêt à utiliser un outil comme screen?
Eric Renouf

Réponses:


16

Pour détacher un processus d'un script bash:

nohup ./process &

Si vous arrêtez votre script bash avec SIGINT(ctrl + c), ou si le shell quitte l'envoi SIGHUPpar exemple, le processus ne sera pas dérangé et continuera à s'exécuter normalement. stdoutEt stderrsera redirigé vers un fichier journal: nohup.out.

Si vous souhaitez exécuter une commande détachée tout en pouvant voir la sortie dans le terminal, utilisez alors tail:

TEMP_LOG_FILE=tmp.log
> "$TEMP_LOG_FILE"
nohup ./process &> "$TEMP_LOG_FILE" & tail -f "$TEMP_LOG_FILE" &

Pourquoi est-il nohupnécessaire? Quelle est la différence entre nohup COMMAND &et COMMAND &si votre objectif est uniquement d'exécuter la commande en arrière-plan et de libérer le terminal?
James Wierzba

@JamesWierzba L'une des différences est que si vous avez besoin de la commande pour continuer à exécuter même après avoir quitté le shell, alors rien n'est la voie à suivre. Il existe des milliers d'explications détaillées sur le Web. Par exemple , stackoverflow.com/questions/15595374/...
marc


4

La solution que j'ai trouvée implique un programme appelé «détachement» écrit par Annon Inglorion et téléchargeable à partir de son site Web

Une fois compilé, il peut être utilisé dans un script comme suit:

$ ./detach -p debug.pid openocd <args> # detach openocd
$ gdb <args>                           # run gdb
$ kill -9 $(cat debug.pid)             # end openocd process
$ rm debug.pid                         # remove file containing process id

Cette première ligne crée un nouveau processus (exécutant openocd) et stocke l'ID du processus dans le fichier (debug.pid) pour une utilisation ultérieure. Cela évite les problèmes de recherche du pid comme indiqué dans la réponse d'Oliver. En quittant le programme de blocage suivant (gdb), le fichier stockant le pid est utilisé pour tuer directement le processus détaché.


Peut confirmer, detachfait des merveilles.
AS

2

une solution simple et portable:

echo "openocd" | at now #openocd starts now, but via the at daemon, not the current shell!
pid=$(ps -ef | grep "[o]penocd" | awk '{print $1}')  
echo "openocd is running with pid: $pid"
gdb

Quelques mises en garde psconcernant la portabilité: les options dépendent du système d'exploitation! vous pourriez plutôt utiliser une variante de: { ps -ef || ps aux ;} | grep '[o]penocd | cut -f 1. atn'a pas pu être disponible (bizarre, mais cela arrive ...). $(...)nécessite un shell pas vraiment vieux, sinon utilisez des astuces.


Cela semble dangereux, chercher pid peut faire des choses inattendues si plusieurs processus s'exécutent avec le même nom, ou même si un autre processus contient le mot openocd.
orion

1
@orion: je donne un exemple simple pour donner les idées, les préoccupations que vous mentionnez sont faciles à éliminer: avoir atdémarré un script qui lance le programme et donne son pid à la place dans un fichier, et faire attendre le script principal fichier à apparaître, puis lisez-le.
Olivier Dulac

bien sûr, vous devriez remplacer dans mon exemple (trop simple) le grep par un test à l'intérieur de awk, dans la colonne de droite (8 $, généralement) (les colonnes dépendent de votre système d'exploitation et de la version / options de ps)
Olivier Dulac
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.