Raspberry Pi 0W运行Python拍照脚本一周后崩溃,重启报段错误求助
以下是导致运行一周后出现segmentation fault的几个核心原因,结合你的脚本和硬件环境逐一分析:
1. 文件资源泄漏
你的脚本中用open()打开图片文件后,没有显式关闭文件句柄。虽然requests可能会在发送后处理部分资源,但长期循环运行(每天数百次调用)会累积未释放的文件句柄,耗尽系统的文件描述符资源,最终触发底层的段错误。而且脚本里的异常捕获逻辑几乎吞掉了所有错误,无法及时发现这类泄漏问题。
2. USB摄像头硬件资源泄漏
fswebcam直接操作USB摄像头的硬件驱动,Raspberry Pi 0W的USB带宽和硬件资源本身就很有限。如果每次调用fswebcam后,驱动没有正确释放摄像头的硬件锁或缓冲区,长期运行会导致驱动层的资源耗尽,进而引发内核级的段错误——这类问题通常只能通过重启系统或重装驱动修复,而格式化SD卡重装系统相当于重置了驱动状态。
3. SD卡文件系统隐性损坏
你每天频繁创建、删除图片文件,SD卡本身是闪存介质,长期随机写入会产生碎片化,甚至出现隐性的文件系统损坏。当Python进程尝试访问损坏的文件或存储块时,就可能触发段错误。重装系统格式化SD卡会修复文件系统的损坏,这也侧面印证了存储层面的问题。
4. requests连接池资源泄漏
脚本中尝试关闭r.connection.close(),但如果请求失败(比如触发超时或网络异常),r变量可能未被定义,这部分的异常被吞掉后,连接池里的网络连接无法被正常释放。长期累积会耗尽网络套接字资源,导致requests底层的库(比如urllib3)出现崩溃,表现为Python进程的段错误。
5. 脚本逻辑的隐性错误
你的while循环中,第一次调用take_photo()时date变量还未定义,但take_photo()里直接用了datetime.timestamp(date)——这会触发NameError,但这部分代码不在任何try-except块里,理论上脚本应该直接崩溃。如果实际运行中你做了调整但没修正逻辑,这类未被捕获的异常可能会导致进程状态异常,长期累积后触发段错误。
对应的修复建议
- 文件资源管理:用
with open(...) as f语法打开文件,让Python自动处理文件关闭,比如:with open(filePath, 'rb') as f: photo = {'photo': f} r = requests.post(url=url, data=payload, headers=headers, files=photo) - 摄像头资源释放:改用
subprocess.run()调用fswebcam,捕获返回码确保命令正常执行,每次调用后添加1-2秒的延迟,让驱动有时间释放资源:result = subprocess.run(["fswebcam", "-r", "1280x720", "-S", "15", "--no-banner", file_path], capture_output=True) if result.returncode != 0: print(f"fswebcam failed: {result.stderr.decode()}") - 存储优化:将图片目录挂载到
tmpfs(内存文件系统),减少SD卡写入:
在/etc/fstab中添加一行:tmpfs /home/esjee/photo-monster/photos tmpfs defaults,size=100M 0 0,重启后生效。同时启用文件系统自动修复,在fstab中对应SD卡的行添加errors=remount-ro。 - 连接池管理:使用
requests.Session()来统一管理连接,确保连接被复用或正确释放:session = requests.Session() try: r = session.post(url=url, data=payload, headers=headers, files=photo) finally: session.close() - 修正循环逻辑:把
date = datetime.today()移到take_photo()调用之前,避免未定义变量:while x > 0: date = datetime.today() take_photo() if (date.hour > 22 and date.minute > 45): break
内容的提问来源于stack exchange,提问作者esjee

