【问题标题】:MQTT Python unable to start Bash script when invoked via cron通过 cron 调用时,MQTT Python 无法启动 Bash 脚本
【发布时间】:2017-01-31 21:01:03
【问题描述】:

好的,过去几周这一直让我发疯,我不知道发生了什么事,所以我希望能全神贯注,看看是否有更聪明的人能弄清楚发生了什么,或者至少让我走上正轨,弄清楚发生了什么。

我有 200 多台 ARM 设备(Raspberry Pi 3)运行客户端脚本 (Python v2.7),连接到 1 台 ARM 设备,即我所谓的服务器,运行 MQTT (v3.1.1)。

因为经常会添加很多调整和新功能,所以我继续创建了一个“更新”功能。

基本上,它的工作原理如下:

  1. 客户端连接到 MQTT ->
  2. 客户端发送运行客户端脚本版本->
  3. 如果更新可用,服务器会响应 .tar.gz 文件的链接 ->
  4. 客户端下载 .tar.gz 文件并解压。
  5. 客户端在解压后的文件夹中运行标准 bash 脚本“update.sh”。

此 bash 文件包含新命令,例如“apt-get update”或新软件包和新脚本(取决于需要安装的内容。)

通过向特定主题发送有效负载(例如带有链接的“更新/[设备名称]”)来强制客户端进行更新。设备订阅了该主题,并在获得此有效负载时下载并运行该文件。

现在这是绝对奇怪的部分!

效果很好!

你说的很完美,那你为什么需要帮助?

嗯,当我通过 SSH 运行脚本时,它完美运行。 如果我在启动时运行脚本,除了更新之外一切正常。似乎更新了味精,似乎获取了文件并解压,但运行 bash 脚本似乎失败。

目前,Python 使用以下命令运行 bash 脚本:

call(["sudo", "sh", "/update/update.sh"])

如果我不得不猜测:

它没有运行 bash 脚本。我不确定为什么。正如我之前提到的,当我通过 SSH 运行它时它运行良好,不知何故,当 crontab 在重新启动时运行它时,它不会被调用。

它确实拥有所有特权,据我所知,不是这样。

我试过了:

嗯,我能想到的几乎都是!不同的调用方法,从 subprocess.call 到 os.call,似乎没有任何效果。我还在 sudoers 下添加了用户,我还尝试记录 Python 和 Bash 脚本的输出。 Python 没有显示任何错误,而且 Bash 日志文件似乎根本没有启动。

我们将不胜感激!

【问题讨论】:

  • 你可以试试shell=True
  • @Jean-FrançoisFabre,请不要在没有令人信服的理由的情况下提出增加更多复杂性和额外故障点的建议。
  • 这只是一个评论,而不是一个答案。如果它不起作用,那就太糟糕了。
  • ...所以,cron 的环境和典型的用户环境有很大的不同。首先要检查这些差异。
  • 例如,如果脚本依赖于/usr/local/bin 中的内容,而用于cron 的PATH/bin:/usr/bin,那么你就是。

标签: python linux bash shell ssh


【解决方案1】:

这里有几个可能的差异。举几个特别有可能的例子:

  • cron 暴露的环境可能缺少用户登录脚本建立的变量,这些变量是手头脚本成功运行所必需的。

    比较 os.environ 在工作和非工作案例之间可能会提供信息。

  • 您的 sudo 命令可能需要 TTY。

    捕获命令的标准错误,并在错误时检查它,在这里可能会有所帮助。使用set -x shell 选项,如下所示,将通过捕获由 shell 调用的确切命令,使此日志更加丰富(如果事实上sudo 成功执行了您的 shell;如果您需要 TTY /etc/sudoers,可能不会)。

    cmd = ['sudo', 'sh', '-x', '/update/update.sh']
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (output, err) = p.communicate()
    if p.returncode != 0:
      # TODO: LOG THE CONTENTS OF err SOMEWHERE YOU CAN REVIEW THEM!
      raise subprocess.CalledProcessError(p.returncode, err)
    

【讨论】:

  • @user5740843,很高兴您的问题得到了解决 - 是否有机会就问题的原因或确切的问题提供反馈?
  • os.environ 似乎与 cron 和普通用户不同。我已经以不同的方式设置了 os.environ['PATH'] 和 os.environ['HOME'] 并且它能够正常工作。再次感谢!
  • 顺便说一下,您可以直接在 crontab 中设置这些,方法是在文件顶部添加 PATH=...HOME=... 行。
猜你喜欢
  • 2011-08-15
  • 2011-08-14
  • 2012-04-03
  • 1970-01-01
  • 2015-08-05
  • 2011-08-10
  • 2020-09-27
  • 2016-11-26
  • 2023-03-06
相关资源
最近更新 更多