Sua suposição de que é ela ssh
mesma que retorna o status de saída 255 está correta. A ssh
página do manual afirma que:
O ssh sai com o status de saída do comando remoto ou com 255 se ocorreu um erro.
Se você simplesmente executasse ssh pi@10.20.0.10 "pkill -f asdf"
, provavelmente obteria um status de saída 1
correspondente ao pkill
status de " Nenhum processo correspondido ".
A parte desafiadora é entender por que ocorre um erro no SSH quando você executa
ssh pi@10.20.0.10 "pkill -f asdf || true"
Comandos remotos SSH
O servidor SSH inicia um shell para executar comandos remotos. Aqui está um exemplo disso em ação:
$ 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
Observe que o shell padrão é bash
e que o comando remoto não é um comando simples, mas um pipeline , “uma sequência de um ou mais comandos separados pelo operador de controle |
”.
O shell Bash é inteligente o suficiente para perceber que, se o comando que está sendo passado pela -c
opção for um comando simples , ele pode otimizar não sendo realmente bifurcado em um novo processo, ou seja, é diretamente exec
o comando simples em vez de passar pela etapa extra de fork
ing antes que ele exec
é. Aqui está um exemplo do que acontece quando você executa um comando simples remoto ( ps -elf
neste caso):
$ 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
Já deparei com esse comportamento antes, mas não consegui encontrar uma referência melhor além desta resposta do AskUbuntu .
comportamento pkill
Como pkill -f asdf || true
não é um comando simples (é uma lista de comandos ), a otimização acima pode não ocorrer; portanto, quando você executa ssh pi@10.20.0.10 "pkill -f asdf || true"
, o sshd
processo bifurca e executa bash -c "pkill -f asdf || true"
.
Como a resposta da ctx aponta, pkill
não matará seu próprio processo. No entanto, ele vai matar qualquer outro processo cuja linha de comando corresponde ao -f
padrão. O bash -c
comando corresponde a esse padrão e mata esse processo - seu próprio pai (por acaso).
O servidor SSH vê, então, que o processo do shell iniciado para executar os comandos remotos foi interrompido inesperadamente e, portanto, relata um erro ao cliente SSH.
pkill
mata seu processo de shell pai porque sua lista arg corresponde ao regexp, levantarei uma objeção terminológica: nãox || y
é um comando composto , é uma lista de comandos .