10
votes

En écrivant un script de shell Linux pour détacher en toute sécurité les programmes d'un terminal

J'essaie d'écrire un script de shell de Linux (de préférence bash), supposément nommé détach.sh , pour détacher en toute sécurité les programmes d'un terminal, tel que:

  1. Invocation: ./ détache.sh prog [arg1 arg2 ...] .

  2. est exécutable -Brable, par exemple. En l'exécutant dans votre shell: XXX

  3. avec une citation appropriée (principalement la manipulation des arguments contenant des espaces blanchisseurs).

  4. rejette les sorties (car elles sont inutiles).

  5. n'utilise pas l'écran , tmux , etc. (même raison avec 4, plus pas besoin d'un processus de garde d'enfants supplémentaire).

  6. utilise des commandes et des programmes portables (raisonnablement), et aucune chose comme start-stop-daemon qui est assez spécifique à la distribution.

    J'ai pensé de plusieurs manières (lignes de shebang #! / bin / bash négligé Pour des raisons de briefs):

    1. nohup : XXX

    2. désavantage : XXX

    3. setsID : XXX

    4. Utilisation d'un sous-vase: XXX

    5. nohup / setsID combiné avec SUBSHELL: XXX

      Lorsque vous utilisez Gedit comme programme de test (substituant le "$ @" partie), la condition 1 peut être satisfaite de toutes les méthodes ci-dessus, mais la condition 2 peut être satisfaite d'aucun.

      Cependant, si un programme arbitraire (mais pas une coquille intégrée) est ajouté au script 5, Toutes les conditions semblent être satisfaites (au moins pour moi dans le cas gedit ). Par exemple: xxx

      Quelqu'un avec une idée d'une explication des phénomènes ci-dessus et comment mettre correctement mettre en œuvre les exigences?

      Edit:

      avec condition 2, je veux dire que le programme doit être détaché du terminal mais fonctionne comme d'habitude sinon. Par exemple, avec le boîtier gedit , la condition échoue si gedit juste sort immédiatement juste à droite après la fin du processus du script.


8 commentaires

De quelle manière la solution 5 ne répond pas aux exigences 2, en supposant que vous ayez le shebang? Ou bien de manière équivalente, quelle est la nécessité 2 signifie que ce n'est pas satisfait de la solution 5?


Que vous attendez-vous à arriver lorsque gedit est exécuté en arrière-plan? Etant donné que Gedit est un éditeur qui fonctionne de manière interactive, mais un processus d'arrière-plan est, plus ou moins par définition, quelque chose qui fonctionne sans interaction utilisateur, peut-être que le problème est votre choix de programme de test. Gestion des programmes basés sur X11 est plutôt différente des compilateurs de manutention et similaires. Que voyez-vous se produire lorsque vous exécutez gedit en arrière-plan?


Désolé pour l'explication incorrecte de mon idée. Je voulais dire "détacher" lorsque "fond". Veuillez consulter la version mise à jour de cette question. Merci pour ton aide :)


La chaîne "Shebang Lines #! / Bin / bash négligé d'enregistrer l'espace disque du serveur de STACKEXCHANGE" prend plus d'espace disque que les shebangs réels.


@ Pumbaa80: La raison devrait peut-être être "pour des raisons de brieilles" :)


Afaik, "détachement" n'est pas vraiment un terme qui signifie quelque chose qui ne veut rien dire - je n'ai jamais entendu parler en dehors du contexte de l'écran ou de TMUX, donc je ne sais vraiment pas ce que vous voulez arriver au processus quand il est "détaché" . désavantage fonctionne sur le côté de la coque - il indique à la coque de ne pas envoyer de HUP ou supprime le travail de la table de travail, auquel cas je ne suis pas sûr de ce que EXEC Faites-vous pour vous, car vous remplacez la coquille. NOHUP est un programme externe qui masque le signal HUP fondamentalement.


