bash スクリプトを使用して複数のコマンドをリモートで実行する

bash スクリプトを使用して複数のコマンドをリモートで実行する

SSH 経由でリモート サーバーにログインし、tmp フォルダーに移動して、rm コマンドを実行する必要があります。しかし、以下のスクリプトを実行すると、リモート サーバーに移動しますが、temp フォルダーには移動せず、rm コマンドも実行されません。

#!/bin/bash
for i in `cat list`
echo $server
echo "------------------------------------------"
ssh $server << MYCOMMANDS
cd /tmp
rm log52.log
MYCOMMANDS

答え1

コードの唯一の本当の問題は、ループに と がないためdo構文doneエラーが発生し、 をiループ変数として使用して、設定されていない可能性のある変数に接続しようとしていることですserver

それ以外にも、cat引用符で囲まれていないコマンド置換を使用しています。一般的に空白やファイル名のグロブ文字のない文字列を読み取ることが確実にわからない場合は、これは良い考えではありません (ただし、ほとんどのホスト名はこの点では適切に動作します)。

ほとんどの場合、次のように入力を 1 行ずつ読み取る方が適切です。

while IFS= read -r remote; do
    ssh -n "$remote" 'rm -f /tmp/log52.log'
done <list

ssh -nここで は、ssh標準入力ストリーム (ファイルに接続される) の読み取りを停止するために使用しますlist。 がない場合-nsshは の残りの内容を読み取りlist、ループは 1 回の反復のみを実行します。

あるいは、実際にヒアドキュメントからコマンドを読み取りたい場合は、次のようにします。

while IFS= read -r remote; do
    ssh -T "$remote" <<'END'
rm -f /tmp/log52.log
END
done <list

ここでは、ssh -T擬似端末の割り当てを明示的に無効にするために を使用していますが、ユーザーとの対話を必要とすることは何もしていないので、これは必要ありません。 はssh標準入力ストリームにデータがあることに気づき、対話的な操作を行うためのリモート システムに機能する端末がないことを警告するため、これを行います。 の標準入力ストリームをヒアドキュメントから再割り当てしているので、ここ-nでは は必要ありません。sshssh

しかし、ループは単一のコマンドに置き換えることができます

xargs -I {} ssh {} 'rm -f /tmp/log52.log' <list

...xargsユーティリティは次のように読み取りますファイルからlist、コマンド{}内の をファイルから読み取った行に置き換え、リモート システムにアクセスして特定のファイルを削除するアクションを実行します。削除するファイルがない場合にエラーが発生しないようにするために をssh使用しています。rm -f

の実装によってxargsは、たとえばユーティリティの並列実行が可能になります(一度に-P 4最大 4 つのコマンドを同時に実行できます)。ssh

答え2

#! /bin/bash
for i in `cat list`
do
    echo $i
    echo "-------------------------"
    ssh $i "rm /tmp/log52.log"
done

1 つのファイルだけを削除する必要がある場合は、それを 1 行で指定するだけで済みます。また、-fに追加すると便利な場合がありますrm

答え3

このように ssh セッションの stdin を単純にリダイレクトすることはできません。次のようなエラー メッセージが表示されるはずです。

stdin は端末ではないため、擬似端末は割り当てられません。

擬似ttyを強制的に割り当てるには、sshにオプション -tt を使用する必要があります。以下を試してください:

#!/bin/bash
for i in `cat list`
echo $server
echo "------------------------------------------"
ssh -tt $server << MYCOMMANDS
cd /tmp
rm log52.log
MYCOMMANDS

関連情報