2023年11月25日发(作者:)

解决Linux关闭终端(关闭SSH等)后运⾏的程序或者服务⾃动

停⽌【后台运⾏程序】

问题描述:当SSH远程连接到服务器上,然后运⾏⼀个服务 ./ start,然后把终端开闭(切断SSH连接)之后,发现该服务中断,

导致⽹页⽆法访问。

解决⽅法:使⽤nohup命令让程序在关闭窗⼝(切换SSH连接)的时候程序还能继续在后台运⾏。

Unix/Linux下⼀般⽐如想让某个程序在后台运⾏,很多都是使⽤& 在程序结尾来让程序⾃动运⾏。⽐如我们要运⾏mysql在后台:

/usr/local/mysql/bin/mysqld_safe --user=mysql &

但是加⼊我们很多程序并不象mysqld⼀样做成守护进程,可能我们的程序只是普通程序⽽已,⼀般这种程序使⽤& 结尾,但是如果终端关

闭,那么程序也会被关闭。但是为了能够后台运⾏,那么我们就可以使⽤nohup这个命令,⽐如我们有个需要在后台运⾏,并且希

望在后台能够定期运⾏,那么就使⽤nohup

nohup /root/ &

提⽰:

[~]$ appending output to

嗯,证明运⾏成功,同时把程序运⾏的输出信息放到当前⽬录的 ⽂件中去。

nohup命令说明:

⽤途:不挂断地运⾏命令。

语法:nohup Command [ Arg ... ] [ & ]

描述:nohup 命令运⾏由 Command 参数和任何相关的 Arg 参数指定的命令,忽略所有挂断(SIGHUP)信号。在注销后使⽤ nohup

命令运⾏后台中的程序。要运⾏后台中的 nohup 命令,添加 & 表⽰“and”的符号)到命令的尾部。

⽆论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前⽬录的 ⽂件中。如果当前⽬录的 ⽂件不可写,

输出重定向到 $HOME/ ⽂件中。如果没有⽂件能创建或打开以⽤于追加,那么 Command 参数指定的命令不可调⽤。如果标准错

误是⼀个终端,那么把指定的命令写给标准错误的所有输出作为标准输出重定向到相同的⽂件描述符。

退出状态:该命令返回下列出⼝值:

126 可以查找但不能调⽤ Command 参数指定的命令。

127 nohup 命令发⽣错误或不能查找由 Command 参数指定的命令。

否则,nohup 命令的退出状态是 Command 参数指定命令的退出状态。

nohup命令及其输出⽂件

nohup命令:如果你正在运⾏⼀个进程,⽽且你觉得在退出帐户时该进程还不会结束,那么可以使⽤nohup命令。该命令可以在你退出

帐户/关闭终端之后继续运⾏相应的进程。nohup就是不挂起的意思( n ohang up)

该命令的⼀般形式为:nohup command &

使⽤nohup命令提交作业

如果使⽤nohup命令提交作业,那么在缺省情况下该作业的所有输出都被重定向到⼀个名为的⽂件中,除⾮另外指定了输出⽂

:(也就是说⾃定义输出的⽂件名)

nohup command > 2>&1 &

在上⾯的例⼦中,输出被重定向到⽂件中。

使⽤ jobs 查看任务。

使⽤ fg %n 关闭。

另外有两个常⽤的ftp⼯具ncftpgetncftpput,可以实现后台的ftp上传和下载,这样我就可以利⽤这些命令在后台上传和下载⽂件了。

思考:问题1为什么ssh⼀关闭,程序就不再运⾏了?

元凶:SIGHUP 信号

让我们来看看为什么关掉窗⼝/断开连接会使得正在运⾏的程序死掉。

简⽽⾔之:就是ssh 打开以后,bash等都是他的⼦程序,⼀旦ssh关闭,系统将所有相关进程杀掉!! 导致⼀旦ssh关闭,执⾏中的任务就

取消了

例⼦:

我们来看⼀个例⼦。打开两个SSH终端窗⼝,在其中⼀个运⾏top命令。

[root@tivf09 root]# top

在另⼀个终端窗⼝,找到top的进程ID5180,其⽗进程ID5128,即登录shell

[root@tivf09 root]# ps -ef|grep top

root 5180 5128 0 01:03 pts/0 00:00:02 top

root 5857 3672 0 01:12 pts/2 00:00:00 grep top

使⽤pstree命令可以更清楚地看到这个关系:

[root@tivf09 root]# pstree -H 5180|grep top

|-sshd-+-sshd---bash---top

使⽤ps-xj命令可以看到,登录shellPID 5128)和top在同⼀个会话期,shell为会话期⾸进程,所在进程组PGID5128top所在进程组

PGID5180,为前台进程组。

[root@tivf09 root]# ps -xj|grep 5128

5126 5128 5128 5128 pts/0 5180 S 0 0:00 -bash

5128 5180 5180 5128 pts/0 5180 S 0 0:50 top

3672 18095 18094 3672 pts/2 18094 S 0 0:00 grep 5128

关闭第⼀个SSH窗⼝,在另⼀个窗⼝中可以看到top也被杀掉了。

