La tua supposizione che sia esso sshstesso a restituire lo stato di uscita 255 è corretta. La sshpagina 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 pkillstato 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 è bashe 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 -cdall'opzione è un comando semplice , può essere ottimizzato non in realtà un fork di un nuovo processo, ovvero è direttamente execil comando semplice invece di passare attraverso il passaggio aggiuntivo di forking prima che execsia. Ecco un esempio di ciò che accade quando si esegue un comando remoto semplice ( ps -elfin 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 || truenon è 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 sshdprocesso si biforca e si esegue bash -c "pkill -f asdf || true".
Come sottolinea la risposta di ctx, pkillnon ucciderà il suo stesso processo. Tuttavia, sarà uccidere qualsiasi altro processo la cui linea di comando corrisponde al -fmodello. Il bash -ccomando 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.
pkilluccide 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 .