pdshによる分散シェル

**複数のノードに同時にコマンドを実行したい。**

ホスト毎に一々sshしてコマンドを叩くのが面倒くさい....
Ansibleに手を出すほど大きな規模ではない
高々十数台程度に対して、サクッと実行させたい...

そんなニーズに答えるのが**pdsh**である。
pdshのインストールから、簡単な利用法について本記事で纏める。

**[注意] pdshは標準でユーザー入力を求めるような処理には対応していない。**

# pdshとは何か？
リモートシェル(rsh,ssh等)を利用して、リモートの複数ノードに対して**非対話的**にコマンドを並列実行出来るラッパープログラムである。

[ソースコード](https://github.com/chaos/pdsh/)・Ubuntuリポジトリ・EPELリポジトリにて提供されている。環境に応じてお好きな手法でインストールするべし。

# インストール

### apt
```bash
apt install pdsh
```
### yum
```bash
yum --enablerepo=epel install pdsh
```


# 使用方法
基本的なコマンド構文は以下の通り。
```bash
pdsh {-オプション} {コマンド}
```

より細かい使用方法は、helpで確認出来る。
```bash
$ pdsh -help

-S                return largest of remote command return values
-h                output usage menu and quit
-V                output version information and quit
-q                list the option settings and quit
-b                disable ^C status feature (batch mode)
-d                enable extra debug information from ^C status
-l user           execute remote commands as user
-t seconds        set connect timeout (default is 10 sec)
-u seconds        set command timeout (no default)
-f n              use fanout of n nodes
-w host,host,...  set target node list on command line
-x host,host,...  set node exclusion list on command line
-R name           set rcmd module to name
-M name,...       select one or more misc modules to initialize first
-N                disable hostname: labels on output lines
-L                list info on all loaded modules and exit
-g query,...      target nodes using genders query
-X query,...      exclude nodes using genders query
-F file           use alternate genders file"file"
-i                request alternate or canonical hostnames if applicable
-a                target all nodes except those with "pdsh_all_skip" attribute
-A                target all nodes listed in genders database
available rcmd modules: ssh,rsh,exec (default: rsh)
```

## 使用例
pdshはバックエンドでrshやsshを利用する。その為、予めそちらの設定は済ませておく必要がある。
例として、今回はsshを利用する。```~/.ssh/config```にホストの設定をしておく。

以下の様に設定されているものとして以後の解説を行う。
```bash:~/.ssh/config
Host node1
    HostName 192.168.0.2
    User node1
    Port 22
    IdentityFile ~/.ssh/node1

Host node2
    HostName 192.168.0.3
    User node2
    Port 22
    IdentityFile ~/.ssh/node2
```

例として、各nodeのNIC(eth0)に設定されているIPアドレスを表示させるコマンドを並列実行してみる。

```bash
$ pdsh -R ssh -w node1,node2 "ip a | grep eth0"

node1: 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
node1:     inet 192.168.0.2/24 brd 192.168.1.255 scope global noprefixroute eth0
node2: 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
node2:     inet 192.168.0.3/24 brd 192.168.1.255 scope global noprefixroute eth0
```

コマンドの実行結果が```node* : hogehoge```と言ったフォーマットで、各ノードからレスポンスが返ってくる。

## pdshは対話形式に非対応
基本的にpdshは非対話形式でのコマンド実行を目的として設計されている為、コマンドの実行結果にユーザー入力が必要な操作には対応できない。

その為、入力が必要な処理に対しては、パイプ処理```|```や```expect```を使用して、無理矢理対話形式に丸め込む様な工夫が必要である。

例えば、node1・node2のパスワードが`password`だったとして、それらに対し```sudo```コマンドを実行する例を考えると、```echo```と```|```を応用して以下の様にする。
```bash
pdsh -R ssh -w node1,node2 "echo 'password' | sudo -S apt update -y
```
上記のコマンドの解説する。
`sudo -S apt update -y`を実行後にパスワードを求められるが、`echo 'password'`にてパスワードをリダイレクトする事で、対話形式の処理に対応している。なお、aptコマンドに`-y`オプションをつける理由は、を実行した際の全ての質問に対して自動的に`Yes`を選択する為である。

また、このコマンドはセキュリティ的にリスクがある為、実環境での実行は推奨されない。