简体   繁体   中英

MQTT Python unable to start Bash script when invoked via cron

Okay so this has been driving me insane for the last couple of weeks and I have no idea what's going on so I'm hoping to pick all of your brains and see if someone smarter can figure out what's going on or at least get me on the track to figuring out what's going on.

I have 200 odd ARM devices (Raspberry Pi 3's) running a client script (Python v2.7) connecting to 1 ARM device, my so called server, running the MQTT (v3.1.1).

Because a lot of tweaks and new functions are added on a frequent basis, I went ahead and created a 'update' function.

Essentually, it works as follows:

  1. Client connect to MQTT ->
  2. Client sends running client script version ->
  3. Server responds if update is available with a link to a .tar.gz file ->
  4. Client downloads .tar.gz file and unpacks it.
  5. Client runs standard bash script 'update.sh' in unpacked folder.

This bash file contains new commands, such as 'apt-get update' or new packages and a new script (depending what needs to be installed.)

The update is forced upon the client by sending a payload to a specific topic, like 'update/[devicename]' with the link. The device is subscriped to this topic and will download and run the file when it gets this payload.

Now here's the absolute weird part!

It works perfect!

Perfect you say, then why do you need help?

Well, it works perfect ONLY when I run the script through SSH. If I run the script on startup, everything works except the update. It seems to get the msg to update, it seems to get the file and unpack it, but it seems to fail running the bash script.

Currently, Python runs the bash script with the following command:

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

If I had to guess:

It's not running the bash script. I'm not sure why. As I mentioned earlier, it works perfect when I run it through SSH, somehow, when crontab runs it on reboot, it won't be called.

It does have all the privileges, so as far as I know, that's not it.

I've tried:

Well pretty much all I can think of! Different call methods, from subprocess.call to os.call, nothing seemed to work. I've also add the user under sudoers and I've also tried logging the output of the Python and Bash script. Python showed no errors and Bash log file didn't seem to start at all.

ANY HELP WOULD BE REALLY APPRECIATED!

There are several possible differences here. To name a few particularly likely ones:

  • The environment exposed by cron may be missing variables established by the user's login scripts which are mandatory for successful operation of the scripts at hand.

    Comparing os.environ between the working and non-working cases is likely to be informative.

  • Your sudo command may require a TTY.

    Capturing stderr of your command, and inspecting it on error, is likely to be helpful here. Using the set -x shell option, as below, will make this log even more informative, by capturing exact commands invoked by the shell (if in fact sudo succeeds in executing your shell; in the case where a TTY is required by your /etc/sudoers , it may not).

     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) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM