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 simplemente catjuntarlas. Sin embargo, en mi caso, el file1.txty file2.txtque quiero pasar al programa solo existen 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 stdin:
cat file1.txt | ssh host.name /path/to/program -a /dev/stdin -b file2.txt
pero, dado que no se me permite almacenar archivos en el host, también necesito una forma de obtenerlos file2.txtallí. Estoy pensando que podría ser posible mediante el abuso de las variables de entorno 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?
fuente

catysedno son la solución aquí.Respuestas:
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í:
Aquí
cathay un comando de muestra que toma nombres de archivos como argumentos. Podría ser en su lugar:Reemplace cada uno
EOTcon algo que no ocurra en cada uno de los archivos, respectivamente.fuente
dash(el/bin/shen debian, ubuntu, etc.),busybox shel/bin/shde FreeBSD yyashno use archivos temporales para documentos aquí. De hecho, lo he probado con un chroot de solo lectura. Por supuesto, los/dev/fd/archivos tienen que estar disponibles, solo en un sistema de stock de FreeBSD/dev/fd/0-2, por lofdescfsque deben montarse/dev/fd.U+001Ces "Information Separator Four" (separador de archivos, FS) y es ideal para este caso, aunque los archivos binarios pueden utilizarlo de manera coincidente. Por lo tanto, sugeriríaEOT="$(printf $'\x1c')"en shells avanzados o de lo contrarioEOT="$(awk 'BEGIN{printf"%c",28}')"para la compatibilidad. Deberá citarlo cuando lo coloque en su lugar, comoecho "$EOT$EOT$EOT"(triplicado para reducir las probabilidades de que coincida con un archivo binario).ttycomando? A menos que me falte algo, ¿qué supongo que es posible?Tal vez no sea exactamente lo que quieres ... Pero tal vez considere enviar un tarball a través de la tubería abierta por ssh?
Dijiste eso:
Es posible que no tenga un directorio personal de escritura u otra ubicación conveniente para almacenar archivos a largo plazo, pero diría que es poco probable que no tenga una ubicación de escritura, incluso si hay un temporal
tmpfsque estará disponible solo para su conexión particularMuchos programas (e incluso rutinas de libc) requieren una escritura
/tmp, por lo que es muy probable que haya uno disponible para usted.Luego, puede usar un script que descomprima el tarball en un directorio temporal, ejecute su programa y limpie a través de la conexión ssh.
Algo como:
Esto podría necesitar un cuidado especial con las rutas de archivo y hay algunos casos de esquina para considerar (probar para ellos), pero el enfoque general debería funcionar.
Si no hay un directorio de escritura disponible, un posible enfoque sería modificar
programpara tomar un tarball como entrada única y descomprimir su contenido en la memoria. Por ejemplo, si seprogramtrata de un script de Python, el uso deltarfilemódulo incorporado fácilmente lograría algo así.fuente
/tmp/y usarlo directamente.Si puede configurar un escucha TCP (puede ser un puerto más alto), entonces podría usar una segunda sesión SSH para establecer la segunda fuente de entrada
nc.Ejemplo:
Hay este script en el servidor (
~/script.bash):Y existen estos dos archivos localmente:
Ahora primero inicie la segunda fuente (
$serves el servidor):Y ejecute el comando apropiado:
fuente
Se estableció en un comentario que
/tmpse puede escribir, así que simplemente copie previamente uno de los archivos:Esto también limpia el archivo copiado después de una ejecución exitosa (cambie
&&a a;si desea eliminarlo independientemente del éxito, pero luego tenga en cuenta que perderá el valor de salida).Si eso no es aceptable, propondría retoques
/path/to/programo un contenedor que pueda separar los dos archivos de una sola secuencia de entrada como:Esto utiliza el separador de información ASCII cuatro (separador de archivos, FS) y lo ha triplicado para minimizar la posibilidad de que un archivo binario coincida con esa cadena. Su
tweaked_programentonces dividir la entrada dado el separador y luego operar en los dos archivos guardados como variables.Por supuesto, si usa un lenguaje que tiene bibliotecas para manejar tarballs, un enfoque más seguro y limpio sería simplemente canalizar
tardicho código desshesta manera:Y
tweaked_programdescomprimiría y abriría el archivo, guardaría cada archivo en una variable diferente y luego ejecutaría laprogramlógica del original en las variables.fuente
Si se le permite reenviar puertos
sshy tiene acceso awgetla máquina remota y abusyboxla máquina local, puede hacer algo como:(utilizando
catcomo programa de ejemplo que toma dos argumentos de archivo).Solo la capacidad de reenviar puertos
-Res esencial; en lugar de hacer http, puede usar otros métodos, por ejemplo. si sunetcatadmite las opciones-dy-N:Puede haber formas de reemplazar el
<(...)proceso si el shell de inicio de sesión en la máquina remota no es similar a ksh o bash.En general, esto no es demasiado bueno: un mejor conocimiento sobre el sistema / shells / config / permisos (que no ha proporcionado) podría permitir soluciones más inteligentes.
fuente
ACTUALIZACIÓN: Esto realmente no funciona, ssh tiene una idea muy clara de lo que significa stdin y stdout / stderr y realmente no permite que usurpando stderr lea de él. Eliminaré esta respuesta en unos días ya que no funciona. Gracias por la muy interesante discusión !!!
Desafortunadamente, no hay una excelente manera de hacer esto directamente, ya que el
sshcliente solo pasará los tres descriptores de archivo (stdin,stdoutystderr) en el servidor y que no tiene disposiciones para pasar descriptores de archivos adicionales (que sería útil para este caso en particular .)(También tenga en cuenta que el protocolo SSH tiene disposiciones para pasar descriptores de archivo adicionales, solo que el
sshcliente no implementa una forma de usar esa característica. Teóricamente, extender el cliente con un parche sería suficiente para exponer esta característica).Una forma hacky de lograr lo que está buscando es usar el descriptor de archivo 2 (el
stderrdescriptor de archivo) para pasar el segundo archivo. Algo como:Esto debería funcionar, podría causar un problema si
programintenta escribir en stderr. Puede evitar eso volviendo a hacer malabarismos con los descriptores de archivos en el extremo remoto antes de ejecutar el programa. Puede pasarfile2.txtal descriptor de archivo 3 y volver a abrir stderr para duplicar stdout:fuente
3<&2es un operador de shell Bourne, y sshd ejecuta el shell de inicio de sesión del usuario para interpretar el comando enviado por el cliente)SSH_MSG_CHANNEL_EXTENDED_DATAmensajes con el tipo establecido enSSH_EXTENDED_DATA_STDERR. Puedes leer todo aquí