ssh-keygen+ssh-keyscan+ssh-copy-id三条命令实现ssh免密 non interactive登录
如下代码实现从A机器(192.168.1.100)到B机器(192.168.1.111)的ssh免密non interactive登录。
## 在A机上操作如下三句
ssh-keygen -t rsa -b 4096 -N '' -m PEM <<<$'\ny\n'
ssh-keyscan -H 192.168.1.111 >> ~/.ssh/known_hosts
ssh-copy-id -i ~/.ssh/id_rsa.pub jerry@192.168.1.111
解释
ssh-keygen -t rsa -b 4096 -N '' -m PEM <<<$'\ny\n'
这句是生成密钥对
,不产生交互,如果以前存在则删除重建。
参考https://stackoverflow.com/questions/43235179/how-to-execute-ssh-keygen-without-prompt
ssh-keyscan -H 192.168.1.111 >> ~/.ssh/known_hosts
这句是把ssh fingerprint
加入到A机器~/.ssh/known_hosts
。
参考https://www.techrepublic.com/article/how-to-easily-add-an-ssh-fingerprint-to-your-knownhosts-file-in-linux/
ssh-copy-id -i ~/.ssh/id_rsa.pub jerry@192.168.1.111
这句是附加公钥(即A机器的~/.ssh/id_rsa.pub
)到B机器~/.ssh/authorized_keys
,第一次提示输入密码。
20220826更新
想了以下,认为这个也不叫免密登陆,叫ssh 通过私钥实现无交互登陆
20220827更新
更简洁的使用两条命令就可以了,无需增加 ssh-keyscan 这一条,但是需要通过-o
增加ssh参数。参考
## 测试用例
ssh-keygen -f "$HOME/.ssh/known_hosts" -R "192.168.1.111" > /dev/null;
ssh-copy-id -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i ~/.ssh/id_rsa.pub jim@192.168.1.111
第一次输入密码可以通过sshpass or expect
方式实现自动完成。参考
20220929更新
脚本:批量根据密码拷贝公钥到目标机器的bash脚本
#!/bin/bash
# cat > hosts <<'EOF'
# #hostname user password port identity_file
# 192.168.1.111 root password 22
# EOF
auto_ssh_copy_id() {
#ssh-keygen -R "$1" -f "$HOME/.ssh/known_hosts" > /dev/null;
expect -c "set timeout -1;
spawn ssh-copy-id -p $3 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $1;
expect {
*(yes/no)* {send -- yes\r;exp_continue;}
*assword:* {send -- $2\r;exp_continue;}
eof {exit 0;}
}";
}
ssh_copy_id_to_all() {
while IFS= read -r line || [ -n "$line" ]; do
if [[ "$line" =~ ^\#.* ]]; then
continue
fi
server=$(echo "${line}" | awk -F " " '{print $1}')
user=$(echo "${line}" | awk -F " " '{print $2}')
password=$(echo "${line}" | awk -F " " '{print $3}')
port=$(echo "${line}" | awk -F " " '{print $4}')
echo "${line}" && auto_ssh_copy_id "${user}@${server}" "${password}" "${port}"
done < hosts
}
ssh_copy_id_to_all