0

导入大批量的数据,在阿里云服务器上写了一个shell脚本来执行,本人MAC终端连接服务器,但是突然公司断网了。我在终端看到shell脚本终止了,输出了结束标识符。但是本人不知道脚本再断网之前就结束了还是断网的时候结束的???而且,断网对脚本运行有影响吗?图片描述

2017-12-22 提问

查看全部 4 个回答

9

已采纳

TD;TR: 多年Linux服务器运维经验的老司机告诉你,会有影响,所以长时间运行并且不允许中断的脚本你应该放在screen/tmux这一类虚拟终端执行,帮你hold住session不中断。

但并不意味着ssh断开你运行的脚本一定会崩溃,我们假定你的脚本通常都是单线程同步运行的命令行

#!/bin/bash -e
command1
command2
command3

那么在Linux上用ps -efx命令看你的进程树大致是这个样子的:

sshd
\_ -bash
    \_ bash -e /path/to/your_script.sh
        \_ command1

如果此时强行断开ssh连接(比如你强行关闭终端窗口,或者网络断开),那么你的ssh通道会broken pipe,于是系统会收到SIGHUP信号,干掉你的sshd fork出来的bash进程。于是你的command1就变成孤儿进程了。这个套路是不是有点眼熟?没错就是杀死僵尸进程的方法,那么command1将会被init进程(pid为1的进程)托管。如果你的子进程开启了NOSIGHUP,是不会被SIGHUP信号干掉的,直接变成init进程的子进程继续运行。所以此时你再次登录ssh会发现command1已经变成了init的子进程,像这样:

init
\_ command1
如果你的command1没有开启NO_SIGHUP,那么是不会看到这个情况的,bash被干掉,下面的command1也将被干掉,并且不会再执行command2,command3

当然session已经丢失,你也无法看到command1的stdout和stderr了。这时候你发现由于bash已经被干掉,所以在command1执行完毕之后,command2;command3自然无法执行了。这就可能会对你的逻辑造成比较严重的影响——你的脚本执行步骤并未完成,并且如果你的脚本不是幂等,也将难以重试或继续。

因此,对于长时间运行并且不允许中断的脚本,你应该使用screen/tmux托管。

另:不一定所有的进程都会默认开启忽略SIGHUP信号,因此大多数进程对于SIGHUP信号的响应是直接退出
1
回复 命中水ヽ

看TD;TR的结论就行了

Feng_Yu · 2017年12月22日

展开评论

推广链接