Lorsque j'essaie d'exécuter pkill -f
à distance via ssh, et essayez de supprimer le code d'erreur possible (pour continuer avec le reste de mon script même si aucun processus n'est trouvé), || true
ne se comporte pas comme je m'y attendais.
$ pkill asdf || true
$ echo $?
0
$ pkill -f asdf || true
$ echo $?
0
$ ssh [email protected] "pkill asdf || true"
$ echo $?
0
$ ssh [email protected] "pkill -f asdf || true"
255
Je suppose que c'est ssh qui renvoie 255, pas la commande entre guillemets, mais pourquoi ?
Réponse acceptée :
Votre supposition que c'est ssh
lui-même qui renvoie le statut de sortie 255 est correct. Le ssh
la page de manuel indique que :
ssh se termine avec le statut de sortie de la commande à distance ou avec 255 si une erreur s'est produite.
Si vous deviez simplement exécuter ssh [email protected] "pkill -f asdf"
, vous obtiendrez très probablement un statut de sortie de 1
, correspondant au pkill
statut pour "Aucun processus correspondant ”.
Le défi consiste à comprendre pourquoi une erreur se produit avec SSH lorsque vous exécutez
ssh [email protected] "pkill -f asdf || true"
Commandes à distance SSH
Le serveur SSH lance un shell pour exécuter des commandes à distance. Voici un exemple de ceci en action :
$ 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: [email protected]
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
Notez que le shell par défaut est bash
et que la commande à distance n'est pas une simple commande mais un pipeline, "une séquence d'une ou plusieurs commandes séparées par l'opérateur de contrôle |
”.
Le shell Bash est assez intelligent pour se rendre compte que si la commande lui est passée par le -c
option est une commande simple, elle peut optimiser en ne forçant pas réellement un nouveau processus, c'est-à-dire qu'elle est directement exec
s la commande simple au lieu de passer par l'étape supplémentaire de fork
ing avant exec
s. Voici un exemple de ce qui se passe lorsque vous exécutez une commande simple à distance (ps -elf
dans ce cas):
$ 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: [email protected]
0 R anthony 34830 34829 0 80 0 - 40340 - 11:51 ? 00:00:00 ps -elf
J'ai déjà rencontré ce comportement, mais je n'ai pas trouvé de meilleure référence que cette réponse AskUbuntu.
En relation :Quelle est la différence entre un point-virgule et une double esperluette && ?comportement pkill
Depuis pkill -f asdf || true
n'est pas une simple commande (c'est une liste de commandes), l'optimisation ci-dessus ne peut pas se produire, donc lorsque vous exécutez ssh [email protected] "pkill -f asdf || true"
, le sshd
traiter les forks et les execs bash -c "pkill -f asdf || true"
.
Comme le souligne la réponse de ctx, pkill
ne tuera pas son propre processus. Cependant, cela va tue tout autre processus dont la ligne de commande correspond à -f
modèle. Le bash -c
La commande correspond à ce modèle et tue donc ce processus - son propre parent (en l'occurrence).
Le serveur SSH voit alors que le processus shell qu'il a démarré pour exécuter les commandes à distance a été tué de manière inattendue, il signale donc une erreur au client SSH.