Pasar varios archivos a través de stdin (a través de ssh)

Pasar varios archivos a través de stdin (a través de ssh)

Tengo un programa en un host remoto, cuya ejecución necesito automatizar. El comando ejecutar ese programa, en la misma máquina, se parece a esto:

/path/to/program -a file1.txt -b file2.txt

En este caso, file1.txty file2.txtse usan para cosas completamente diferentes dentro del programa, por lo que no puedo usarlas catjuntas. Sin embargo, en mi caso, los archivos file1.txty file2.txtque quiero pasar al programa existen solo en mi dispositivo, no en el host donde necesito ejecutar el programa. Sé que puedo alimentar al menos un archivo a través de SSH pasándolo por stdin:

cat file1.txt | ssh host.name /path/to/program -a /dev/stdin -b file2.txt

pero, como no tengo permiso para almacenar archivos en el host, file2.txttambién necesito una forma de llevarlos allí. Estoy pensando que podría ser posible mediante el abuso de las variables ambientales y el uso creativo de caty sedjuntos, pero no conozco las herramientas lo suficientemente bien como para entender cómo las usaría para lograr esto. ¿Es factible y cómo?

Respuesta1

Si los archivos proporcionados como argumentos para su programa son archivos de texto y puede controlar su contenido (conoce una línea que no aparece dentro de ellos), puede usar varios documentos aquí:

{
    echo "cat /dev/fd/3 3<<'EOT' /dev/fd/4 4<<'EOT' /dev/fd/5 5<<'EOT'"
    cat file1
    echo EOT
    cat file2
    echo EOT
    cat file3
    echo EOT
} | ssh user@host sh

Aquí cathay un comando de muestra que toma nombres de archivos como argumentos. Podría ser en su lugar:

echo "/path/to/prog -a /dev/fd/3 3<<'EOT' -b /dev/fd/4 4<<'EOT'

Reemplace cada uno EOTcon algo que no ocurra en cada uno de los archivos, respectivamente.

Respuesta2

Quizás no sea exactamente lo que quieres... ¿Pero tal vez consideres enviar un tarball a través de la tubería abierta por ssh?

Dijiste eso:

No tengo permiso para almacenar archivos en el host.

Es posible que no tenga un directorio de inicio en el que se pueda escribir u otra ubicación conveniente para almacenar archivos a largo plazo, pero yo diría que es poco probable que no tenga ninguna ubicación en la que se pueda escribir, incluso si es una ubicación temporal tmpfsque estará disponible solo para su conexión particular.

Muchos programas (e incluso rutinas libc) requieren un permiso de escritura /tmp, por lo que es muy probable que haya uno disponible para usted.

Luego, podría usar un script que descomprimirá el archivo tar en un directorio temporal, ejecutará su programa y lo limpiará a través de la conexión ssh.

Algo como:

$ tar cf - file1.txt file2.txt |
  ssh host.name '
      set -e
      tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX)
      cleanup () { rm -rf "$tmpdir"; }
      trap cleanup EXIT
      cd "$tmpdir"
      tar xf -
      /path/to/program -a file1.txt -b file2.txt
  '

Es posible que esto requiera un poco de cuidado adicional con las rutas de los archivos y hay algunos casos extremos a considerar (probarlos), pero el enfoque general debería funcionar.

Si no hay ningún directorio grabable disponible, un posible enfoque sería modificarlo programpara tomar un archivo tar como entrada única y descomprimir su contenido en la memoria. Por ejemplo, si programse trata de un script de Python, utilizar el módulo incorporado tarfilefácilmente lograría algo así.

Respuesta3

Si puede configurar un escucha TCP (puede ser un puerto superior), entonces podría usar una segunda sesión SSH para establecer la segunda fuente de entrada con nc.

Ejemplo:

Hay este script en el servidor ( ~/script.bash):

#!/usr/bin/env bash
cat "$1" | tr a 1
nc localhost "$2" | tr '[:lower:]' '[:upper:]'

Y existen estos dos archivos localmente:

$ cat a 
aaa
aaa
aaa
$ cat b
bbb
bbb
bbb

Ahora primero inicie la segunda fuente ( $serves el servidor):

ssh "$serv" nc -l -p 2222 -q1 <b &

Y ejecute el comando adecuado:

$ ssh "$serv" ./script.bash - 2222 <a
111
111
111
BBB
BBB
BBB
[1]+  Done                    ssh "$serv" nc -l -p 2222 -q1 < b

Respuesta4

Si se le permite reenviar puertos sshy tiene acceso wgeten la máquina remota y en busyboxla máquina local, puede hacer algo como:

mkdir /tmp/test; cd /tmp/test
echo 1st_file > 1st_file
echo 2nd_file > 2nd_file

busybox httpd -f -p 127.0.0.1:11080 &
ssh USER@HOST -R 10080:127.0.0.1:11080 '
        cat <(wget -q -O- http://localhost:10080/1st_file) \
            <(wget -q -O- http://localhost:10080/2nd_file)
'
kill $!

(usando catcomo ejemplo un programa que toma dos argumentos de archivo).

Sólo es esencial la capacidad de reenviar puertos a través de -R: en lugar de hacer http, puede utilizar otros métodos, por ejemplo. Si netcatadmite las opciones -dy -N:

nc -Nl localhost 11001 < 1st_file &
nc -Nl localhost 11002 < 2nd_file &
ssh USER@HOST -R 10001:localhost:11001 -R 10002:localhost:11002 '
        cat <(nc -d localhost 10001) <(nc -d localhost 10002)

Puede haber formas de reemplazar las <(...)sustituciones de procesos si el shell de inicio de sesión en la máquina remota no es similar a ksh o bash.

Considerándolo todo, esto no es demasiado bueno: un mejor conocimiento sobre el sistema/shells/config/permissions exactos (que no ha proporcionado) podría permitir soluciones más inteligentes.

información relacionada