如何挂起后台进程并将其置于前台


166

我有一个最初在前台运行的进程。我先按Ctrl+ 暂停Z,然后按继续在后台运行bg <jobid>

我想知道如何暂停在后台运行的进程?

如何使后台进程成为前台?

编辑:

该进程输出到stderr,那么fg <jobid>当该进程输出到终端时我应该如何发出命令?


1
您仍然可以在出现错误的终端中键入命令。在STDERR上显示的文本不算作输入,仅算作您发送的键。它在屏幕上看起来令人困惑,但是可以正常工作。
卡勒布(Caleb)2012年

@Caleb:即使当进程输出到stdout时,我仍然可以键入fg <jobid>使其成为前台?
蒂姆(Tim)

@Tim:是的,可以。
卡列布(Caleb)2012年

Answers:


214

正如Tim所说,键入fg以使最后一个过程回到前台。

如果您在后台运行多个进程,请执行以下操作:

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

fg %3使vim 23流程回到前台。

要暂停在后台运行的进程,请使用:

kill -STOP %job_id

SIGSTOP信号以与Ctrl+ 相同的方式停止(暂停)进程Z

例如:kill -STOP %3

资料来源:如何将信号发送到Linux和Unix中的进程 以及如何管理后台和前台作业


23
信号19是SIGCONT给我的;无论如何,我kill -STOP还是kill -CONT会优先使用数字来记住数字,但是您可以检查一下kill -l以使自己想起数字值
无用的2012年

该过程输出到stderr,因此jobfg <jobid>当该过程输出到终端时,我应该如何发出命令?
蒂姆(Tim)

1
@Tim只需像平常一样键入命令即可。只要作业是有背景的,它就不会读取您键入的内容-您的外壳程序就是。您键入的内容可能看起来很不完整,但是Shell会很好地理解它。
AlexWebr 2012年

@AlexWebr:谢谢,它有效!(1)后台作业是否不接受任何输入和输出,包括“ Ctrl + Z”等,对吗?(2)是否可以直接暂停后台运行的作业?如果是,怎么办?如果不是,是否必须先将其更改为在前台运行才能将其挂起?
蒂姆(Tim)

2
可以直接暂停在后台运行的作业吗?::kill -STOP %job_id如所解释的
2012年

31

对于具有作业控制功能的任何外壳来说,这都是正确的,除非处理真正的古老外壳,否则在大多数情况下,您可以认为这是理所当然的。 它属于POSIX标准,因此甚至dash支持作业控制(以交互方式运行或与一起运行时-m)。

互动

  • Ctrl+ z将暂停当前前景的程序
  • bg将后台最近暂停的程序
    bg %2与作业号一起使用,可以通过进行检查jobs
  • fg 将显示最近暂停的程序

在中zsh,您可以编写一个键绑定,以fg通过另一个Ctrl+ 从提示隐式运行z

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

bg在挂起时隐含地运行还可能有一个聪明的方法,但这似乎是不明智的。至少对我而言,我Ctrl+ 的大部分z用法是因为Ctrl+ c未能爆发;我想使用eg kill %1而不是来跟随它bg,我当然也不想默认为killing!(此逻辑还扩展了我不再使用此键绑定的原因:如果我要踩Ctrl+ z停止一个进程,那么我最后要做的就是恢复!)

非互动

如果您在其他Shell实例(或其他用户,有时包括sudo命令)中,则可能无法使用作业编号。

一旦知道另一个进程的进程ID(PID),您仍然可以对其执行操作。你可以用获得的PID pgrep …,或ps aux |grep …(或从同一个shell,jobs -l$!),然后你可以运行:

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

如果您不知道进程ID,并且不担心按名称挂起该进程的其他实例,则可以将信号传递给以下之一:

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

CONTCtrl+ z(而不是bg'd)停止的程序的信号将恢复其进度(在前台),就像处理该信号一样fg

回复:标准错误

对这个问题的编辑询问标准错误:

该进程输出到stderr,那么fg <jobid>当该进程输出到终端时我应该如何发出命令?

除非所讨论的作业的背景组件(或整个作业(可能通过kill -CONT),都已背景),否则在挂起时您实际上不应看到输出。

如果它仍在输出数据(无论是标准输出还是标准错误),那肯定会使您的终端显得杂乱无章,但是所有这些输出都将被忽略,因为它不是输入的一部分。这可能会使您更难知道您没有输入任何错别字,但是(盲目地)键入fgEnter就足够了(除非您有多个作业并且所涉及的作业不是最新的,在这种情况下,您确实需要作业描述符) )。

如果确实需要查找作业描述符,请使用另一个终端STOP通过上述非交互式方法向其发送信号。这样可以释放您的显示(可能打Enter了几次,或者运行clearCtrl+ L),因此您可以运行jobs以查找作业描述符,然后fg %NN该数字的位置运行。


暂停和恢复过程的唯一问题是,如果您与其他程序(例如RabbitMQ)建立任何连接,则在恢复时该连接将丢失。
导航

@Nav –那是因为您没有无脑地运行它。在bash和zsh中,我相信您只需要放弃后台进程即可。我宁愿运行这样的任务与nohup的终端复用器屏幕TMUX。您无法启动nohup进程(就像您无法从单独的连接中恢复后台进程一样),但是可以连接到多路复用器。
亚当·卡兹

这是一个后台过程。我关闭了终端,然后从另一个终端登录到服务器。
Nav

是的,除非考虑到启动它的过程,否则您无法从另一个shell恢复该过程。我建议使用屏幕或tmux。
亚当·卡兹

我相信,如果您向CONT通过Ctrl + Z停止的进程(作业/管道)发送信号,即使您没有将其在后台继续执行bg
G-Man

10

键入fg以将其带到前台。


谢谢!该进程输出到stderr,那么fg <jobid>当该进程输出到终端时我应该如何发出命令?
蒂姆(Tim)

1
  1. 使用jobs命令列出作业
  2. 使用fg; 将目标工作放在前台; 例如: fg %4
  3. 击中CTRL Z暂停
  4. 要在后台启动它,请使用bg;。例如:bg %4

0

结束进程可以用几种不同的方式完成。通常,从基于控制台的命令中发送Ctrlc按键(默认中断字符)将退出命令。当进程在前台模式下运行时,此方法有效。

如果某个进程在后台模式下运行,则首先需要使用以下ps命令获取其作业ID ,然后可以使用kill命令杀死该进程,如下所示:

$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

在此kill命令将终止该first_one过程。如果某个进程忽略了常规kill命令,则可以使用kill -9如下的进程ID,如下所示:

$kill -9 6738
Terminated

1
尽管这是真的,但它并未回答问题……
jasonwryan 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.