杰瑞科技汇

Python如何用zabbixsender发送监控数据?

Of course! Using a Python script to send data to Zabbix is a very common and powerful way to monitor custom metrics. The standard and most reliable method for this is by using the zabbix_sender command-line utility, which Python can execute.

Python如何用zabbixsender发送监控数据?-图1
(图片来源网络,侵删)

Here's a comprehensive guide covering everything from the basics to advanced Python scripts.

Core Concept: Why zabbix_sender?

Zabbix is designed for high-frequency data collection. Running a new Python script for every single metric check would be inefficient and could overload your Zabbix server.

The zabbix_sender utility is optimized for this:

  • Batch Processing: It can send hundreds or thousands of values in a single, efficient network packet.
  • Reliability: It handles communication with the Zabbix server/proxy and reports success/failure for each item.
  • Simplicity: It uses a simple, space-delimited text format for input.

Our Python script's job will be to:

Python如何用zabbixsender发送监控数据?-图2
(图片来源网络,侵删)
  1. Collect the data we want to monitor.
  2. Format this data into the format zabbix_sender expects.
  3. Execute the zabbix_sender command with our formatted data.
  4. (Optional) Parse the output to check if the data was successfully sent.

Part 1: Prerequisites

Before you start, ensure you have the following:

  1. Zabbix Server/Proxy: A running Zabbix instance.
  2. Zabbix Agent: A Zabbix agent installed on the machine where you'll run the Python script. This agent must be configured to allow active checks.
  3. zabbix_sender Binary: This is usually included with the Zabbix agent package. You can verify its location:
    • On Debian/Ubuntu: which zabbix_sender (usually /usr/bin/zabbix_sender)
    • On RHEL/CentOS: which zabbix_sender (usually /usr/bin/zabbix_sender or /usr/local/bin/zabbix_sender)
  4. Zabbix Configuration File (zabbix_agentd.conf): You need to know the location of this file (usually /etc/zabbix/zabbix_agentd.conf). It must contain the server's address:
    Server=192.168.1.100  # Your Zabbix server IP
    ServerActive=192.168.1.100  # For active checks
    Hostname=my-python-host  # The exact hostname as defined in Zabbix

Part 2: The zabbix_sender Data Format

The zabbix_sender utility reads data from standard input (stdin). The format is one line per metric, with the following space-delimited fields:

<hostname> <key> <value> [<timestamp>]

  • <hostname>: The exact hostname of the host in Zabbix.
  • <key>: The key you want to update (e.g., custom.disk.space, custom.cpu.usage).
  • <value>: The actual numerical value you are sending.
  • <timestamp> (Optional): The Unix timestamp for the value. If omitted, the current time is used. It's good practice to let Zabbix handle the timestamp.

Example: my-python-host custom.disk.space /dev/sda1 75.5

Python如何用zabbixsender发送监控数据?-图3
(图片来源网络,侵删)

Part 3: Python Script Examples

Here are three examples, from the most basic to a more robust and reusable script.

Example 1: Basic Script (Hardcoded Values)

This is the simplest script. It sends a single, hardcoded value to demonstrate the concept.

import subprocess
import sys
# --- Configuration ---
ZABBIX_SENDER = "/usr/bin/zabbix_sender"
ZABBIX_CONFIG = "/etc/zabbix/zabbix_agentd.conf"
HOSTNAME = "my-python-host" # Must match the hostname in Zabbix
KEY = "custom.script.hello"
VALUE = "Hello from Python!"
# --- Data Preparation ---
# The data must be formatted as a string with a newline at the end
data_to_send = f"{HOSTNAME} {KEY} {VALUE}\n"
# --- Execution ---
try:
    # We use a list of arguments for the command
    command = [ZABBIX_SENDER, "-c", ZABBIX_CONFIG, "-i", "-"]
    # The data is passed to stdin
    process = subprocess.Popen(
        command,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True
    )
    stdout, stderr = process.communicate(input=data_to_send)
    if process.returncode == 0:
        print("Data sent successfully.")
        # You can print stdout to see the Zabbix sender's response
        # print("Zabbix Sender Output:\n", stdout)
    else:
        print(f"Error sending data. Return code: {process.returncode}", file=sys.stderr)
        print(f"Stderr: {stderr}", file=sys.stderr)
except FileNotFoundError:
    print(f"Error: '{ZABBIX_SENDER}' not found. Is Zabbix agent installed?", file=sys.stderr)
except Exception as e:
    print(f"An unexpected error occurred: {e}", file=sys.stderr)

Example 2: Script to Monitor Disk Usage

This script calculates the used disk space for a specific partition and sends it to Zabbix.

import subprocess
import sys
import shutil
# --- Configuration ---
ZABBIX_SENDER = "/usr/bin/zabbix_sender"
ZABBIX_CONFIG = "/etc/zabbix/zabbix_agentd.conf"
HOSTNAME = "my-python-host"
KEY = "custom.disk.space.root" # Example key
PATH_TO_CHECK = "/" # The partition to check
# --- Data Collection ---
def get_disk_usage(path):
    """Calculates disk usage percentage for a given path."""
    try:
        total, used, free = shutil.disk_usage(path)
        # Calculate percentage, handle division by zero
        usage_percent = (used / total) * 100
        return round(usage_percent, 2)
    except Exception as e:
        print(f"Error calculating disk usage for {path}: {e}", file=sys.stderr)
        return None
