GNU/Linux >> Tutoriels Linux >  >> Linux

Quelqu'un peut-il expliquer en détail ce que fait set -m ?

Citant la documentation bash (à partir de man bash ):

JOB CONTROL
       Job  control  refers to  the  ability  to selectively  stop
       (suspend) the execution of  processes and continue (resume)
       their execution at a later point.  A user typically employs
       this facility via an interactive interface supplied jointly
       by the operating system kernel's terminal driver and bash.

Donc, tout simplement dit, avoir set -m (la valeur par défaut pour les shells interactifs) permet d'utiliser des éléments intégrés tels que fg et bg ,qui serait désactivé sous set +m (la valeur par défaut pour les shells non interactifs).

Cependant, le lien entre le contrôle des tâches et la suppression des processus d'arrière-plan à la sortie n'est pas évident pour moi, mais je peux confirmer qu'il y en a un :exécuter set -m; (sleep 10 ; touch control-on) & créera le fichier si l'on quitte le shell juste après avoir tapé cette commande, mais set +m; (sleep 10 ; touch control-off) & ne le sera pas.

Je pense que la réponse se trouve dans le reste de la documentation pour set -m :

-m      Monitor  mode. [...]                     Background pro‐
        cesses run in a separate process group and a  line  con‐
        taining  their exit status is printed upon their comple‐
        tion.

Cela signifie que les tâches en arrière-plan ont commencé sous set +m ne sont pas de véritables "processus d'arrière-plan" ("Les processus d'arrière-plan sont ceux dont l'ID de groupe de processus diffère de celui du terminal") :ils partagent le même ID de groupe de processus que le shell qui les a démarrés, plutôt que d'avoir leur propre groupe de processus comme les processus d'arrière-plan appropriés. Ceci explique le comportement observé lorsque le shell quitte avant certains de ses backgroundjobs :si j'ai bien compris, lors de la fermeture, un signal est envoyé aux processus du même groupe de processus que le shell (tuant ainsi les tâches d'arrière-plan lancées sous set +m ), mais pas à ceux des autres groupes de processus (laissant ainsi les vrais processus d'arrière-plan démarrés sous set -m ).

Donc, dans votre cas, le startup.sh le script démarre vraisemblablement une tâche en arrière-plan. Lorsque ce script est exécuté de manière non interactive, comme sur SSH comme dans la question à laquelle vous avez lié, le contrôle du travail est désactivé, le travail "en arrière-plan" partage le groupe de processus du shell distant, et est donc tué dès que ce shell se termine. Inversement, en activant jobcontrol dans ce shell, le travail en arrière-plan acquiert son propre groupe de processus et n'est pas tué lorsque son shell parent se termine.


J'ai trouvé ceci sur la liste des problèmes de github, et je pense que cela répond vraiment à votre question.

Ce n'est pas vraiment un problème SSH, c'est plus le comportement subtil autour des modes BASH non interactifs/interactifs et la propagation du signal vers les groupes de processus.

Ce qui suit est basé surhttps://stackoverflow.com/questions/14679178/why-does-ssh-wait-for-my-subshells-without-t-and-kill-them-with-t/14866774#14866774et http:// www.itp.uzh.ch/~dpotter/howto/daemonize, avec certaines hypothèses non entièrement validées, mais des tests sur son fonctionnement semblent confirmer.

pty/tty =faux

Le shell bash lancé se connecte à stdout/stderr/stdin du processus démarré et continue de fonctionner jusqu'à ce qu'il n'y ait plus rien attaché aux sockets et que ses enfants soient sortis. Un bon processus démon s'assurera qu'il n'attend pas que ses enfants se terminent, bifurque un processus enfant puis quitte. Dans ce mode, aucun SIGHUP ne sera envoyé au processus enfant par SSH. Je pense que cela fonctionnera correctement pour la plupart des scripts exécutant un processus qui gère lui-même la démonisation et n'a pas besoin d'être en arrière-plan. Là où les scripts d'initialisation utilisent '&' pour mettre un processus en arrière-plan, il est probable que le principal problème sera de savoir si le processus en arrière-plan tente de lire à partir de stdin, car cela déclenchera un SIGHUP si la session a été terminée.

pty/tty =vrai*

Si le script d'initialisation démarre le processus en arrière-plan, le BASHshell parent renverra un code de sortie à la connexion SSH, qui cherchera à son tour à quitter immédiatement car il n'attend pas qu'un processus enfant se termine et n'est pas bloqué sur stdout/stderr/ stdin. Cela entraînera l'envoi d'un SIGHUP au groupe de processus shell bash parent, qui, puisque le contrôle des tâches est désactivé en mode non interactif dans bash, inclura les processus enfants qui viennent d'être lancés. Lorsqu'un processus démon démarre explicitement une nouvelle session de processus lors du fork ou dans le processus forked, alors lui ou ses enfants ne recevront pas le SIGHUP de la sortie du processus parent BASH. Notez que ceci est différent des travaux suspendus qui verront un SIGTERM. Je soupçonne que les problèmes liés à ce seul travail sont parfois liés à une légère condition de concurrence. Si vous regardez l'approche standard de désamonisation -http://www.itp.uzh.ch/~dpotter/howto/daemonize, vous verrez que dans le code, la nouvelle session est créée par le processus fourchu qui ne peut pas être exécuté avant le parent sort, ce qui entraîne le comportement aléatoire de réussite/échec mentionné ci-dessus. Une déclaration de mise en veille laissera suffisamment de temps au processus dupliqué pour créer une nouvelle session, c'est pourquoi cela fonctionne dans certains cas.

pty/tty =true et le contrôle des tâches est explicitement activé dans bash

SSH ne se connectera pas à stdout/stderr/stdin du shell bash ou à tout processus enfant lancé, ce qui signifie qu'il se fermera dès que le shell bash parent aura fini d'exécuter les commandes demandées. Dans ce cas, avec le contrôle des tâches explicitement activé, tout processus lancé par le shell bash avec '&' en arrière-plan sera immédiatement placé dans une session séparée et ne recevra pas le signal SIGHUP lorsque le processus parent de la session BASH se termine (connexion SSH dans ce cas).

Ce qu'il faut réparer

Je pense que les solutions doivent simplement être explicitement mentionnées dans la documentation des opérations run/sudo en tant que cas particulier lorsque vous travaillez avec des processus/services d'arrière-plan. Fondamentalement, utilisez 'pty=false' ou, si cela n'est pas possible, activez explicitement le contrôle des tâches en tant que première commande, et le comportement sera correct.

Depuis https://github.com/fabric/fabric/issues/395


Linux
  1. Que fait "lc_all=c" ?

  2. Que signifie set -e dans un script bash ?

  3. Que fait `set -x` ?

  4. quels tueurs de processus Linux a-t-il?

  5. Que fait kill -- -0 ?

Et si "kill -9" ne fonctionne pas ?

Que signifie la sortie de Ps ?

Qu'est-ce que cette statistique de processus indique ?

Qu'est-ce que Echo $ ? Faire??

Que fait exactement Grub_gfxpayload_linux=text ?

Qu'est-ce que la table des processus Linux ? En quoi cela consiste?