Я пытаюсь понять, почему это не работает:
#!/bin/bash
sudo sleep 60 &
sudo_pid=$!
sudo kill $sudo_pid
Я ожидаю, что после kill
команда sudo
и ее дочерний процесс sleep
будут завершены, но это не так, как показано в этом скрипте:
#!/bin/bash
sudo sleep 60 &
sudo_pid=$!
sudo kill $sudo_pid
if ps -p $sudo_pid > /dev/null; then
sudo kill $sudo_pid
else
echo "No sudo process running"
exit 1
fi
if ps -p $sudo_pid > /dev/null; then
echo "sudo (pid $sudo_pid) is still running"
ps -F $sudo_pid
else
echo "sudo successfully killed"
fi
Что дает этот вывод, когда я запускаю его (с кэшированными кредитами sudo
):
jon@ubuntu:~$ ./so.sh
sudo (pid 46199) is still running
UID PID PPID C SZ RSS PSR STIME TTY STAT TIME CMD
root 46199 46198 0 14764 3984 3 13:37 pts/0 S+ 0:00 sudo sleep 60
После завершения скрипта (и sudo sleep 60
все еще работает) его можно убить идентичной командой:
jon@ubuntu:~$ ps -F 46199
UID PID PPID C SZ RSS PSR STIME TTY STAT TIME CMD
root 46199 1 0 14764 3984 3 13:37 pts/0 S 0:00 sudo sleep 60
jon@ubuntu:~$ sudo kill 46199
jon@ubuntu:~$ ps -F 46199
UID PID PPID C SZ RSS PSR STIME TTY STAT TIME CMD
jon@ubuntu:~$
Я заметил, что после завершения сценария so.sh
идентификатор родительского процесса для sudo sleep 60
изменился со сценария на процесс init
, что я считаю важным. Также возможно успешно завершить процесс sudo sleep 60
из другой оболочки, пока скрипт so.sh
все еще работает.
Я также заметил, что использование sudo kill -ABRT
в сценарии (в отличие от kill
по умолчанию SIGTERM
) успешно убивает процесс sudo
, поэтому я предполагаю, что это как-то связано с тем, как sudo
обрабатывает SIGTERM
. Однако, основываясь на справочной странице, я не думаю, что это должно делать что-то особенное:
Signal handling
When the command is run as a child of the sudo process, sudo will relay
signals it receives to the command. The SIGINT and SIGQUIT signals are
only relayed when the command is being run in a new pty or when the sig‐
nal was sent by a user process, not the kernel. This prevents the com‐
mand from receiving SIGINT twice each time the user enters control-C.
Единственная специальная обработка SIGTERM
, упомянутая на странице руководства, касается signals that were sent by the command it is running
; здесь не так. Кроме того, я изменил ps -F
в приведенном выше сценарии на ps -o blocked,caught,ignored,pending
, и он вывел
sudo (pid 46429) is still running
BLOCKED CAUGHT IGNORED PENDING
0000000000000000 00000001800b7a07 0000000000000000 0000000000000000
Что, по-видимому, указывает на то, что SIGTERM не блокируется и не игнорируется, так почему же процесс sudo sleep 60
не завершается?
Я придумал несколько обходных путей (setsid
, sudo -b
, уничтожение дочернего процесса sleep
, а не родительского процесса sudo
), поэтому я не ищу ответы на альтернативные подходы. Я просто хочу понять, что здесь происходит.
Если это важно:
jon@ubuntu:~$ uname -a
Linux ubuntu 4.13.0-16-generic #19-Ubuntu SMP Wed Oct 11 18:35:14 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
jon@ubuntu:~$ sudo --version
Sudo version 1.8.20p2
Sudoers policy plugin version 1.8.20p2
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.20p2