¿Cómo ejecutar un comando remoto y pasar el archivo local como entrada?

22

Es posible hacer esto:

ssh user@socket command /path/to/file/on/local/machine

Es decir, quiero ejecutar un comando remoto usando un archivo local en un solo paso, sin usar primero scppara copiar el archivo.

jsj
fuente
Es posible si la computadora remota tiene un montaje en red de un directorio principal del archivo de la máquina local o si redirige el archivo al comando ssh
h3rrmiller

Respuestas:

23

Te perdiste solo un símbolo =)

ssh user@socket command < /path/to/file/on/local/machine
prisa
fuente
¡Por supuesto! Me pregunto por qué no consideré la redirección de entrada sobre ssh.
jsj
¿Qué pasa si el comando remoto solo puede tomar un argumento de archivo y no leerlo desde stdin?
iruvar
@ChandraRavoori en ese caso, debes copiarlo scpantes.
Rush
44
@ChandraRavoori Puedes intentar darle el argumento del archivo /dev/stdino -. Puede o no funcionar ( /dev/stdines un archivo, pero buscarlo fallará)
derobert
1
@derobert and rush, jugó un poco con él y descubrió una forma hacky de hacerlo usando la sustitución de procesos en bash. Esto todavía está sujeto a la limitación de búsqueda y puede ser difícil de manejar con todas las citas adicionales que se necesitarán. El siguiente ejemplo. cat test.file | ssh user @ machine 'bash -c "wc -l <(cat -)"'
iruvar
4

Una forma que funciona independientemente del comando es hacer que el archivo esté disponible en la máquina remota a través de un sistema de archivos remoto. Como tienes una conexión SSH:

  1. Establecer un túnel SSH inverso . Ver también SSH copiar fácilmente el archivo al sistema local
  2. Monte un árbol de directorios de su máquina que contenga el archivo para compartir en la máquina remota con SSHFS . ( Ejemplo )
Gilles 'SO- deja de ser malvado'
fuente
De todos modos, esta forma requiere movimientos adicionales antes de la ejecución del comando.
prisa el
@Gilles: Creo que el título original fue engañoso, y entendiste su pregunta basada en el título engañoso. Por lo que puedo decir, pensó, en realidad no quería actuar en el archivo local, sino simplemente pasarlo como entrada. (¡Pero su respuesta es asombrosa, si la entiendo correctamente! Tal vez debería hacer la pregunta que respondió, solo para darle un lugar donde colocar la respuesta donde obtendrá el crédito adecuado por ella). He editado el título de las preguntas para que sea coherente con el cuerpo y con la respuesta elegida.
iconoclasta
@iconoclast No recuerdo mi estado mental cuando escribí esto, pero sigo esta respuesta. Requiere algo de configuración, pero tiene la ventaja de generalizar más allá del requisito inmediato a otros casos en los que no es suficiente copiar la entrada. También habría mencionado la redirección si alguien más no lo hubiera hecho. La pregunta más general se ha hecho muchas veces en formas ligeramente diferentes.
Gilles 'SO- deja de ser malvado'
Bien, debo haber entendido mal tu respuesta. No lo intenté, pero deduje que dado que estabas estableciendo un túnel inverso (¿de remoto a host local?), Estabas permitiendo que el archivo local fuera modificado por la máquina remota. No es ese el caso?
iconoclasta
@iconoclast Sí, esto permite que la máquina remota modifique el archivo local (además de permitirle leerlo, que es lo que requiere la pregunta).
Gilles 'SO- deja de ser malvado'
1
# What if remote command can only take a file argument and not read from stdin? (1_CR)
ssh user@socket command < /path/to/file/on/local/machine
...
cat test.file | ssh user@machine 'bash -c "wc -l <(cat -)"'  # 1_CR

Como alternativa a la bashsustitución de procesos <(cat -)o < <(xargs -0 -n 1000 cat)(ver más abajo), puede usar xargsy catcanalizar el contenido de los archivos especificados wc -l(que es más portátil).

# Assuming that test.file contains file paths each delimited by an ASCII NUL character \0
# and that we are to count all those lines in all those files (provided by test.file).

#find . -type f -print0 > test.file
# test with repeated line count of ~/.bash_history file
for n in {1..1000}; do printf '%s\000' "${HOME}/.bash_history"; done > test.file

# xargs & cat
ssh localhost 'export LC_ALL=C; xargs -0 -n 1000 cat | wc -l' <test.file

# Bash process substitution
cat test.file | ssh localhost 'bash -c "export LC_ALL=C; wc -l < <(xargs -0 -n 1000 cat)"'
franco
fuente