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.txt
y file2.txt
se usan para cosas completamente diferentes dentro del programa, por lo que no puedo usarlas cat
juntas. Sin embargo, en mi caso, los archivos file1.txt
y file2.txt
que 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.txt
tambié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 cat
y sed
juntos, 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í cat
hay 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 EOT
con 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 tmpfs
que 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 program
para tomar un archivo tar como entrada única y descomprimir su contenido en la memoria. Por ejemplo, si program
se trata de un script de Python, utilizar el módulo incorporado tarfile
fá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 ( $serv
es 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 ssh
y tiene acceso wget
en la máquina remota y en busybox
la 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 cat
como 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 netcat
admite las opciones -d
y -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.