使用PSSH批量管理Linux进阶篇

文章目录
  1. 1. 前言
  2. 2. 批量添加密钥
    1. 2.1. 基线版本
    2. 2.2. 升级版本
    3. 2.3. 批量版本
    4. 2.4. 批量删除
    5. 2.5. 批量修改权限
    6. 2.6. 修改StrictModes
    7. 2.7. 调试
    8. 2.8. 使用dsa密钥
  3. 3. 设置sudo免密
  4. 4. 批量修改密码
  5. 5. 批量修改hosts
    1. 5.1. 自动生成hosts
    2. 5.2. 修改客户机hosts
  6. 6. 后记
  7. 7. 20180614更新

前言

《使用PSSH批量管理Linux》一文中,学习了pssh的基本用法,实际上已经涵盖了pssh的大部分内容。

本文主要记录利用pssh和expect脚本来解决一些实际问题,就算是进阶篇了。

批量添加密钥

《添加密钥认证访问》一节中,已经写清楚了挨个给客户机添加密钥的方法。但是,在客户机数量非常多的时候,挨个添加也很麻烦,写个脚本吧!(假设所有客户机用户都是test,密码都是123456)

参考无密钥登录的自动脚本实现expect - 自动交互脚本

基线版本

1、新建脚本addkey.sh,内容为:

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/expect 
set timeout 60
set password 123456

spawn ssh-copy-id -i /home/test/.ssh/id_rsa.pub -p 22 test@192.168.56.101
expect "install the new keys"
send "\r"
expect "password:"
send "$password\r"
expect eof

2、执行脚本
chmod a+x addkey.sh

./addkey.sh

注意:

  • 如果密码是六个空格,那么set password " "即可。
  • expect "install the new keys"这里其实是不需要交互的,但是密码会直接出现在这里,所以加一个回车。

升级版本

在使用ssh-copy-id命令的时候,有两种情况,一种是直接输入密码,就像基线版本;另一种情况是会先提示添加主机到known_hosts。

1、新建脚本addkey.sh,主要目的是测试,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/expect 
set timeout 60
set password 123456

spawn ssh-copy-id -i /home/test/.ssh/id_rsa.pub -p 22 test@192.168.56.101
expect {
#first connect, no public key in ~/.ssh/known_hosts
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"; exp_continue
}
#already has public key in ~/.ssh/known_hosts
"install the new keys" {
send "\r"; exp_continue
}
"password:" {
send "$password\r"; exp_continue
}
"Now try logging into the machine" {
#it has authorized, do nothing!
; exp_continue
}
}

2、执行脚本
chmod a+x addkey.sh

./addkey.sh

批量版本

1、升级脚本,新建addkeys.sh,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/expect 
set timeout 60
set password 123456

for {set i 101} {$i < 201} {incr i} {
spawn ssh-copy-id -i /home/test/.ssh/id_rsa.pub -p 22 test@192.168.56.$i
expect {
#first connect, no public key in ~/.ssh/known_hosts
"Are you sure you want to continue connecting (yes/no)?" {
send "yes\r"; exp_continue
}
#already has public key in ~/.ssh/known_hosts
"install the new keys" {
send "\r"; exp_continue
}
"password:" {
send "$password\r"; exp_continue
}
"Now try logging into the machine" {
#it has authorized, do nothing!
; exp_continue
}
}
}

2、执行脚本
chmod a+x addkeys.sh

./addkeys.sh

批量删除

添加完密钥之后,发现部分机器不能免密登录。检查客户机中的authorized_keys文件,发现添加了两次密钥。于是决定删除重新添加。

1、管理机新建脚本delkeys.sh

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/expect 
set timeout 30
set password 123456

for {set i 101} {$i < 201} {incr i} {
spawn ssh test@192.168.56.$i "rm /home/test/.ssh/authorized_keys"
expect {
"password:" { send "$password\r"}
"No route to host" { send "\r" }
}
}

2、执行脚本
chmod a+x delkeys.sh

./delkeys.sh

