语境:
我有一个 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
and命令(sleep
sleep 只是一个例子)被运行exec
以防止创建僵尸进程,如果我在它们运行时杀死父脚本,并且每个可能长时间运行的命令都包装在它自己的子 shell 中,这样当exec
完成,它不会终止整个脚本。
问题:
如果我在执行 exec/subshell 包装命令期间中断脚本(通过kill
或 CTRL+C)sleep
,陷阱会正常工作,我会看到“正在清理!” 回显并记录。如果我在命令期间中断脚本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。