Pourquoi exécuter une commande shell Linux avec '&'?

30

J'utilise Red Hat Linux Enterprise version 5. J'ai remarqué que des personnes exécutaient parfois des commandes avec quelques &options. Par exemple, dans la commande ci-dessous, il y a deux &signes. Quel est leur but? Sont-ils toujours utilisés avec nohup?

nohup foo.sh <script parameters> >& <log_file_name> &
George2
la source

Réponses:

15

En plus des réponses de Martin, Ash et Kevin, vous verrez parfois une esperluette utilisée mathématiquement pour un ET binaire * :

$ echo $(( 11 & 7 ))
3

Si vous n'êtes pas familier avec les opérateurs de bits:

11: 1011
 7: 0111
-------- AND
 3: 0011

Dans chaque position, il y a un bit dans le premier nombre ET le deuxième nombre, mettez ce bit à un dans la réponse.

* La fonctionnalité de la réponse de Kevin est appelée un ET logique .

Pour développer la réponse d'Ash, lorsqu'elle est utilisée dans la redirection, l'esperluette peut dire au shell de copier un descripteur de fichier. Dans cette commande, echo "hello" > outputfile 2>&1l'esperluette fait que toute sortie pouvant aller à l'erreur standard (stderr, descripteur de fichier 2) va au même endroit que la sortie standard (stdout, descripteur de fichier 1, la valeur par défaut pour le côté gauche de >). L' >& outputfileopérateur est un raccourci pour > outputfile 2>&1.

De plus, nouveau dans Bash 4, il y a deux nouveaux terminateurs pour les clauses dans la casecommande ;&et ;;&qui affectent si un cas "tombe" et, si c'est le cas, si le prochain test est effectué.

En pause jusqu'à nouvel ordre.
la source
Cool, Dennis! Supposons que j'utilise le journal du terminal ssh dans une machine, puis j'utilise le terminal du ssh pour exécuter la commande (supposons un processus à long terme), puis si je quitte la session du terminal, le processus à long terme de la commande se terminera correctement? Et si je veux que la commande continue à s'exécuter même si je quitte le shell, dois-je utiliser nohup ou & (à la fin de la commande) ou utiliser à la fois nohup et &?
George2
1
@ George2: Non, >& filenamerenvoie à la fois stdout et stderr dans le même fichier. Si vous souhaitez rediriger stderr uniquement (et laisser stdout seul), vous le feriez 2> filename. Quant à votre autre question, vous utiliserez très probablement à la fois nohupet &.
pause jusqu'à nouvel ordre.
1
@ George2: Si vous ne mettez pas la commande en arrière-plan, vous ne recevrez pas d'invite shell afin de pouvoir exécuter une commande logoutou exit.
pause jusqu'à nouvel ordre.
2
George: Si vous n'utilisez pas &, vous ne serez jamais invité à faire autre chose. Le terminal sera «suspendu» jusqu'à ce que le processus (quel qu'il soit) se termine ou qu'il soit terminé / tué. Le & garantit que le processus s'exécute en arrière-plan. Cependant, si vous vous déconnectez, le système d'exploitation mettra fin à tous vos processus, ce qui tue également votre processus d'arrière-plan. Si vous utilisez nohup, vous dites au processus «ignorez la commande qui vous terminera».
Martin Marconcini
1
@ George2: Oui. "à l'abri des blocages" == "poursuite du processus" et "non-tty" == "quitter la session de la console du terminal"
pause jusqu'à nouvel ordre.
32

Dans un script shell Bash, l'esperluette «&» est utilisée pour bifurquer des processus:

find -name hello &

Cela entraînera la commande find à être forkée et exécutée en arrière-plan (vous pouvez toujours la tuer par son PID).

Martin Marconcini
la source
Merci Martin, supposons que j'utilise le journal du terminal ssh dans une machine, puis que j'utilise le terminal du ssh pour exécuter la commande (supposons un processus à long terme), puis si je quitte la session du terminal, le processus à long terme de la commande se terminera correctement ? Et si j'exécute la commande à l'aide de & in ssh terminal, même si je quitte le terminal, le processus à long terme de la commande est toujours en cours d'exécution, n'est-ce pas?
George2
1
C'est vrai George. Les processus d'arrière-plan doivent se poursuivre jusqu'à leur sortie ou jusqu'à ce que vous les tuiez. Cependant, comme cela a déjà été souligné, vous aurez besoin de rien pour éviter que le processus ne meure lorsque l'utilisateur se déconnecte.
Martin Marconcini
Merci Martin! Je veux savoir pourquoi nous devons utiliser à la fois & et nohup, et quelles sont leurs fonctions individuelles qui nous permettent d'atteindre l'objectif de laisser la commande continuer à s'exécuter même si la console du terminal se ferme. J'ai lu la page de manuel pour nohup, et il est mentionné "exécuter une commande à l'abri des blocages, avec une sortie vers un non-tty", je ne sais pas si l'immunité aux blocages est ce que vous voulez dire laisser la commande continuer à s'exécuter sans être impacté par quitter console de terminal? Si c'est le cas, je pense que l'utilisation de nohup est suffisante, et pas besoin d'utiliser &. Des commentaires?
George2
1
Vous devez utiliser les deux, si vous n'utilisez pas &, le terminal ne vous permettra pas d'entrer d'autres commandes. La meilleure façon pour vous de le voir, c'est de l'essayer. Un bon exemple est une commande qui prend un certain temps, comme une recherche: find -name SomeName /> somefile.txt essayez cela avec nohup et & et voyez les différences.
Martin Marconcini
Cela a une excellente réponse à la question nohup: serverfault.com/questions/311593/…
joshperry
26

Pourquoi exécuter une commande shell Linux avec '&'?

Pour récupérer immédiatement votre invite et exécuter le processus en arrière-plan.

Quelle est leur fonction?

nohup permet au processus d'arrière-plan de continuer à s'exécuter même après la déconnexion de l'utilisateur (ou la fermeture du shell initiateur).

> & redirige la sortie standard et l'erreur standard dans le fichier journal.

& exécute le tout en arrière-plan, vous renvoyant immédiatement votre invite.

Explication:

Chaque processus Linux ouvre trois canaux d'E / S, une entrée "stdin", une sortie standard "stdout" et une sortie d'erreur standard "stderr". Ils peuvent être utilisés pour le binaire, mais ils sont traditionnellement du texte. Lorsque la plupart des programmes voient stdin fermer, ils se terminent (cela peut être modifié par le programmeur).

Lorsque le shell parent se termine, stdin est fermé sur les enfants et (souvent, généralement) les enfants sortent également. De plus, les enfants reçoivent un signal logiciel, SIGHUP, indiquant que l'utilisateur a "raccroché" (anciennement, le modem) et que la valeur par défaut ici est de quitter également. (Remarque, un programmeur peut changer tout cela lors de l'écriture du programme).