注意,执行完之后检查一下最后一台客户机,也许会删除失败,不知道为什么。

批量修改权限

删除后重新添加,依然无法登录,后来发现,是目录权限的问题。用户目录权限是750,~/.ssh权限是700, ~/.ssh/authorized_keys权限是600。

1、权限修改脚本chmods.sh

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/expect 
set timeout 30
set password 123456

for {set i 101} {$i < 201} {incr i} {
spawn ssh test@192.168.56.$i -t "sudo chmod 750 /home/test/ && sudo chmod 700 /home/test/.ssh && sudo chmod 600 /home/test/.ssh/authorized_keys"
expect {
"password:" { send "$password\r"; exp_continue }
"password for test" { send "$password\r"; exp_continue }
"No route to host" { send "\r" }
}
}

2、执行脚本
chmod a+x chmods.sh

./chmods.sh

修改StrictModes

设置完权限,依然无法免密登录,猜测是StrictModes的问题。

1、编辑sshd_config
sudo vi /etc/ssh/sshd_config

2、找到StrictModes yes,改成StrictModes no

3、重启sshd,sudo service ssh restart

然后,依然失败。

调试

1、不服,进行ssh登录调试,ssh -v test@192.168.56.102或者ssh -vvv test@192.168.56.102

1
2
3
4
5
6
7
8
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/test/.ssh/id_rsa
debug1: Authentications that can continue: publickey,password
debug1: Trying private key: /home/test/.ssh/id_dsa
debug1: Trying private key: /home/test/.ssh/id_ecdsa
debug1: Trying private key: /home/test/.ssh/id_ed25519
debug1: Next authentication method: password

一番折腾,失败,失败,失败。。。

2、参考ssh免密登录失败问题排查思路,在客户机查看日志,cat /var/log/auth.log

调试方法:
(1)客户机执行tail -f /var/log/auth.log
(2)管理机执行ssh -v test@192.168.56.102

然而,各种尝试依然失败,失败,失败。。。

3、然后找到一篇重建home分区后出现的ssh公钥认证失败问题,猜测是SElinux的问题,于是在客户机执行:

sudo apt-get install policycoreutils

restorecon -r -vv /home/

然而,依然没有用。

使用dsa密钥

1、生成dsa密钥
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa

2、添加公钥到客户机
ssh-copy-id -i /home/test/.ssh/id_dsa.pub -p 22 test@192.168.56.102

3、管理机测试登录
ssh test@192.168.56.102

依然失败。换一个管理机重新添加密钥,依然失败,看来确实是客户机的锅。好吧,放弃了,不玩了!

设置sudo免密

以上,假设已经实现了批量添加密钥,也就是实现了所有客户机的免密登录。但是,在客户机执行sudo命令的时候,会提示输入密码,也是很麻烦,所以接下来设置sudo免密执行。

1、管理机新建脚本addsudo.sh,内容为:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/expect 
set timeout 10
set password 123456

for {set i 101} {$i <= 200} {incr i} {
spawn ssh test@192.168.56.$i -t "sudo -i"
expect "password for test:"
send "$password\r"
expect "*#"
send "echo test ALL = NOPASSWD: ALL >> /etc/sudoers \r"
expect "*#"
send "exit\r"
}

2、执行脚本
chmod a+x addsudo.sh

./addsudo.sh

批量修改密码

《批量修改密码》一节中,我们采用的修改密码的方式是给所有的客户机都安装expect,然后发送脚本到客户机并执行脚本。给每台机器安装expect,不是一个好的做法。不妨参照设置sudo免密,在管理机执行脚本,虽然无法并行,但是胜在不需要给客户机安装expect。

不过,这次我们换一种脚本写法,使用bash脚本循环调用expect脚本。这种写法更好,更加稳定。因为在expect脚本中写循环语句,有些字符串会不显示,影响执行效果。

1、新建expect脚本m-chpasswd.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/expect 
set timeout 10
set newpassword 12345678
set i [lindex $argv 0]

