好的,所以这让我疯了几个星期,我不知道发生了什么,所以我希望能挑选你所有的大脑,看看是否有人更聪明可以弄清楚发生了什么或者至少让我上场找出发生了什么的轨道。
我有200多个ARM设备(Raspberry Pi 3)运行客户端脚本(Python v2.7)连接到1个ARM设备,我所谓的服务器,运行MQTT(v3.1.1)。
因为经常添加了很多调整和新功能,所以我继续创建了一个“更新”功能。
基本上,它的工作原理如下:
- 客户端连接到MQTT - >
- 客户端发送运行客户端脚本版本 - >
- 如果更新可用,并且链接指向.tar.gz文件,则服务器会响应 - >
- 客户端下载.tar.gz文件并将其解压缩。
- 客户端在解压缩文件夹中运行标准bash脚本'update.sh'。
此bash文件包含新命令,例如'apt-get update'或新包和新脚本(取决于需要安装的内容)。
通过向特定主题发送有效负载来强制更新客户端,例如带有链接的“update / [devicename]”。设备已订阅此主题,并在获取此有效内容时下载并运行该文件。
现在这是绝对奇怪的部分!
它完美无缺!
完美的你说,那你为什么需要帮助?
好吧,只有当我通过SSH运行脚本时,它才能完美运行。如果我在启动时运行脚本,除了更新之外一切正常。它似乎得到了msg更新,它似乎获取文件并解压缩它,但它似乎无法运行bash脚本。
目前,Python使用以下命令运行bash脚本:
call(["sudo", "sh", "/update/update.sh"])
如果我不得不猜测:
它没有运行bash脚本。我不知道为什么。正如我之前提到的,当我通过SSH运行时,它运行得很完美,不知何故,当crontab在重启时运行它时,它将不会被调用。
它确实拥有所有特权,所以据我所知,那不是它。
我试过了:
好吧,我几乎可以想到的一切!不同的调用方法,从subprocess.call到os.call,似乎没什么用。我还在sudoers下添加了用户,我也尝试记录Python和Bash脚本的输出。 Python没有显示任何错误,Bash日志文件似乎根本没有启动。
任何帮助将非常感激!
这里有几个可能的差异。仅举几例:
cron
暴露的环境可能缺少用户登录脚本建立的变量,这些变量对于手头脚本的成功操作是必需的。
比较工作和非工作案例之间的os.environ
可能会提供信息。sudo
命令可能需要TTY。
捕获命令的stderr并在出错时检查它可能对此有所帮助。使用set -x
shell选项,如下所示,通过捕获shell调用的确切命令,使该日志更具信息性(如果实际上sudo
成功执行了shell;如果/etc/sudoers
需要TTY,则可能不)。
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)