后台运行程序的几种方式

目录

参考:https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/index.html

1. 当前终端后台运行

示例1,使用ctrlz, bg

$ mate-system-monitor
//运行中,终端被占用;使用快捷键 [ctrl z] 暂停运行,返回终端
job1, 'mate-system-monitor' has stopped

$ jobs   //查看后台运行程序,有这个状态为停止的后台程序
Job Group CPU State Command
1 7870 0% stopped mate-system-monitor

$ bg %1    //在后台继续运行程序
Send job 1 “mate-system-monitor” to background

$ jobs //查看,状态已变为运行了
Job Group CPU State Command
1 7870 0% running mate-system-monitor

$ fg %1 //将后台程序返回到前台,
Send job 1, “mate-system-monitor” to foreground

// [ctrl c]      //终止程序

示例2,使用&

$ mate-system-monitor &
$ jobs -l
Job Group CPU State Command
1 10084 4% running mate-system-monitor

$ mate-system-monitor &  //相当与如下3个步骤:

  • $ mate-system-monitor
  • [ctrl z]
  • $ bg %1

示例3,重定向标准输出和标准错误输出

当后台运行程序有输出时,会扰乱当前终端的内容。可用">filename 2>&1"来更改缺省的重定向文件名。

$ mate-system-monitor > mate-system-monitor_log.txt 2>&1 &
$ jobs
Job Group CPU State Command
1 10565 22% running mate-system-monitor > mate-system-monitor_log.txt 2>&1 &

这样终端就不会收到干扰了。

$ sslocal -c s.json > sw_log 2>&1 &
$ jobs
Job Group CPU State Command
2 10880 12% running sslocal -c s.json > sw_log 2>&1 &
1 10565 11% running mate-system-monitor > mate-system-monitor_log.txt 2>&1 &

以上都是在某个终端执行,父进程都是终端。若父进程关闭,则会关闭下面所有子进程。

2. 脱离当前终端运行

示例4,使用nohup, 忽略挂起,避免终端关闭导致程序也被关闭。

nohup (no hangup 不挂起)放在命令的前面; 标准输出和标准错误缺省会被重定向到nohup.out 文件中。
一般我们可在结尾加上"&"来将命令同时放入后台运行,也可用">filename 2>&1"来更改缺省的重定向文件名。

$ nohup mate-system-monitor > mate-system-monitor_log.txt 2>&1 &
$ jobs
Job Group CPU State Command
1 11164 2% running nohup mate-system-monitor > mate-system-monitor_log.txt 2>&1 &

$ exit   //要退出终端会提示
There are still jobs active:
PID Command
12086 nohup mate-system-monitor > mate-system-monitor_log.txt 2>&1 &
A second attempt to exit will terminate them.
Use 'disown PID' to remove jobs from the list without terminating them.

若强行关闭后,上面进程的父进程由原本的bash的pid变为1。

示例5,使用setsid, 使程序直接运作在init下(即父进程为1),自然不会受到当前终端的影响了。

setsid setsid(8) run a program in a new session

$ setsid mate-system-monitor > mate-system-monitor_log.txt 2>&1 &
$ jobs
jobs: There are no jobs
Job 1, 'setsid mate-system-monitor > ma…' has ended
$ jobs
jobs: There are no jobs

父进程直接就是1了,jobs也看不到了,只能通过ps等查找了。
$ ps -ef |grep mate-system-monitor
toma 12799 12546 1 08:04 pts/1 00:00:14 mate-system-monitor
toma 13758 12546 0 08:18 pts/1 00:00:00 grep --color=auto mate-system-monitor

示例6,使用disown

若运行命令时未加nohup 或者setsid,可用disown补救,
$ mate-system-monitor > mate-system-monitor_log.txt 2>&1 &
$ jobs
Job Group CPU State Command
1 14318 9% running mate-system-monitor > mate-system-monitor_log.txt 2>&1 &
$ disown %1
$ jobs
jobs: There are no jobs

$ ps -ef |grep mate-system-monitor
toma 14318 12546 1 08:24 pts/1 00:00:25 mate-system-monitor
toma 16098 12546 0 08:51 pts/1 00:00:00 grep --color=auto mate-system-monitor
父进程变为1,已脱离当前的终端。
以上命令实现在后台运行,还脱离了当前终端的影响,但是无法再重新连接到这个会话。

3. 伪终端下运行

示例7,使用screen

注:这部分内容,未测试过,完全摘抄2008 年的原文:https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/

$ sudo pacman -Ss screen
extra/screen 4.6.2-1
Full-screen window manager that multiplexes a physical terminal
简单的说,screen 提供了ANSI/VT100 的终端模拟器,使它能够在一个真实终端下运行多个全屏的伪终端。screen命令提供了分离和重新连接一个会话的功能。
常用选项:
用screen -dmS session name来建立一个处于断开模式下的会话(并指定其会话名)。
用screen -list 来列出所有会话。
用screen -r session name来重新连接指定会话。
用快捷键CTRL-a d 来暂时断开当前会话。

screen 示例
[root@pvcent107 ~]# screen -dmS Urumchi
[root@pvcent107 ~]# screen -list
There is a screen on:
12842.Urumchi (Detached)
1 Socket in /tmp/screens/S-root.

