ssh経由でリモートマシンでローカルbashスクリプトを実行するにはどうすればよいですか?


51

リモートマシンに何もインストールすることなく、1台の中央マシンから複数のリモートマシンに設定をプッシュする方法を探しています。

目的は、のようなツールを使用しcfengineて、エージェントが設定されていない一連のマシンで見つけるようなことをすることです。これは、実際にはcfagent、既存のリモートマシンのセットに設定する優れた手法かもしれません。



1
実際の質問には23の賛成票があり、SOの重複には55:P
MoJo

回答:


55

スクリプトを渡し、シェルにパイプして実行することで、エフェメリックにスクリプトを実行させることができます。

例えば

echo "ls -l; echo 'Hello World'" | ssh me@myserver /bin/bash

当然、"ls -l; echo 'Hello World'"パーツはローカルマシンのファイルに保存されているbashスクリプトに置き換えることができます。

例えば

cat script.sh | ssh me@myserver /bin/bash

乾杯!


2
私は、リモートサーバーに記録されていた場合、私は、リモートsystem.eg上のsudoとして、この実行を行うにはどうすればよい私は通常のようにこれを実行しますのsudo -u testuserをscript.sh
Sharjeel

呼び出しているスクリプトにユーザーの操作が含まれている場合はどうなりますか?
Abhimanyu Srivastava

20

いくつかの方法があります。

1:

ssh user@remote_server 'bash -s' < localfile

2:

cat localfile  | ssh user@remote_server

3:

ssh user@remote_server "$(< localfile)"

番号3は私の好みの方法で、インタラクティブなコマンドを許可します。例えば su -S service nginx restart

(#1は、を使用するときにパスワードの質問の入力としてスクリプトの残りを消費しますsu -S。)


4
リモートマシンでのローカルスクリプトの実行について-変数をリモートマシンに引数として送信する方法はありますか?つまり、スクリプトとともに、変数(複数行を含む)をリモートマシンへの引数として送信したいと思います。その後、スクリプトは変数を使用する予定です。

13

私はこの目的のためにPythonのファブリックをお勧めします:

#!/usr/bin/python
# ~/fabfile.py

from fabric_api import *

env.hosts = ['host1', 'host2']
def deploy_script():
    put('your_script.sh', 'your_script.sh', mode=0755)
    sudo('./your_script.sh')

# from shell
$ fab deploy_script

上記を使用して開始できるはずです。残りは、Fabricの優れたドキュメントを参照してください。補足として、スクリプトをFabric内で完全に記述することは完全に可能です-コピーは不要ですが、すべてのマシンでスクリプトを変更するには、ローカルコピーを編集して再デプロイするだけでよいことに注意してください。さらに、APIの基本的な使用法を少し超えるだけで、現在実行しているホストや他の変数に基づいてスクリプトを変更できます。これは一種のpythonic Expectです。


私はこれが質問に正確に答えているとは思わないが、私はそのアイデアが好きで、Fabricは有用なツールとして見ることができた。
トレモロキ

1
@tremoloqui FabricはsshのPythonラッパーです。ターゲットマシンに何もインストールする必要はありません。プッシュされるスクリプトを保存します。これは、一連のFabricコマンドとして(runおよびを使用してsudo)書き直された場合、必要さえありません。
イズカタ

5

これはまさにAnsibleの使用目的です。エージェントはありません。次のテキストファイルを作成するだけです。

/etc/ansible/hosts

次のようなコンテンツで:

[webhosts]
web[1-8]

これは、マシン「web1、web2 ... web8」がグループ「webhosts」にあることを指定します。その後、次のようなことができます:

ansible webhosts -m service -a "name=apache2 state=restarted" --sudo

sudoを使用して、すべてのマシンでapache2サービスを再起動します。

次のようなオンザフライコマンドを実行できます。

ansible webhosts -m shell -a "df -h"

または、リモートマシンでローカルスクリプトを実行できます。

ansible webhosts -m script -a "./script.sh"

または、サーバーが準拠する完全な構成でプレイブックを作成し(詳細についてはドキュメントを参照してください)、それを展開します:

ansible-playbook webplaybook.yml

基本的に、複数のサーバーでコマンドを実行するためのコマンドラインツールとして使用を開始し、適切に使用できるようにその使用を完全な構成ツールに拡張できます。


3
私は次の人と同じくらいansibleが好きですが、彼がスクリプトについて質問している場合、ansibleは本当に素晴らしいスクリプトモジュールを持っていますansible webhosts -m script script.sh
ptman 14

1
他のすべての答えにはbashスクリプトが関係していますが、彼が具体的に求めたものではありません。彼は設定をリモートマシンにプッシュするだけだと言った。しかし、スクリプトモジュールの良い言及:)
seumasmac 14

