Comment suspendre et mettre en avant un processus d'arrière-plan

167

J'ai un processus en cours d'exécution à l'avant-plan. J'ai suspendu par Ctrl+ Z, puis j'ai repris l'exécution en arrière-plan bg <jobid>.

Je me demande comment suspendre un processus en arrière-plan?

Comment puis-je faire apparaître un processus d'arrière-plan au premier plan?

Modifier:

Le processus est envoyé à stderr, comment dois-je exécuter la commande fg <jobid>pendant que le processus est envoyé au terminal?

Tim
la source
1
Vous pouvez toujours taper des commandes dans un terminal qui crache des erreurs. Le texte vomi sur STDERR ne compte pas comme une entrée, seules les clés que vous envoyez. Cela semble déroutant à l'écran mais cela fonctionne.
Caleb
@Caleb: Même quand le processus sort sur stdout, je peux toujours taper fg <jobid>pour le faire apparaître au premier plan?
Tim
@ Tim: Oui, vous pouvez.
Caleb

Réponses:

216

Comme Tim a dit, tapez fgpour ramener le dernier processus au premier plan.

Si vous avez plusieurs processus en cours d'exécution en arrière-plan, procédez comme suit:

$ jobs
[1]   Stopped                 vim
[2]-  Stopped                 bash
[3]+  Stopped                 vim 23

fg %3pour ramener le vim 23processus au premier plan.

Pour suspendre le processus en arrière-plan, utilisez:

kill -STOP %job_id

Le signal SIGSTOP arrête (met en pause) un processus essentiellement de la même manière Ctrl+ Z.

exemple: kill -STOP %3.

sources: comment envoyer des signaux aux processus sous Linux et Unix et comment gérer les travaux d’arrière-plan et de premier plan .

de naboo
la source
23
le signal 19 est SIGCONTpour moi; J'utilise kill -STOPet kill -CONTde préférence me souvenir des chiffres de toute façon, mais vous pouvez vérifier kill -lpour vous rappeler les valeurs numériques
Inutile
Le processus est envoyé à stderr. Alors, comment dois-je exécuter la commande jobet fg <jobid>pendant que le processus est envoyé au terminal?
Tim
1
@ Tim Il suffit de taper la commande comme vous le feriez normalement. Tant que le travail est en arrière-plan, il ne lit pas ce que vous tapez, mais votre shell. Ce que vous tapez peut sembler fragmenté, mais le shell le comprendra très bien.
AlexWebr
@ AlexWebr: Merci, ça marche! (1) Un travail en arrière-plan n'accepte aucune entrée et sortie, y compris "Ctrl + Z", etc. (2) Un travail exécuté en arrière-plan peut-il être suspendu directement? Si oui comment? Si non, faut-il d'abord le modifier pour qu'il soit affiché au premier plan avant de pouvoir être suspendu?
Tim
2
Un travail exécuté en arrière-plan peut-il être suspendu directement? Oui:, kill -STOP %job_idcomme expliqué
Inutile
31

Cela devrait être vrai de tout shell avec contrôle de travail, que vous pouvez prendre pour acquis (pour la plupart) à moins de traiter avec un shell vraiment ancien. C'est le standard POSIX , donc dashsupporte même le contrôle du travail (lorsqu'il est exécuté de manière interactive ou avec -m).

Interactif

  • Ctrl+ zsuspendra le programme actuellement mis en avant
  • bgContiendra le dernier programme suspendu
    (à utiliser bg %2avec le numéro du travail que vous pouvez vérifier jobs)
  • fg mettra en avant le programme suspendu le plus récemment

Dans zsh, vous pouvez écrire une liaison de clé à exécuter implicitement à fgpartir de l'invite via un autre Ctrl+ z:

_zsh_cli_fg() { fg; }
zle -N _zsh_cli_fg
bindkey '^Z' _zsh_cli_fg

