本文目录导读:

这里有几个不同场景下定时检查并同步时间的脚本,你可以根据操作系统和需求选择使用。
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
使用建议
-
选择合适的时间间隔:
- 服务器:建议每30-60分钟同步一次
- 桌面系统:每2-4小时同步一次
- 嵌入式系统:每6-12小时同步一次
-
注意事项:
- 确保网络连接可用
- 某些系统可能需要 root/管理员权限
- 考虑使用多个 NTP 服务器提高可靠性
- 记录日志便于排查问题
-
备份方案:
- 本地 RTC (硬件时钟) 作为备用
- 使用多个 NTP 服务器 (pool.ntp.org 自动负载均衡)
根据你的具体需求选择合适的脚本和配置。