[root@tivf09 root]# ps -ef|grep 5128

root 18699 3672 0 04:35 pts/2 00:00:00 grep 5128

问题2 为什么守护程序就算ssh 打开的,就算关闭ssh也不会影响其运⾏?

因为他们的程序特殊,⽐如httpd –k start运⾏这个以后,他不属于sshd这个进程组 ⽽是单独的进程组,所以就算关闭了ssh,和他也没有任

何关系!

[root@CentOS5-4 ~]# pstree |grep http

|-httpd

[root@CentOS5-4 ~]# pstree |grep top

|-sshd-+-sshd---bash---top

结论:守护进程的启动命令本⾝就是特殊的,和⼀般命令不同的,⽐如mysqld_safe 这样的命令 ⼀旦使⽤了 就是守护进程运⾏。所以想把

⼀般程序改造为守护程序是不可能,

问题3 使⽤后台运⾏命令& 能否将程序摆脱ssh进程组控制呢 也就是ssh关闭,后台程序继续运⾏?

我们做⼀个试验: find / -name ‘*http*’&

利⽤ctrl+d 注销以后 再进⼊系统 会不会看见这个命令再运⾏?

答案是 :命令被中⽌了!!

因为他依然属于这个ssh进程组 就算加了&也⽆法摆脱!!

[root@CentOS5-4 ~]# pstree |grep find

|-sshd-+-sshd---bash---find

结论就是:只要是ssh 打开执⾏的⼀般命令,不是守护程序,⽆论加不加&,⼀旦关闭ssh,系统就会⽤SIGHUP终⽌

问题4 nohup能解决的问题

但是为了能够再注销以后 依然能后台运⾏,那么我们就可以使⽤nohup这个命令,我们现在开始查找find / -name ‘*http*’&

,并且希望在后台运⾏,

那么就使⽤nohupnohup find / -name "*httpd*"

此时默认地程序运⾏的输出信息放到当前⽂件夹的 ⽂件中去

加不加&并不会影响这个命令 只是让程序 前台或者后台运⾏⽽已

延伸:Linux命令nohup+screen命令

如果想在关闭ssh连接后刚才启动的程序继续运⾏怎么办,可以使⽤nohup。但是如果要求第⼆天来的时候,⼀开ssh,还能查看到昨天运⾏

的程序的状态,然后继续⼯作,这时nohup是不⾏了,需要使⽤screen来达到这个⽬的。

虽然nohup很容易使⽤,但还是⽐较简陋的,对于简单的命令能够应付过来,对于复杂的需要⼈机交互的任务就⿇烦了。

其实我们可以使⽤⼀个更为强⼤的实⽤程序screen。流⾏的Linux发⾏版(例如Red Hat Enterprise Linux 4)通常会⾃带screen实⽤程序,

如果没有的话,可以从GNU screen的官⽅⽹站下载。

1)使⽤

执⾏screen 按任意键进⼊⼦界⾯;

我⽤ping命令开始执⾏,如果下班了,但是想关闭ssh以后ping继续运⾏,那么按ctrl+a 再按d 这样暂停了⼦界⾯,会显⽰[detached]的字

样,这时候 我回到了⽗界⾯;

screen –ls查看⽬前⼦界⾯的状态screen -ls

There is a screen on: (Detached)

1 Socket in /tmp/screens/S-root,这⾥的22292其实是⼦界⾯的pid号;

如果回到⼦界⾯ screen –r 22292,⼀下⼦弹到了ping 的⼦界⾯;

2)更多帮助

可以通过C-actrl+a?来查看所有的键绑定,常⽤的键绑定有:

C-a ?

显⽰所有键绑定信息

C-a w

显⽰所有窗⼝列表

C-a C-a

切换到之前显⽰的窗⼝

C-a c

创建⼀个新的运⾏shell的窗⼝并切换到该窗⼝

C-a n

切换到下⼀个窗⼝

C-a p

切换到前⼀个窗⼝(C-a n相对)

C-a 0..9

切换到窗⼝0..9

C-a a

发送C-a到当前窗⼝

C-a d

暂时断开screen会话

C-a k

杀掉当前窗⼝

C-a [

进⼊拷贝/回滚模式

其他常⽤选项:

-c file

使⽤配置⽂件file,⽽不使⽤默认的$HOME/.screenrc

-d|-D []

不开启新的screen会话,⽽是断开其他正在运⾏的screen会话

-h num

指定历史回滚缓冲区⼤⼩为num

-list|-ls

列出现有screen会话,格式为

-d -m

启动⼀个开始就处于断开模式的会话

-r sessionowner/ []

重新连接⼀个断开的会话。多⽤户模式下连接到其他⽤户screen会话需要指定sessionowner,需要setuid-root权限

-S sessionname

创建screen会话时为会话指定⼀个名字

-v

显⽰screen版本信息

-wipe [match]

-list,但删掉那些⽆法连接的会话

其他资料:

1. Linux 技巧:让进程在后台可靠运⾏的⼏种⽅法,/developerworks/cn/linux/l-cn-nohup/