J'ai un script qui se connecte à un serveur distant et vérifie si un paquet est installé:
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
Cet exemple pourrait être simplifié. Voici myscript2.sh
qui a le même problème:
read -p "Package is not installed. Do you want to install it (y/n)?" choise
Mon problème est que bash ne peut pas lire mes réponses de manière interactive.
Existe-t-il un moyen d'exécuter un script local à distance sans perdre la capacité d'inviter l'utilisateur?
Réponses:
Essayez quelque chose comme ceci:
Le
-t
force une allocation tty,$(<your_script)
lit le fichier entier et dans ce cas passe le contenu en un seul argumentssh
, qui sera exécuté par le shell de l'utilisateur distant.Si le script a besoin de paramètres, passez-les après le script:
Fonctionne pour moi, je ne sais pas si c'est universel cependant.
la source
your script
, tout en conservant les avantages de la syntaxe que vous avez utilisée dans votre réponse? Utiliserssh -t yourserver "$(<your_script --some_arg)"
uniquement des résultatsbash: --some_arg: command not found
.ssh ... $(<script) script_arg1 script_arg2 ...
Votre problème est que
ssh
démarre un shell de connexion non interactif sur la machine distante. La solution évidente serait de copier le script sur le serveur distant et de l'exécuter à partir de là:Si la copie n'est pas une option pour une raison quelconque, je modifierais le script pour d'abord me connecter et vérifier s'il
$1
est installé, puis reconnecter et installer si nécessaire:la source
$OUT=$(ssh root@server rpm -qa | grep "$1");
sorties puis la 2ème connexion prendra autant de temps que la première. Ai-je tort?ssh -M foo.example.com sleep 99999999
ou enssh -M foo.example.com read <somefifo
tant que maître et tuez-le explicitement (aveckill
ouecho done >somefifo
) lorsque vous avez terminé.Voici une bonne explication .
J'ai donc adapté le script
et cela n'a pas fonctionné.
j'ai donc déplacé le script vers la télécommande pour éviter la redirection locale sur ssh. (Mes commandes sont dans un fichier nommé f )
Cela a fonctionné. Voici la sortie:
Comme @terdon a mentionné que l'intention d'origine était d'exécuter des scripts locaux à distance, la copie à distance peut être automatisée, ce n'est qu'un exemple sur une seule ligne.
la source
bash -s < script.sh
comme l'OP l'a fait? Pourriez-vous inclure l'explication dans votre réponse au lieu de vous y relier?J'ai cherché des solutions à ce problème à plusieurs reprises dans le passé, mais je n'ai jamais trouvé de solution pleinement satisfaisante. Tuyauter dans ssh perd votre interactivité. Deux connexions (scp / ssh) sont plus lentes et votre fichier temporaire peut être laissé traîner. Et tout le script sur la ligne de commande finit souvent par s'échapper de l'enfer.
Récemment, j'ai rencontré que la taille du tampon de ligne de commande est généralement assez grande ('getconf ARG_MAX> 2 Mo où j'ai regardé). Et cela m'a fait réfléchir sur la façon dont je pourrais utiliser cela et atténuer le problème d'évasion.
Le résultat est:
ou en utilisant un document et un chat ici:
J'ai développé cette idée pour produire un exemple de script BASH pleinement fonctionnel
sshx
qui peut exécuter des scripts arbitraires (pas seulement BASH), où les arguments peuvent également être des fichiers d'entrée locaux, sur ssh. Voyez ici .la source
"
caractères qui devront être échappés. Et il est également limité aux scripts BASH. Ma solution est un cas général pour tout contenu de script de n'importe quel langage de script installé. De plus, dans sshx, je démontre davantage les fichiers d'arguments de sérialisation, ce qui est assez astucieux.echo "$(cat my_script | base64)" | base64 --decode
apparence est équivalente à (-ish)cat my_script | base64 | base64 --decode
, ce qui ressemble beaucoup à 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
. Ici (a) fonctionne efficacement:bash -c $'#!/bin/bash\necho "ARG1=$1, USER=$USER, END" foo'
ou quelque chose de similaire. Notez que l'argument ne fonctionne pas. Où (b) est en cours d' exécution:bash <(echo IyEvY...5EIgo= | base64 --decode) foo
. (2) J'ai utilisé base64 comme codage de transport.