python-2.7cronsubprocesspopentop-command

Python cron job returns different output than manual execution


My python script cuts off strings when run via cron.

I have a python script that captures the output from the unix "top" command, iterates through to find the metrics I require and prints these to an output file. I want to capture these metrics every 15 minutes so I have added the script to the user crontab.

However, the script executed via cron produces different output.

Command line output (Desired):

User       %CPU    %MEM    Time_Running    Command
-------------------------------------------------------------------------------------------------------
hpc        977.8   12.1    19689:06        ./mix99s
3tb        94.4    0.1     0:06.67         python -c import sys;
3tb        94.4    2.2     50:57.58        /apps/anaconda3/bin/python3 Cross_Platform_Validation.py
fhpc       16.7    0.0     0:00.05         top -b -c -n1
---------------------------------------------------------------------------------------------------------

Cron job output:

User       %CPU    %MEM    Time_Running    Command
-------------------------------------------------------------------------------------------------------
hpc        977.8   12.1    19689:06        ./mix99s
3tb        94.4    0.1     0:06.67         python -c+
3tb        94.4    2.2     50:57.58        /apps/ana+
fhpc       16.7    0.0     0:00.05         top -b -c+
---------------------------------------------------------------------------------------------------------

The cron job always cuts off any field greater than 10 characters long (see "Command" above) I thought this may be due to buffersize in the subprocess Popen but changing the bufsize=-1 had no impact.

The important parts of my script are:

# Get Top command output
top_out = subprocess.Popen(['top', '-b', '-c', '-n1'], bufsize=-1, stdout=subprocess.PIPE).stdout
...

    # Task output always starts on line 7
    elif i > 6:
        # sep=None ie. split by whitespace. Max 11 splits
        cols = line.split(None, 11)

        user = cols[1]
        cpu = cols[8]
        mem = cols[9]
        time_run = cols[10]
        command = cols[11]

        outfile.write('{}'.format(user))
        outfile.write('{}'.format(cpu))
        outfile.write('{}'.format(mem))
        outfile.write('{}'.format(time_run))
        outfile.write('{}'.format(command))


Solution

  • The problem was to do with the top command output being truncated to 80 characters when run via cron as answered here: https://unix.stackexchange.com/questions/95877/output-of-top-gets-truncated-to-80-columns-when-run-by-cron

    Changing my cron job to include the COLUMNS option fixed the problem

    Original

    # Run monitor script every 15 minutes
    */15 * * * * /mnt/active/monitor_cluster/monitor.py
    
    

    Working

    # Run monitor script every 15 minutes
    */15 * * * * COLUMNS=200 /mnt/active/monitor_cluster/monitor.py