Назад | Перейти на главную страницу

bash rsync завершается сигналом 2

Я пытаюсь запретить пользователю отменить сценарий, используя ctrl + c. Следующий скрипт выполняется полностью, за исключением rsync который настаивает на смерти, отображая ошибку Killed by signal 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. По окончании вывода strace команда в PID rsync:

[...]
write(4, "\374\17\0\7", 4)              = 4
select(5, NULL, [4], [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, WNOHANG, NULL) = -1 ECHILD (No child processes)
rt_sigreturn(0xffffffffffffffff)        = 0
select(0, NULL, NULL, NULL, {0, 400000}) = 0 (Timeout)
rt_sigaction(SIGUSR1, {SIG_IGN, [], SA_RESTORER, 0x3fcb6326b0}, NULL, 8) = 0
rt_sigaction(SIGUSR2, {SIG_IGN, [], SA_RESTORER, 0x3fcb6326b0}, NULL, 8) = 0
wait4(12738, 0x7fffaea6aa7c, WNOHANG, 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

Как это устроено

Хитрость здесь в том, что мы сообщаем Bash через set -m чтобы отключить управление заданиями для любых фоновых заданий в нем. Затем мы делаем фон rsync а затем запустить wait команда, которая будет ждать последней команды запуска, rsync, пока он не будет завершен.

Затем мы защищаем весь сценарий с помощью trap '' SIGINT SIGTERM EXIT.

Ссылки

Вам нужно поймать Ctrl + C на время выполнения скрипта.

#!/bin/bash

trap ctrl_c INT

function ctrl_c() {
        echo "Oops CTRL-C not allowed!"
}

for i in `seq 1 5`;
do
    echo "doing something... blah blah blah... try pressing Ctrl+C"
    sleep 1
done