优化跨分支Linux机器SSH密钥认证文件传输脚本的问题
批量推送配置文件脚本优化求助
我是公司IT专员,公司多分支服务器使用Linux Fedora 35系统,需要批量向所有机器推送配置文件。我用Fedora 39机器执行任务,已通过Bash脚本完成SSH公钥分发,实现无密码密钥认证访问。
当前编写的文件传输脚本会遍历网关IP列表,对每个网关生成尾段10-22的机器IP,ping通后用rsync传输文件,但部分IP会导致脚本冻结甚至停止。我曾尝试将循环进程放入后台,但仍未解决问题,请教如何调整脚本以实现高效稳定运行。
现有脚本
#!/bin/bash # Specify the default location for the SSH key SSH_KEY=/root/.ssh/id_rsa current_date=$(date +%Y-%m-%d) source_file="/home/abdulrahman/firefox-redhat-default-prefs.js" remote_dir="/usr/lib64/firefox/browser/defaults/preferences/" source_file2="/etc/hosts" remote_dir2="/etc/" source_file3="/home/abdulrahman/Tamweely-CA.cer" remote_dir3="/" # Function to ping an IP address ping_ip() { local ip=$1 # Remove non-numeric characters from the IP address ip=$(echo "$ip" | tr -cd '[:digit:].') # Check if the IP address is empty after cleaning if [ -z "$ip" ]; then echo "Skipping invalid IP address." return fi ping -W 5 -c 1 "$ip" > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "IP address $ip is up." return 0 else echo "IP address $ip is down." return 1 fi } send_file(){ local source_file=$1 local ip_addr=$2 local remote_dir=$3 #scp -l "250" -o "StrictHostKeyChecking=no" "$source_file" "root@$ip_addr:$remote_dir" rsync -avmzPR -e "ssh -o StrictHostKeyChecking=no -o ConnectTimeout=60" --progress "$source_file" "root@$ip_addr:$remote_dir" if [ $? -eq 0 ]; then echo "File is sent successfully to $ip_addr" | tee -a "/home/abdulrahman/scs/reports/file_report_$current_date.txt" else echo "Failed to send file to $ip_addr" | tee -a "/home/abdulrahman/scs/reports/file_report_$current_date.txt" fi } # Specify the path to your text file IP_FILE="/home/abdulrahman/scs/ip_addresses.txt" #IP_FILE="/home/abdulrahman/scs/ip_address2.txt" # Check if the file exists if [ ! -f "$IP_FILE" ]; then echo "Error: File $IP_FILE not found." exit 1 fi # Initialize an array to store background process IDs #declare -a bg_pids # Read each line (IP address) from the file and perform an action while IFS= read -r ip_address; do # You can replace the echo statement with the action you want to perform for device_ip in ${ip_address%.*}.{10..22}; do if ping_ip "$device_ip"; then send_file "$source_file" "$device_ip" "$remote_dir" send_file "$source_file2" "$device_ip" "$remote_dir2" send_file "$source_file3" "$device_ip" "$remote_dir3" #Store the background process ID #bg_pids+=($!) fi done done < "$IP_FILE" # Wait for all background processes to complete #for pid in "${bg_pids[@]}"; do # wait "$pid" #done
IP列表文件(ip_addresses.txt)
192.168.119.1 192.168.3.1 192.168.2.1 192.168.7.1 192.168.6.1 192.168.4.1 192.168.20.1 192.168.110.1 192.168.13.1 192.168.21.1 172.27.13.1 192.168.114.1 172.27.15.1 172.27.16.1 172.27.17.1 172.28.18.1 172.27.19.1 172.27.20.1 172.27.21.1 172.27.22.1 172.28.23.1 172.27.24.1 172.27.25.1 172.27.26.1 172.27.27.1 172.27.28.1 172.27.29.1 172.27.30.1 172.27.31.1 172.27.32.1 172.27.33.1 172.28.34.1 172.28.35.1 172.27.36.1 172.28.37.1 172.28.38.1 172.27.39.1 172.27.40.1 172.27.41.1 172.28.42.1 172.28.43.1 172.27.44.1 172.27.45.1 172.27.46.1 172.28.47.1 172.27.48.1 172.27.49.1 172.27.50.1 172.27.51.1 172.28.53.1 172.28.54.1 172.27.56.1 172.27.57.1 172.28.58.1 172.27.59.1 172.27.60.1 172.27.61.1 172.28.63.1 172.27.64.1 172.28.65.1 172.28.66.1 172.28.67.1 172.28.68.1 172.27.69.1 172.27.70.1 172.27.71.1 172.28.72.1 172.28.73.1 172.28.74.1 172.27.75.1 172.27.76.1 172.27.77.1 172.27.78.1 172.27.79.1 172.27.80.1 172.27.81.1 172.27.82.1 172.28.83.1 172.27.84.1 172.27.85.1 172.27.86.1 172.28.87.1 172.28.88.1 172.28.89.1 172.27.90.1 172.27.91.1 172.27.92.1 172.28.93.1 172.28.94.1 172.28.95.1 172.28.96.1 172.27.97.1 172.27.98.1 172.27.99.1 172.27.100.1 172.27.101.1 172.27.102.1 172.28.103.1 172.28.104.1 172.28.105.1 172.28.106.1 172.28.107.1 172.28.108.1 172.28.109.1 172.28.110.1 172.27.111.1 172.28.112.1 172.27.113.1 172.27.114.1 172.27.115.1 172.27.116.1 172.27.117.1 172.28.118.1 172.28.119.1 172.27.120.1 172.27.121.1 172.27.122.1 172.27.123.1 172.27.124.1 172.27.125.1 172.27.126.1 172.27.127.1 172.27.128.1 172.28.129.1 172.27.130.1 172.28.131.1 172.28.132.1 172.28.133.1 172.28.134.1 172.28.135.1 172.27.136.1 172.28.137.1 172.28.138.1 172.27.139.1 172.27.140.1 172.27.141.1 172.27.142.1 172.27.143.1 172.28.144.1 172.27.145.1 172.28.146.1 172.28.147.1 172.27.148.1 172.28.149.1 172.27.150.1 172.28.151.1 172.28.152.1 172.28.153.1 172.27.154.1 172.28.155.1 172.27.156.1 172.28.157.1 172.28.158.1 172.28.159.1 172.28.160.1 172.27.161.1 172.28.162.1 172.28.163.1 172.27.164.1 172.27.165.1 172.27.166.1 172.27.167.1 172.28.168.1 172.27.169.1 172.27.170.1 172.28.171.1 172.28.172.1 172.28.173.1 172.28.174.1 172.28.175.1 172.27.176.1 172.28.177.1 172.28.178.1 172.28.179.1 172.28.180.1 172.28.181.1 172.27.182.1 172.28.183.1 172.27.184.1 172.27.185.1 172.28.186.1 172.28.187.1 172.27.188.1 172.28.189.1 172.28.190.1 172.27.191.1 172.27.192.1 172.28.193.1 172.27.194.1 172.27.195.1 172.27.196.1 172.27.197.1 172.28.198.1 172.28.199.1 10.173.0.1 10.172.1.1 10.173.2.1 10.173.3.1 10.173.4.1
解决方案
脚本冻结的核心原因是无限制的后台进程导致资源耗尽,以及SSH/rsync连接未设置足够严格的超时机制,以下是针对性优化方案:
1. 核心优化点
- 限制并发进程数:避免一次性启动数百个rsync进程,占用过多CPU和网络带宽,同时防止服务器拒绝过多连接。
- 强化超时控制:给SSH和rsync添加多层超时,彻底杜绝连接挂起导致的脚本冻结。
- 批量处理单IP任务:将单个IP的三个文件传输打包为一个后台任务,简化进程管理。
- 日志写入优化:避免多进程同时写入日志导致的内容错乱。
2. 修改后的脚本
#!/bin/bash SSH_KEY=/root/.ssh/id_rsa current_date=$(date +%Y-%m-%d) REPORT_FILE="/home/abdulrahman/scs/reports/file_report_$current_date.txt" # 创建日志目录(如果不存在) mkdir -p "$(dirname "$REPORT_FILE")" # 定义要传输的文件列表(数组形式,便于扩展) declare -a FILES=( "/home/abdulrahman/firefox-redhat-default-prefs.js:/usr/lib64/firefox/browser/defaults/preferences/" "/etc/hosts:/etc/" "/home/abdulrahman/Tamweely-CA.cer:/" ) # 并发进程数限制(根据服务器性能调整,建议10-20) MAX_PARALLEL=15 # 优化ping检测:更快判断主机存活 ping_ip() { local ip=$1 ip=$(echo "$ip" | tr -cd '[:digit:].') [ -z "$ip" ] && echo "跳过无效IP" && return 1 # 使用fping更快(如果没有则用原ping),或者保留ping但缩短超时 if command -v fping >/dev/null 2>&1; then fping -t 2000 -c 1 "$ip" >/dev/null 2>&1 else ping -W 2 -c 1 "$ip" >/dev/null 2>&1 fi if [ $? -eq 0 ]; then echo "IP $ip 在线" return 0 else echo "IP $ip 离线" return 1 fi } # 单个IP的完整文件传输任务 process_ip() { local ip_addr=$1 local success=0 local fail=0 # SSH超时配置:连接超时10秒,每5秒发心跳,3次无响应则断开 SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=10 -o ServerAliveInterval=5 -o ServerAliveCountMax=3" for file_pair in "${FILES[@]}"; do
相关产品推荐
相关产品推荐

