expect交互式公钥推送
expect实现非交互登录
- expect用于自动化控制交互式应用程序。
- expect脚本通常需要用户输入或确认等自动化任务。
例:使用expect实现SSH非交互登录
[root@localhost ~]# yum install expect
[root@localhost ~]# which expect
/usr/bin/expect
[root@localhost ~]# vim expect_ssh01.sh
#!/usr/bin/expect \\使用expect作为命令解释器
spawn ssh root@192.168.40.135 \\使用spawn开启脚本和命令会话
expect { \\实现交互过程"yes/no" { send "yes\r"; exp_continue } \\等待用户输入,yes则继续"password:"{ send "123456\r" }
}
interact
\\实现效果
[root@localhost ~]# ./expect_ssh01.sh
spawn ssh root@192.168.40.135
Authorized users only. All activities may be monitored and reported.
root@192.168.40.135's password: Jan16@gdcp
Authorized users only. All activities may be monitored and reported.
Web console: https://localhost:9090/
Last login: Mon Jul 15 15:21:40 2024
[root@localhost ~]# ip add
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000link/ether 00:0c:29:20:c5:3a brd ff:ff:ff:ff:ff:ffinet 192.168.40.135/24 brd 192.168.40.255 scope global dynamic noprefixroute ens160valid_lft 1556sec preferred_lft 1556secinet6 fe80::e786:f90a:9f18:cc7d/64 scope link noprefixroute valid_lft forever preferred_lft forever
expect实现非交互传输文件
- 使用expect非交互式与scp命令结合,实现scp批量传输本地不同文件到不同远程主机的不同路径。
- 第一次scp需要做验证,同时需注意列表文件与变量的顺序。
例:
[root@localhost ~]# touch test.txt
[root@localhost ~]# echo test.txt >> /etc/hosts
[root@localhost ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
test.txt
[root@localhost ~]# vim expect_scp.sh
#!/usr/bin/expect
set ip [lindex $argv 0] \\脚本的第一个位置参数
set user root
set password 11223344
set timeout 5
#把本地目录及目录下的文件以$user这个用户批量复制到对方$ip主机上的/tmp目录下
spawn scp -r /etc/hosts $user@$ip:/tmp
expect {"yes/no" { send "yes\r"; exp_continue }"password" { send "$password\r" }
}
#当看到eof时,事情做完后结束expect,脚本退出
expect eof
执行结果:
[root@localhost ~]# ./expect_scp.sh 192.168.40.156
spawn scp -r /etc/hosts root@192.168.40.156:/tmp
The authenticity of host '192.168.40.156 (192.168.40.156)' can't be established.
ECDSA key fingerprint is SHA256:Q8mRLuY/2Xwj2vPTpQLR/pJJzAYRnOA2BGojyhfNSJ0.
ECDSA key fingerprint is MD5:60:36:8b:21:87:22:7a:e3:03:77:63:1a:de:bb:69:1d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.40.156' (ECDSA) to the list of known hosts.
root@192.168.40.156's password:
hosts 100% 206 209.1KB/s 00:00
192.168.40.156主机:
[root@localhost tmp]# ls
hosts vmware-root_696-2722173465
systemd-private-651b437eb58b4b9b90b5b2b53fb44b92-chronyd.service-t4xDDM vmware-root_712-2957059153
systemd-private-651b437eb58b4b9b90b5b2b53fb44b92-nginx.service-7lNjij
expect实现批量主机公钥推送
[root@localhost ~]# vim getip_push_public.sh
#!/bin/bash
#检查是否安装了expect软件
rpm -q expect &>/dev/null
if [ $? -ne 0 ];thenyum -y install expectif [ $? -eq 0 ];thenecho "install success!"elseecho "install faile!"exit 2fi
fi
#检查客户端是否生成了公钥和私钥
if [ ! -f ~/.ssh/id_rsa ];thenssh-keygen -P "" -f ~/.ssh/id_rsaif [ $? -eq 0 ] ;thenecho "success!"elseecho "fail!"exit 2fi
fi
#检查客户端能否ping通,如果能ping通就使用expect推送密钥
>ip.txt
password=Jan16@gdcpfor i in {2..254};doip=192.168.40.$iping -c1 -W1 $ip &>/dev/nullif [ $? -eq 0 ];thenecho "$ip" >> ip.txt#推送公钥,ping通一个推送一个/usr/bin/expect <<EOFset timeout 10spawn ssh-copy-id $ipexpect {"yes/no" { send "yes\r"; exp_continue }"password:" { send "$password\r" } timeout { send_user "连接超时$ip\n"; exit 1 }eof { send_user "expect caught exception!\n" exit 1 }}expect eof
EOFresult=$?if [ $result -ne 0 ];thenecho "推送密钥到$ip失败!"elseecho "推送密钥到$ip成功!"fifidone
echo "finish..."
:set list #查看特殊字符(隐形字符)
:set nolist #取消查看特殊字符(隐形字符)
执行结果如下所示:
[root@localhost ~]# ./getip_push_public.sh
spawn ssh-copy-id 192.168.40.156
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@192.168.40.156's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh '192.168.40.156'"
and check to make sure that only the key(s) you wanted were added.
推送密钥到192.168.40.156成功!
^C^C^Z
[6]+ Stopped ./getip_push_public.sh
[root@localhost ~]# ssh 192.168.40.156
Last login: Fri Aug 16 04:39:28 2024 from 192.168.40.10
[root@localhost ~]# exit
logout
Connection to 192.168.40.156 closed.
for循环语句实现批量主机密码修改
[root@localhost ~]# vim modify_password.sh
#!/bin/bash
read -p "Please enter a New password: " pass
echo
for ip in $(cat ip.txt)
do{ping -c1 -W1 $ip &>/dev/nullif [ $? -eq 0 ];thenssh $ip "echo $pass |passwd --stdin root"if [ $? -eq 0 ];thenecho "$ip" >>ok_`date +%F`.txtelseecho "$ip" >>fail_`date +%F`.txtfielseecho "$ip">>fail.txtfi}&
done
wait
echo "finish..."
执行结果如下所示:
[root@localhost ~]# ./modify_password.sh
Please enter a New password: 11223344
Changing password for user root.
passwd: all authentication tokens updated successfully.
[root@localhost ~]# cat ip.txt
192.168.40.2
192.168.40.10
192.168.40.136
192.168.40.156
[root@localhost ~]# cat ok_2024-08-19.txt
192.168.40.156
[root@localhost ~]# cat fail_2024-08-19.txt
192.168.40.156
[root@localhost ~]# cat fail.txt
192.168.40.156
for循环语句实现批量远程主机SSH配置
[root@localhost ~]# vi modify_sshconfig.sh
#!/bin/bashfor ip in `cat ip.txt`do{ping -c1 -W1 $ip &>/dev/nullif [ $? -eq 0 ];thenssh $ip "sed -ri '/^#UsedNS/cUsedNS no' /etc/ssh/sshd_config"ssh $ip "sed -ri '/^GSSAPIAuthentication/cGSSAPIAuthentication no' /etc/ssh/sshd_config"ssh $ip "sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config"ssh $ip "systemctl stop firewalld;systemctl disable firewalld"ssh $ip "setenforce 0"fi }&
done
wait
echo "finish..."
执行结果如下所示:
[root@localhost ~]# ./modify_sshconfig.sh
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
setenforce: SELinux is disabled
finish..
注:检查脚本语法可以使用bash -n命令
[root@localhost ~]# bash -n modify_sshconfig.sh