Donc, ce que fait rien est de donner au processus enfant un environnement d'E / S séparé, de lier les tenants et les aboutissants à quelque chose qui n'est pas lié au shell parent, et de protéger l'enfant du signal SIGHUP. Une fois que l'utilisateur se déconnecte, vous verrez le processus d'arrière-plan nohup appartenant à init (processus 1), pas le shell de l'utilisateur.

Cependant, nohupne peut pas faire le travail complètement si le processus est exécuté au premier plan, il &est donc utilisé pour exécuter le programme en arrière-plan, où il peut continuer à fonctionner avec ou sans utilisateur connecté.

kmarsh
la source
Supposons que j'utilise le journal du terminal ssh dans une machine, puis j'utilise le terminal du ssh pour exécuter la commande (supposons un processus à long terme), puis si je quitte la session du terminal, le processus à long terme de la commande se terminera correctement? Et si je veux que la commande continue à s'exécuter même si je quitte le shell, dois-je utiliser nohup ou & (à la fin de la commande) ou utiliser à la fois nohup et &?
George2
1
Correct, utilisez à la fois nohup et & pour que le processus se poursuive après la déconnexion de SSH.
kmarsh
Merci Kmarsh! Je veux savoir pourquoi nous devons utiliser à la fois & et nohup, et quelles sont leurs fonctions individuelles qui nous permettent d'atteindre l'objectif de laisser la commande continuer à s'exécuter même si la console du terminal se ferme. J'ai lu la page de manuel pour nohup, et il est mentionné "exécuter une commande à l'abri des blocages, avec une sortie vers un non-tty", je ne sais pas si l'immunité aux blocages est ce que vous voulez dire laisser la commande continuer à s'exécuter sans être impacté par quitter console de terminal? Si c'est le cas, je pense que l'utilisation de nohup est suffisante, et pas besoin d'utiliser &. Des commentaires?
George2
1
Je vais modifier ma réponse pour répondre.
kmarsh
13

En plus de la réponse de @ Martin: L'autre utilisation de l'esperluette ( >&comme ci-dessus) est de capturer à la fois stdoutet stderr. Normalement, si vous redirigiez la sortie vers un fichier avec seulement '>', vous n'obtiendrez que la sortie stdout, sans aucune erreur.

