Sua suposição de que é ssh
em si que retorna o status de saída 255 está correta. A página ssh
man afirma que:
ssh exits with the exit status of the remote command or with 255 if an error occurred.
Se você simplesmente executasse ssh [email protected] "pkill -f asdf"
, provavelmente obteria um status de saída de 1
, correspondente ao status pkill
para " Nenhum processo correspondido ".
A parte desafiadora é entender por que um erro ocorre com o SSH quando você executa
ssh [email protected] "pkill -f asdf || true"
Comandos remotos SSH
O servidor SSH inicia um shell para executar o (s) comando (s) remoto (s). Veja 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 bastante para perceber que se o comando que está sendo passado para ele pela opção -c
é um comando simples , ele pode otimizar por não realmente bifurcar um novo processo, isto é, diretamente exec
s o comando simples em vez de passar pela etapa extra de fork
ing antes de exec
s. Veja um exemplo do que acontece quando você executa um comando simples e 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
Eu já vi esse comportamento antes, mas não consegui encontrar uma referência melhor do que esta resposta do AskUbuntu .
comportamento pkill
Como pkill -f asdf || true
não é um comando simples (é uma lista de comandos ) , a otimização acima não pode ocorrer, portanto, quando você executar ssh [email protected] "pkill -f asdf || true"
, os sshd
process forks e execs bash -c "pkill -f asdf || true"
.
Como a resposta do ctx aponta, pkill
não mata seu próprio processo. No entanto, ele irá matar qualquer outro processo cuja linha de comando corresponda ao padrão -f
. O comando bash -c
corresponde a esse padrão para que ele mate esse processo - seu próprio pai (como acontece).
O servidor SSH, em seguida, vê que o processo de shell iniciado para executar os comandos remotos foi morto inesperadamente, de modo que ele relata um erro para o cliente SSH.