在 Linux 终端上执行命令的通常风格是简单地运行它并等待它正常退出,命令退出后,可以继续连续执行其他命令,这就是所谓的在前台运行命令。正如这个词所暗示的那样,您可以在终端上直观地看到命令的输出。
而有时候我们并不在意命令的输出,而是要求命令执行的同时,在终端执行其他任务,这时候就要用到后台运行命令,nohup
和&
就是两个比较常用的后台运行命令。
1.本节用到的其他知识
1)重定向
通常情况下我们想要后台挂起的任务都会产生输出打印在当前屏幕上,这会影响后面再当前shell执行其他操作,我们可以使用<
<<
重定向命令将输出日志进行转移。
重定向的具体知识详见这篇文章:commond >/dev/null 2>&1 命令详解
2)两种中断信号
关闭屏幕,执行CTRL+C等原因造成ssh断开造成正在运行程序退出,常常会使我们的工作功亏一篑。
其背后的主要原因在于上述的相关操作,shell默认会发送中断信号给该终端session关联的进程,从而导致进程跟随终端退出,为了弄清这个问题我们首先要了解两种中断信号:
sigint
:signal interrupt,ctrl+c会发送此信号,主动关闭程序sighup
:signal hang up,关闭终端,网络断线,关闭屏幕会发送此挂断信号。
了解了程序退出的原因,接下来就是对这两种中断信号对应的解决办法。
用到的示例程序:test.sh
while true
do
echo "I'm still here!"
sleep 1
done
2.& 命令
将 &
放在执行命令的最后,此时执行ctrl+c关闭就不会关闭此进程,但是当屏幕关闭、断网仍然会造成进程退出。
也就是免疫sigint
信号,无法免疫sighup
信号。
关闭当前shell会话,重新打开一个会话,查看进程会发现test.sh已经不在:
3.nohup 命令
nohup
(no hang up),即不挂断运行,用nohup运行命令可以使命令永久执行下去,和用户终端没有关系,断开SSH不影响运行,nohup捕获了SIGHUP,并做了忽略处理,因此当屏幕关闭,断网等造成ssh中断时进程不会退出。但是ctrl+c可以关闭关闭该进程。
也就是也就是免疫sighup
信号,无法免疫sigint
信号。
此时关闭当前shell会话,在其他会话查看进程:
此时进程依旧存在。
还有一点需要提及,使用nohup
默认会将标准输出
重定向到~/nohuo.out
文件中,shell窗口不在打印输出信息,此时我们读取一下nohup.out
文件:
nohup.out
可以自定义其他文件
nohup commond >file
4.结合使用
sigint | sighup | |
---|---|---|
& | 免疫 | 不免疫 |
nohup | 不免疫 | 免疫 |
既然两种命令分别对两种信号免疫,那将他们一起使用会是什么效果呢?执行 Ctrl + C
:
关闭当前会话,检测进程:刚刚显示的[1]403
进程依旧存在,最强钉子户诞生!
此时想要关闭进程的话,只能使用kill
命令杀死进程了:
后记——screen
使用nohup
+ &
的方法是比较常用的后台运行手段,但也有它的局限性,如果一个进程需要与用户进行交互,等待用户输入,那就无法使用nohup
+ &
的方法了。对于这个需求,我的解决办法是使用screen
,篇幅问题,在这里只说一下简略使用方法,下一篇文章再进行具体介绍吧。
1)新建会话
screen -S screenname #新建一个叫screenname的session
2) 列出当前所有的session
screen -ls
3)回到某个会话
screen -r screenname
4) detach某个session
screen -d screenname #远程detach某个session
screen -d -r screenname #结束当前session并回到screenname这个session
5)删除会话
screen -S pid-X quit