Cendre
la source
1. Merci Ash, je veux confirmer avec vous que "> & <nom du fichier journal>", va vider tous les stderr et stdout dans le fichier journal, correct? 2. Et en utilisant "> <nom du fichier journal>", tout le stdout sera vidé dans le fichier journal, n'est-ce pas?
George2
1
@George: Oui, c'est vrai.
Ash
Merci Ash! Je veux savoir pourquoi nous devons utiliser à la fois & et nohup, et quelles sont leurs fonctions individuelles qui nous permettent d'atteindre l'objectif de laisser la commande continuer à s'exécuter même si la console du terminal se ferme. J'ai lu la page de manuel pour nohup, et il est mentionné "exécuter une commande à l'abri des blocages, avec une sortie vers un non-tty", je ne sais pas si l'immunité aux blocages est ce que vous voulez dire laisser la commande continuer à s'exécuter sans être impacté par quitter console de terminal? Si c'est le cas, je pense que l'utilisation de nohup est suffisante, et pas besoin d'utiliser &. Des commentaires?
George2
4

En plus de la réponse de Martin et Ash, vous pouvez parfois voir l'utilisation d'un &&jeton. Ceci est utilisé pour dire "exécuter la deuxième commande si et seulement si la première commande s'est déroulée avec succès". Une commande bien écrite, si elle contient des erreurs, ne se terminera pas correctement.

[kevin@box ~]$ ls file && echo removing file && rm file
ls: file: No such file or directory
[kevin@box ~]$ touch file
[kevin@box ~]$ ls file && echo removing file && rm file
file
removing file
[kevin@box ~]$
Kevin M
la source
Cool, Kevin! Supposons que j'utilise le journal du terminal ssh dans une machine, puis j'utilise le terminal du ssh pour exécuter la commande (supposons un processus à long terme), puis si je quitte la session du terminal, le processus à long terme de la commande se terminera correctement? Et si je veux que la commande continue à s'exécuter même si je quitte le shell, dois-je utiliser nohup ou & (à la fin de la commande) ou utiliser à la fois nohup et &?
George2
L'un ou l'autre fonctionnerait. NOHUP était la façon originale de le faire, j'imagine (mais je devine totalement), mais l'arrière-plan fonctionne maintenant. Une différence importante est lors de l'exécution d'un shell interactif en sshing dans un système distant. Le processus NOHUP s'exécuterait au premier plan, mais continuerait de fonctionner si vous quittez, tandis que le processus d'arrière-plan reviendrait immédiatement après avoir généré la commande. Mais lorsque vous essayez de quitter un shell interactif avec une commande exécutée en arrière-plan, vous êtes d'abord averti.
Kevin M
2

La réponse de Martin est bonne, mais un peu ambiguë. La commande est toujours forkée et exécutée, mais le comportement normal du shell est d'attendre la commande jusqu'à ce qu'elle se termine. L'esperluette le met en arrière-plan afin que vous obteniez votre invite de terminal et que vous puissiez faire d'autres choses. Si le processus crache des données vers stdout ou stderr, cela sera mélangé avec tout ce que vous faites à l'invite et peut vous confondre. C'est pourquoi vous redirigez ensuite avec> & /path/to/logfile.txt.

En réponse à George2, le comportement normal d'un shell sortant consiste à envoyer le signal SIGHUP à tous les processus du même groupe de processus (essentiellement les choses que vous avez générées) et ils se terminent généralement. Si vous voulez que cela continue même si vous fermez le processus shell, vous pouvez utiliser la commande nohup pour leur faire ignorer ce signal et continuer à fonctionner. Il y a un nom spécial pour ce type de processus, il s'appelle un processus démon (prononcé «démon»).

Rich Homolka
la source
Merci Rich! Supposons que j'utilise le journal du terminal ssh dans une machine, puis j'utilise le terminal du ssh pour exécuter la commande (supposons un processus à long terme), puis si je quitte la session du terminal, le processus à long terme de la commande se terminera correctement? Et si je veux que la commande continue à s'exécuter même si je quitte le shell, dois-je utiliser nohup ou & (à la fin de la commande) ou utiliser à la fois nohup et &? Et pourquoi?
George2
Salut George, désolé, je réponds si tard. Oui, si vous quittez le shell, le processus à long terme sera interrompu. Si vous voulez qu'il continue, vous devez faire à la fois nohup (pour ne pas le terminer à la fermeture du shell) et & (pour le mettre en arrière-plan, afin que vous puissiez Crtl-D ou quitter votre shell). Vous pouvez également consulter la commande setsid, qui permettra à votre processus de s'exécuter, en ignorant SIGHUP d'une manière légèrement différente.
Rich Homolka
Excellente réponse, explique les meilleures pratiques pour les processus démarrés en shell exécutés en arrière-plan.
Marcel Valdez Orozco