如何使用信号从自身重启BASH脚本?

时间:2011-01-11 22:18:13

标签: bash unix signals

例如,我有一个带有无限循环的脚本将某些内容打印到stdout。我需要捕获一个信号(例如SIGHUP),因此它将使用不同的PID重新启动脚本,循环将从0再次启动。杀戮和启动不能按预期工作:

function traphup(){  
    kill $0  
    exec $0
}  
trap traphup HUP

也许我应该在后台放置一些东西或使用nohup,但我不熟悉这个命令。

1 个答案:

答案 0 :(得分:3)

在你的功能中:

traphup(){
    $0 "$@" &
    exit 0
}

这将在后台启动一个新进程,其中包含原始命令名称和参数(根据您的要求更改参数)以及新进程ID。原来的shell然后退出。如果您的守护程序使用一个标识符来识别自己,请不要忘记整理PID文件 - 但重启可能会这样做。

请注意,使用nohup将是错误的方向;第一次启动守护进程时,它会响应HUP信号,但是使用nohup启动的信号将忽略该信号,而不是重新启动 - 除非您明确覆盖'ignore'状态,这是一个坏主意出于各种原因。


回答评论

我不太确定是什么问题。

当我运行以下脚本时,我只会在ps输出中看到该脚本的一个副本,无论我是以./xx.sh还是./xx.sh &启动它。

#!/bin/bash

traphup()
{
    $0 "$$" &
    exit 0
}

trap traphup HUP
echo
sleep 1

i=1
while [ $i -lt 1000 ]
do
    echo "${1:-<none>}: $$: $i"
    sleep 1
    : $(( i++ ))
done

输出包含以下行:

<none>: 1155: 21
<none>: 1155: 22
<none>: 1155: 23

1155: 1649: 1
1155: 1649: 2
1155: 1649: 3
1155: 1649: 4

具有“<none>”的是原始流程;第二组是子进程(1649)报告其父进程(1155)。此输出可以轻松跟踪将HUP信号发送到哪个进程。 (初始echo和sleep使得命令行提示不受输出限制。)

我怀疑你所看到的内容取决于你脚本的内容 - 在我的例子中,循环的主体很简单。但是,如果我有一个管道或其他东西,那么我可能会看到第二个具有相同名称的进程。但我认为这不会改变,具体取决于原始脚本是在前台还是后台运行。