进程前后台切换

这篇笔记我们学习如何在Linux命令行中切换前台进程和后台进程。

什么是前台进程和后台进程

我们都知道Linux下在Shell中执行一个程序流程(非Shell内置命令),父Shell进程会先fork一个子Shell进程,然后子Shell进程exec切换到我们要运行的程序上,被运行的程序stdinstdoutstderr都对接到了我们使用的Shell,因此这个程序能够接受我们的输入,并把信息输出到屏幕。

所谓的前台进程,意思就是我们当前Shell的输入输出都被程序进程占据了,把它切换到后台,可以方便我们用当前Shell继续执行其他命令,这在SSH连接到服务器上进行各种配置时经常用到。

为了介绍相关操作,这里我们用一个C语言程序来作为例子,假设编译后程序名为a.out

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    while(1)
    {
        printf("running...\n");
        sleep(1);
    }
    return 0;
}

前台进程切换到后台

在前台进程运行的过程中,我们可以使用Ctrl+Z暂停前台进程。

启动前台进程。

./a.out

在终端中按下Ctrl+Z,可以看到类似如下输出内容。

^Z
[1]  + 7180 suspended  ./a.out

前台进程暂停后,我们可以使用jobs -l命令,该命令可以查看当前所有的后台进程,-l参数表示显示进程号,通常都会加上该参数。

此时我们可以使用命令bg %<job id>,让暂停的进程继续在后台运行。

bg %1

我们会看到类似如下输出。

[1]  + 7180 continued  ./a.out

我们使用ps命令可以查看进程的信息,下面例子中,输出的内容显示该进程的进程号是7180,其父进程号是7122(也就是我们的Shell)。

ps -ef | grep a.out

输出内容如下。

ubuntu  7180  7122  0 12:04 pts/2    00:00:00 ./a.out

查看父进程相关的信息。

ps -f -P 7122

输出内容如下。

UID     PID  PPID PSR  C STIME TTY      STAT   TIME CMD
ubuntu  7122  4566   3  0 12:04 pts/2    Ss+    0:00 zsh

注意:当有后台进程运行时,是无法退出当前Shell的,如果强行终止当前Shell进程,其下的子进程也就全终止了。下面例子中我们在Shell中输入了exit,但相关的提示信息阻止我们退出。

# ubuntu @ ubuntu in ~/workspace/cpp/test1 [12:05:50]
$ exit
zsh: you have running jobs.

如果后台进程被从其他地方kill掉,当前shell会有一个terminated的提示。

[1]  + 7180 terminated  ./a.out

在后台启动进程

如果希望直接在后台启动进程,可以使用&写法,下面是一个例子。

./a.out &

输出内容如下。

[1] 7462

运行程序的命令后面加上一个&就可以自动把程序放到后台了。

后台进程调回前台

使用命令fg %<job id>,可以将后台进程调回前台。

fg %1

输出内容如下。

[1]  + 7462 running    ./a.out

disown命令

使用disown %<job id>可以指定当前Shell关闭后,指定的后台进程会自动挂到init进程上。

disown %1

注:我用的系统是Ubuntu Gnome 16.04,这样操作后进程实际会挂到/sbin/upstart --user上,按照PPID一层层查上去都是和gdm相关的进程,这个应该是Gnome图形界面下所有进程的父进程。

nohup命令

nohup命令顾名思义能够让Shell运行的程序忽略SIGHUP,该信号通常在用户退出登录或者终端关闭时发送给进程,因此关闭终端不会使得nohup启动的后台进程中断。nohup命令一般和&连用,除此之外,如果程序有向stdoutstderr输出,nohup会自动将其重定向到当前路径下的nohup.out文件,如果我们想忽略输出,将其手动重定向到/dev/null就行了。

nohup ./a.out>/dev/null &

输出内容如下。

[1] 7774
nohup: 忽略输入重定向错误到标准输出端

常见用法总结

  • 按下CTRL+Z:暂停前台进程
  • bg %<job id>:将一个进程移到后台
  • fg %<job id>:将一个后台进程调回前台
  • jobs -l:查看当前shell管理的进程
  • disown %<job id>:当前Shell退出时,将后台进程挂到init进程下
  • nohup <cmd> &:后台运行一个命令,并使其忽略SIGHUP信号
作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap