Intenté hacer una copia de seguridad de algunos archivos a través de SSH, pero en lugar de obtener tar
los que quería, obtuve mi carpeta de inicio. Hice algunas pruebas adicionales y se reduce a esto:
ssh root@server /bin/sh -c "cd /boot && ls -l"
Que para mi sorpresa enumera los archivos en /root
no /boot
. Pero si ejecuto todo el /bin/sh
comando desde un terminal, se cd
imprime correctamente los /boot
archivos.
¿Que esta pasando aqui?
shell
ssh
cd-command
Ambroz Bizjak
fuente
fuente
ssh root@server /bin/sh -c "ls -l /boot"
?Respuestas:
ssh no le permite especificar un comando con precisión, como lo ha hecho, como una serie de argumentos para pasar a execvp en el host remoto. En su lugar, concatena todos los argumentos en una cadena y los ejecuta a través de un shell remoto. Esto se destaca como una falla de diseño importante en ssh en mi opinión ... es una herramienta de Unix que se comporta bien en la mayoría de los casos, pero cuando llega el momento de especificar un comando, elige usar una sola cadena monolítica en lugar de un argumento, como ¡Fue diseñado para MSDOS o algo así!
Como ssh pasará su comando como una sola cadena a
sh -c
, no necesita proporcionar el suyosh -c
. Cuando lo haces, el resultado escon la cita original perdida. Entonces los comandos separados por el
&&
son:El primero de ellos ejecuta un shell con el texto de comando "cd" y
$0
="boot"
. El comando "cd" se completa con éxito,$0
es irrelevante y el/bin/sh -c
indica éxito, entoncesls -l
sucede.fuente
ssh
comporte así, si no fuera así, tendría que llamarsesexec
, nossh
.ssh
es la versión segura dersh
(que se comportó igual en ese sentido) yrlogin
(rsh
llamadarlogin
cuando no se pasa una línea de comando). Es lamentable que no se implementerexec
tan bien."`printf "%q " "$@"`"
con bashprintf
para citar una cadena o cadenas con escapes de shell.Es un problema de citas. Ssh ya ejecuta el comando que le pasa en un shell. Cuando pasa múltiples parámetros, se concatenan con un espacio intermedio para construir una cadena. Entonces, el comando remoto que está ejecutando de forma remota es
/bin/sh -c cd /boot && ls -l
(sin comillas, porque las comillas en su comando fueron interpretadas por el shell local)./bin/sh -c cd /boot
carreras/bin/sh
y le dice que se ejecute el comandocd
y también para conjunto$0
a/boot
. Una vez hecho esto, sesshd
ejecuta el shell principal (el lanzado por )ls -l
.En su caso, simplemente elimine el
sh -c
que es completamente inútil a menos que su shell remoto (como se indica en/etc/passwd
otra base de datos de contraseñas) no comprenda este comando.Si necesita invocar un shell diferente, debe citar el comando remoto para protegerlo de la expansión del shell remoto invocado por
sshd
. Por ejemplo, si su shell de inicio de sesión es dash y desea ejecutar un comando bash:fuente
Creo que tiene más que ver con cómo el shell analiza las opciones. Por ejemplo, esto funciona:
Esto tiene el mismo problema que su comando:
Si habilita el
-v
cambio assh
puede ver lo que está sucediendo:1er comando:
2do comando:
Por lo general, al enviar comandos a través de
ssh
, debe prestar especial atención a las comillas y ajustar las comillas dentro de las comillas, ya que las diversas capas las eliminan. Tampoco te molestes en enviar/bin/sh
.Puede hacer algo muy útil una vez que comprenda la cita de
ssh
lo siguiente. Esto ejecutará el comando en el servidor remoto pero recopilará los resultados en un archivo local en el sistema donde ejecutó elssh
comando:o esto, donde alquila un directorio en un servidor remoto y lo crea en el sistema local:
Referencias
fuente
Por lo general, no tiene que especificar qué shell usar. Esto funciona:
Pero si su shell predeterminado es problemático, asegúrese de citar todo el comando, incluida la invocación del shell. Cualquiera de los siguientes trabajos
fuente
cd /boot && pwd
funciona en todos los shells de las familias principales (Bourne, csh, rc),/bin/sh -c "cd /boot && pwd"
no funcionaría si el shell remoto es de larc
familia donde"
no es especial.