0

With this code I'm sending data to zabbix using trapper:

def zabbix_sender(key, output):
    server = "1.2.2.4"
    hostname = "host"
    cmd = "zabbix_sender -z " + server + " -s " + hostname + " -k " + key +\
            " -o \"" + output +"\""
    print os.system(cmd)

It outputs this to the screen

info from server: "processed: 1; failed: 0; total: 1; seconds spent: 0.000041"
sent: 1; skipped: 0; total: 1

I need to output above to variable so, if failed: 1 I can create error handling.

Currently I'm getting 0 as output when calling this function:

r = zabbix_sender (key,"failed")
                print  r

output:0

Tried with subprocesses:

r=subprocess.check_output(zabbix_sender (key,"failed"),shell=False) 
print r

TypeError:None object is not iterable

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • You obviously need `subprocess.check_output` *instead of* `os.system`, not on the output from `os.system`. – tripleee Jan 04 '19 at 08:46
  • The importance of precise error messages cannot be overstated. The spelling is "iterable" and the problem is surely that `None` is *not* iterable. – tripleee Jan 04 '19 at 08:50

1 Answers1

0

The return value from os.system() is not the output from the command. You want to use subprocess.run() instead.

from subprocess import run, PIPE

def zabbix_sender(key, output):
    server = "1.2.2.4"
    hostname = "host"
    cmd = ["zabbix_sender", "-z", server, "-s",  hostname,
        "-k", key, "-o",  output]
    result = run(cmd, stdout=PIPE, stderr=PIPE
        universal_newlines=True, check=True)
    return result.stdout, result.stderr

Notice also how you don't want quoting around the option argument for -o when you are not using shell=True, and how your original function would print instead of return the result.

I speculate that the output you want is on stderr, not stdout; but I leave this up to you to establish.

If zabbix_sender is at all correctly implemented, it will return a non-zero exit code if it fails; you should handle this instead of examine its human-readable output. With check=True an exception will be raised if the called process returns a failure status.

def zabbix_sender(key, output):
    server = "1.2.2.4"
    hostname = "host"
    try:
        result = run(["zabbix_sender", "-z", server, "-s", hostname,
            "-k", key, "-o", output],
            stdout=PIPE, stderr=PIPE,
            universal_newlines=True, check=True)
         return result.stdout, result.stderr
    except CalledProcessError:
         # your zabbix error handling here
         # then probably
         return None

If you are stuck on Python before 3.5 you can try subprocess.check_output and friends. More information at Running Bash commands in Python.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • thank, i'm on python 2.7 and getting `from subprocess import run, PIPE ImportError: cannot import name run` also installed pip install run –  Jan 04 '19 at 08:51
  • Like I wrote in the last paragraph, you can use `subprocess.check_output` instead of `subprocess.run` on older Python versions. But see also update just now; you probably just want to call `subprocess.check()` and trap the exception. The linked answer has (a lot) more details. – tripleee Jan 04 '19 at 08:55
  • Also, you really should be thinking feverishly about how to migrate your code to Python 3, which is the supported and recommended version of the language. By the original timeline, Python 2 would have been end-of-lifed last year already. It is a zombie; you should avoid going near it if you can. – tripleee Jan 04 '19 at 08:57
  • ok, switched to python 3 and now getting:`return run.stdout, run.stderr AttributeError: 'function' object has no attribute 'stdout'` –  Jan 04 '19 at 09:08