Ваше предположение, что оно ssh
само возвращает статус 255, верно. ssh
Страница людей заявляет , что:
ssh завершает работу с состоянием выхода удаленной команды или с 255, если произошла ошибка.
Если бы вы просто запустились ssh pi@10.20.0.10 "pkill -f asdf"
, вы, скорее всего, получили бы статус выхода 1
, соответствующий pkill
статусу « Нет соответствующих процессов ».
Задача состоит в том, чтобы понять, почему при запуске SSH возникает ошибка
ssh pi@10.20.0.10 "pkill -f asdf || true"
SSH удаленные команды
Сервер SSH запускает оболочку для запуска удаленных команд. Вот пример этого в действии:
$ ssh server "ps -elf | tail -5"
4 S root 35323 1024 12 80 0 - 43170 poll_s 12:01 ? 00:00:00 sshd: anthony [priv]
5 S anthony 35329 35323 0 80 0 - 43170 poll_s 12:01 ? 00:00:00 sshd: anthony@notty
0 S anthony 35330 35329 0 80 0 - 28283 do_wai 12:01 ? 00:00:00 bash -c ps -elf | tail -5
0 R anthony 35341 35330 0 80 0 - 40340 - 12:01 ? 00:00:00 ps -elf
0 S anthony 35342 35330 0 80 0 - 26985 pipe_w 12:01 ? 00:00:00 tail -5
Обратите внимание, что оболочкой по умолчанию является bash
и что удаленная команда - это не простая команда, а конвейер , «последовательность из одной или нескольких команд, разделенных оператором управления |
».
Оболочка Bash достаточно умна, чтобы понять, что если команда, передаваемая ей с помощью -c
опции, является простой командой , она может оптимизироваться, фактически не разветвляя новый процесс, т. Е. Она напрямую exec
выполняет простую команду вместо выполнения дополнительного шага. из fork
ING до того , как exec
с. Вот пример того, что происходит, когда вы запускаете простую удаленную команду ( ps -elf
в данном случае):
$ ssh server "ps -elf" | tail -5
1 S root 34740 2 0 80 0 - 0 worker 11:49 ? 00:00:00 [kworker/0:1]
1 S root 34762 2 0 80 0 - 0 worker 11:50 ? 00:00:00 [kworker/0:3]
4 S root 34824 1024 31 80 0 - 43170 poll_s 11:51 ? 00:00:00 sshd: anthony [priv]
5 S anthony 34829 34824 0 80 0 - 43170 poll_s 11:51 ? 00:00:00 sshd: anthony@notty
0 R anthony 34830 34829 0 80 0 - 40340 - 11:51 ? 00:00:00 ps -elf
Я сталкивался с таким поведением раньше, но я не мог найти лучшую ссылку, кроме этого ответа AskUbuntu .
поведение pkill
Так как pkill -f asdf || true
это не простая команда (это список команд ), выше оптимизации не могут произойти так , при запуске ssh pi@10.20.0.10 "pkill -f asdf || true"
, в sshd
процессе вилки и Execs bash -c "pkill -f asdf || true"
.
Как указывает ответ ctx, pkill
не будет убивать свой собственный процесс. Тем не менее, он будет убивать любой другой процесс , командная строка которого соответствует -f
шаблону. Команда bash -c
соответствует этому шаблону, поэтому убивает этот процесс - своего родителя (как это происходит).
Затем SSH-сервер видит, что процесс оболочки, который он запустил для запуска удаленных команд, был неожиданно завершен, поэтому он сообщает об ошибке клиенту SSH.
pkill
убивает его процесс оболочки родительского , потому что его агд список совпадает с регулярным выражением, я подниму терминологическую возражение:x || y
это не команда соединения , это список команд .