定时检查并同步时间的脚本

wen 实用脚本 3

本文目录导读:

定时检查并同步时间的脚本

  1. Linux 系统 (使用 cron 定时任务)
  2. Windows 系统 (PowerShell 脚本)
  3. macOS 系统
  4. Docker 容器内的时间同步
  5. 高级版本:带偏差检测和报警
  6. 使用建议

这里有几个不同场景下定时检查并同步时间的脚本,你可以根据操作系统和需求选择使用。

Linux 系统 (使用 cron 定时任务)

脚本:sync_time.sh

#!/bin/bash
# 时间同步脚本
# 支持:ntpdate, chronyd, systemd-timesyncd
log_file="/var/log/time_sync.log"
date_format="%Y-%m-%d %H:%M:%S"
# 获取当前时间
current_time=$(date +"$date_format")
echo "[$current_time] 开始时间同步检查..." >> $log_file
# 尝试不同的时间同步方法
sync_success=false
# 方法1: 使用 ntpdate (传统方法)
if command -v ntpdate &> /dev/null; then
    echo "使用 ntpdate 同步时间..." >> $log_file
    ntpdate -u pool.ntp.org >> $log_file 2>&1
    if [ $? -eq 0 ]; then
        sync_success=true
    fi
fi
# 方法2: 使用 chronyd
if command -v chronyc &> /dev/null && [ "$sync_success" = false ]; then
    echo "使用 chrony 同步时间..." >> $log_file
    chronyc -a makestep >> $log_file 2>&1
    if [ $? -eq 0 ]; then
        sync_success=true
    fi
fi
# 方法3: 使用 systemd-timesyncd
if command -v timedatectl &> /dev/null && [ "$sync_success" = false ]; then
    echo "使用 systemd-timesyncd 同步时间..." >> $log_file
    systemctl restart systemd-timesyncd >> $log_file 2>&1
    timedatectl set-ntp true >> $log_file 2>&1
    if [ $? -eq 0 ]; then
        sync_success=true
    fi
fi
# 记录同步结果
if [ "$sync_success" = true ]; then
    synced_time=$(date +"$date_format")
    echo "[$synced_time] 时间同步成功" >> $log_file
else
    echo "[$current_time] 时间同步失败" >> $log_file
fi
# 显示当前时间
echo "当前系统时间: $(date)"

设置定时任务 (每1小时同步一次)

# 赋予执行权限
chmod +x /path/to/sync_time.sh
# 编辑 crontab
crontab -e
# 添加以下行 (每小时执行一次)
0 * * * * /path/to/sync_time.sh
# 或者每30分钟执行一次
*/30 * * * * /path/to/sync_time.sh

Windows 系统 (PowerShell 脚本)

脚本:Sync-Time.ps1

# Windows 时间同步脚本
$logFile = "C:\Logs\time_sync.log"
$dateFormat = "yyyy-MM-dd HH:mm:ss"
# 创建日志目录(如果不存在)
$logDir = Split-Path $logFile -Parent
if (-not (Test-Path $logDir)) {
    New-Item -ItemType Directory -Path $logDir -Force
}
# 记录开始时间
$startTime = Get-Date -Format $dateFormat
"[$startTime] 开始时间同步..." | Out-File -FilePath $logFile -Append
# 方法1: 使用 w32tm (Windows Time Service)
try {
    # 停止时间服务
    Stop-Service w32time -Force
    # 重新配置
    w32tm /config /manualpeerlist:"pool.ntp.org" /syncfromflags:manual /reliable:yes /update
    # 启动服务
    Start-Service w32time
    # 强制同步
    w32tm /resync /force
    $syncTime = Get-Date -Format $dateFormat
    "[$syncTime] 时间同步成功" | Out-File -FilePath $logFile -Append
}
catch {
    $errorTime = Get-Date -Format $dateFormat
    "[$errorTime] 时间同步失败: $_" | Out-File -FilePath $logFile -Append
}
# 显示当前时间
Write-Host "当前系统时间: $(Get-Date)"

设置定时任务 (使用任务计划程序)

# 创建定时任务 (每小时执行一次)
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\Sync-Time.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "00:00" -RepetitionInterval (New-TimeSpan -Hours 1) -RepetitionDuration (New-TimeSpan -Days 365)
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
Register-ScheduledTask -TaskName "TimeSync" -Action $action -Trigger $trigger -Principal $principal -Settings $settings

macOS 系统

脚本:sync_time_mac.sh

