Con ssh, ¿cómo puede ejecutar un comando en la máquina remota sin salir?

29

Normalmente, si le pasa un comando a ssh así

ssh [email protected] 'some-command.sh'

Obtiene una sesión no interactiva y ssh se cierra tan pronto como se ejecuta el comando (o script, o lo que sea). ¿Cómo puedo obtener una sesión interactiva y ejecutar un comando que he especificado desde mi máquina local? Por ejemplo, me gustaría poder abrir la pantalla y reiniciar una sesión de pantalla específica:

ssh [email protected] 'screen -r 12345'

pero esto no está permitido, devuelve el error "Debe estar conectado a un terminal". que supongo significa esencialmente "debe llamar a este comando desde un shell interactivo".

Como otro ejemplo, uso un montón de máquinas en el trabajo que a menudo requieren que use una cuenta compartida para tener derecho a hacer ciertas cosas (sí, lo sé: mala idea, pero no me culpes, no configuré cosas que manera), y generalmente tienen ksh como shell predeterminado. Me gustaría iniciar sesión, cambiar a bash (o zsh) y obtener el .bash_profile (o .zshrc) de mi propia cuenta. Esto sería fácil si pudiera establecer una sesión ssh interactiva y pasar un comando a la máquina remota para que se ejecute al iniciar sesión.

Tengo en mente una solución muy burlona (y no probada) que publicaré, pero espero que alguien conozca una mejor manera.

ACTUALIZACIÓN: para aquellos que no se dieron cuenta de esto, no estoy planeando hacer todo esto a mano, por lo que decirme que abra una sesión interactiva y luego hacerlo a mano en realidad no resuelve nada.

2ª ACTUALIZACIÓN: para intentar aclarar una vez más: estoy tratando de ejecutar comandos (arbitrarios) en el servidor (especificados programáticamente en el cliente) pero luego tengo una sesión interactiva abierta que se ve afectada por cualquier cosa hecha por esos comandos programáticos.

iconoclasta
fuente
echo "command" | ssh user@remote_host
laggingreflex
2
¿Te perdiste la parte "sin salir" de la pregunta? Estoy bastante seguro de que esto saldrá una vez que finalice el comando.
iconoclasta

Respuestas:

26

Puede probar el siguiente comando para iniciar bash y obtener su propio perfil cuando ssh:

ssh  -t hostname "bash --rcfile ~user/.bashrc"
dogbane
fuente
44
+1. El -tinterruptor también soluciona el problema del interrogador screen.
Parches
3
¿Se puede usar esto con comandos arbitrarios, sin cerrar la conexión? Si lo intento ssh -t www.dev "echo 'hi there'", la conexión se cierra inmediatamente después de ejecutar el comando.
iconoclasta
11

Sobre la base de la respuesta de Dogbane, una solución completa se ve así:

ssh -t user@server 'cd /a/great/place; bash'

Aquí uso -tpara forzar la asignación de un pseudo-terminal, que se requiere para un shell interactivo. Luego ejecuto dos comandos en el servidor: primero lo que quería hacer antes de abrir el shell interactivo (en mi caso, cambiar el directorio a una carpeta específica), y luego el shell interactivo en sí. bash ve que tiene un pseudo-terminal y responde de forma interactiva.

Las comillas simples aseguran que todo se pasa al servidor remoto como el comando que debe ejecutar su shell predeterminado.

Gracias de nuevo a dogbane por proporcionar la pista necesaria -t. Solía ​​resolver este problema con expect, que definitivamente está matando a un ratón con un cañón. (:

usuario1179239
fuente
2

Prueba esta solución.

echo "command" | ssh user@remote_host

El inicio de sesión es interactivo y su comando se pasa como si lo hubiera escrito en la línea de comandos interactiva. La sesión finaliza como si hubiera escrito

ssh user@remote_host 'command'
usuario210540
fuente
3
Si la sesión finaliza después de completar el comando, esto no responde la pregunta. Todo el punto del comando debe dejarse con una sesión interactiva después de que se ejecute el comando, no solo para enviar comandos a los servidores ssh.
iconoclasta
Esto es al menos bueno para simular una interacción para que el comando se ejecute, sin usar -to su propio archivo bash. +1
laggingreflex
0

Use ssh -X para usar cmd de termIO.

Además, puede encadenar sus cmds como "ssh 'source ~ / .bashrc && cd && do'"

ethrbunny
fuente
pero después de terminar toda la cadena, no me queda una sesión interactiva, ¿verdad? Todavía se cierra, ¿verdad?
iconoclasta el
¿Y le gustaría dar más detalles sobre la solución termIO?
iconoclasta el
0

por qué no instalar detach en el sistema remoto y usar:

ssh -t [email protected] "/home/user/bin/detach ls"
Dan D.
fuente
¿Esto ejecutará 'ls' y LUEGO me dejará con una sesión interactiva? ¿Qué pasa si, en lugar de 'ls', ejecuto 'source .somefile' para obtener algunos alias y funciones? ¿Estarán disponibles en mi sesión interactiva o se ejecutarán en una sesión diferente?
iconoclasta
No, debido a detach, lsno mantener la sesión abierta y se desconectará sin imprimir la salida ls, pero todavía va a correr.
Dan D.
Estoy tratando de ejecutar comandos (arbitrarios) en el servidor (especificados programáticamente en el cliente) pero luego tengo una sesión interactiva abierta que se ve afectada por cualquier cosa hecha por esos comandos programáticos. Entonces, si te entiendo correctamente, esto no me ayuda.
iconoclasta
0

La respuesta de laggingreflex está cerca ... Lo cambiaría de la siguiente manera:

echo "command\n$(cat -)" | ssh user@remote_host

Desafortunadamente, no es probable que te guste la forma en que funciona, porque "cat" amortigua las líneas que escribe en stdout ... Si creamos un script llamado "echo-cat" que se parece a esto:

{
  echo "${@}"
 #cat buffers & won't flush to stdout immediately
 #cat -
  IFS='\n'
  while read line
  do
        echo "${line}"
  done
}

obtendremos el mismo resultado sin el almacenamiento en búfer:

echo-cat "command" | ssh user@remote_host

Eso probablemente te acercará mucho más a tu objetivo ...

Cuenta
fuente
0

Esto no es probado, pero creo que debería funcionar.

Cree un script llamado (p. Ej.) Arranque remoto que tome un argumento entre comillas después de un argumento de usuario @ host:

remote-starter [email protected] 'some-command.sh arg1 arg2'

Este script primero debe guardar el comando entre comillas (sin comillas) en el archivo llamado (por ejemplo) .onetimeen la máquina remota, y luego ejecutar un comando ssh normal, esta vez sin pasar ningún comando para que se ejecute en la máquina remota. (Si ejecuta ssh [email protected] desde un script, puede funcionar ejecutar exe ssh [email protected]).

Para que esto funcione, la máquina remota debe obtener .onetimede su .bash_profile o .zshrc o lo que sea. Después de ejecutarse .onetime, debería eliminarse .onetime, por lo que el archivo no se ejecutará la próxima vez que inicie sesión regularmente.

iconoclasta
fuente