Armbian设备Python更新RTC时间脚本异常处理优化问询
问题分析与解决方案
原代码常见问题
- 未处理权限问题:写入RTC设备需要root权限,普通用户执行会直接报错,尤其是外接的
/dev/rtc1 - 忽略RTC硬件初始化状态:部分RTC芯片在从未设置过时间的情况下,读/写操作会抛出IO异常,原代码未捕获这类场景
- 未验证系统时间同步结果:联网同步ntp时可能因网络问题失败,原代码直接继续写RTC,导致写入错误时间
- 缺乏写入后验证:写完RTC后未读取确认,硬件故障导致的写入失败无法被发现
- 异常捕获不全面:仅捕获特定异常或完全未处理,脚本遇到意外直接崩溃
改进后的健壮代码
import subprocess import time import os def check_root(): if os.geteuid() != 0: print("错误:必须以root权限运行此脚本") exit(1) def sync_system_time(): """联网同步系统时间,带重试机制""" max_retries = 3 retry_delay = 5 for attempt in range(max_retries): try: # 使用chronyd同步(Armbian默认工具) result = subprocess.run( ["chronyc", "-a", "makestep"], check=True, capture_output=True, text=True ) print(f"系统时间同步成功:{result.stdout.strip()}") return True except subprocess.CalledProcessError as e: print(f"同步尝试 {attempt+1}/{max_retries} 失败:{e.stderr.strip()}") time.sleep(retry_delay) except FileNotFoundError: # 兼容旧版Armbian的ntpdate工具 try: subprocess.run( ["ntpdate", "pool.ntp.org"], check=True, capture_output=True, text=True ) print("使用ntpdate同步系统时间成功") return True except subprocess.CalledProcessError as e: print(f"ntpdate同步失败:{e.stderr.strip()}") time.sleep(retry_delay) print("所有同步尝试失败,使用当前系统时间继续") return False def set_rtc(rtc_device, rtc_name): """写入RTC并验证,处理未初始化的RTC场景""" try: # 预读取RTC状态,检测硬件可用性 with open(f"/sys/class/rtc/{rtc_device}/date", "r") as f: current_date = f.read().strip() with open(f"/sys/class/rtc/{rtc_device}/time", "r") as f: current_time = f.read().strip() print(f"{rtc_name} 当前时间:{current_date} {current_time}") except OSError: # 未初始化的RTC可能无法读取,直接跳过检测尝试写入 print(f"{rtc_name} 未初始化,直接尝试写入") try: # 用hwclock命令写入(比直接操作sysfs更稳定) subprocess.run( ["hwclock", "--systohc", "--rtc", f"/dev/{rtc_device}"], check=True, capture_output=True, text=True ) # 验证写入结果 result = subprocess.run( ["hwclock", "--show", "--rtc", f"/dev/{rtc_device}"], check=True, capture_output=True, text=True ) print(f"{rtc_name} 写入成功,当前时间:{result.stdout.strip()}") return True except subprocess.CalledProcessError as e: print(f"{rtc_name} 写入失败:{e.stderr.strip()}") return False except PermissionError: print(f"{rtc_name} 权限不足:需要root权限") return False except OSError as e: print(f"{rtc_name} 硬件错误:{str(e)}") return False def main(): check_root() print("=== 开始同步时间流程 ===") # 1. 同步系统时间 sync_system_time() # 2. 更新无电池备份的RTC0 set_rtc("rtc0", "内置RTC0") # 3. 更新带电池备份的RTC1 set_rtc("rtc1", "外接RTC1") print("=== 时间同步流程结束 ===") if __name__ == "__main__": main()
关键改进点
- 权限前置检查:启动时立即验证root权限,避免后续无效操作
- 网络同步重试:支持两种同步工具,最多重试3次,网络不通时降级使用当前系统时间
- RTC异常全覆盖:处理权限错误、硬件未初始化、IO故障等场景,针对未初始化的RTC直接尝试写入
- 写入验证机制:每次写入后读取RTC时间确认,确保操作生效
- 清晰日志输出:每一步操作都有明确反馈,方便定位故障
内容的提问来源于stack exchange,提问作者Tibibs
相关产品推荐
相关产品推荐

