You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

远程服务器文件最后修改时间对比脚本问题求助

问题描述

我更新了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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 11:36:13