SEワンタンの独学備忘録

IT関連の独学した内容や資格試験に対する取り組みの備忘録

【Linux】ログイン中サーバから別のサーバにあるシェルスクリプトを実行する

知っている人にとっては当たり前かもしれませんが私はよくわかっていないのでやります系の備忘録。

【今回やりたいこと】


基本的にはタイトル通りですが、今回は自宅環境であるため、仮想サーバに対して実行します。

f:id:wantanBlog:20190905225528p:plain

ホストのWindowsから一号機のLinuxサーバに接続してそこで 「start.sh」 を実行。そのスクリプトのなかで別のサーバ(二号機)のシェルスクリプト(action.sh)を実行します。単にSSHで実行せずシェルで実行することになっているのは、二号機側が複数台になることを想定しているからです。


★追加要素
二号機の実行結果を一号機側に返す
一号機にあるシェルスクリプトを二号機側で実行する。

一号機から二号機への接続

まずはサーバ間でSSH接続してみる

一号機にログインした状態で以下のコマンドを実行し、二号機に接続を試みる。

ssh ユーザ名@ホスト名

私が実際に実行したコマンドは以下の通り。ユーザ名がどちらもwantanなのはわかりにくいですね。。

ssh wantan@192.168.56.101

初回接続時は以下のメッセージが表示されましたが、yesとしてそのまま続行しパスワードを入力すると無事、接続が確認できました。

The authenticity of host '192.168.56.101 (192.168.56.101)' can't be established.
ECDSA key fingerprint is SHA256:eW0Qu8jn+9wYj+DN3bRPUX5nTOfpvj99X9PxE95t3Mc.
ECDSA key fingerprint is MD5:b3:8d:d2:fb:59:ac:a8:7e:e3:b8:3b:40:fd:15:b4:70.
Are you sure you want to continue connecting (yes/no)?

おまけ:tmuxを使えば

tmuxを使っているなら画面を分割して片方をSSH接続することで一つのターミナルで複数マシンにログインできた状態にできますね。
これはかっこいい(素人並みの感想)

f:id:wantanBlog:20190905233739p:plain


SSH接続で二号機上でコマンドを実行してみる

今度は単なる接続ではなくコマンドを実行してみます。と言っても後にコマンドをつけるだけのようです。

ssh ユーザ名@ホスト名 コマンド

私が実際に実行したコマンドは以下の通り。

ssh wantan@192.168.56.101 ls-l

では次に同じ要領でシェルスクリプトを実行してみます。
以下のコマンドで実行できました。

ssh wantan@192.168.56.101 ./work/sampleDir/action.sh

ちなみにこれは以下の二号機の以下のパスのスクリプトを実行する場合です。ここで少しはまりました。

/home/wantan/work/sampleDir/action.sh

SSHでログインしたときカレントディレクトリは私の場合で「/home/wantan/」ですが実行したいシェルスクリプトはさらに深い階層にあります。
そこでパスを指定するときに相対パスで書くので以下のどちらかがパスとなります。

./work/sampleDir/action.sh
work/sampleDir/action.sh

良くわからなかったらホームディレクトリにスクリプトを配置しておけば単に以下で実行できるはずです。

ssh wantan@192.168.56.101 ./action.sh

一号機のシェルスクリプトで二号機へ接続

ちなみにパスワードの入力を自動化したりもできるようですが、今回は範囲外として実行時のパスワード入力は手動で行う想定です。

シェルスクリプトでSSH接続する

やっと本題に近づいてきました。まずはSSH接続するところまで。


一号機のシェルスクリプト「start.sh」

#!/bin/bash

ssh wantan@192.168.56.101


なんてことはない接続コマンドを書いただけです。

シェルスクリプトで別サーバのシェルスクリプトを実行する

こちらも実行するだけなら一つのコマンドでいいので問題ないですね。

start.sh

#!/bin/bash

ssh wantan@192.168.56.101 ./work/sampleDir/action.sh


シェルスクリプトを実行し、実行ログを二号機から一号機に転送する。

#!/bin/bash
#一号機
machine1="192.168.56.101"

#接続先でスクリプトを実行する
ssh wantan@$machine1 ./work/sampleDir/action.sh

#接続先のログファイルを接続元にコピーする
scp wantan@$machine1:~/work/sampleDir/shell_20190907.log ~/work/shelldev/

サーバ間のファイルの転送にはscpコマンドを使用します。

思ったより味気ない感じになってしまったので少し追加でやります。


一号機のスクリプトを二号機に対して実行する

やること

f:id:wantanBlog:20190907233426p:plain

一号機に二つのスクリプトを用意し、一号機のstart.shを実行し、action.shを呼び出し二号機に対して実行しログを作成する。
start.shでログを一号機にコピーする。

start.sh⇒キックスクリプト
action.sh⇒実行スクリプト

実行スクリプト

今回の中身はなんでもいいです。
action.sh

#!/bin/bash

#変数に日付を格納する
today=$(date +%Y%m%d)
#実行元マシン
machine="192.168.56.102"

logName=action_$today.log

ls -l >> $logName;
キックスクリプト

まずは確認として、一号機のスクリプトを二号機で実行することから。

ssh ユーザ名@ホスト名(IPアドレス)  'sh' < hoge.sh

私の場合は以下の通り。'sh'をつけることによって、接続元のシェルスクリプトを接続先で実行できるそうです。
ちなみにaction.shでファイル等を作成している場合は接続先に作成されるようです。

ssh wantan@192.168.56.101 'sh' < action.sh


次にシェルスクリプト内に実装し、実際に実行してみる。

start.sh

#!/bin/bash
#二号機
machine1="192.168.56.101"
#日付
today=$(date +%Y%m%d)

#接続先でスクリプトを実行する
ssh wantan@$machine1 'sh' < action.sh

#ログファイル名
logName=action_$today.log

#接続先のログファイルを接続元にコピーする
scp wantan@$machine1:~/$logName ~/work/shelldev/

ホントは実行スクリプト側にscpコマンドを書いた方がいい気がするんだけどなんかうまくいかなかった。
ログファイル名をどちらのスクリプトでも生成しているのはおかしい気がする。

複数台サーバに対してシェルスクリプトを実行する

やること

f:id:wantanBlog:20190908000507p:plain

ホスト部分は省きました。

複数台のサーバ想定ですが、もう一台用意するのが面倒なので一号機を三号機と見立てました
サーバの数だけ実行スクリプトを実行して、そのログを一号機に集めます。
実行スクリプトは前項のままです。

キックスクリプトの内容

start3.shの内容

#!/bin/bash
#二号機
machine2="192.168.56.101"
#三号機(一号機)
machine3="192.168.56.102"
#実行マシンリスト
machineList=($machine2 $machine3)

#日付
today=$(date +%Y%m%d)

for machine in "${machineList[@]}"
do
	#接続先でスクリプトを実行する
	ssh wantan@$machine 'sh' < action.sh

  #ログファイル名
	logName=action_$today.log

	#接続先のログファイルを接続元にコピーする
	scp wantan@$machine:~/$logName ~/work/shelldev/
	
	#ログの名前を変更する
	mv $logName action_${today}_${machine}.log
	
done

実行対象のマシンはハードコードして配列を作成してループにかけます。
2台のマシンに対する実行でパスワードを4回打ち込む必要があるのは最高にセンスない。。


基本が抜けているせいか、なんかダサい実装になってしまう悩み

【追記】パスワード入力なしで実現したい場合

www.wantanblog.com