SSH自动部署

SSH自动部署

五月 25, 2025

环境准备

安装sshpass工具,确保默认端口为22或者按需配置其下配置

脚本配置

以下提供两个脚本,原脚本连接放置文章末尾,在原脚本基础上添加对首次指纹确认的操作

  • 多服务器为同密码:
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/bash
PUB_KEY_FILE="$HOME/.ssh/id_rsa.pub"

# 检查sshpass是否安装
if ! command -v sshpass &> /dev/null; then
echo "sshpass 未安装。请先安装 sshpass,然后再运行此脚本。"
exit 1
fi

#检查是否提供列表文件
if [ $# -eq 0 ]; then
echo "用法: $0 <目标主机列表文件> <SSH端口号> <密码>"
exit 1
fi

# 设置目标主机列表文件 ,并检查文件是否存在
host_list_file="$1"
if [ ! -f "$host_list_file" ]; then
echo "错误: 文件 '$host_list_file' 不存在"
exit 1
fi

# SSH端口号及密码
ssh_port="$2"
password="$3"

while IFS= read -r host; do
echo "正在处理 $host..."
# 生成SSH密钥对
if [ ! -f ~/.ssh/id_rsa ]; then
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
fi
# 使用sshpass和ssh-copy-id将公钥拷贝到目标主机上
sshpass -p "$password" ssh-copy-id -i ~/.ssh/id_rsa.pub "-p $ssh_port" -o StrictHostKeyChecking=no "$host"
# 检查并输出
if [ $? -eq 0 ]; then
echo "成功至$host"
else
echo "无法至$host,请手动处理"
fi
done < "$host_list_file"

服务器列表文件格式:

1
2
3
[IP地址1]
[IP地址2]
.......

使用脚本:

1
./[脚本名] [服务器列表文件] [端口号] [服务器密码]

脚本默认登录为root账户,如需其他可按照 [账户名]@[IP地址] 格式书写

  • 多服务不同密码:
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/bin/bash

# 全局配置
LOG_FILE="./deploy_ssh_key.log"
KEY_TYPE="rsa"
USER="root" # 如果目标用户不是 root,请修改这里
SSH_TIMEOUT=10
RETRY_TIMES=3

# 输入验证
validate_input() {
TARGET_FILE="$1"
if [ ! -f "$TARGET_FILE" ]; then
echo "[ERROR] 目标文件不存在: $TARGET_FILE" | tee -a $LOG_FILE
exit 1
fi
mapfile -t TARGET_ENTRIES < <(grep -vE '^#|^$' "$TARGET_FILE")
if [ ${#TARGET_ENTRIES[@]} -eq 0 ]; then
echo "[ERROR] 目标文件中未找到有效IP和密码" | tee -a $LOG_FILE
exit 1
fi
}

# 生成密钥
generate_key() {
if [ ! -f ~/.ssh/id_${KEY_TYPE} ]; then
ssh-keygen -t ${KEY_TYPE} -N "" -f ~/.ssh/id_${KEY_TYPE} -q
fi
}

# 部署公钥
deploy_key() {
local ip="$1"
local password="$2"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 正在处理 $ip..." | tee -a $LOG_FILE
for ((i=1; i<=$RETRY_TIMES; i++)); do
if sshpass -p "$password" ssh-copy-id \
-o StrictHostKeyChecking=no \
-o ConnectTimeout=$SSH_TIMEOUT \
-i ~/.ssh/id_${KEY_TYPE}.pub \
"$USER@$ip" >> "$LOG_FILE" 2>&1; then
echo "成功:$ip 公钥已部署" | tee -a $LOG_FILE
return 0
else
echo "[尝试 $i/$RETRY_TIMES] $ip 失败,等待重试..." | tee -a $LOG_FILE
sleep $((i*2))
fi
done
echo "[ERROR] $ip 公钥部署失败!" | tee -a $LOG_FILE
return 1
}

# 主流程
main() {
validate_input "$1"
generate_key
while IFS=: read -r ip password; do
deploy_key "$ip" "$password"
done < "$TARGET_FILE"
}

main "$@"

服务器列表格式:

1
2
3
192.168.150.142:[密码]
192.168.150.145:[密码]
192.168.150.146:[密码]

使用脚本:

1
./[脚本名] [服务器列表文件]

如需使用其他账户,同上

脚本1

脚本2