spawn ssh test@192.168.56.$i -t "sudo passwd test"
expect "Enter new UNIX password:"
send "$newpassword\r"
expect "Retype new UNIX password:"
send "$newpassword\r"
expect "closed"
send "\r"
expect eof

2、新建bash脚本loop-passwd.sh

1
2
3
4
5
6
7
8
#!/bin/bash
for ((i=101;i<=200;i++))
do
echo "begin..."
echo $i
./m-chpasswd.sh $i
echo "end..."
done

3、执行脚本
chmod a+x m-chpasswd.sh

chmod a+x loop-passwd.sh

./loop-passwd.sh

批量修改hosts

《批量修改hostname》一节中,我们给三台机器设置了主机名,比较简单。现在假设我们有100台机器需要管理,IP为192.168.56.101-200,现在要给它们设置主机名,同时修改它们的/etc/hosts文件,方便使用主机名相互寻找。

自动生成hosts

1、在管理机新建脚本makehosts.sh,内容为:

1
2
3
4
5
6
7
8
9
#!/bin/bash

echo "127.0.0.1 localhost" > /home/test/hosts
NUM=101
while [ $NUM -lt 201 ]
do
echo "192.168.56.$NUM vk$NUM" >> /home/test/hosts
NUM=`expr $NUM + 1`
done

2、执行脚本
sudo chmod a+x makehosts.sh

./makehosts.sh

3、替换hosts
sudo cp hosts /etc/hosts

PS:添加一条新的记录到 /etc/hosts ,sudo bash -c "echo 192.168.56.201 vk201 >> /etc/hosts"

修改客户机hosts

1、拷贝hosts文件到客户机
pscp -h hosts.txt ./hosts /home/test

2、替换hosts文件
pssh -h hosts.txt -i "sudo cp /home/test/hosts /etc/hosts"

后记

本文在写作之前,思路很明确,以为可以半天搞定,没想到遇到了一个大坑:部分机器无法免密登录。大大小小试了十几种解决办法,未果,折腾了一整天,还是无奈放弃。

设置sudo免密时还有一个方案,就是写一个脚本发送到客户机,在客户机执行修改/etc/sudoers文件。但是要求所有客户机都安装了expect,这个很麻烦,不如在管理机操作。

20180614更新

今天,突然冒出一个想法,如果换一个用户呢?不再用test,而是使用test2用户。于是,进行了测试。

1、客户机新建test2用户
sudo useradd -m test2 -s /bin/bash

sudo passwd test2

根据需要给予sudo权限,sudo adduser test2 sudo

2、管理机添加免密登录
ssh-copy-id -i .ssh/id_rsa.pub -p 22 test2@192.168.56.102

3、测试登录
ssh test2@192.168.56.102

登录成功!!!

那么,如果我删除test用户,再添加新的test用户,是不是也可以呢?

1、客户机删除test用户
sudo userdel -r test
提示userdel: user test is currently used by process 62901

2、查看最近登录情况
wlast

并没有人在使用这个账号,那就继续想办法删除。

3、使用vipw
sudo vipw,找到test用户那行,删除。

sudo vipw -s,找到test用户那行,删除。

4、删除test目录
cd /home && sudo rm -rf test

5、新建test用户
sudo useradd -m test -g test -s /bin/bash

sudo passwd test

sudo adduser test sudo

7、管理机添加免密登录
ssh-copy-id -i .ssh/id_rsa.pub -p 22 test@192.168.56.102

8、测试登录
ssh test@192.168.56.102

登录成功!!!问题完美结局,不过确实很麻烦。

如果,单纯地拷贝其他客户机的整个test用户目录呢?假设客户机A的IP为192.168.56.102,已经配置完成,可以免密登录;客户机B的IP为192.168.56.103,不可以免密登录。

1、删除客户机B的test目录下所有文件
rf -rf ./*

rf -rf ./.*

2、拷贝配置好的客户机A的test目录到客户机B
scp test@192.168.56.102:~/.* .

scp test@192.168.56.102:~/.ssh/* .ssh/

3、在管理机测试登录
ssh test@192.168.56.103

登录成功!!!这个方法明显更好,nice。