【发布时间】:2012-03-26 08:47:18
【问题描述】:
上下文:
我有一个 bash 脚本,其中包含一个子 shell 和一个用于 EXIT 伪信号的陷阱,但它在 rsync 期间没有正确捕获中断。这是一个例子:
#!/bin/bash
logfile=/path/to/file;
directory1=/path/to/dir
directory2=/path/to/dir
cleanup () {
echo "Cleaning up!"
#do stuff
trap - EXIT
}
trap '{
(cleanup;) | 2>&1 tee -a $logfile
}' EXIT
(
#main script logic, including the following lines:
(exec sleep 10;);
(exec rsync --progress -av --delete $directory1 /var/tmp/$directory2;);
) | 2>&1 tee -a $logfile
trap - EXIT #just in case cleanup isn't called for some reason
脚本的想法是这样的:大部分重要的逻辑都在一个子shell中运行,该子shell通过tee和一个日志文件传输,所以我不必tee主逻辑的每一行来全部记录下来。每当 subshell 结束,或脚本因任何原因停止(EXIT 伪信号应捕获所有这些情况)时,陷阱将拦截它并运行cleanup() 函数,然后删除陷阱。 rsync 和 sleep 命令(sleep 只是一个示例)通过 exec 运行,以防止创建僵尸进程,如果我在父脚本运行时杀死它们,并且每个可能长时间运行的命令被包裹在自己的子外壳中,因此当exec 完成时,它不会终止整个脚本。
问题:
如果我在 exec/subshell 包装的sleep 命令期间中断脚本(通过kill 或 CTRL+C),陷阱工作正常,我看到“正在清理!”回显并记录。如果我在rsync 命令期间中断脚本,我看到rsync 结束,并将rsync error: received SIGINT, SIGTERM, or SIGHUP (code 20) at rsync.c(544) [sender=3.0.6] 写入屏幕,然后脚本就死了;不清理,不诱捕。为什么打断/杀死rsync 不会触发陷阱?
我已经尝试将--no-detach 开关与 rsync 一起使用,但它并没有改变任何东西。
我有 bash 4.1.2、rsync 3.0.6、centOS 6.2。
【问题讨论】:
-
这不是您的问题的原因,但您的日志记录不可靠,因为您同时使用两个不同的程序写入同一个文件。
-
你的
trap - EXIT在一个子shell中(明确),所以清理函数返回后它不会有效果 -
在子 shell 中运行 exec 与正常运行命令相同 - 您不需要额外的标点符号。
标签: linux bash shell rsync bash-trap