Crontab执行Python REST请求脚本报临时域名解析错误问题求助
问题描述
我需要每天凌晨3点运行一个通过REST API请求数据的Python脚本,为此配置了如下crontab定时任务:
0 3 * * * python3 /home/pi/path/to/script.py >> /home/pi/logfile.txt 2>&1
手动执行该脚本时运行正常,但通过cron启动时会抛出名称服务器无法解析请求的错误,报错栈如下:
File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 159, in _new_conn (self._dns_host, self.port), self.timeout, **extra_kw) File "/usr/lib/python3/dist-packages/urllib3/util/connection.py", line 57, in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo for res in _socket.getaddrinfo(host, port, family, type, proto, flags): socket.gaierror: [Errno -3] Temporary failure in name resolution
已确认两种执行方式的运行用户均为pi,且网络处于公司代理环境下,手动运行时代理生效无异常。原本以为二者执行环境完全一致,想知道两种执行方式的差异是什么?
运行环境信息
- 硬件:Pi4 4GB
- OS:Linux raspi 5.10.11-v7l+ #1399 SMP Thu Jan 28 12:09:48 GMT 2021 armv7l GNU/Linux
- 软件:
- Python 3.7.3 (default, Jul 25 2020, 13:03:44) [GCC 8.3.0] on linux
- requests==2.21.0
问题原因及解决方法
核心差异
cron执行任务时使用的是非交互式非登录shell,不会自动加载用户目录下的.bashrc、.profile等配置文件,因此你在这些文件中配置的代理相关环境变量(http_proxy、https_proxy)在cron的执行环境中不存在。而你手动执行脚本时用的是登录/交互式shell,会正常加载这些环境变量,所以代理生效请求正常。
缺失代理配置后,请求无法通过公司代理完成域名解析,就会抛出Temporary failure in name resolution报错。
解决方案
可以通过封装执行脚本的方式预先加载代理配置,步骤如下:
- 新建一个bash执行脚本,内容如下:
#!/bin/bash export http_proxy="http://proxyip:proxyport" export https_proxy="http://proxyip:proxyport" python3 /home/pi/path/to/script.py >> /home/pi/logfile.txt 2>&1
- 给脚本添加可执行权限:
chmod +x /home/pi/path/to/run_script.sh - 修改crontab配置,调用该bash脚本即可:
0 3 * * * /home/pi/path/to/run_script.sh
除此之外也可以直接在crontab配置的开头声明全局环境变量,或者在Python脚本中主动设置requests的代理参数,可根据自己的使用场景选择。
内容的提问来源于stack exchange,提问作者Moritz Vierneusel
相关产品推荐
相关产品推荐

