Escapar de espacios en una ruta remota cuando se usa rsync a través de una conexión SSH remota

10

Cuando usa SSH para conectar rsync a un servidor remoto, ¿cómo escapa de espacios y demás en la ruta remota? Una barra invertida simple escapa del espacio para la solicitud de bash local, pero en la máquina remota, el espacio se lee como una interrupción en la ruta, marcando así el final de esa ruta.

Entonces, cuando hago, rsync -avz /path/to/source/some\ dir/ [email protected]:/path/to/dest/some\ dir/lo que sucede es que el servidor remoto está leyendo eso como justo /path/to/dest/some/y dado que no puede encontrar ese destino de forma remota, porque el destino real es "algún directorio" en lugar de solo "algunos".

Si intento el mismo comando y escapo de la barra diagonal inversa y el espacio para pasar el indicador bash local y mantener la barra diagonal inversa para el servidor remoto (tres barras diagonales en total:) /path/to/dest/some\\\ dir/, de hecho envía la barra diagonal inversa al servidor remoto, pero al servidor remoto luego interpreta el camino como en /path/to/dest/some\/lugar de /path/to/dest/some\ dir/quitar el espacio y los caracteres que siguen.

Si trato de ajustar el camino con comillas, se comporta de la misma manera, cortando efectivamente el camino en el espacio. Por lo tanto, también solo funciona para pasar el indicador de bash local.

Inicialmente, estaba usando una ruta que tenía un segmento "-" (espacio-guión-espacio), y el servidor remoto estaba devolviendo un error, rsync: on remote machine: -: unknown optionque es lo que inició todo este esfuerzo de escape del espacio en primer lugar.

Entonces, ¿qué debo hacer para que esto funcione correctamente con el servidor remoto, sin tener que eliminar los espacios u otros caracteres erróneos como guiones de la ruta remota?

purefusion
fuente
1
Pruebe con comillas simples y dobles.
jftuga
Javier también mencionó esto, y terminó funcionando, así que pegué mi segmento de código de trabajo en una respuesta a su respuesta.
purefusion
@purefusion Considere marcar la respuesta de Grégory como correcta. El problema se -ssoluciona sin la necesidad de aplicar doble escape de forma manual.
m000

Respuestas:

9

En la máquina iniciadora, rsynccrea una línea de comando que invoca el objetivo rsync en la máquina remota, luego envía esa línea de comando usando ssh .... como una sola cadena . Esa única cadena se pasa al shell para analizar, dividir en argumentos y ejecutar rsync. No tengo idea de por qué se hace eso, en lugar de empaquetar los argumentos (ya divididos, expandidos y sin comillas) en un contenedor seguro binario para el rsync remoto.

Eso significa que sus argumentos serán analizados por dos shells diferentes, cite y vuelva a cotizar en consecuencia. Por lo general, envuelvo cada argumento con comillas dobles y luego la expresión completa entre comillas simples. a veces no es suficiente, o puede ser complicado si desea que la misma expresión se use de forma local y remota.

En esos casos, generalmente establezco algunos enlaces suaves con nombres simples, sin espacios, todos ASCII, y los uso.

Javier
fuente
8
Y el ganador es ... ¡comillas simples + dobles! Tal vez esto sea diferente en cada servidor, por lo que si las otras respuestas no funcionan para algunas personas, tal vez esta sí lo haga. Aquí está el código exitoso que utilicé en el lado remoto del comando rsync:'[email protected]:"/path/to/dest/some\ dir/"'
purefusion
Ahora surge la pregunta, ¿por qué ESTO funciona (en mi servidor), pero no ninguna de las otras opciones (simplemente envolviendo la ruta entre comillas dobles o usando barras invertidas triples)? Estoy ejecutando CentOS 5 si eso importa.
purefusion
Eso no debería ser necesario. Como lo estas ejecutando ¿Lo está ejecutando usando evalo mediante una llamada a una función tal vez?
Mikel
No está utilizando comillas simples más dobles. Está utilizando comillas simples más comillas dobles más escapes de barra invertida. TRES niveles de cotización. Esto debería ser innecesario. Pregunto nuevamente: ¿Cómo lo estás ejecutando ?
Mikel
@Javier "No tengo idea de por qué se hace eso". Presumiblemente para que funcione la expansión tilde.
Mikel
2

