web-dev-qa-db-ja.com

Bash:インタラクティブなリモートプロンプト

リモートサーバーに接続し、パッケージがインストールされているかどうかを確認するスクリプトがあります。

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

この例は簡略化できます。ここは myscript2.sh同じ問題があります:

read -p "Package is not installed. Do you want to install it (y/n)?" choise

私の問題は、bashが私の答えをインタラクティブに読み取ることができないことです。

ユーザーにプロンプ​​トを表示する機能を失うことなくローカルスクリプトをリモートで実行する方法はありますか?

16
Anthony Ananich

このようなものを試してください:

_$ ssh -t yourserver "$(<your_script)"
_

_-t_はttyの割り当てを強制し、$(<your_script)はファイル全体を読み取り、この場合、コンテンツを1つの引数としてsshに渡します。これは、リモートユーザーのシェルによって実行されます。

スクリプトにパラメーターが必要な場合は、スクリプトの後にパラメーターを渡します。

_$ ssh -t yourserver "$(<your_script)" arg1 arg2 ...
_

それは普遍的かどうかはわかりませんが、私にとってはうまくいきます。

22
Mat

あなたの問題は、sshがリモートマシンで非対話型のログインシェルを起動することです。明らかに簡単な解決策は、スクリプトをリモートサーバーにコピーして、そこから実行することです。

scp myscript.sh root@server:/tmp && ssh root@server /tmp/myscript.sh

何らかの理由でコピーできない場合は、スクリプトを変更して最初に接続し、$1がインストールされているかどうかを確認してから、必要に応じて再接続してインストールします。

OUT=$(ssh root@server rpm -qa | grep "$1");
if [ "$OUT" != "" ] ; then
    echo "$1 already installed"
else
   read -p "Package $1 is not installed. Do you want to install it (y/n)?" choice
   if [ "$choice" -eq "y" ]; then
       ssh root@server yum install "$1"
   fi
fi
3
terdon

これが良い 説明 です。

だから私はスクリプトを

hostname
echo -n "Make your choice :"
read choice
echo "You typed " ${choice}
echo done

そして、これはうまくいきませんでした。

スクリプトをリモートに移動して、sshでのローカルリダイレクトを回避しました。 (私のコマンドはfという名前のファイルにあります)

cat f | ssh [email protected] 'cat >remf'
ssh user@remotehost bash remf

これはうまくいきました。これが出力です:

christian@clafujiu:~/tmp$ ssh localhost bash tmp/f
christian@localhost's password: 
Linux clafujiu 2.6.32-52-generic #114-Ubuntu SMP Wed Sep 11 19:00:15 UTC 2013 i686 GNU/Linux
Sun Nov 10 14:58:56 GMT 2013
Make your choice :abc
You typed  abc
done

@terdonが元々の意図はローカルスクリプトをリモートで実行することであると述べたように、リモートコピーは自動化できます。これはすべて1行での1つの例にすぎません。

REMID=`cat f |ssh user@remotehost 'cat > remf_$$; echo $$'` ;ssh [email protected] "bash remf_${REMID} ; rm -v remf_${REMID}"
0
X Tian

私は過去に何度かこの問題の解決策を探しましたが、完全に満足のいくものを見つけることはできませんでした。 sshに接続すると、対話性が失われます。 2つの接続(scp/ssh)は遅く、一時ファイルはそのままにしておく可能性があります。そして、コマンドラインのスクリプト全体は、しばしば地獄から逃れることになります。

最近、コマンドラインバッファーのサイズが通常かなり大きいことに気付きました( 'getconf ARG_MAX> 2MB私が見たところ)。そして、これを使用して、これをどのように使用し、脱出する問題を軽減できるかについて考えました。

結果は次のとおりです。

ssh -t <Host> /bin/bash "<(echo "$(cat my_script | base64 | tr -d '\n')" | base64 --decode)" <arg1> ...

またはヒアドキュメントと猫を使用する:

ssh -t <Host> /bin/bash $'<(cat<<_ | base64 --decode\n'$(cat my_script | base64)$'\n_\n)' <arg1> ...

このアイデアを拡張して、完全に機能するBASHサンプルスクリプト sshx を作成し、引数をssh経由でローカル入力ファイルにすることもできます(BASHだけでなく)。 。 こちら を参照してください。

0
SourceSimian