Il existe probablement aussi un moyen astucieux de procéder implicitement bgà la suspension, mais cela semble peu judicieux; du moins pour moi, la majorité de mon Ctrl+ zusage est dû au fait que Ctrl+ cne parvient pas à éclater; Je veux suivre cela avec, par exemple, kill %1plutôt que bg, et je ne veux certainement pas laisser tomber le meurtre! (Cette logique s'étend également à la raison pour laquelle je n'utilise plus cette liaison de clé: si je martèle Ctrl+ zpour arrêter un processus, la dernière chose que je veux qu'il fasse est de reprendre!)

Non interactif

Si vous êtes dans une autre instance du shell (ou un utilisateur différent, y compris parfois des sudocommandes), vous ne pourrez probablement pas utiliser de numéro de travail.

Vous pouvez toujours agir sur un autre processus une fois que vous connaissez son ID de processus (PID). Vous pouvez obtenir le PID avec pgrep …, ou ps aux |grep …(ou à partir du même shell,, jobs -lou $!) et vous pouvez ensuite exécuter:

kill -STOP $PID  # suspend
kill -CONT $PID  # continue (resume)

Si vous ne connaissez pas l'ID du processus et que vous ne craignez pas de suspendre son nom par d'autres instances du processus, vous pouvez transmettre des signaux à l'un de ces éléments:

killall -STOP program_name
pkill -STOP program_name
pkill -f -STOP program_name_or_args

Un CONTsignal envoyé à un programme arrêté avec Ctrl+ z(et non bg'd) reprendra sa progression (au premier plan), comme si vous y étiez fg.

Re: erreur standard

La modification de cette question concerne l'erreur standard:

Le processus est envoyé à stderr, comment dois-je exécuter la commande fg <jobid>pendant que le processus est envoyé au terminal?

À moins que le travail en question ne contienne des composants avec arrière-plan (ou que le travail tout entier soit peut-être via kill -CONT, par exemple ), vous ne devriez pas voir la sortie tant qu'elle est suspendue.

S'il émet toujours des données (que ce soit sur la sortie standard ou sur l'erreur standard), votre terminal sera visuellement surchargé visuellement, mais toute cette sortie sera ignorée car elle ne fait pas partie de votre entrée. Cela peut rendre plus difficile le fait de savoir que vous n'avez pas saisi de fautes de frappe, mais la frappe (à l'aveugle) fgEnterdevrait suffire (à moins que vous n'ayez plusieurs travaux et que celui en question ne soit pas le plus récent, auquel cas vous aurez effectivement besoin du descripteur de travail. ).

Si vous avez besoin de trouver le descripteur de travail, utilisez un autre terminal pour lui envoyer le STOPsignal via les méthodes non interactives ci-dessus. Cela devrait libérer votre affichage (peut-être frappé Enterplusieurs fois ou exécuté clearou Ctrl+ L) afin que vous puissiez ensuite jobsrechercher le descripteur de travail, puis exécuter fg %Noù se Ntrouve ce nombre.

Adam Katz
la source
Le seul problème avec les processus de pause et de reprise est que si vous établissez des connexions avec un autre programme (comme RabbitMQ par exemple), la connexion sera perdue lors de la reprise.
Nav
@Nav - C'est parce que vous ne l'avez pas exécuté sans tête. En bash et zsh, je crois que vous avez simplement besoin de désavouer un processus en arrière-plan. Je préfère exécuter de telles tâches avec nohup ou un multiplexeur de terminal tel que screen ou tmux . Vous ne pouvez pas choisir un processus nohup (tout comme vous ne pouvez pas reprendre un processus en arrière-plan à partir d'une connexion séparée), mais vous pouvez vous connecter à un multiplexeur.
Adam Katz
C'était un processus en arrière-plan. J'avais fermé le terminal puis connecté au serveur à partir d'un autre terminal.
Nav
Oui, vous ne pouvez pas reprendre un processus à partir d'un autre shell à moins qu'il n'ait été lancé avec cet objectif en tête. Je recommande screen ou tmux pour ça.
Adam Katz
Je crois que si vous envoyez un CONTsignal à un processus (travail / pipeline) arrêté avec Ctrl + Z, il reprendra en arrière-plan, même si vous ne l'avez pas encore bgfait.
G-Man
10

Tapez fgpour l'amener au premier plan.

Tim
la source
Merci! Le processus est envoyé à stderr, comment dois-je exécuter la commande fg <jobid>pendant que le processus est envoyé au terminal?
Tim
1
  1. liste des travaux avec jobscommande
  2. Amenez votre travail cible au premier plan avec fg; par exemple: fg %4
  3. Hit CTRL Zpour suspendre
  4. Pour le lancer en tâche de fond, utilisez bg; par exemple:bg %4
kmiklas
la source
0

La fin d'un processus peut être effectuée de plusieurs manières différentes. Souvent, à partir d'une commande basée sur la console, l'envoi d'une Ctrlcfrappe de touche (le caractère d'interruption par défaut) permet de quitter la commande. Cela fonctionne lorsque le processus s'exécute en mode avant-plan.

Si un processus est en cours d'exécution en arrière-plan, vous devez d'abord obtenir son ID de travail à l'aide de la pscommande, puis utiliser la commande kill pour tuer le processus de la manière suivante:

$ps -f
UID      PID  PPID C STIME    TTY   TIME CMD
amrood   6738 3662 0 10:23:03 pts/6 0:00 first_one
amrood   6739 3662 0 10:22:54 pts/6 0:00 second_one
amrood   3662 3657 0 08:10:53 pts/6 0:00 -ksh
amrood   6892 3662 4 10:51:50 pts/6 0:00 ps -f
$kill 6738
Terminated

Ici, la killcommande mettrait fin au first_oneprocessus. Si un processus ignore une killcommande normale , vous pouvez utiliser kill -9suivi de l'ID de processus comme suit:

$kill -9 6738
Terminated
Lakshmi
la source
1
Bien que cela soit vrai, cela ne répond pas à la question ...
jasonwryan