私はすでにsshエージェントをセットアップしています、そしてBashスクリプトで外部サーバーでコマンドを実行することができます。
ssh blah_server "ls; pwd;"
さて、私が本当にやりたいことは、外部サーバーでたくさんの長いコマンドを実行することです。これらすべてを引用符で囲むのは非常に醜いでしょう。そして、これを避けるために、何度もsshすることを避けたいのです。
それで、括弧か何かで囲まれた私がこれを一度にすることができる方法はありますか?私は以下の方針に沿って何かを探しています。
ssh blah_server (
ls some_folder;
./someaction.sh;
pwd;
)
基本的に、私はそれがきれいである限りどんな解決策でも満足するでしょう。
明確にするために、私はこれがより大きなbashスクリプトの一部であることについて話しています。他の人がスクリプトをすぐに処理する必要があるかもしれないので、私はそれを清潔に保ちたいです。次のような1行のbashスクリプトを作成したくありません。
ssh blah_server "ls some_folder; ./someaction.sh 'some params'; pwd; ./some_other_action 'other params';"
それは非常に醜くて読むのが難しいからです。
Bashについてはどうでしょうか こちらドキュメント :
ssh otherhost << EOF
ls some_folder;
./someaction.sh 'some params'
pwd
./some_other_action 'other params'
EOF
コメントで@Globalzによって言及されている問題を避けるために、あなたは(あなたがリモートサイトで何をしているかによって)最初の行を次のように置き換えることで済むかもしれません
ssh otherhost /bin/bash << EOF
Hereドキュメントでは変数置換を行うことができますが、引用の問題に対処する必要があるかもしれません。たとえば、「制限文字列」(つまり上記のEOF
)を引用すると、変数の置換はできません。しかし制限文字列を引用せずに、変数が代入されます。たとえば、シェルスクリプトで上記の$NAME
を定義した場合は、次のようにします。
ssh otherhost /bin/bash << EOF
touch "/tmp/${NAME}"
EOF
そしてそれは、あなたが$NAME
に割り当てたものは何でもの名前で目的地otherhost
にファイルを作成するでしょう。シェルスクリプトの引用に関する他の規則も適用されますが、ここで説明するには複雑すぎます。
あなたのスクリプトをローカルで編集し、それをsshにパイプしてください。
cat commands-to-execute-remotely.sh | ssh blah_server
commands-to-execute-remotely.sh
は上記のリストのようになります。
ls some_folder
./someaction.sh
pwd;
サンプルコードに合わせて、コマンドを一重引用符または二重引用符で囲むことができます。例えば
ssh blah_server "
ls
pwd
"
2つの方法があります。
最初にこのようなコントロールソケットを作ります。
ssh -oControlMaster=yes -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip>
そしてあなたのコマンドを実行する
ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p <yourip> -t <yourcommand>
こうすれば、実際にサーバーに再接続せずにsshコマンドを書くことができます。
もう1つは、スクリプトを動的に生成し、それをscp
ingして実行することです。
これは次のようにして行うこともできます。コマンドをスクリプトに入れて、commands-inc.shという名前を付けましょう。
#!/bin/bash
ls some_folder
./someaction.sh
pwd
ファイルを保存する
今すぐリモートサーバーで実行します。
ssh user@remote 'bash -s' < /path/to/commands-inc.sh
私のために失敗したことはありません。
すべてのコマンドをスクリプトに書き込めば、次のように実行できます。
ssh <remote-user>@<remote-Host> "bash -s" <./remote-commands.sh
SSHとBashでの複数のコマンドの実行
Echoに渡された文字列内でセミコロンでコマンドを区切り、すべてsshコマンドに渡します。例えば:
echo "df -k;uname -a" | ssh 192.168.79.134
Pseudo-terminal will not be allocated because stdin is not a terminal.
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda2 18274628 2546476 14799848 15% /
tmpfs 183620 72 183548 1% /dev/shm
/dev/sda1 297485 39074 243051 14% /boot
Linux newserv 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux
私のようにここにつまずく人のために - 私はセミコロンと改行をエスケープすることに成功しました:
最初のステップはセミコロンです。このようにして、sshコマンドを壊しません。
ssh <Host> echo test\;ls
^ backslash!
リモートのhosts/homeディレクトリ(rootとしてログイン)を一覧表示します。
ssh <Host> echo test;ls
^ NO backslash
現在の作業ディレクトリを一覧表示します。
次のステップ:行を分割する:
v another backslash!
ssh <Host> echo test\;\
ls
これは再びリモート作業ディレクトリをリストアップしました - 改善されたフォーマット:
ssh <Host>\
echo test\;\
ls
ここで説明しているよりも本当に良ければ、折れ線を囲むように文書や引用符を付けてください。
(bashを使って、Ubuntu 14.04 LTS。)
他のファイルを含める必要がないので、これはスクリプトを作成するのに適しています。
#!/bin/bash
ssh <my_user>@<my_Host> "bash -s" << EOF
# here you just type all your commmands, as you can see, i.e.
touch /tmp/test1;
touch /tmp/test2;
touch /tmp/test3;
EOF
デフォルトで多重化を使用して単一のsshセッションを使用するようにシステムを設定する最も簡単な方法。
これは、ソケット用のフォルダを作成することによって実行できます。
mkdir ~/.ssh/controlmasters
そして、.ssh設定に以下を追加してください。
Host *
ControlMaster auto
ControlPath ~/.ssh/controlmasters/%r@%h:%p.socket
ControlMaster auto
ControlPersist 10m
今、あなたはあなたのコードのどれも修正する必要はありません。これにより、複数のセッションを作成せずにsshとscpを複数回呼び出すことができます。これは、ローカルマシンとリモートマシンの間でより多くの対話が必要な場合に便利です。
@ terminusの回答のおかげで、 http://www.cyberciti.biz/faq/linux-unix-osx-bsd-ssh-multiplexing-to-speed-up-ssh-connections/ および https://en.wikibooks.org/wiki/OpenSSH/Cookbook/Multiplexing 。
複数行の文字列と複数のbashスクリプトを使用して投稿された回答が私にはうまくいきませんでした。
これは、ローカルコンテキストを維持しながら複数のコマンドをSSHで実行するための機能的な方法です。
LOCAL_VARIABLE=test
run_remote() {
echo "$LOCAL_VARIABLE"
ls some_folder;
./someaction.sh 'some params'
./some_other_action 'other params'
}
ssh otherhost "$(set); run_remote"
長いコマンドが最もクリーンかどうかはわかりませんが、最も簡単です。
ssh user@Host "cmd1; cmd2; cmd;3"