我有一个脚本来处理某些文件中的记录,通常需要 1-2 小时。当它运行时,它会打印处理的记录数的进度。
现在,我想做的是:当它运行时nohup
,我不希望它打印进度;它应该仅在手动运行时打印进度。
我的问题是如何知道 bash 脚本是否正在运行nohup
?
假设命令是nohup myscript.sh &
。在脚本中,如何获取nohup
from 命令行?我尝试使用$0
,但它给出了myscript.sh
.
检查文件重定向并不可靠,因为nohup
可以(并且经常)在标准输入、标准输出和/或标准错误已经明确重定向的脚本中使用。
除了这些重定向之外,唯一要做的nohup
就是忽略SIGHUP
信号(感谢Blrfl的链接。)
所以,我们真正需要的是一种检测是否SIGHUP
被忽略的方法。/proc/$PID/status
在 linux 中,信号忽略掩码暴露在hex 字符串的最低有效位中SigIgn
。
如果我们知道要检查的 bash 脚本的 pid,我们可以使用egrep
. 在这里,我查看当前 shell 是否忽略SIGHUP
(即“nohuppy”):
$ egrep -q "SigIgn:\s.{15}[13579bdf]" /proc/$$/status && echo nohuppy || echo normal
normal
$ nohup bash -c 'egrep -q "SigIgn:\s.{15}[13579bdf]" /proc/$$/status && echo nohuppy || echo normal'; cat nohup.out
nohup: ignoring input and appending output to `nohup.out'
nohuppy
您可以检查 STDOUT 是否与终端相关联:
[ -t 1 ]
一种方法,但不是真正可移植的,是做一个 readlink/proc/$$/fd/1
并测试它是否以 nohup.out 结尾。
假设您在pts0
终端上(并不真正相关,只是为了能够显示结果):
#!/bin/bash
if [[ $(readlink /proc/$$/fd/1) =~ nohup.out$ ]]; then
echo "Running under hup" >> /dev/pts/0
fi
但解决此类问题的传统方法是测试输出是否为终端:
[ -t 1 ]
您可以检查父 pid 是否为 1:
if [ $PPID -eq 1 ] ; then
echo "Parent pid=1 (runing via nohup)"
else
echo "Parent pid<>1 (NOT running via nohup)"
fi
或者如果您的脚本忽略 SIGHUP 信号(请参阅https://stackoverflow.com/a/35638712/1011025):
if egrep -q "SigIgn:\s.{15}[13579bdf]" /proc/$$/status ; then
echo "Ignores SIGHUP (runing via nohup)"
else
echo "Doesn't ignore SIGHUP (NOT running via nohup)"
fi
谢谢你们。检查 STDOUT 是个好主意。我只是找到另一种方法来做到这一点。也就是测试tty。test tty -s 检查它的返回码。如果它是 0 ,那么它在终端上运行;如果它是 1,那么它使用 nohup 运行。