Search code examples
pythonsubprocessarp

Python script calling `arp` produces error when run from crontab


My server:

Linux dhcpns 3.19.0-28-generic #30-Ubuntu SMP Mon Aug 31 15:52:51 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

My Python script:

#! /usr/bin/python

import syslog, traceback
import subprocess as sp

def getarp():
  cmd = ["arp", "-a"]
  arp = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE)
  output, err = arp.communicate()
  entries = output.splitlines()
  return entries

def syslog_trace(trace):
  log_lines = trace.split('\n')
  for line in log_lines:
    if len(line):
      syslog.syslog(syslog.LOG_ALERT,line)

if __name__ == '__main__':
  try:
    lstArp =  getarp()
    print lstArp
  except Exception as e:
    syslog.syslog(syslog.LOG_ALERT,e.__doc__)
    syslog_trace(traceback.format_exc())
    raise

When I run the script from the commandline it produces the expected output. However, when I call the script from crontab -e (redirecting output to a file, obviously) the script fails.

The log:

Sep 28 18:36:01 dhcpns testarp.py[9984]: OS system call failed.
Sep 28 18:36:01 dhcpns testarp.py[9984]: Traceback (most recent call last):
Sep 28 18:36:01 dhcpns testarp.py[9984]: File "/home/ubuntu/testarp.py", line 23, in <module>
Sep 28 18:36:01 dhcpns testarp.py[9984]: lstArp =  getarp()
Sep 28 18:36:01 dhcpns testarp.py[9984]: File "/home/ubuntu/testarp.py", line 10, in getarp
Sep 28 18:36:01 dhcpns testarp.py[9984]: arp = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE)
Sep 28 18:36:01 dhcpns testarp.py[9984]: File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
Sep 28 18:36:01 dhcpns testarp.py[9984]: errread, errwrite)
Sep 28 18:36:01 dhcpns testarp.py[9984]: File "/usr/lib/python2.7/subprocess.py", line 1335, in _execute_child
Sep 28 18:36:01 dhcpns testarp.py[9984]: raise child_exception
Sep 28 18:36:01 dhcpns testarp.py[9984]: OSError: [Errno 2] No such file or directory

WTF? What am I missing?


Solution

  • Commands that are run via cron inherit a different environment. In particular, PATH envvar may be different. To workaround it, specify the full path to arp program in your Python script or configure PATH in the corresponding crontab explicitly:

    PATH=/bin:/usr/bin:/path/where/arp/lives