用nohup远程执行后台作业
很多时候我们都是通过ssh远程连接linux主机。如果你的bash环境是通过ssh远程登录获取的,那么在执行一个后台作业的时候可能会出现一些问题。
由于bash后台作业不像linux后台进程(组)那样完全脱离控制终端,bash后台作业进程还是可以拥有控制终端的。此时如果ssh连接因为意外而断开,比如网络异常。 那么由sshd生成的用户登录bash进程也就终止了,而依附在这个登录bash环境下的作业进程也就没有存在的意义了,也会随着远程登录bash进程的终止而终止。
所以在实际的运维工作中,如果你通过ssh远程连接linux服务器,然后通过&执行了一个后台作业进程。如果此时后台作业进程还没有执行完毕, 但是网络连接突然断开或者用户自行退出登录,等再次连接上该linux主机后,就会发现先前执行的后台作业进程已经不存在了,注意这里排除后台作业运行完毕正常退出的情况。
那么应该怎么做才能防止这种问题的发生呢?正确的做法应该是将要运行的进程放到linux系统的后台运行,而不是bash环境的后台。 因为在linux系统后台运行的进程和控制终端没有任何关系,即使登录bash进程意外终止,也不会影响到linux后台进程。 可以使用at命令将进程放到linux系统后台运行,指定在某个时刻执行。除了at命令,更常用的方法是在原来执行后台作业命令的前面加上nohup。
用nohup配合&
需要注意的是nohup并不支持bash内置命令。 nohup命令的格式如下所示:
[root@initroot ~]# nohup [指令与参数] #在终端机前台中工作 [root@initroot ~]# nohup [指令与参数] & #在终端机后台中工作例如使用wget下载linux内核:
[root@initroot ~]# nohup wget -c https://git.kernel.org/torvalds/t/linux-5.5-rc6.tar.gz & [1] 5902 [root@initroot ~]# nohup: ignoring input and appending output to 'nohup.out'上面nohup给出提示nohup: ignoring input and appending output to 'nohup.out', 意思是nohup会忽略进程的输入,并且将进程的输出附加(appending)到nohup.out文件中,其实也就是将进程的输出重定向到nohup.out文件中了。
我们上面提到过如果进程有输出的话,在放入bash后台运行之前,最好能够将输出重定向到飞屏幕文件,上面我们没有做重定向, 于是nohup就会很体贴的帮我们做了输出重定向。
我们会发现在当前工作目录下确实多了一个nohup.out文件,并且文件中的内容正是get进程的输出。 这样nohup就将我们执行的后台作业进程彻底脱离了控制终端,变成了linux系统的后台进程,但是要注意此时的后台进程并没有脱离作业机制的管理, 我们还是可以通过作业管理命令控制这个后台进程。毕竟我们在运行命令的时候最后加上了&,这还是一个作业进程
由于linux内核文件比较大,所以下载需要一定的时间,此时如果退出登录,然后再次登录,用pstree或者ps命令就会发现wget进程依然在运行中。
而如果没有通过nohup,只是直接将进程放入bash后台运行,退出登录然后再次登录,就会发现wget进程已经不存在。 大家可以亲自在自己的linux主机上面试验一下。有的朋友可能会问,我的linux主机就在跟前,没有可以远程连接的linux主机怎么办? 可以通过虚拟机安装多个linux系统,这些linux就可以组成一个局域网,从一个虚拟linux主机就可以远程连接另一个虚拟linux主机。
上面wget进程会输出一些下载信息,nohup也帮我们把这些输出信息重定向到了nohup.out文件中, 但是更合理的做法是我们自己对输出做重定向,下面我们将wget的输出重定向到downloadlog.txt文件:
[root@initroot ~]# nohup wget -c https://git.kernel.org/torvalds/t/linux-5.5-rc6.tar.gz > downloadlog.txt 2>&1 & [1] 6495因为我们自己做了重定向,就不需要nohup做重定向了,也就不会出现上面nohup的提示信息了。
有些时候我们并不关心进程的输出信息,如果将输出重定向到磁盘文件,还会占用磁盘空间。这时候就可以将进程的输出重定向到null设备:
[root@initroot ~]# nohup wget -c https://git.kernel.org/torvalds/t/linux-5.5-rc6.tar.gz > /dev/null 2>&1 & [1] 6685这样进程的输出信息就被彻底丢弃了,既不会输出到屏幕,也不会输出到磁盘文件中。
我们再来做一个简单的练习:
1. 用vim创建一个sleep500.sh文件,该文件为shell脚本文件,功能为使进程睡眠500秒,文件内容如下所示:
[root@initroot ~]# vim sleep500.sh #!/bin/bash /bin/sleep 500s /bin/echo "I have slept 500 seconds."2. 执行该脚本程序,用nohup命令放到后台运行。然后立刻注销系统:
[root@initroot ~]# chmod a+x sleep500.sh [root@initroot ~]# nohup ./sleep500.sh & [2] 6992 [root@initroot ~]# nohup: ignoring input and appending output to 'nohup.out' [root@initroot ~]# exit3.再次登录系统,使用pstree或者ps查看运行中的进程,会发现sleep500.sh进程还在执行中!并不会被中断掉!
initroot编辑整理,转载请注明www.initroot.com
100次点赞
100次阅读