Processus en arrière-plan sans «&»

24

Disons que vous avez démarré une nouvelle application sous Linux (comme un éditeur de texte, etc.), mais vous avez oublié d'utiliser le «&». Quelle (s) commande (s) utiliseriez-vous pour faire fonctionner ce processus en arrière-plan, sans devoir FERMER cette application? De cette façon, vous pouvez avoir les deux processus ouverts et travailler séparément (par exemple, le terminal de ligne de commande que vous avez utilisé pour créer le processus et le processus tel qu'un éditeur de texte toujours en cours d'exécution.?

D0uble7
la source
Techniquement non mais tmuxdonne peut-être les mêmes fonctionnalités que souhaité dans votre question.
mkc
1
Ne négligez pas l'alternative simple d'ouvrir un autre shell lorsque cela est possible.
jpmc26

Réponses:

43

Dans la fenêtre du terminal, vous tapez généralement Control+ Zpour "suspendre" le processus, puis utilisez la bgcommande pour le "mettre en arrière-plan".

par exemple avec une commande de sommeil

$ /bin/sleep 1000
^Z[1] + Stopped                  /bin/sleep 1000
$ bg
[1]     /bin/sleep 1000&
$ jobs
[1] +  Running                 /bin/sleep 1000
$ 

Nous pouvons voir que le processus est en cours d'exécution et j'ai toujours ma ligne de commande.

Stephen Harris
la source
5
Il pourrait être intéressant d'ajouter que le processus peut être ramené au premier plan avec la fgcommande, qui prend l'ID du travail (spécifié entre parenthèses, 1dans ce cas) comme paramètre. Il n'est pas spécifique à l'utilisation de bget peut être effectué sur des processus lancés avec &.
Aaron
14

Ctrl+ Zest le moyen de le faire, mais juste pour être complet: la question demande "commande", et ce serait (depuis un autre terminal):

kill -STOP pid_of_the_running_applications

et puis bien sûr

bg

depuis le terminal d'application.

Radovan Garabík
la source
6
kil -STOP, puis tuer -CONT
Michel Billaud
10

Dans Bash:

Ctrl+ Zet puis bg.

Maintenant, exécutez jobset voyez le résultat.

Tomasz
la source
2
@grooveplex Tomas a répondu en premier, il serait donc plus approprié de commenter ci-dessous la réponse de Stephen, qu'il s'agit essentiellement de la réponse de Tomas avec plus de détails.
Anthon
2
Nous avons en fait répondu simultanément. Pas étonnant que nous ayons tous deux dit la même chose car c'est la réponse évidente :-) Aucun de nous n'a copié l'autre. Ma réponse est arrivée peu de temps après celle de Thomas parce que j'avais consacré plus de temps à la création et au formatage de l'exemple.
Stephen Harris
1
Et le mien dit que c'est à Bash, donc ce n'est pas pareil.
Tomasz
1
Hé, il y a là un point potentiel. Il nécessite que le shell ait le contrôle du travail. Certaines des premières machines sur lesquelles j'ai travaillé (basées sur SVr2) n'en avaient pas /bin/shet cela n'aurait donc pas fonctionné :-)
Stephen Harris
1

Par mesure préventive pour l'inconvénient d'avoir à appuyer sur CTRL- z, vous pouvez créer un script wrapper pour votre éditeur sur lequel exécuter votre éditeur en arrière-plan. De cette façon, vous n'auriez pas besoin de vous souvenir de le démarrer en arrière-plan explicitement:

    #!/bin/sh

    EDITOR="emacs" # or whatever

    if [ -z "${DISPLAY}" ]; then
      ${EDITOR} "$@"
    else
      ${EDITOR} "$@" &
    fi

Ci-dessus, nous essayons d'abord de déterminer si vous avez un serveur X disponible et d'exécuter l'éditeur en arrière-plan (sinon, de nombreux éditeurs Unix utiliseront votre terminal à la place et vous ne voulez pas exécuter l'éditeur en tant que processus d'arrière-plan dans ce cas) . Il passera tous les arguments à votre éditeur de choix verbatim ( "$@") comme vous l'avez fourni pour le script wrapper.

Quant à la commande qui vous manque ... Selon mon expérimentation de base, pour les programmes GUI qui n'impliquent pas de terminal, cela pourrait être aussi simple que d'envoyer d'abord SIGSTOPpuis SIGCONTau processus de premier plan (en utilisant la killcommande si vous utilisez un script shell pour l'implémenter) . Vous auriez bien sûr besoin de l'exécuter dans une autre fenêtre / onglet de terminal, et la difficulté serait de trouver de manière pratique et générique le PID auquel vous souhaitez envoyer votre signal. Vous pouvez par défaut envoyer les deux signaux à tous les processus du nom donné (par défaut à votre éditeur préféré et autorisant également l'utilisation des PID comme arguments):

    #!/bin/sh

    EDITOR=emacs # whatever

    stop_cont_prog()
    {
      case "$1" in
        # begin with number is considered PID - this is not good 
        # enough to be taken seriously...
        [1-9]*) kill -SIGSTOP "$1"; kill -SIGCONT "$2";;
        *)      killall -SIGSTOP "$1"; killall -SIGCONT "$2";;
      esac
    }

    if [ -n "$1" ]; then
      for prog in "$@"; do stop_cont_prog "$1"; done
    else  
      stop_cont_prog "${EDITOR}"
    fi

Cette méthode m'a correctement donné mes onglets de terminal après avoir exécuté (plusieurs) emacscommandes en arrière-plan. Mais le processus emacs en cours d'exécution dans le terminal n'a pas été correctement restauré en raison du contrôle du travail du shell ou de la confusion des paramètres du terminal. Cette méthode bénéficierait donc d'une certaine sophistication.

C'est SIGSTOPexactement ce qui est envoyé au processus de premier plan lorsque vous appuyez sur (par défaut commun) CTRL- z. Se référer à la stty -asortie

$ stty -a
speed 38400 baud; rows 50; columns 200; line = 0;
intr = ^C; [...] start = ^Q; stop = ^S; susp = ^Z; [...]
[...]

(sortie abrégée) et sttypage de manuel:

   susp CHAR
          CHAR will send a terminal stop signal

Les processus arrêtés à l'aide du SIGSTOPsignal peuvent être redémarrés en envoyant SIGCONT. Normalement, c'est la logique de contrôle du travail du shell qui enverra SIGCONTet prendra en charge les autres manipulations nécessaires impliquées avec les commandes fget bgque nous ignorerons.

FooF
la source