この回答に投票してください!これがその方法です!

@ptman質問で脚本については言及していませんが、タイトルでは言及していることに気づいただけです。ごめんなさい。更新しました。
seumasmac

3

この回答で説明されているように、heredocを使用できます。

ssh user@host <<'ENDSSH'
#commands to run on remote host
ENDSSH

ヒアドキュメントはテキストを送信するだけなので、ヒアドックには注意する必要がありますが、実際には応答を待つことはありません。つまり、コマンドの実行を待機しません。


1

ここでの回答(https://stackoverflow.com/a/2732991/4752883)は、plinkまたはを使用してリモートLinuxマシンでスクリプトを実行しようとしている場合に最適ですssh。スクリプトに複数の行がある場合に機能しますlinux

**ただし、ローカルlinux/windowsマシンにあるバッチスクリプトを実行しようとしていて、リモートマシンがWindowsであり、それが複数行で構成されている場合は**

plink root@MachineB -m local_script.bat

うまくいきません。

スクリプトの最初の行のみが実行されます。これはおそらくの制限ですplink

解決策1:

複数行のバッチスクリプトを実行するには(特に、数行で構成される比較的単純な場合):

元のバッチスクリプトが次の場合

cd C:\Users\ipython_user\Desktop 
python filename.py

https://stackoverflow.com/a/8055390/4752883のように、local_script.batファイル内で 次のように「&&」セパレータを使用して行を組み合わせることができ ます

cd C:\Users\ipython_user\Desktop && python filename.py

この変更の後、@ JasonR.Coombsがここで指摘したようにスクリプトを実行できます:https ://stackoverflow.com/a/2732991/4752883

解決策2:

バッチスクリプトが比較的複雑な場合、ここで@Martin https://stackoverflow.com/a/32196999/4752883が指摘しているように、plinkコマンドをカプセル化するバッチスクリプトを使用することをお勧めします

rem Open tunnel in the background
start plink.exe -ssh [username]@[hostname] -L 3307:127.0.0.1:3306 -i "[SSH
key]" -N

rem Wait a second to let Plink establish the tunnel 
timeout /t 1

rem Run the task using the tunnel
"C:\Program Files\R\R-3.2.1\bin\x64\R.exe" CMD BATCH qidash.R

rem Kill the tunnel
taskkill /im plink.exe

0

最初にスクリプトを単純にコピーしてから実行してみませんか?

scp your_script.sh the_server:
ssh the_server "chmod +x your_script.sh; ./your_script.sh"

もちろん、それを世界書き込み可能な場所にアップロードしないように注意する必要があります。したがって、実行する前に(おそらくrootとして)誰もそれをいじることができません。


1
スクリプトをアップロードしたくないのは、管理する必要がなく、あなたが言及したリスクを負う必要がないためです。また、アップロード、処理、および(オプションで)削除のマルチステッププロセスよりも簡単であるように思えます。
トレモロキ

0

スクリプト内の各コマンドの先頭にssh 付けられ、ホスト名/ IPまたはそのリストが引数としてスクリプトに渡されるようにスクリプトを書き直します(パスワードなし/ ssh-agentキー認証がセットアップされている場合)。リモートコマンドからエラー/リターンコードを正しく渡すには、いくつかの作業が必要になる場合があります。


0

スクリプトが大きすぎず、bashまたはkshを使用している場合...

ssh vm24 -t bash -c "$(printf "%q" "$(< shell-test.sh )")"

stdinとstdoutは両方とも正常に機能しますが、スクリプトは引数サイズ(通常は約100k)に制限されています。スクリプトの引数は、行の最後で機能する場合があり、余分な「-」引数が続く場合があります。ptyを割り当てる「-t」はオプションです。

注意:これはbashの完了を混乱させます。タブを押さないでください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.