Ubuntu下systemd服务运行Python脚本时goodreads-user-scraper未识别
问题与解决方案
问题描述
我有一个goodreads-user-scraper工具,在Ubuntu终端运行包含它的scheduler.py脚本(通过cron调度)时一切正常,能完成站点爬取并将文件保存到脚本指定的output_dir。但当我通过socialAggregator.service服务文件运行该脚本时,goodreads-user-scraper却无法被识别,使用的是终端中运行的同一脚本。
错误日志:
Jan 12 22:13:15 speedypersonal2 python[2668]: --user_id: 1: goodreads-user-scraper: not found
服务文件socialAggregator.service内容:
[Unit] Description=Run Social Aggregator scheduler - collect data from API's and store in socialAggregator Db --- DEVELOPMENT --- After=network.target [Service] User=nick ExecStart= /home/nick/environments/social_agg/bin/python /home/nick/applications/socialAggregator/scheduler.py --serve-in-foreground [Install] WantedBy=multi-user.target
scheduler.py关键代码片段:
def run_goodreads(): logger_init.info(f"- START run_goodreads() -") output_dir = os.path.join(config.PROJ_DB_PATH) goodreads_process = subprocess.Popen(['goodreads-user-scraper', '--user_id', config.GOODREADS_ID,'--output_dir', output_dir], shell=True, stdout=subprocess.PIPE) logger_init.info(f"- send subprocess now on::: goodreads_process.communicate() -") _, _ = goodreads_process.communicate() logger_init.info(f"- FINISH run_goodreads() -")
问题原因
systemd服务运行时的环境变量PATH与终端登录后的PATH存在核心差异:
- 终端会加载用户的shell配置文件(如
.bashrc、.profile),这些文件会把goodreads-user-scraper的安装路径加入PATH,因此能正常找到命令。 - systemd服务默认不会加载用户的shell配置,导致PATH不包含该工具的路径,自然无法识别命令。
- 代码中使用
shell=True后,subprocess会调用默认的/bin/sh而非终端的bash,进一步放大了环境变量的差异。
解决思路
使用工具的绝对路径:在终端执行
which goodreads-user-scraper获取工具的绝对路径(例如/home/nick/environments/social_agg/bin/goodreads-user-scraper),替换subprocess中的命令:goodreads_process = subprocess.Popen(['/home/nick/environments/social_agg/bin/goodreads-user-scraper', '--user_id', config.GOODREADS_ID,'--output_dir', output_dir], shell=True, stdout=subprocess.PIPE)在service文件中指定PATH:在
[Service]段添加Environment变量,将工具所在目录加入PATH(可从终端执行echo $PATH复制完整路径):[Service] User=nick Environment="PATH=/home/nick/environments/social_agg/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ExecStart= /home/nick/environments/social_agg/bin/python /home/nick/applications/socialAggregator/scheduler.py --serve-in-foreground关闭
shell=True(推荐):由于已经使用列表传参,shell=True完全没必要,关闭它不仅能规避shell环境差异问题,还能提升安全性(防止命令注入)。修改代码如下:goodreads_process = subprocess.Popen(['goodreads-user-scraper', '--user_id', config.GOODREADS_ID,'--output_dir', output_dir], stdout=subprocess.PIPE)配合前两种方法中的任意一种,即可正常运行。
内容的提问来源于stack exchange,提问作者costa rica
相关产品推荐
相关产品推荐

