我试图阻止用户使用ctrl c取消脚本.以下脚本完全执行,除了坚持死亡的rsync,显示由信号2杀死的错误.
是否有可能避免rsync死亡?如果是这样,我可以将它放在后台,还是应该在前台?
脚本:
trap '' SIGINT SIGTERM SIGQUIT cd /tmp nohup rsync -e 'ssh -o LogLevel=ERROR' -av --timeout=10 --delete-excluded myapp.war myserver:/tmp/ < /dev/null > /tmp/teste 2> /tmp/teste2 let index=0 while [ $index -lt 400000 ] do let index=index+1 done echo "script finished" echo "index:$index"
我怀疑ssh频道在rsync之前就已经死了.在rsync的pid中输出strace命令结束之后:
[...] write(4,"\374\17\0\7",4) = 4 select(5,NULL,[4],{10,0}) = 1 (out [4],left {9,999998}) --- SIGINT (Interrupt) @ 0 (0) --- --- SIGCHLD (Child exited) @ 0 (0) --- wait4(-1,[{WIFEXITED(s) && WEXITSTATUS(s) == 255}],WNOHANG,NULL) = 12738 wait4(-1,0x7fffaea6a85c,NULL) = -1 ECHILD (No child processes) rt_sigreturn(0xffffffffffffffff) = 0 select(0,{0,400000}) = 0 (Timeout) rt_sigaction(SIGUSR1,{SIG_IGN,[],SA_RESTORER,0x3fcb6326b0},8) = 0 rt_sigaction(SIGUSR2,8) = 0 wait4(12738,0x7fffaea6aa7c,NULL) = -1 ECHILD (No child processes) getpid() = 12737 kill(12738,SIGUSR1) = -1 ESRCH (No such process) write(2,"rsync error: unexplained error ("...,72) = 72 write(2,"\n",1) = 1 exit_group(255) = ? Process 12737 detached
从实验中可以清楚地看出,rsync的行为与其他工具(如ping)一样,并且不会从调用Bash父级继承信号.
因此,您必须对此有一点创意,并执行以下操作:
$cat rsync.bash #!/bin/sh set -m trap '' SIGINT SIGTERM EXIT rsync -avz LargeTestFile.500M root@host.mydom.com:/tmp/. & wait echo FIN
现在当我运行它:
$./rsync.bash X11 forwarding request Failed building file list ... done LargeTestFile.500M ^C^C^C^C^C^C^C^C^C^C sent 509984 bytes received 42 bytes 92732.00 bytes/sec total size is 524288000 speedup is 1027.96 FIN
我们可以看到文件完全转移:
$ll -h | grep Large -rw-------. 1 501 games 500M Jul 9 21:44 LargeTestFile.500M
这个怎么运作
这里的诀窍是我们通过set -m告诉Bash在其中的任何后台作业上禁用作业控制.然后,我们将后台运行rsync,然后运行wait命令,该命令将等待最后一个运行命令rsync,直到它完成.
然后我们用陷阱”SIGINT SIGTERM EXIT保护整个脚本.
参考
> https://access.redhat.com/solutions/360713
> https://access.redhat.com/solutions/1539283
> Delay termination of script