Cuando trato de ejecutar pkill -f
de forma remota a través de ssh e intente descartar el posible código de error (para continuar con el resto de mi secuencia de comandos incluso si no se encuentra ningún proceso), || true
no se comporta como esperaba.
$ 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
Supongo que es ssh que devuelve 255, no el comando entre comillas, pero ¿por qué?
Respuesta aceptada:
Su suposición de que es ssh
mismo que devuelve el estado de salida 255 es correcto. El ssh
La página del manual indica que:
ssh sale con el estado de salida del comando remoto o con 255 si ocurrió un error.
Si simplemente ejecutara ssh [email protected] "pkill -f asdf"
, lo más probable es que obtenga un estado de salida de 1
, correspondiente al pkill
estado para “No hay procesos coincidentes ”.
La parte desafiante es entender por qué se produce un error con SSH cuando se ejecuta
ssh [email protected] "pkill -f asdf || true"
Comandos remotos SSH
El servidor SSH inicia un shell para ejecutar comandos remotos. Aquí hay un ejemplo de esto en acción:
$ 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
Tenga en cuenta que el shell predeterminado es bash
y que el comando remoto no es un simple comando sino un pipeline, “una secuencia de uno o más comandos separados por el operador de control |
”.
El shell Bash es lo suficientemente inteligente como para darse cuenta de que si el comando que se le pasa mediante -c
La opción es un comando simple, puede optimizarse sin bifurcar un nuevo proceso, es decir, directamente exec
s el comando simple en lugar de pasar por el paso adicional de fork
ing antes de que exec
s. Aquí hay un ejemplo de lo que sucede cuando ejecuta un comando remoto simple (ps -elf
en este 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: [email protected]
0 R anthony 34830 34829 0 80 0 - 40340 - 11:51 ? 00:00:00 ps -elf
Me he encontrado con este comportamiento antes, pero no pude encontrar una referencia mejor que esta respuesta de AskUbuntu.
Relacionado:¿Cuál es la diferencia entre punto y coma y doble ampersand &&?comportamiento pkill
Desde pkill -f asdf || true
no es un comando simple (es una lista de comandos), la optimización anterior no puede ocurrir, por lo que cuando ejecuta ssh [email protected] "pkill -f asdf || true"
, el sshd
bifurcaciones de proceso y ejecuciones bash -c "pkill -f asdf || true"
.
Como señala la respuesta de ctx, pkill
no matará su propio proceso. Sin embargo, podrá elimine cualquier otro proceso cuya línea de comando coincida con -f
patrón. El bash -c
El comando coincide con este patrón, por lo que elimina este proceso:su propio padre (como sucede).
El servidor SSH luego ve que el proceso de shell que inició para ejecutar los comandos remotos se eliminó inesperadamente, por lo que informa un error al cliente SSH.