Winse Blog

走走停停都是风景, 熙熙攘攘都向最好, 忙忙碌碌都为明朝, 何畏之.

Pdsh

弄hadoop总是需要折腾不少机器,单单执行 rsync 就挺折腾人的,有时还要排除部分机器来查看一堆机器使用内存情况,等等。以前都使用 expect 结合 for in 来实现,总归简单用着也觉得还行。

但是最近,升级hadoop、tez、安装ganglia被折腾的不行。复制 for 语句到累,原来看过 pdsh 的介绍,不过原来就部署4-5台机器,最近查找Ganglia安装问题的博文里面再次 pdsh ,觉得非常亲切和简洁。再次安装使用也就有了本文。

安装

1
2
3
4
[root@bigdatamgr1 pdsh-2.29]# umask 0022
[root@bigdatamgr1 pdsh-2.29]# ./configure -h
[root@bigdatamgr1 pdsh-2.29]# ./configure --with-dshgroups  --with-exec --with-ssh 
[root@bigdatamgr1 pdsh-2.29]# make && make install

挺多选项的,用 disgroups 加上 ssh 差不多够用了,以后不够用的时刻再慢慢研究这些选项。

当然更简单的安装方式是使用yum: yum install pdsh -y

简单使用

使用pdsh管理机器的前提是已经建立了到目标机器的SSH无密钥登录,而建立这N台机器的无秘钥登录还是少不了 expect (当然你愿意一个个输入yes和密码也是OK的)!

  • 加载的模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 查看,安装的ssh/exec
[esw@bigdatamgr1 ~]$ pdsh -L

# 设置默认使用的模块
[esw@bigdatamgr1 ~]$ export PDSH_RCMD_TYPE=exec
[esw@bigdatamgr1 ~]$ pdsh -w bigdata[1-2] ssh %h hostname
bigdata2: bigdata2
bigdata1: bigdata1

# 命令行指定模块
[esw@bigdatamgr1 ~]$ pdsh -R ssh -w bigdata1,bigdata2 hostname
bigdata2: bigdata2
bigdata1: bigdata1

# 一个个的指定
[esw@bigdatamgr1 ~]$ pdsh -w ssh:bigdata1,ssh:bigdata2 hostname
bigdata2: bigdata2
bigdata1: bigdata1
[esw@bigdatamgr1 ~]$ pdsh -w ssh:bigdata[1,2] hostname
bigdata2: bigdata2
bigdata1: bigdata1
  • 主机加载
1
2
3
4
5
6
[esw@bigdatamgr1 ~]$ pdsh -w bigdata[1-2,5,6-8] -X nodes hostname
bigdata5: bigdata5
bigdata6: bigdata6
bigdata2: bigdata2
bigdata8: bigdata8
bigdata7: bigdata7

pdsh除了使用 -w 来指定主机列表,还可以通过文件来指定,如编译时的 --with-machines ,同时可以通过读取默认的位置的文件来获取。在编译pdsh时可以通过 --with-dshgroups 参数来激活此选项,默认可以将一组主机列表写入一个文件中并放到本地主机的 ~/.dsh/group/etc/dsh/group 目录下,这样就可以通过 -g 参数调用了。同时 -X groupname 可以用来排除主机列表中属于groupname组的主机(下面会提到group分组)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[esw@bigdatamgr1 ~]$ export PDSH_RCMD_TYPE=ssh

[esw@bigdatamgr1 ~]$ mkdir -p .dsh/group
[esw@bigdatamgr1 ~]$ cd .dsh/group/
[esw@bigdatamgr1 group]$ vi nodes
bigdata1
bigdata3

[esw@bigdatamgr1 ~]$ pdsh -g nodes hostname
bigdata3: bigdata3
bigdata1: bigdata1

[esw@bigdatamgr1 ~]$ pdsh -w bigdata[1-8] -X nodes hostname
bigdata2: bigdata2
bigdata8: bigdata8
bigdata5: bigdata5
bigdata6: bigdata6
bigdata4: bigdata4
bigdata7: bigdata7