@ormaaj: ici en disant "détacher", je veux rediriger le stdout / stardr d'un processus à / dev / null , créez le processus indépendant de l'appel d'invoquant, et laissez ainsi le processus d'exécution comme habituel même d'afer la coquille a disparu.


@ORMAAJ: Le EXEC est présent ici car il est parfois nécessaire de remplacer une coque. Par exemple, pour personnaliser un programme de menu utilisé pour lancer (par EXEC -ing) Autres programmes, il peut être pratique de lancer quelque chose de détaché à l'aide de détach.sh dans le fichier de configuration du menu.


3 Réponses :


0
votes

Vous essayez de créer un processus de démon unix (c.-à-d. Un processus qui n'a pas de terminal de contrôle et c'est son propre Session leader). La commande setsid doit le faire pour vous, mais vous êtes responsable de la fermeture de tous les descripteurs de fichiers ouverts sur le terminal que vous abandonnez. Cela peut être fait en les redirectant sur / dev / null ou à l'aide de la syntaxe de la coque pour la fermeture des descripteurs de fichier (par exemple, 2> & - et 0 <& - en bash).


1 commentaires

Merci, mais je pense que les scripts 3 et 5 (voir ma question) ont tous deux fait ces deux, tout en ne résolvant pas le problème. De plus, la cause du phénomène qu'un appel à / bin / true résout le problème est encore inexpliquée.



4
votes

Après une enquête plus étroite, ces faits précédemment inopposés ont été révélés:

  1. Les deux scripts 3 et 5 (la variante SETSID UNIQUEMENT) Satisfaire toutes les conditions si un / bin / true est ajouté au script.

  2. Ces scripts, comme modifié en fait 1, fonctionneront également si / bin / true est remplacé par pour i in {0..9999}; faire :; fait .

    Par conséquent, nous pouvons conclure que:

    • (du fait 1)

      Plusieurs niveaux de détachement (comme dans le script 5) sont inutiles, et la clé est d'utiliser l'utilitaire de droite ( setsid ).

    • (de fait 2)

      Un délai approprié avant la sortie Bash est nécessaire pour le succès du script. (Appeler le programme externe / bin / true consomme quelque temps, Tout comme le consommateur de l'heure pure-bash pour i in {0..9999}; faire :; fait .)

      Je n'ai pas regardé le code source, mais je suppose qu'une explication possible est-ce que Bash peut quitter avant setsid finitions Configuration de l'exécution Environnement du programme à exécuter, si un délai approprié n'est pas appliqué.

      et enfin, une solution optimale doit être xxx

      edit 1 :

      la nécessité de Un retard a été expliqué ici . Merci beaucoup à @wilx!

      EDIT 2 :

      (Merci à @mateidavid), nous semblons avoir oublié de rediriger l'entrée standard et mieux Way serait: xxx


2 commentaires

Essayez de quitter la formation et le retard: setsid "$ @"> & - 2> & - <& - .


@Mateidavid: Merci beaucoup! J'ai mis à jour ma réponse, mais la formation semble toujours nécessaire pour Bash.



1
votes

Je pense que vous devez faire setsid "$ @"> & / dev / null & wait de sorte que le terminal de contrôle ne disparaisse pas avant setingsid gère à la fourchette enfant.

update

Il me semble que cela fonctionne à la fois sur la ligne de commande et comme argument de -c : < Pré> xxx


3 commentaires

Merci beaucoup :) J'ai mis à jour ma propre réponse pour refléter votre suggestion.


L'explication est très raisonnable. Mais bash -c 'setsid dormir 1> & / dev / null & wait' ' des blocs d'une manière ou d'une autre (lorsqu'il ne bloque pas dans Interactive Bash ), donc ne résout pas le problème pour l'instant.


Mais $ exec Bash -C '(Seidid Geany> & / dev / null) et désaveux' échoue; Je pense qu'il serait peut-être préférable de regarder pourquoi setsid d processus a un PID différent de setsid dans une coque interactive (mais le même PID dans une coque non interactive) .