web-dev-qa-db-fra.com

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

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 commande disown directement dans le terminal, mais en bash, disown n'empêche pas la transmission 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.

19
user2328113

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

Nohup ./process &

Si vous arrêtez votre script bash avec SIGINT (ctrl + c), ou que le shell quitte l'envoi de SIGHUP par exemple, le processus ne sera pas dérangé et continuera à s'exécuter normalement. stdout & stderr seront redirigés vers un fichier journal: Nohup.out.

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

TEMP_LOG_FILE=tmp.log
> "$TEMP_LOG_FILE"
Nohup ./process &> "$TEMP_LOG_FILE" & tail -f "$TEMP_LOG_FILE" &
16
marc

Pour moi, cela fonctionne parfaitement bien avec le reniement

command & disown
12
ManuelSchneid3r

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é.

4
user2328113

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 concernant la portabilité: ps les options dépendent du système d'exploitation! vous pouvez utiliser à la place une variante de: { ps -ef || ps aux ;} | grep '[o]penocd | cut -f 1. at ne peut pas être disponible (bizarre, mais cela arrive ...). $(...) a besoin d'un Shell pas vraiment vieux, sinon utilisez des astuces.

2
Olivier Dulac