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

脚本在命令行可运行但在Cron中执行失败:keyring错误

解决crontab运行yagmail脚本时的NoKeyringError问题

这个问题我之前帮朋友排查过,核心原因其实很典型:命令行运行脚本时你处于桌面会话中,系统的密钥环服务(比如gnome-keyring)是活跃的,但crontab是后台运行,没有加载桌面环境的上下文,导致keyring找不到可用的后端。下面给你几个实用的解决方案和排查思路:

快速解决方案(适合个人场景)

1. 直接在脚本中指定邮箱密码(最简单但安全性低)

如果是自己用的私人脚本,可以跳过keyring,直接在代码里传入邮箱账号和授权码/密码:

import yagmail
# 替换成你的邮箱地址和授权码(Gmail需要用应用专用密码,国内邮箱一般用授权码)
yag = yagmail.SMTP('your_email@example.com', 'your_email_password')
yag.send(to='notify_email@example.com', subject='脚本运行完成', contents='任务已执行完毕')

注意:不要把这个脚本共享给其他人,密码明文存储有风险。

2. 安装keyrings.alt替代后端

按照错误提示安装非推荐的后端包,让keyring在无桌面环境下也能工作:
首先安装包:

pip3 install keyrings.alt

然后在脚本开头添加代码指定使用明文文件存储密钥的后端(比明文写脚本里安全一点):

import keyring
from keyrings.alt.file import PlaintextKeyring
# 设置使用明文文件存储密钥
keyring.set_keyring(PlaintextKeyring())
# 后面正常使用yagmail即可
import yagmail
yag = yagmail.SMTP('your_email@example.com')
yag.send(...)

这个后端会把密码存在~/.keyring文件里,虽然是明文,但至少不会直接暴露在脚本中。

更安全的方案(适合追求安全性的场景)

如果想继续使用系统的gnome-keyring,需要让crontab运行时能访问密钥环服务,步骤稍复杂:

  1. 先记录桌面会话中的DBUS_SESSION_BUS_ADDRESS环境变量:在命令行输入echo $DBUS_SESSION_BUS_ADDRESS,复制输出内容(比如unix:path=/run/user/1000/bus)
  2. 编辑crontab任务时,添加这个环境变量:
    crontab -e
    
    修改任务行,比如:
    DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus 0 10 * * * /usr/bin/python3 /path/to/your/script.py >> /tmp/script.log 2>&1
    
    注意替换成你自己的DBUS_SESSION_BUS_ADDRESS值和脚本路径。

排查思路

  • 对比环境变量:在crontab里添加一行env > /tmp/cron_env.log,然后在命令行输入env > /tmp/shell_env.log,对比两个文件,看看crontab缺少哪些关键的桌面相关变量(比如DISPLAY、XDG_RUNTIME_DIR)
  • 模拟crontab环境:用su - your_username -c "python3 /path/to/script.py"模拟crontab的运行环境,看是否会出现同样的错误,这样更容易调试。

内容的提问来源于stack exchange,提问作者Hectobros

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 15:37:38