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

Normalmente, si pasas un comando a ssh así

ssh me@example.com 'some-command.sh' 

Obtiene una sesión no interactiva y ssh sale tan pronto como se ejecuta el comando (o el script, o lo que sea). ¿Cómo puedo obtener una sesión interactiva, y sin embargo 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 me@example.com 'screen -r 12345' 

Pero esto no está permitido, devolviendo el error "Debe estar conectado a un terminal." Que supongo significa esencialmente "debe llamar a este comando de una shell interactiva".

Como otro ejemplo, yo uso una tonelada de máquinas en el trabajo que a menudo me obligan a usar una cuenta compartida para tener derechos de hacer ciertas cosas (sí lo sé: mala idea, pero no me culpes, yo no configuré las cosas que Manera), y por lo general tienen ksh como el shell por defecto. Me gustaría iniciar sesión, cambiar a bash (o zsh) y crear mi propia cuenta .bash_profile (o .zshrc). Esto sería fácil si pudiera establecer una sesión ssh interactiva y pasar un comando a la máquina remota para ejecutar al iniciar sesión.

Tengo una solución muy kludgey (y no probado) en mente que voy a publicar, pero espero que alguien sabe 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 para abrir una sesión interactiva y luego hacerlo a mano realmente no resolver nada.

2ª ACTUALIZACIÓN: Para intentar aclarar una vez más: Estoy tratando de ejecutar comandos (arbitrarios) en el servidor (programáticamente especificado en el cliente), pero luego tener una sesión interactiva abierta que se ve afectada por cualquier cosa realizada por esos comandos programáticos.

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

 ssh -t hostname "bash --rcfile ~user/.bashrc" 

Basándose en la respuesta del perro, una solución completa se ve así:

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

Aquí utilizo -t para 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 interactivamente.

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 con -t . Solía ​​resolver este problema con expect , que es definitivamente matar a un ratón con un cañón. (:

Pruebe 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' 

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

Cree un script llamado (por ejemplo) remote-starter que toma un argumento entre comillas después de un argumento user @ host:

 remote-starter user@example.com 'some-command.sh arg1 arg2' 

Esta secuencia de comandos debe guardar primero el comando citado (sin comillas) en un archivo llamado (por ejemplo) .startup en la máquina remota, y luego ejecutar un comando ssh regular, esta vez no pasar ningún comando que se ejecute en la máquina remota. (Si ejecuta ssh user@example.com desde dentro de una secuencia de comandos, puede funcionar para ejecutar exec ssh user@example.com.)

Para que esto funcione, la máquina remota debe generar .startup desde su .bash_profile o .zshrc o lo que sea. Después de ejecutar .startup, debe eliminar .startup, por lo que el archivo no se ejecuta la próxima vez que realice un inicio de sesión regular.

Utilice ssh -X para usar cmds de termio.

También puedes encadenar tus cmds como "ssh 'source ~ / .bashrc && cd && do'"

Por qué no instalar detach en el sistema remoto y utilizar:

 ssh -t user@example.com "/home/user/bin/detach ls" 

Laggingreflex la respuesta está cerca … Yo lo cambiaría de la siguiente manera:

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

Por desgracia, no es probable que le guste la forma en que funciona, porque "gato" almacena 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 búfer:

 echo-cat "command" | ssh user@remote_host 

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