
背景写了个 Python 脚本每分钟往数据库写一次 CPU、内存数据* * * * * /usr/bin/python3 /home/YOUR_USER/app/write_db.py手动跑没问题但 Crontab 里跑总是失败。原因两个问题问题 1Crontab 环境没有 .env 变量write_db.py 里用 os.environ.get(“DB_ROOT_PASSWORD”) 读密码。手动跑时终端有这些变量但 Crontab 是一个干净的环境什么都没有。问题 2脚本可能堆积如果某次脚本卡住数据库慢、网络抖动1 分钟后又起一个进程10 分钟后堆积 10 个。解决第一步加载 .env* * * * * export $(cat /home/YOUR_USER/app/.env | xargs) /usr/bin/python3 /home/YOUR_USER/app/write_db.py /home/YOUR_USER/app/write_db.log 21拆解export $(cat .env | xargs) → 把 .env 里的 KEYVALUE 加载为环境变量 → 加载成功才执行后面的命令log 21 → 输出和错误都追加到日志第二步加锁防重入* * * * * flock -xn /tmp/write_db.lock bash -c export $(cat /home/YOUR_USER/app/.env | xargs) /usr/bin/python3 /home/YOUR_USER/app/write_db.py /home/YOUR_USER/app/write_db.log 21flock -xn 含义-x → 排他锁-n → 非阻塞拿不到锁立即退出不等待效果上一次没跑完这一次直接跳过。不会堆积。第三步验证# 看 Crontab 生效 crontab -l # 等 1 分钟看日志 tail -5 /home/YOUR_USER/app/write_db.log预期每分钟出现一条新记录。测锁生效# 手动持锁 30 秒 flock -xn /tmp/write_db.lock sleep 30 # 立刻再试一次应该拿不到锁 flock -xn /tmp/write_db.lock echo 这行不该输出 echo 退出码: $?预期第二行不输出退出码是 1。三个坑坑 1以为 Crontab 会继承用户环境不会。Crontab 的环境极其干净连 PATH 都跟登录 Shell 不一样。所有环境变量都要显式加载。坑 2export $(cat .env | xargs) 里 .env 有空格会炸如果 .env 的值里有空格比如 DB_DESCmy databasexargs 会把它拆成两个参数。.env 里尽量别写带空格的值。坑 3flock 的锁文件放 /tmp 就行不用放项目目录——/tmp 重启会自动清没有残留。而且不同脚本要用不同的锁文件/tmp/scriptA.lock、/tmp/scriptB.lock否则会互相阻塞。