[root@pvcent107 ~]# screen -r Urumchi
当我们用“-r”连接到 screen 会话后,我们就可以在这个伪终端里面为所欲为,再也不用担心 HUP 信号会对我们的进程造成影响,也不用给每个命令前都加上“nohup”或者“setsid”了。这是为什么呢?让我来看一下下面两个例子吧。

1. 未使用 screen 时新进程的进程树
[root@pvcent107 ~]# ping www.google.com &
[1] 9499
[root@pvcent107 ~]# pstree -H 9499
init─┬─Xvnc
├─acpid
├─atd
├─2*[sendmail]
├─sshd─┬─sshd───bash───pstree
│ └─sshd───bash───ping
我们可以看出,未使用 screen 时我们所处的 bash 是 sshd 的子进程,当 ssh 断开连接时,HUP 信号自然会影响到它下面的所有子进程(包括我们新建立的 ping 进程)。

2. 使用了 screen 后新进程的进程树
[root@pvcent107 ~]# screen -r Urumchi
[root@pvcent107 ~]# ping www.ibm.com &
[1] 9488
[root@pvcent107 ~]# pstree -H 9488
init─┬─Xvnc
├─acpid
├─atd
├─screen───bash───ping
├─2*[sendmail]
而使用了 screen 后就不同了,此时 bash 是 screen 的子进程,而 screen 是 init(PID为1)的子进程。那么当 ssh 断开连接时,HUP 信号自然不会影响到 screen 下面的子进程了。



=========
https://wiki.archlinux.org/index.php/GNU_Screen
-4 Resolve hostnames only to IPv4 addresses. 仅将主机名解析为IPv4地址。
-6 Resolve hostnames only to IPv6 addresses. 仅将主机名解析为IPv6地址。
-a Force all capabilities into each window's termcap. 强制所有功能进入每个窗口的termcap。
-A -[r|R] Adapt all windows to the new display width & height. 使所有窗口适应新的显示宽度和高度。
-c file Read configuration file instead of '.screenrc'. 读取配置文件而不是“.screenrc”。
-d (-r) Detach the elsewhere running screen (and reattach here). 分离其他正在运行的屏幕(并重新连接到此处)。
-dmS name Start as daemon: Screen session in detached mode. 作为守护程序启动:处于分离模式的屏幕会话。
-D (-r) Detach and logout remote (and reattach here). 分离并注销远程(并在此处重新连接)。
-D -RR Do whatever is needed to get a screen session. 做任何需要的屏幕会话。
-e xy Change command characters. 更改命令字符。
-f Flow control on, -fn = off, -fa = auto. 流量控制开启,-fn =关闭,-fa = auto。
-h lines Set the size of the scrollback history buffer. 设置回滚历史记录缓冲区的大小。
-i Interrupt output sooner when flow control is on. 当流量控制打开时,中断输出更快。
-l Login mode on (update /var/run/utmp), -ln = off. 登录模式开启(更新/ var / run / utmp), - ln =关闭。
-ls [match] or 要么
-list Do nothing, just list our SockDir [on possible matches]. 什么都不做,只需列出我们的SockDir [在可能的比赛中]。
-L Turn on output logging. 打开输出记录。
-Logfile file Set logfile name. 设置日志文件名称。
-m ignore $STY variable, do create a new screen session. 忽略$ STY变量,以创建新的屏幕会话。
-O Choose optimal output rather than exact vt100 emulation. 选择最佳输出而不是精确的vt100仿真。
-p window Preselect the named window if it exists. 如果存在,则预选指定的窗口。
-q Quiet startup. Exits with non-zero return code if unsuccessful. 安静的启动。如果不成功,则退出非零返回码。
-Q Commands will send the response to the stdout of the querying process. 命令会将响应发送到查询过程的标准输出。
-r [session] Reattach to a detached screen process. 重新连接到分离的屏幕进程。
-R Reattach if possible, otherwise start a new session. 如果可能,重新连接,否则,开始新的会话。
-s shell Shell to execute rather than $SHELL. Shell执行而不是$ SHELL。
-S sockname Name this session <pid>.sockname instead of <pid>.<tty>.<host>. 将此会话命名为<pid> .sockname而不是<pid>。<tty>。<host>。
-t title Set title. (window's name). 设置标题。 (窗口的名字)。
-T term Use term as $TERM for windows, rather than "screen". 使用术语作为Windows的$ TERM,而不是“屏幕”。
-U Tell screen to use UTF-8 encoding. 告诉屏幕使用UTF-8编码。
-v Print "Screen version 4.06.02 (GNU) 23-Oct-17". 打印“屏幕版本4.06.02(GNU)23-Oct-17”。
-wipe [match] Do nothing, just clean up SockDir [on possible matches]. 什么都不做,只是清理SockDir [在可能的比赛中]。
-x Attach to a not detached screen. (Multi display mode). 附加到未分离的屏幕。 (多显示模式)。
-X Execute <cmd> as a screen command in the specified session. 在指定的会话中执行<cmd>作为屏幕命令。

原文地址:https://www.cnblogs.com/sztom/p/10756014.html