He visto las preguntas y respuestas sobre la necesidad de escapar doblemente de los argumentos a los comandos ssh remotos. Mi pregunta es: ¿exactamente dónde y cuándo se realiza el segundo análisis?
Si ejecuto lo siguiente:
$ ssh otherhost pstree -a -p
Veo lo siguiente en la salida:
|-sshd,3736
| `-sshd,1102
| `-sshd,1109
| `-pstree,1112 -a -p
El proceso principal para el comando remoto ( pstree
) es sshd
que no parece haber ningún shell allí que esté analizando los argumentos de la línea de comando al comando remoto, por lo que no parece que sea necesaria una doble cita o escape ( pero definitivamente lo es). Si, en cambio, ssh allí primero y obtengo un shell de inicio de sesión, y luego ejecuto pstree -a -p
, veo lo siguiente en la salida:
├─sshd,3736
│ └─sshd,3733
│ └─sshd,3735
│ └─bash,3737
│ └─pstree,4130 -a -p
Entonces, claramente hay un bash
shell allí que analizaría la línea de comandos en ese caso. Pero en el caso en que utilizo un comando remoto directamente, no parece haber un shell, entonces, ¿por qué es necesaria una doble cita?
Creo que lo descubrí:
Los argumentos a
pstree
son: mostrar argumentos de la línea de comandos, mostrar pids y mostrar solo los procesos principales del pid dado. The'$$'
es una variable de shell especial que bash reemplazará con su propio pid cuando bash evalúa los argumentos de la línea de comandos. Se cita una vez para evitar que sea interpretado por mi shell local. Pero no se cita ni se escapa doblemente para permitir que el shell remoto lo interprete.Como podemos ver, se reemplaza por,
12001
así que ese es el pid del shell. También podemos ver en la salida:pstree,12001
que el proceso con un pid de 12001 es pstree en sí. Entonces, ¿pstree
es el caparazón?Lo que sé que está sucediendo allí es que
bash
se invoca y analiza los argumentos de la línea de comandos, pero luego se invocaexec
para reemplazarse con el comando que se ejecuta.Parece que solo hace esto en el caso de un solo comando remoto:
En este caso, solicito que se ejecuten dos comandos:
pstree
seguido porecho
. Y podemos ver aquí quebash
, de hecho, aparece en el árbol de procesos como padre depstree
.fuente
Apoyando lo que han dicho las otras respuestas, busqué el código que invoca comandos en el control remoto, https://github.com/openssh/openssh-portable/blob/4f29309c4cb19bcb1774931db84cacc414f17d29/session.c#L1660 ...
... que, como puede ver, invoca incondicionalmente
shell
con el primer argumento-c
y el segundo argumentocommand
. Anteriormente, lashell
variable se configuraba en el shell de inicio de sesión del usuario como se registró en/etc/passwd
.command
es un argumento para esta función y, en última instancia, se establece en una cadena que se lee al pie de la letra (versession_exec_req
en el mismo archivo ). Entonces, el servidor no interpreta el comando en absoluto, pero siempre se invoca un shell en el control remoto.Sin embargo, la parte correspondiente de la especificación del protocolo SSH no no parece requerir este comportamiento; solo dice
Esto probablemente se deba a que no todos los sistemas operativos tienen el concepto de un shell de línea de comandos. Por ejemplo, no habría sido una locura para un servidor ssh clásico de MacOS alimentar cadenas de comandos "exec" al intérprete de AppleScript .
fuente