惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
博客园_首页
博客园 - 聂微东
T
Tailwind CSS Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
The Cloudflare Blog
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
D
Docker
人人都是产品经理
人人都是产品经理
WordPress大学
WordPress大学
博客园 - 三生石上(FineUI控件)
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
Apple Machine Learning Research
Apple Machine Learning Research
阮一峰的网络日志
阮一峰的网络日志
B
Blog RSS Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
Jina AI
Jina AI
博客园 - Franky
D
DataBreaches.Net

OhYee 博客

小鹏辅助驾驶测评|OhYee 博客 小鹏非支持手机开启自动解锁|OhYee 博客 使用函数计算实现 301 重定向|OhYee 博客 针对 HTML 内容使用 Ant Design 图片弹框|OhYee 博客 博客进程泄露及僵尸进程解决|OhYee 博客 蓝易云服务器体验|OhYee 博客 SSH 调起本地 VSCode|OhYee 博客 【2022 秋招内推】阿里云后端研发工程师|OhYee 博客 使用函数计算获取 IP 地址信息|OhYee 博客 正确获取客户端 IP/HTTP Header 也可能重复|OhYee 博客 评测 Oculus Quest2 及 BigScreen|OhYee 博客 NextJS 热重载保留状态|OhYee 博客 如何优雅地贴 gist 代码|OhYee 博客 Linux 精细化文件权限|OhYee 博客 VSCode 容器开发环境|OhYee 博客 Clash 的不兼容更新排查|OhYee 博客 Zeek 导出 PCAP|OhYee 博客 记一次 ssh 配置问题|OhYee 博客 Git Commit 规范化工具|OhYee 博客 谈谈《星之卡比-探索发现》|OhYee 博客 VSCode 快捷键绑定 Shell 命令|OhYee 博客 ASN.1 语法及 X.509 证书格式解析解析|OhYee 博客 腾讯企业邮箱忽略 MX 记录发信|OhYee 博客 Chrome/Edge 标签组插件|OhYee 博客 【应届内推】阿里云后端研发工程师|OhYee 博客 损坏的 Typecho 备份处理为 JSON|OhYee 博客 VS Code VIM 插件高效使用|OhYee 博客 SSH 正反向代理|OhYee 博客 Let's Encrypt 根证书过期引发的问题|OhYee 博客 OpenWRT 忽略内核依赖|OhYee 博客
为 crontab 正确设置环境变量避免无法正确运行程序|OhYee 博客
2020-09-04 · via OhYee 博客

crontab 本身不携带系统环境变量,因此如果需要运行 Pyhon 等脚本,可能会导致找不到相应的第三方包

这是一篇最后编辑于 6 年前 的文章,其内容可能与目前实际情况差异较大,请注意甄别

为 crontab 正确设置环境变量避免无法正确运行程序

问题简述: 直接运行能正确执行的定时爬虫在 crontab 中无法执行
解决方案: 在 crontab 执行的脚本中使用 export 手动设置环境变量

问题背景

该博客的自动爬虫是每天凌晨三点自动执行的。原本是可以正常进行的,但是某天开始突然发现爬虫数据一直不会更新。

经过检查,其他的定时任务(百度自动推送、自动备份)都可以正确进行。因此怀疑是爬虫的 Python 脚本出现问题,但是其直接运行又没有任何问题。

问题探索

首先想到的是是否是权限问题,检查了脚本是 root 运行(即脚本定时任务配置在sudo crontab -e,而非crontab -e)。同时相应的 Shell 执行文件、Python 脚本都没有任何权限问题(严格来说也没有能限制 root 用户的情况吧)

于是猜测是 Python 脚本本身存在问题,因此尝试将报错信息重定向到文件中。相应的 crontab 配置如下:

0 3 * * * bash /home/ubuntu/blog/spider 1>>/home/ubuntu/blog/crontab.log 2>>/home/ubuntu/blog/crontab.err

在 Linux 系统中,万物皆文件,因此内容输入和输出的设备(终端)也对应着不同类型的文件,称为标准输出流(stdout)、标准错误流(stderr)、标准输入流(stdin)。如果有 C++ 编程经验,应该是很熟悉这些“文件的”。
其中,标准输入流和标准输出流就是通常在命令行程序中的输入和输出。而为了将错误与输出分离开,还存在标准错误流(程序日志过多可能会导致错误信息被覆盖在信息流中,难以阅读)
在文件重定向中,1>>表示重定向标准输出流,2>>表示重定向标准错误流。
这样,就可以将上述脚本的执行过程中的所有输出内容保存到文件中

通过查看错误输出,可以发现问题的关键所在:

ModuleNotFoundError: No module named 'pymongo'

Python 无法找到相应的第三方包。但是明明已经在 root 和 普通用户下都安装了第三方包,sudo bash spiderbash spider 都可以正常运行。
因此猜测问题可能出在环境变量上

使用env可以输出所有的环境变量,将该命令在 crontab 中执行,并保存输出内容。可以看到:

HOME=/root
LOGNAME=root
PATH=/usr/bin:/bin
LANG=en_US.utf8
SHELL=/bin/sh
PWD=/root

这说明,尽管 crontab 以某个特定用户权限执行,但是其并未配置对应的环境变量。而这也可能导致crontab 找不到 Python 等程序的问题

解决方案

要解决该问题也很容易,手动设置环境变量即可。

以 Python 为例,首先可以使用which python获得 Python 的运行地址,如:

$ which python3.8
/usr/bin/python3.8

而后,在 Python 中,使用sys.path获取其环境变量

$ python3.8
Python 3.8.0 (default, Oct 28 2019, 16:14:01)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/ubuntu/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']

这些目录就是 Python 在 import 包时检索的地址。可以使用PYTHONPATH环境变量来设置这些地址。

由于只需要设置临时的环境变量,不需要设置成用户级环境变量,因此可以使用export来实现该要求(=两边没有空格,使用:作为不同目录的分隔符)

再加上使用绝对路径调用 Python,即可完美使用 crontab 定时调用 Python。对应的脚本如下:

#!/bin/bash
export PYTHONPATH="/usr/lib/python38.zip:/usr/lib/python3.8:/usr/lib/python3.8/lib-dynload:/home/ubuntu/.local/lib/python3.8/site-packages:/usr/local/lib/python3.8/dist-packages:/usr/lib/python3/dist-packages"
/usr/bin/python3.8 /home/ubuntu/blog/blotter/spider/main.py >> /home/ubuntu/blog/spider.log