Tengo un script que se conecta a un servidor remoto y verifico si algún paquete está instalado:
ssh root@server 'bash -s' < myscript.sh
myscript.sh:
OUT=`rpm -qa | grep ntpdate`
if [ "$OUT" != "" ] ; then
echo "ntpdate already installed"
else
yum install $1
fi
Este ejemplo podría simplificarse. Aquí está el myscript2.sh
que tiene el mismo problema:
read -p "Package is not installed. Do you want to install it (y/n)?" choise
Mi problema es que bash no puede leer mis respuestas de forma interactiva.
¿Hay alguna manera de ejecutar el script local de forma remota sin perder la capacidad de solicitar al usuario?
Respuestas:
Intenta algo como esto:
Las
-t
fuerzas de una asignación tty,$(<your_script)
lee el archivo completo y en estos casos pasa el contenido como un argumento assh
, que será ejecutado por el shell del usuario remoto.Si el script necesita parámetros, páselos después del script:
Funciona para mí, aunque no estoy seguro de si es universal.
fuente
your script
vez que conserva las ventajas de la sintaxis que usó en su respuesta? Usandossh -t yourserver "$(<your_script --some_arg)"
solo resultados enbash: --some_arg: command not found
.ssh ... $(<script) script_arg1 script_arg2 ...
Su problema es que
ssh
inicia un inicio de sesión, un shell no interactivo en la máquina remota. La solución fácil obvia sería copiar el script en el servidor remoto y ejecutarlo desde allí:Si copiar no es una opción por alguna razón, modificaría el script para conectar primero y verificar si
$1
está instalado, luego volver a conectar e instalar según sea necesario:fuente
$OUT=$(ssh root@server rpm -qa | grep "$1");
salidas y luego la segunda conexión tomará tanto tiempo como la primera. ¿Me equivoco?ssh -M foo.example.com sleep 99999999
ossh -M foo.example.com read <somefifo
como maestro y mátalo explícitamente (conkill
oecho done >somefifo
) cuando hayas terminado.Aquí hay una buena explicación .
Así que adapté el guión a
Y esto no funcionó.
así que moví el script al control remoto para evitar la redirección local en ssh. (Mis comandos están en un archivo llamado f )
Esto funcionó. Aquí está la salida:
Como @terdon mencionó que la intención original era ejecutar scripts locales de forma remota, la copia remota se puede automatizar, este es solo un ejemplo en una sola línea.
fuente
bash -s < script.sh
el OP? ¿Podría incluir la explicación en su respuesta en lugar de vincularla?He buscado soluciones a este problema varias veces en el pasado, sin embargo, nunca he encontrado una solución completamente satisfactoria. La conexión a ssh pierde tu interactividad. Dos conexiones (scp / ssh) son más lentas, y su archivo temporal podría quedar por ahí. Y todo el script en la línea de comando a menudo termina escapando del infierno.
Recientemente descubrí que el tamaño del búfer de la línea de comandos suele ser bastante grande ('getconf ARG_MAX> 2MB donde busqué). Y esto me hizo pensar en cómo podría usar esto y mitigar el problema de escape.
El resultado es:
o usando un documento aquí y cat:
He ampliado esta idea para producir un script de ejemplo BASH completamente funcional
sshx
que pueda ejecutar scripts arbitrarios (no solo BASH), donde los argumentos también pueden ser archivos de entrada locales, a través de ssh. Ver aquí .fuente
"
caracteres que se deben escapar. Y también está restringido a los scripts de BASH. Mi solución es un caso general para cualquier contenido de script de cualquier lenguaje de script instalado. Además, en sshx demuestro aún más la serialización de archivos de argumentos, lo cual es bastante ingenioso.echo "$(cat my_script | base64)" | base64 --decode
aspecto es equivalente (-ish) acat my_script | base64 | base64 --decode
, que se parece mucho a un no-op.echo "ARG1=$1, USER=$USER, END"
. a)$ ssh host "$(<my_bash)" foo
->ARG1=, USER=user, END foo
. b)$ ssh host bash "<(echo $(cat my_bash|base64) | base64 --decode)" foo
->ARG1=foo, USER=user, END
. Aquí (a) se está ejecutando efectivamente:bash -c $'#!/bin/bash\necho "ARG1=$1, USER=$USER, END" foo'
o algo similar. Tenga en cuenta que el argumento no funciona. Donde (b) se está ejecutando:bash <(echo IyEvY...5EIgo= | base64 --decode) foo
. (2) Usé base64 como la codificación de transporte.