# --- Main Execution ---
disk_usage = get_disk_usage(PATH_TO_CHECK)
if disk_usage is not None:
    data_to_send = f"{HOSTNAME} {KEY} {disk_usage}\n"
    try:
        command = [ZABBIX_SENDER, "-c", ZABBIX_CONFIG, "-i", "-"]
        process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        stdout, stderr = process.communicate(input=data_to_send)
        if process.returncode == 0:
            print(f"Successfully sent disk usage for {PATH_TO_CHECK}: {disk_usage}%")
        else:
            print(f"Failed to send data. Return code: {process.returncode}", file=sys.stderr)
            print(f"Stderr: {stderr}", file=sys.stderr)
    except FileNotFoundError:
        print(f"Error: '{ZABBIX_SENDER}' not found.", file=sys.stderr)
    except Exception as e:
        print(f"An unexpected error occurred: {e}", file=sys.stderr)
else:
    print("Could not retrieve disk usage, aborting send.", file=sys.stderr)

Example 3: Advanced Script (Reusable Function & Error Parsing)

This version is more robust. It includes a reusable function and parses the zabbix_sender output to get a clear success/failure status for each item.

import subprocess
import sys
import shutil
# --- Configuration ---
ZABBIX_SENDER = "/usr/bin/zabbix_sender"
ZABBIX_CONFIG = "/etc/zabbix/zabbix_agentd.conf"
HOSTNAME = "my-python-host"
def send_zabbix_data(metrics_list):
    """
    Sends a list of metrics to Zabbix using zabbix_sender.
    metrics_list should be a list of strings, e.g., ["host key value", "host2 key2 value2"]
    Returns True on success, False on failure.
    """
    if not metrics_list:
        print("No metrics to send.", file=sys.stderr)
        return False
    # Join all metrics with newlines
    data_string = "\n".join(metrics_list) + "\n"
    command = [ZABBIX_SENDER, "-c", ZABBIX_CONFIG, "-i", "-"]
    try:
        process = subprocess.Popen(
            command,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        stdout, stderr = process.communicate(input=data_string)
        if process.returncode == 0:
            print("Zabbix Sender executed successfully.")
            # Check the detailed output for processing errors
            # A successful batch can still have individual item failures
            for line in stdout.splitlines():
                if "processed:" in line:
                    parts = line.split()
                    # Example: "my-host custom.key1 1  (OK) processed: 1; failed: 0; total: 1"
                    if int(parts[-3]) > 0:
                        print(f"Warning: Some items failed to process. Details: {line}")
            return True
        else:
            print(f"Error: zabbix_sender failed with return code {process.returncode}", file=sys.stderr)
            if stderr:
                print(f"Stderr: {stderr}", file=sys.stderr)
            return False
    except FileNotFoundError:
        print(f"Error: '{ZABBIX_SENDER}' not found.", file=sys.stderr)
        return False
    except Exception as e:
        print(f"An unexpected error occurred: {e}", file=sys.stderr)
        return False
# --- Main Execution ---
if __name__ == "__main__":
    # --- Data Collection ---
    root_disk_usage = round((shutil.disk_usage("/").used / shutil.disk_usage("/").total) * 100, 2)
    cpu_load = 45.5 # Example: get this from psutil or /proc/loadavg
    # --- Prepare data list ---
    metrics = [
        f"{HOSTNAME} custom.disk.space.root {root_disk_usage}",
        f"{HOSTNAME} custom.cpu.load {cpu_load}"
    ]
    # --- Send Data ---
    if send_zabbix_data(metrics):
        print("All metrics processed and sent.")
    else:
        print("Failed to send one or more metrics.", file=sys.stderr)
        sys.exit(1)

Part 4: Zabbix Configuration

To receive this data, you must configure a Zabbix template.

  1. Create a Template:

    • Go to Configuration -> Templates and create a new template (e.g., "Template Custom Python Metrics").
  2. Create Items:

    • Go to the "Items" tab in your new template and create an item for each key you send.

    • Name: CPU Load (Python Script)

    • Key: custom.cpu.load

    • Type: Zabbix trapper

    • Data type: Numeric (float)

    • Update interval: 0 (This is crucial! For trapper items, set to 0. The script controls the frequency.)

    • History/Storage: Configure as needed.

    • Create another item:

    • Name: Root Disk Space (Python Script)

    • Key: custom.disk.space.root

    • Type: Zabbix trapper

    • Data type: Numeric (float)

  3. Create Triggers (Optional but Recommended):

    Create a trigger for the disk space item to alert if usage is > 90%.

  4. Link the Template:

    • Link this template to the target host (my-python-host).

Part 5: Automation

Finally, you need to run your Python script periodically. The best way to do this is with a cron job.

  1. Make your Python script executable:

    chmod +x /path/to/your/zabbix_python_sender.py
  2. Open the crontab for editing:

    crontab -e
  3. Add a line to run the script every 5 minutes. For example:

    */5 * * * * /usr/bin/python3 /path/to/your/zabbix_python_sender.py >/dev/null 2>&1
    • */5 * * * *: At every 5th minute.
    • /usr/bin/python3: The path to your Python interpreter.
    • >/dev/null 2>&1: This suppresses the standard output and error, so you don't get emails from cron for every run. You might want to redirect output to a log file for debugging initially (/var/log/zabbix_python_script.log 2>&1).
分享:
扫描分享到社交APP
上一篇
下一篇