J'utilise Tilda (terminal à menu déroulant) sur Ubuntu en tant que "centre de commande" - à peu près comme d'autres pourraient utiliser GNOME Do, Quicksilver ou Launchy.
Cependant, je ne parviens pas à détacher complètement un processus (par exemple, Firefox) du terminal depuis lequel il a été lancé - c’est-à-dire à empêcher qu’un tel processus (non) enfant
Par exemple, afin de démarrer Vim dans une fenêtre de terminal "correcte", j'ai essayé un script simple comme celui-ci:
exec gnome-terminal -e "vim $@" &> /dev/null &
Cependant, cela cause toujours de la pollution (de plus, passer un nom de fichier ne semble pas fonctionner).
Tout d'abord; une fois que vous avez démarré un processus, vous pouvez l’arrière-plan en l’arrêtant d’abord (touche Ctrl-Z) puis en tapant bg
pour le laisser reprendre en arrière-plan. C'est maintenant un "job", et son stdout
name __/stderr
name __/stdin
sont toujours connectés à votre terminal.
Vous pouvez démarrer un processus en arrière-plan immédiatement en ajoutant un "&" à la fin de celui-ci:
firefox &
Pour l'exécuter en arrière-plan silencieux, utilisez ceci:
firefox </dev/null &>/dev/null &
Quelques informations supplémentaires:
Nohup
est un programme que vous pouvez utiliser pour exécuter votre application avec tel que son stdout/stderr puisse être envoyé à un fichier à la place et que la fermeture du script parent ne détecte pas l'enfant. Cependant, vous devez avoir eu la clairvoyance de l'avoir utilisé avant de démarrer l'application. En raison du fonctionnement de Nohup
name__, vous ne pouvez pas simplement l'appliquer à un processus en cours d'exécution .
disown
est une commande intégrée de bash qui supprime un travail Shell de la liste des travaux du shell. Cela signifie essentiellement que vous ne pouvez plus utiliser fg
name__, bg
name__, mais plus important encore, lorsque vous fermez votre shell, il ne se bloque plus ni n'envoie un SIGHUP
name__. Contrairement à Nohup
name__, disown
est utilisé after le processus a été lancé et mis en arrière-plan.
Ce que vous ne pouvez pas , c’est modifier le stdout/stderr/stdin d’un processus après l’avoir lancé. Du moins pas de la coquille. Si vous lancez votre processus et que vous lui indiquez que sa sortie standard est votre terminal (ce que vous faites par défaut), alors ce processus est configuré pour générer une sortie vers votre terminal. Votre Shell n'a aucune relation avec la configuration FD des processus, c'est simplement quelque chose que gère le processus lui-même. Le processus lui-même peut décider de fermer ou pas son stdout/stderr/stdin, mais vous ne pouvez pas utiliser votre shell pour le forcer à le faire.
Pour gérer la sortie d'un processus en arrière-plan, vous disposez de nombreuses options de scripts, "Nohup" étant probablement le premier à venir à l'esprit. Mais pour les processus interactifs, vous démarrez, mais vous avez oublié de taire (firefox < /dev/null &>/dev/null &
), vous ne pouvez pas faire grand-chose, vraiment.
Je vous recommande d’obtenir GNU screen
name__. Avec screen, vous pouvez simplement fermer votre Shell en cours d’exécution lorsque la sortie du processus devient un problème et en ouvrir un nouveau (^Ac
).
Oh, et d'ailleurs, n'utilisez pas "$@
" à l'endroit où vous l'utilisez.
$@
signifie, $1
, $2
, $3
..., ce qui transformerait votre commande en:
gnome-terminal -e "vim $1" "$2" "$3" ...
Ce n'est probablement pas ce que vous voulez car -e ne prend que n argument. Utilisez $1
pour montrer que votre script ne peut gérer qu'un seul argument.
Il est vraiment difficile de faire fonctionner plusieurs arguments correctement dans le scénario que vous avez donné (avec le gnome-terminal -e
) car -e
ne prend qu'un seul argument, qui est une chaîne de commande Shell. Vous devrez encoder vos arguments en un seul. La meilleure et la plus robuste, mais assez lourde, ressemble à ceci:
gnome-terminal -e "vim $(printf "%q " "$@")"
Nohup cmd &
Nohup
détache complètement le processus (le démonise)
Si vous utilisez bash
, essayez disown [jobspec]
; voir bash (1) .
Une autre approche que vous pouvez essayer est at now
. Si vous n'êtes pas superutilisateur, votre permission d'utiliser at
peut être restreinte.
En lisant ces réponses, j'ai eu l’impression initiale que l’émission de Nohup <command> &
serait suffisante. En exécutant zsh dans gnome-terminal, j’ai constaté que Nohup <command> &
n’empêchait pas mon shell de tuer les processus enfants à la sortie. Bien que Nohup
soit utile, en particulier avec les shells non interactifs, il ne garantit ce comportement que si le processus enfant ne réinitialise pas son gestionnaire pour le signal SIGHUP
.
Dans mon cas, Nohup
aurait dû empêcher les signaux de raccrochage d'atteindre l'application, mais l'application enfant (VMWare Player dans ce cas) était en train de réinitialiser son gestionnaire SIGHUP
. Par conséquent, lorsque l'émulateur de terminal se ferme, il pourrait toujours tuer vos sous-processus. À ma connaissance, cela ne peut être résolu qu'en veillant à ce que le processus soit supprimé de la table des tâches du shell. Si Nohup
est remplacé par un shell intégré, comme cela peut parfois arriver, cela peut suffire, toutefois, si ce n'est pas le cas ...
disown
est un shell intégré dans bash
, zsh
et ksh93
,
<command> &
disown
ou
<command> &; disown
si vous préférez les one-liners. Cela a généralement pour effet souhaitable de supprimer le sous-processus de la table des tâches. Cela vous permet de quitter l'émulateur de terminal sans signaler accidentellement le processus enfant. Peu importe ce à quoi ressemble le gestionnaire SIGHUP
, cela ne devrait pas tuer votre processus enfant.
Après le désaveu, le processus est toujours un enfant de votre émulateur de terminal (jouez avec pstree
si vous voulez regarder cela en action), mais après la sortie de l'émulateur de terminal, vous devriez le voir attaché au processus init. En d'autres termes, tout est comme il se doit, et comme vous le souhaitez vraisemblablement.
Que faire si votre Shell ne prend pas en charge disown
? Je recommanderais fortement de passer à un système qui le fait, mais en l'absence de cette option, vous avez quelques choix.
screen
et tmux
peuvent résoudre ce problème, mais ce sont des solutions beaucoup plus lourdes, et je n'aime pas avoir à les exécuter pour une tâche aussi simple. Ils sont bien plus adaptés aux situations dans lesquelles vous souhaitez gérer un terminal, généralement sur une machine distante.setopt Nohup
de zsh. Cela peut être utilisé pour spécifier que SIGHUP
ne doit pas être envoyé aux travaux de la table des travaux lorsque le shell se ferme. Vous pouvez l'appliquer juste avant de quitter le shell ou l'ajouter à la configuration du shell comme ~/.zshrc
si vous le souhaitez toujours.tcsh
ou csh
, ce qui est quelque peu dérangeant.exec()
. C'est une très mauvaise solution, mais la source ne devrait consister qu'en une douzaine de lignes. Vous pouvez ensuite passer des commandes sous forme d'arguments de ligne de commande au programme C et éviter ainsi une entrée spécifique au processus dans le tableau des travaux.Nohup $COMMAND &
$COMMAND & disown
setsid command
J'utilise le numéro 2 depuis très longtemps, mais le numéro 3 fonctionne aussi bien. De plus, disown
a un indicateur Nohup
de -h
, peut rejeter tous les processus dotés de -a
et peut renoncer à tous les processus en cours d'exécution avec -ar
.
Le silence est accompli par $COMMAND &>/dev/null
.
J'espère que cela t'aides!
dans tcsh (et peut-être aussi dans d'autres shells), vous pouvez utiliser des parenthèses pour détacher le processus.
Comparez ceci:
> jobs # shows nothing
> firefox &
> jobs
[1] + Running firefox
Pour ça:
> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>
Ceci supprime firefox de la liste des tâches, mais reste lié au terminal. si vous vous êtes connecté à ce nœud via 'ssh', le fait d'essayer de vous déconnecter bloquera toujours le processus ssh.
Je pense que l'écran pourrait résoudre votre problème
La réponse la plus simple et la plus correcte pour bash:
command & disown
Vous ne devez pas détacher le processus du terminal, mais du shell.
Pour dissocier la commande d'exécution tty Shell via un sous-shell, par exemple.
(commander)&
Lorsque la sortie utilisée terminal fermé, mais le processus est toujours en vie.
vérifier -
(sleep 100) & exit
Ouvrir un autre terminal
ps aux | grep sleep
Le processus est toujours en vie.
Arrière-plan et mise au premier plan d'un travail est probablement l'une des toutes premières choses que tout administrateur système Unix doit savoir.
Voici comment cela se fait avec bash:
./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg
Vous pouvez exécuter votre commande en utilisant la commande Nohup, cela détache votre processus et redirige les sorties vers un fichier donné ... mais je ne suis pas sûr que ce soit exactement ce dont vous avez besoin.
Essayez daemon - devrait être disponible auprès de votre gestionnaire de paquets convivial et doit prendre en charge de manière exhaustive tout moyen de se dissocier du terminal.
Ajoutez simplement ceci dans votre bashrc/zshrc:
detach() {
"$@" 1>/dev/null 2>/dev/null &; disown
}
Ensuite, vous pouvez exécuter des commandes désapprouvées comme ceci:
detach gedit ~/.zshrc
Dans mon .bashrc, j’ai ces fonctions précisément pour cela:
function run_disowned() {
"$@" & disown
}
function dos() {
# run_disowned and silenced
run_disowned "$@" 1>/dev/null 2>/dev/null
}
Préfixez une commande avec dos
pour l'exécuter détachée du terminal.
La fonction est écrite pour fonctionner avec bash
et zsh
.
J'ai trouvé sur Mac OS X que je devais utiliser à la fois Nohup ET désavoué pour que le processus enfant ne soit pas anéanti par le terminal.
J'utilise le script suivant pour le faire. Il arrête le processus d'impression sur le terminal, se détache avec Nohup
et se termine avec le statut de retour si la commande se termine dans la TIMEOUT
.
#!/bin/bash
TIMEOUT=0.1
CMD=( "$@" )
#Could have some shortcuts here, e.g. replace "somefile.c" with "gedit somefile.c"
#use Nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send Nohup's output to /dev/null, supressing Nohup.out
#run Nohup in the background so this script doesn't block
#print the command for debugging and to see bash variable expansion
printf "%q " "${CMD[@]}"
echo
Nohup "${CMD[@]}" >/dev/null 2>&1 &
Nohup_PID=$!
#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally
#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $Nohup_PID
Nohup_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $Nohup_STATUS != 0 ] && echo "Error: $CMD"
#return the exit status of Nohup, whatever it was
exit $Nohup_STATUS
Exemple d'utilisation:
>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>