#!/bin/bash
# macOS 时间同步脚本
log_file="$HOME/Library/Logs/time_sync.log"
current_time=$(date "+%Y-%m-%d %H:%M:%S")
echo "[$current_time] 开始同步时间..." >> "$log_file"
# macOS 使用 sntp 或 systemsetup
if command -v sntp &> /dev/null; then
    # 使用 sntp
    sudo sntp -sS pool.ntp.org >> "$log_file" 2>&1
    echo "使用 sntp 同步完成" >> "$log_file"
elif command -v systemsetup &> /dev/null; then
    # 使用 systemsetup
    sudo systemsetup -setusingnetworktime on >> "$log_file" 2>&1
    sudo systemsetup -setnetworktimeserver pool.ntp.org >> "$log_file" 2>&1
    echo "使用 systemsetup 设置完成" >> "$log_file"
fi
echo "当前时间: $(date)"
# 设置定时任务 (使用 launchd)
# 创建 plist 文件
cat > ~/Library/LaunchAgents/com.user.timesync.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.user.timesync</string>
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/sync_time_mac.sh</string>
    </array>
    <key>StartInterval</key>
    <integer>3600</integer>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF
# 加载定时任务
launchctl load ~/Library/LaunchAgents/com.user.timesync.plist

Docker 容器内的时间同步

# Dockerfile
FROM alpine:latest
# 安装 ntpdate
RUN apk add --no-cache ntpdate
# 创建同步脚本
COPY sync_time.sh /usr/local/bin/sync_time.sh
RUN chmod +x /usr/local/bin/sync_time.sh
# 设置定时任务 (每30分钟)
RUN echo "*/30 * * * * /usr/local/bin/sync_time.sh" > /etc/crontabs/root
CMD ["crond", "-f", "-l", "2"]

高级版本:带偏差检测和报警

#!/bin/bash
# 高级时间同步脚本 - 带偏差检测和报警
# 配置
NTP_SERVER="pool.ntp.org"
MAX_OFFSET=10        # 最大允许偏差(秒)
ALERT_EMAIL=""       # 报警邮箱(可选)
WEBHOOK_URL=""       # Slack/钉钉 Webhook(可选)
# 获取当前时间偏差
get_time_offset() {
    if command -v ntpdate &> /dev/null; then
        # 使用 ntpdate 的调试输出
        offset=$(ntpdate -q $NTP_SERVER 2>/dev/null | grep "offset" | awk '{print $NF}' | sed 's/,//')
        echo ${offset:-999}
    elif command -v chronyc &> /dev/null; then
        # 使用 chronyc
        offset=$(chronyc tracking 2>/dev/null | grep "RMS offset" | awk '{print $4}')
        echo ${offset:-999}
    else
        echo "999"
    fi
}
# 发送报警
send_alert() {
    local message="$1"
    local timestamp=$(date "+%Y-%m-%d %H:%M:%S")
    # 邮件报警
    if [ -n "$ALERT_EMAIL" ]; then
        echo "[$timestamp] $message" | mail -s "时间同步报警" "$ALERT_EMAIL"
    fi
    # Webhook 报警 (Slack 格式)
    if [ -n "$WEBHOOK_URL" ]; then
        curl -s -X POST -H "Content-Type: application/json" \
            -d "{\"text\":\"[$timestamp] $message\"}" \
            "$WEBHOOK_URL" > /dev/null 2>&1
    fi
    # 系统日志
    logger -t time-sync "ALERT: $message"
}
# 主逻辑
echo "检查时间偏差..."
offset=$(get_time_offset)
if [ "$offset" != "999" ]; then
    if (( $(echo "$offset > $MAX_OFFSET" | bc -l) )); then
        echo "时间偏差过大: ${offset}秒,尝试同步..."
        # 执行同步
        sync_time.sh
        send_alert "时间偏差 ${offset}秒,已执行同步"
    else
        echo "时间偏差正常: ${offset}秒"
    fi
else
    echo "无法获取时间偏差"
fi

使用建议

  1. 选择合适的时间间隔

    • 服务器:建议每30-60分钟同步一次
    • 桌面系统:每2-4小时同步一次
    • 嵌入式系统:每6-12小时同步一次
  2. 注意事项

    • 确保网络连接可用
    • 某些系统可能需要 root/管理员权限
    • 考虑使用多个 NTP 服务器提高可靠性
    • 记录日志便于排查问题
  3. 备份方案

    • 本地 RTC (硬件时钟) 作为备用
    • 使用多个 NTP 服务器 (pool.ntp.org 自动负载均衡)

根据你的具体需求选择合适的脚本和配置。

抱歉,评论功能暂时关闭!