目标:实现免密登陆脚本, expect登陆远程主机,将生成的密钥写入到目标主机, expect测试远程登陆
一般免密钥登陆有两步操作
step1:主机上生成公钥和私钥
[root@n72-1 ~]# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:qzsUaW33T9YCv60HkR9aHKV6z53WBIms9bOmcRU0xa4 root@almalinux9-1.ilvdou.cn
The key's randomart image is:
+---[RSA 3072]----+
| +=|
| . ..+o|
| o + =+.|
| + o .o.oo=o|
| . oS....o*=+|
| . . .oEB*|
| . . .++B=|
| .. =+ o|
| oo . .o |
+----[SHA256]-----+
step2:将公钥文件id_rsa.pub拷贝到远程主机上
具体实现办法有两种:一种是命令方式,一种是手动在远程目标主机上操作。因为本文的目标是通过shell脚本实现自动化操作,所以选择命令的方式实现
[root@n72-1 ~]# ssh-copy-id root@192.168.35.152
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.35.152 (192.168.35.152)' can't be established.
ECDSA key fingerprint is SHA256:ct7zRI04EP17FuGBPe3bBXXCMCZ7U9T7c1DaUOaAd2E.
ECDSA key fingerprint is MD5:14:e1:0a:37:c5:7b:cf:6f:3e:eb:35:3a:b0:ab:c2:5a.
Are you sure you want to continue connecting (yes/no)? yes
/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.35.152's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'root@192.168.35.152'"
and check to make sure that only the key(s) you wanted were added.
[root@n72-1 ~]# ssh root@192.168.35.152
Last login: Tue Dec 6 21:40:34 2022 from 192.168.35.1
[root@almalinux9-1 ~]#
参考文章:
Linux 实现密钥免密登录aliaichidantong的博客-CSDN博客linux免密登录
可以看到ssh-keygen命令和ssh-copy-id命令都是交互式命令,要实现自动化执行,还需要用expect工具进行处理。所以一共会有三个文件,一个keygen的expect脚本文件,一个ssh-copy-id我把它命名为doit 的expect脚本文件,另外一个是shell脚本文件,实现常规的bash命令的执行。
shell脚本一步步实现
step1:用expect实现无交互式生成主机的私钥和公钥
keygen.exp文件内容
#!/bin/expect
spawn ssh-keygen -t rsa
expect "Enter file" { send "\n"; exp_continue }
expect "Enter passphrase" { send "\n"; exp_continue }
expect "Enter same passphrase" {send "\n" }
expect eof
step2:用expect实现无交互式的将主机公钥传给远程目标机器
doit.exp文件内容
#!/bin/expect
set ip [lindex $argv 0]
set password [lindex $argv 1]
spawn ssh-copy-id root@$ip
expect {
"yes/no" { send "yes\n";exp_continue }
"password" { send "$password\n" }
}
expect eof
step3:多系统兼容,菜单式交互实现动态添加免密钥登陆远程主机
shell脚本文件n72-w3-12.sh
#!/bin/bash
. /etc/os-release
if [[ "$ID" -eq "rocky" || "$ID" -eq "centos" || "$ID" -eq "almalinux" ]]; then
OSID="centos"
elif [[ "$ID" -eq "ubuntu" ]];then
OSID="ubuntu"
else
echo "该脚本仅支持centos系列和Ubuntu系列操作系统,其他系统不支持,谢谢,再见!"
exit
fi
password="dashuilvdou"
MAIN_MENU="安装MySQL
安装Apache
免密钥登陆主机
退出"
function select_menu_main() {
PS3="请选择(1-4):"
select menu in $MAIN_MENU;do
case $REPLY in
1)
install_mysql
;;
2)
install_apache
;;
3)
nokey_login
;;
4)
break
;;
*)
echo -e "\e[1;31m输入错误,请输入正确的数字(1-4)!\e[0m"
;;
esac
done
}
function install_mysql() {
echo "hello, you have choose to install MySQL application."
sleep 1
}
function install_apache() {
echo "hello, you have choose to install apache application."
sleep 1
}
function nokey_login() {
while :; do
echo "1.设置免密钥登陆主机"
echo "2.免密钥远程登陆"
echo "输入exit退出"
read -p "$(echo -e '\033[1;32m请输入你的选项:\033[0m')" option
case $option in
1)
set_nokey_login
;;
2)
see_nokey_login
;;
"exit")
break
;;
esac
done
}
function set_nokey_login() {
check_expect_env
check_ssh_key
read -p "$(echo -e '\033[1;32m请输入主机IPLIST:\033[0m')" IPLIST
read -p "$(echo -e '\033[1;32m请输入密码:\033[0m')" PASSWORD
if [[ -n "$PASSWORD" ]] ; then password=$PASSWORD; fi
ssh_copy_id_set $IPLIST
}
function ssh_copy_id_set() {
until [ -z "$1" ]; do
expect doit.exp $1 $password
echo -e "\033[1;32m主机:$1 免密钥远程登陆设置完成。\033[0m"
shift
done
echo
}
function see_nokey_login() {
read -p "$(echo -e '\033[1;31m请输入远程主机IP:\033[0m')" IP
expect -c "
spawn ssh root@$IP;
expect \"*]#\" { send \"uname -a\r\" }
send \"exit\r\"
expect eof
"
}
function check_ssh_key() {
if [[ ! -f /root/.ssh/id_rsa.pub ]]; then
expect keygen.exp
fi
}
function check_expect_env() {
if [[ "$OSID" -eq "centos" ]];then
rpm -q expect &> /dev/null || yum install -y expect
else
dpkg -s expect &> /dev/null || $(apt update; apt install -y expect)
fi
}
#check_ssh_key
select_menu_main
该脚本可以在RHEL系列如centos、rocky、almalinux和Ubuntu上执行。目前只是实现了菜单的两层交互选择,以及shift对输入参数的动态切换,还有expect免交互的脚本实现。
shell脚本上还预留了一些空白函数,待后续补充,欢迎大家评论区交流。
运维之路漫漫,且行且前进。
版权声明:本文为longshuxiao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。