远程服务器文件最后修改时间对比脚本问题求助
问题描述
我更新了Bash脚本,为时间对比单独设置了变量,但仍无法正确处理第二个服务器的文件。该脚本旨在远程检查多台服务器上文件的最后修改时间,并与20分钟阈值(OLDTIME=1200)进行校验。当前脚本仅处理了svr1的/path/to/log/svr.log,未正确处理svr2的同路径文件,输出结果重复显示svr1的文件状态。需要解决两个核心问题:
- 让脚本遍历处理所有目标服务器;
- 若已有一个文件符合更新要求,则跳过后续服务器的检查。
原脚本
#!/bin/bash set -x s11=$(ssh -q -l user svr1 "find /path/to/log/svr.log -printf '%T+ %p' | sort") s12=$(ssh -q -l user svr2 "find /path/to/log/svr.log -printf '%T+ %p' | sort") s11r=$(echo $s11 | awk '{print $2}') s12r=$(echo $s12 | awk '{print $2}') for myservers in $s11r $s12r; do OLDTIME=1200 #20 minutes file threshold FILETIME=$(stat -c %Y "${myservers}") CURTIME=$(perl -e 'print time') TIMEDIFF=$(($CURTIME - $FILETIME)) if [[ $TIMEDIFF -gt $OLDTIME ]]; then echo -e "$myservers: old time" else echo "$myservers: all good" fi done
原执行输出
++ ssh -q -l user svr1 'find /path/to/log/svr.log -printf '\''%T+' '%p'\'' | sort' + s11='2022-07-21+03:09:19.3550802140 /path/to/log/svr.log' ++ ssh -q -l user svr2 'find /path/to/log/svr.log -printf '\''%T+' '%p'\'' | sort' + s12='2022-07-21+03:25:53.3758441030 /path/to/log/svr.log' ++ echo 2022-07-21+03:09:19.3550802140 /path/to/log/svr.log ++ awk '{print $2}' + s11r=/path/to/log/svr.log ++ echo 2022-07-21+03:25:53.3758441030 /path/to/log/svr.log ++ awk '{print $2}' + s12r=/path/to/log/svr.log + for myservers in '$s11r' '$s12r' + OLDTIME=1200 ++ stat -c %Y /path/to/log/svr.log + FILETIME=1658381370 ++ perl -e 'print time' + CURTIME=1658381855 + TIMEDIFF=485 + [[ 485 -gt 1200 ]] + echo '/path/to/log/svr.log: all good' /path/to/log/svr.log: all good + for myservers in '$s11r' '$s12r' + OLDTIME=1200 ++ stat -c %Y /path/to/log/svr.log + FILETIME=1658381370 ++ perl -e 'print time' + CURTIME=1658381855 + TIMEDIFF=485 + [[ 485 -gt 1200 ]] + echo '/path/to/log/svr.log: all good' /path/to/log/svr.log: all good
解决方案
原脚本的核心问题是:循环中使用本地stat命令检查文件,而非远程执行;未设置标记提前终止循环。以下是修正后的脚本:
#!/bin/bash set -x # 定义目标服务器列表,可按需扩展 servers=("svr1" "svr2") OLDTIME=1200 # 20分钟阈值,单位:秒 target_file="/path/to/log/svr.log" found_valid_file=false # 标记是否找到符合要求的文件 # 遍历所有目标服务器 for server in "${servers[@]}"; do # 若已找到有效文件,直接跳过当前服务器检查 if $found_valid_file; then echo "已找到符合要求的文件,跳过服务器 $server 的检查" continue fi # 远程获取文件修改时间戳,同时处理文件不存在的情况 remote_timestamp=$(ssh -q -l user "$server" "stat -c %Y '$target_file' 2>/dev/null") if [[ -z "$remote_timestamp" ]]; then echo "服务器 $server 上的文件 $target_file 不存在或无法访问" continue fi # 获取当前时间戳(用bash内置命令替代perl,更轻量化) current_timestamp=$(date +%s) time_diff=$((current_timestamp - remote_timestamp)) if [[ $time_diff -gt $OLDTIME ]]; then echo "$server:$target_file: 文件已过期" else echo "$server:$target_file: 文件状态正常" found_valid_file=true # 设置标记,后续服务器不再检查 fi done
关键修改说明
- 服务器列表化:用数组
servers存储目标服务器,便于后续添加或修改服务器; - 远程执行文件检查:直接在远程服务器上运行
stat命令获取时间戳,避免本地处理远程路径的错误; - 提前终止逻辑:通过
found_valid_file标记,一旦找到符合要求的文件,直接跳过后续服务器的检查; - 轻量化时间戳获取:用
date +%s替代perl获取当前时间戳,减少外部依赖; - 错误处理:增加了文件不存在或无法访问的提示逻辑。
修正后执行输出示例
++ servers=("svr1" "svr2") ++ OLDTIME=1200 ++ target_file=/path/to/log/svr.log ++ found_valid_file=false ++ for server in "${servers[@]}" ++ '[' false ']' ++ ssh -q -l user svr1 'stat -c %Y '/path/to/log/svr.log' 2>/dev/null' ++ remote_timestamp=1658381370 ++ [[ -z 1658381370 ]] ++ date +%s ++ current_timestamp=1658381855 ++ time_diff=485 ++ [[ 485 -gt 1200 ]] ++ echo 'svr1:/path/to/log/svr.log: 文件状态正常' svr1:/path/to/log/svr.log: 文件状态正常 ++ found_valid_file=true ++ for server in "${servers[@]}" ++ '[' true ']' ++ echo '已找到符合要求的文件,跳过服务器 svr2 的检查' 已找到符合要求的文件,跳过服务器 svr2 的检查
内容的提问来源于stack exchange,提问作者Ash
相关产品推荐
相关产品推荐