Estabas en el camino correcto cuando dijiste:

Si intento el mismo comando y escapo de la barra diagonal inversa y el espacio para pasar el indicador bash local y mantener la barra diagonal inversa para el servidor remoto

Aquí hay una manera que me parece más fácil de hacer:

rsync -av dir\ with\ spaces/ server.tld:"dir\ with\ spaces"

y de esta manera funciona también.

rsync -av dir\ with\ spaces/ server.tld:dir\\\ with\\\ spaces

¿Puedes publicar la salida exacta y los errores que estás viendo?

¿Se puede reemplazar rsyncen ambos lados con un script de envoltura?

$ sudo su -
# cd /usr/bin
# mv rsync rsync.real
# cat <<'EOF' >rsync
#!/bin/bash
logfile=/home/yourname/rsync.log
date >> "$logfile"
i=1
for arg in "$@"; do
    echo "arg $i: $arg" >> "$logfile"
    i=$((i+1))
done

rsync.real "$@"
EOF
# chmod +x rsync

Luego ejecute su rsync nuevamente, y debería probar que esta forma de escapar funciona, por ejemplo

Lado del cliente:

Sun Feb 13 13:48:12 EST 2011
1: -av
2: dir with spaces/
3: server:dir\ with\ spaces

Lado del servidor:

Sun Feb 13 13:48:13 EST 2011
1: --server
2: -vlogDtpre.iL
3: .
4: dir with spaces

En el ejemplo anterior, el hecho de que el 4to argumento en el servidor ( dir with spaces) esté todo en una línea indica que la cita funciona correctamente.

Si esto no ayuda, intente volver a ejecutar rsync -v, o rsync -vv, o rsync -vvv. Le dará información de depuración adicional.

Otras dos sugerencias tontas:

  • ¿El otro servidor es un servidor Linux y cuál es su shell predeterminado?
    • tal vez está expandiendo los nombres de archivo de manera diferente de lo que espera
  • ¿Olvidaste agregar la opción -ao -r?
    • No puedo decir sin ver tu salida
Mikel
fuente
Como se menciona en los detalles de la pregunta, probé los dos primeros métodos. Quizás simplemente no funcionan en mi servidor. Tampoco tenía ganas de perder el tiempo con scripts de envoltura. Intento mantenerme alejado de piratear / usr / bin / ... En cualquier caso, otra forma más específica de citar realmente funcionó para mí, así que tal vez sea solo mi servidor el que está actuando de esta manera. Sus sugerencias aún pueden ser viables para las personas en otros servidores, o aquellos que no ejecutan CentOS, si el sistema operativo es parte del problema después de todo.
purefusion
Entonces, ¿cómo lo citó para que funcione?
Mikel
Estás dejando de lado algunos detalles vitales. Publique el comando real que está ejecutando, en su totalidad.
Mikel
2

El punto de respuesta:

Use -s (proteja los argumentos) y encierre su ruta entre comillas:

rsync -savz user@server:"/my path with spaces/another dir/" "/my destination/"

Funciona con espacios o guiones.

Grégory Boddin
fuente
¡Gracias! Esta es una solución adecuada, en lugar de una solución alternativa.
m000
-2

Simplemente puede encerrar su camino entre comillas.

atx
fuente
1
Como puede haber visto en los detalles de la pregunta, de hecho ya lo he intentado. Sin embargo, otra respuesta sugirió el uso de una cotización específica, y eso terminó funcionando. :)
purefusion
Necesita AMBAS citas y barras invertidas.
Sridhar Sarnobat