La tua supposizione che sia esso ssh
stesso a restituire lo stato di uscita 255 è corretta. La ssh
pagina man afferma che:
ssh esce con lo stato di uscita del comando remoto o con 255 se si è verificato un errore.
Se dovessi semplicemente eseguire ssh pi@10.20.0.10 "pkill -f asdf"
, molto probabilmente otterrai uno stato di uscita 1
, corrispondente allo pkill
stato di " Nessun processo abbinato ".
La parte difficile è capire perché si verifica un errore con SSH durante l'esecuzione
ssh pi@10.20.0.10 "pkill -f asdf || true"
Comandi remoti SSH
Il server SSH avvia una shell per eseguire comandi remoti. Ecco un esempio di questo in azione:
$ 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
Si noti che la shell predefinita è bash
e che il comando remoto non è un semplice comando ma una pipeline , "una sequenza di uno o più comandi separati dall'operatore di controllo |
".
La shell Bash è abbastanza intelligente da rendersi conto che se il comando che gli viene passato -c
dall'opzione è un comando semplice , può essere ottimizzato non in realtà un fork di un nuovo processo, ovvero è direttamente exec
il comando semplice invece di passare attraverso il passaggio aggiuntivo di fork
ing prima che exec
sia. Ecco un esempio di ciò che accade quando si esegue un comando remoto semplice ( ps -elf
in questo 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
Mi sono imbattuto in questo comportamento prima ma non sono riuscito a trovare un riferimento migliore diverso da questa risposta AskUbuntu .
comportamento pkill
Dal momento che pkill -f asdf || true
non è un semplice comando (è un elenco di comandi ), l'ottimizzazione di cui sopra non può avvenire, quindi quando si esegue ssh pi@10.20.0.10 "pkill -f asdf || true"
, il sshd
processo si biforca e si esegue bash -c "pkill -f asdf || true"
.
Come sottolinea la risposta di ctx, pkill
non ucciderà il suo stesso processo. Tuttavia, sarà uccidere qualsiasi altro processo la cui linea di comando corrisponde al -f
modello. Il bash -c
comando corrisponde a questo modello in modo da uccidere questo processo - il suo genitore (mentre succede).
Il server SSH vede quindi che il processo di shell avviato per eseguire i comandi remoti è stato interrotto in modo imprevisto, quindi segnala un errore al client SSH.
pkill
uccide il suo processo di shell genitore perché la sua lista arg corrisponde alla regexp, solleverò un'obiezione terminologica: nonx || y
è un comando composto , è un elenco di comandi .