web-dev-qa-db-ja.com

SSHを使用してリモートマシン上でシェルスクリプトを実行する方法

リモートマシンでシェルスクリプト(windows/Linux)を実行する必要があります。

私はSSHをマシンAとBの両方に設定しています。私のスクリプトはマシンAにあり、リモートマシンであるマシンB上で私のコードの一部を実行します.

ローカルコンピュータとリモートコンピュータは、WindowsまたはUnixベースのシステムです。

Plink/sshを使ってこれを実行する方法はありますか?

1120
Arun

マシンAがWindowsボックスの場合、Plink( PuTTY の一部)を-mパラメーターと一緒に使用すると、リモートサーバーでローカルスクリプトが実行されます。

plink root@MachineB -m local_script.sh

マシンAがUnixベースのシステムの場合は、次のものを使用できます。

ssh root@MachineB 'bash -s' < local_script.sh

実行するためにリモートサーバーにスクリプトをコピーする必要はありません。

1100
Jason R. Coombs

これは古い質問で、Jasonの答えはうまくいきますが、私はこれを付け加えたいと思います。

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

これは、ユーザー入力を必要とするsuおよびコマンドと一緒に使用することもできます。 ('エスケープheredocに注意してください)

編集:この答えはトラフィックのビットを取得し続けているので、私はheredocのこの素晴らしい使用法にさらに多くの情報を追加するでしょう:

この構文でコマンドを入れ子にすることができます。それが入れ子が機能する唯一の方法です(正しい方法で)。

ssh user@Host <<'ENDSSH'
#commands to run on remote Host
ssh user@Host2 <<'END2'
# Another bunch of commands on another Host
wall <<'ENDWALL'
Error: Out of cheese
ENDWALL
ftp ftp.secureftp-test.com <<'ENDFTP'
test
test
ls
ENDFTP
END2
ENDSSH

実際にはtelnet、ftpなどのようないくつかのサービスと会話をすることができます。しかしheredocは標準入力をテキストとして送信するだけで、行間の応答を待ちません。

編集:私はちょうどあなたが<<-ENDを使うなら tabs で内側をインデントできることを知りました!

ssh user@Host <<-'ENDSSH'
    #commands to run on remote Host
    ssh user@Host2 <<-'END2'
        # Another bunch of commands on another Host
        wall <<-'ENDWALL'
            Error: Out of cheese
        ENDWALL
        ftp ftp.secureftp-test.com <<-'ENDFTP'
            test
            test
            ls
        ENDFTP
    END2
ENDSSH

(私はこれでうまくいくはずだと思います)

http://tldp.org/LDP/abs/html/here-docs.html も参照してください。

560
Yarek T

また、あて先のホストからそれらを拾いたい場合は、変数をエスケープすることを忘れないでください。

これは過去に私を見つけ出しました。

例えば:

user@Host> ssh user2@Host2 "echo \$HOME"

/ home/user2をプリントアウトする

しながら

user@Host> ssh user2@Host2 "echo $HOME"

/ home/userをプリントアウトする

もう一つの例:

user@Host> ssh user2@Host2 "echo hello world | awk '{print \$1}'"

"こんにちは"を正しく印刷します。

230
dogbane

これは、インラインリモートコマンドとローカルマシンからリモートホストへのENV変数の受け渡しを組み合わせたYarekTの回答に対する拡張で、リモート側でスクリプトをパラメータ化できます。

ssh user@Host ARG1=$ARG1 ARG2=$ARG2 'bash -s' <<'ENDSSH'
  # commands to run on remote Host
  echo $ARG1 $ARG2
ENDSSH

私はこれを非常に読みやすく保守しやすいように1つのスクリプトにまとめておくことで非常に役立つことがわかりました。

なぜこれが機能するのですか。 sshは次の構文をサポートしています。

ssh user @ Host remote_command

Bashでは、次のように単一行でコマンドを実行する前に、定義する環境変数を指定できます。

ENV_VAR_1 = '値1' ENV_VAR_2 = '値2' bash -c 'echo $ ENV_VAR_1 $ ENV_VAR_2'

これにより、コマンドを実行する前に変数を簡単に定義できます。この場合、echoは実行しているコマンドです。 echoより前のものはすべて環境変数を定義します。

そこで、これら2つの機能とYarekTの答えを組み合わせて取得します。

sshユーザー@ホストARG1 = $ ARG1 ARG2 = $ ARG2 'bash -s' << 'ENDSSH' ...

この場合、ARG1とARG2をローカル値に設定します。 remote_commandとしてuser @ Hostの後にすべてを送信します。リモートマシンでコマンドARG1とARG2が実行されると、リモートサーバーで環境変数を定義するローカルコマンドライン評価によってローカル値が設定され、それらの変数を使用してbash -sコマンドが実行されます。ほら。

142
chubbsondubs
<hostA_Shell_Prompt>$ ssh user@hostB "ls -la"

HostAユーザーの公開鍵をユーザー.sshのディレクトリのホームにあるauthorized_keysファイルにコピーしていない限り、パスワードの入力を求められます。パスワードなしの認証が可能になります(sshサーバーの設定で認証方法として承認された場合)

98
Vinko Vrsalovic

より洗練された操作のために Fabric を使い始めました。 FabricはPythonと他のいくつかの依存関係を必要としますが、それはクライアントマシンだけです。サーバーはsshサーバーであれば十分です。私はこのツールがSSHからSSHに渡されたシェルスクリプトよりもはるかに強力であることを発見しました。 Fabricは、複数のホスト(または特定の役割を持つホスト)で実行中のスクリプトを処理し、(configスクリプトに行を追加するが、すでに存在しない場合は追加するなど)冪等操作を容易にします言語は提供することができます。

26
Jason R. Coombs

ssh user@remote sh ./script.unxを実行してみてください。

10
Jeremy

手動で「リモート」マシンにログインせずに、「ローカル」マシンから自動的にこれを実行したいという場合は、Expectとして知られるTCL拡張機能を調べる必要があります。これは、このような状況向けに設計されています。 SSH経由でログイン/対話するためのスクリプトへのリンクも提供しました。

https://www.nist.gov/services-resources/software/expect

http://bash.cyberciti.biz/security/expect-ssh-login-script/ /

9
George Jempty

私はこれを使ってリモートマシン上でシェルスクリプトを実行します(/ bin/bashでテスト済み):

ssh deploy@Host . /home/deploy/path/to/script.sh
2
Is Ma

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

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

plink root@MachineB -m local_script.bat

仕事をしないでください。

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

解決策1:

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

元のバッチスクリプトが次のようになっている場合

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

local_script.batファイルで次のように "&&"区切り記号を使用して行を組み合わせることができます。 https://stackoverflow.com/a/8055390/4752883

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

この変更後は、@ JasonR.Coombsで指摘されているようにスクリプトを実行できます。 https://stackoverflow.com/a/2732991/4752883 with:

`plink root@MachineB -m local_script.bat`

解決策2:

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

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
1
alpha_989

このtemp=`ls -a` echo $tempコマンドのようなコマンドを ``で実行したい場合は、エラーが発生します。

below commandはこの問題を解決しますssh user@Host ''' temp=`ls -a` echo $temp '''

1
Jinmiao Luo
cat ./script.sh | ssh <user>@<Host>
0
Amir

このbashスクリプトはターゲットのリモートマシンにsshし、リモートマシンでコマンドを実行します。実行する前にexpectをインストールすることを忘れないでください(mac brew install expect

#!/usr/bin/expect
set username "enterusenamehere"
set password "enterpasswordhere"
set hosts "enteripaddressofhosthere"
spawn ssh  $username@$hosts
expect "$username@$hosts's password:"
send -- "$password\n"
expect "$"
send -- "somecommand on target remote machine here\n"
sleep 5
expect "$"
send -- "exit\n"
0
Mohammed Rafeeq
ssh user@hostname ".~/.bashrc;/cd path-to-file/;.filename.sh"

環境ファイル(.bashrc/.bashprofile/.profile)を入手することを強くお勧めします。ターゲットおよびソースホストの環境変数は異なる可能性があるため、リモートホストで何かを実行する前に。

0
Ankush Sahu