Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'm trying to get my Raspberry Pi's CPU usage like so:

def get_cpu_usage():
    return os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip()

When executed normally, this method returns the correct usage, e.g. "7.2". When called from cron however, it returns an empty string.

My crontab looks like this:

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

* * * * * python /home/pi/sysinfo/dashboard.py

What am I doing wrong?

share|improve this question
    
Actually, it is not returning the correct string, you should use top -bn 2 -d 0.01 instead, see my answer here for more info. –  terdon Jul 7 '13 at 18:43
add comment

2 Answers

up vote 3 down vote accepted

Usually when something doesn't behave according to plan when running through cron, but runs fine when you try it in a terminal, the problems are caused by one of two possible things:

  • cron doesn't have the $PATH (or more generally, environment) that you are used to or expect. This can be solved to some degree by simply specifying the full path to everything, setting any appropriate environment variables inside cron or in a script that you launch through cron and which can perform any necessary setup before running the real command.
  • cron doesn't run commands through a TTY. Lots of things don't care and fall back to a sane output format if they are run without an attached TTY, but some things do care. top does care by default and must be told to not care. I don't know if Python's os.popen() allocates a TTY, but I somewhat doubt it.

In your particular case, you can work around the problem by adding the -b parameter to top. As described in the man page:

-b : Batch-mode operation

Starts top in 'Batch' mode, which could be useful for sending output from top to other programs or to a file. In this mode, top will not accept input and runs until the iterations limit you've set with the '-n' command-line option or until killed.

share|improve this answer
    
Thanks for the explanation and the workaround, this did the trick! :) –  Peter W. Jul 7 '13 at 18:47
add comment

You might need to add a PYTHONPATH variable to your crontab file - it's possible that your import os statement (which I assume is at the top of your dashboard.py file) isn't working. You'll have to check the exact directory on your machine, but it should be something along the lines of /usr/local/lib/pythonX.X/ where X.X is the version of Python you're using.

share|improve this answer
    
The weird thing is that I'm using os.popen("/opt/vc/bin/vcgencmd get_config arm_freq") to get the CPU clock just a few lines above the one for the CPU usage and that one works. –  Peter W. Jul 7 '13 at 18:21
    
@PeterW. That sounds exactly like the symptom of a PATH issue, which is commonplace when executing through cron. Either that, or top detects that it isn't running on a TTY and fails because of that. –  Michael Kjörling Jul 7 '13 at 18:24
    
@MichaelKjörling Is there another way to get the CPU usage that doesn't rely on commands that may or may not fail depending on where they're run from? –  Peter W. Jul 7 '13 at 18:29
    
@PeterW. See my answer for what will probably work as a solution. –  Michael Kjörling Jul 7 '13 at 18:41
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.