-w 参数也可以用来读取特定文件中的主机列表,同时结合其他规则和进行过滤(具体查看man帮助)。-x 在主机列表基础上进行过滤(提供多一种的方式来实现过滤)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[esw@bigdatamgr1 ~]$ cat slaves | head -2
bigdata1
bigdata2

[esw@bigdatamgr1 ~]$ pdsh -w ^slaves hostname | head -5
bigdata8: bigdata8
bigdata6: bigdata6
bigdata5: bigdata5
bigdata2: bigdata2
bigdata3: bigdata3

[esw@bigdatamgr1 ~]$ pdsh -w ^slaves,-bigdata[2-8]
pdsh> hostname
bigdata1: bigdata1
pdsh> 
pdsh> exit
[esw@bigdatamgr1 ~]$ pdsh -w ^slaves,-/bigdata.?/
pdsh@bigdatamgr1: no remote hosts specified

[esw@bigdatamgr1 ~]$ pdsh -w ^slaves -x bigdata[1-7] hostname
bigdata8: bigdata8
  • 输出格式化

当一台主机的输出多余一行时,pdsh输出的内容看起来并不和谐。使用dshbak格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[esw@bigdatamgr1 ~]$ pdsh -w bigdata[1-2] free -m  | dshbak -c
----------------
bigdata1
----------------
             total       used       free     shared    buffers     cached
Mem:         64405      59207       5198          0        429      31356
-/+ buffers/cache:      27420      36985
Swap:        65535         57      65478
----------------
bigdata2
----------------
             total       used       free     shared    buffers     cached
Mem:         64405      58192       6213          0        505      29847
-/+ buffers/cache:      27838      36566
Swap:        65535         58      65477

批量SSH无密钥登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[hadoop@hadoop-master4 ~]$ cat ssh-copy-id.expect 
#!/usr/bin/expect  

## Usage $0 [user@]host password

set host [lrange $argv 0 0];
set password [lrange $argv 1 1] ;

set timeout 30;

spawn ssh-copy-id $host ;

expect {
  "(yes/no)?" { send yes\n; exp_continue; }
  "password:" { send $password\n; exp_continue; }
}

exec sleep 1;

[hadoop@hadoop-master4 ~]$ pdsh -w ^slaves ./ssh-copy-id.expect %h 'PASSWD'

# 验证是否全部成功
[hadoop@hadoop-master4 ~]# pdsh -w ^slaves -x hadoop-slaver[1-16] -R ssh hostname

参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
pdsh -w ssh:user00[1-10] "date"
此命令用于在user001到user0010上执行date命令。
pdsh -w ssh:user0[10-31],/1$/ "uptime"
此命令在选择远程主机时使用了正则表达式,表示在user010到user031中选择以1结尾的主机名,即在user011、user021、user031上执行uptime命令

-l    指定在远程主机上使用的用户名称。例如:
pdsh -R ssh -l opsuser -w user00[1-9] "date"

对于-g组,把对应的主机写入到/etc/dsh/group/或~/.dsh/group/目录下的文件中即可

[root@dispatch1 ~]# pdsh -w dispatch1,search1,horizon1 -l bigendian jps 
[root@dispatch1 ~]# vi servers
dispatch1
search1
horizon1
[root@dispatch1 ~]# pdsh -w ^servers -l bigendian hostname 
dispatch1: dispatch1
horizon1: horizon1
search1: search1

-f    设置同时连接到远程主机的个数

dshbak格式化输出

pdcp -R ssh -g userhosts /home/opsuser/mysqldb.tar.gz /home/opsuser #复制文件  
1
2
3
Some quick tips on how to get started using pdsh:
Set up your environment:
export PDSH_SSH_ARGS_APPEND=”-o ConnectTimeout=5 -o CheckHostIP=no -o StrictHostKeyChecking=no” (Add this to your .bashrc to save time.)

–END

Comments