updateAgent.pl is script that handles agent install/upgrades and agent configuration changes for Windows and Linux systems. It's designed to be run from a Linux system.
./updateAgent.pl server
This command will check the Zabbix agent status on the remote system, upgrade the agent if needed, and apply any configuration changes requested. Currently the script handles Windows Server 2003/2008 32bit and 64bit and Ubuntu 8.04/10.04 and Debian systems. However it could be modified to support additional Linux distributions. It was written for my site to support the Zabbix 1.6 to Zabbix 1.8 upgrade on approximately 100 server systems.
This also comes with an expect script used to handle SSH key installation on Linux systems and the Debian package created for Ubuntu 8.04 and older Debian distributions.
This script is released under the GPL v3. It may be too specific to be useful to other sites but if you need a system to update local Windows and Ubuntu hosts this might be handy.
Walt
./updateAgent.pl server
This command will check the Zabbix agent status on the remote system, upgrade the agent if needed, and apply any configuration changes requested. Currently the script handles Windows Server 2003/2008 32bit and 64bit and Ubuntu 8.04/10.04 and Debian systems. However it could be modified to support additional Linux distributions. It was written for my site to support the Zabbix 1.6 to Zabbix 1.8 upgrade on approximately 100 server systems.
This also comes with an expect script used to handle SSH key installation on Linux systems and the Debian package created for Ubuntu 8.04 and older Debian distributions.
This script is released under the GPL v3. It may be too specific to be useful to other sites but if you need a system to update local Windows and Ubuntu hosts this might be handy.
Walt
Code:
#!/usr/bin/perl
############################################################
# updateAgent.pl
#
# v.1.0 - Walt Howd
# 06/07/2011
#
# This script will update Zabbix agent configuration files
# on Linux or Windows systems and install/upgrade the
# Zabbix agent if needed.
#
# Usage:
# ./updateAgent.pl server
#
# Requirements:
# - Linux systems must have open SSH on port 22
# - Windows systems must have administrative ports open
# and this script must have credentials to the system
# - smbclient and net binaries from Samba (samba-common)
# - winexe - Execute Windows commands from a Linux system
# (https://lbtwiki.cern.ch/bin/view/Online/WinExe)
# - ssh-scp-autologin.sh - Expect script to auto login
# to Linux SSH hosts. This is used to install a SSH
# key.
# - The script assumes it will be run as root user
# - The Zabbix sources and paths to the Zabbix agent
# conf files and startup scripts
# - zabbix_1.8.5-1_i386.deb - Debian package for Ubuntu
# 8.04 and Debian systems
#
# Notes:
# This script currently supports and has been tested with
# Windows Server 2003/2008 32bit/64bit. It has also been
# tested with Ubuntu 8.04LTS and 10.04LTS and Debian 5.0.
# The script will not update or install other distributions
# at this time.
#
# When run this script will first check to see if the Zabbix
# agent is installed. If the agent is not installed it will
# attempt to install it. If the agent is an older version
# it will attempt to upgrade the agent.
#
# If or when the agent is at the latest version it will then
# apply any requested agent configuration changes and restart
# the zabbix service.
#
# For Linux systems it expects to have a passwordless SSH
# key setup and authorized on the remote host. If this is not
# installed it will attempt to install it automatically using
# the included expect script. This is a potential security
# issue and should be validated at your site before being
# used. As best practice this SSH key should be removed
# or restricted to a subset of commands.
#
# For Ubuntu 8.04 / Debian 5.0 systems it installs the Zabbix agent
# using the included Debian package. This was generated
# with the following command:
#
# ./configure --enable-agent --enable-static --disable-ipv6
#
# Then packaged automatically with checkinstall.
#
# For Ubuntu 10.04 systems the script will install the
# Zabbix agent from the current Ubuntu sources.
#
# Copyright 2011 - Walt Howd
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
############################################################
use IO::Socket;
$host = $ARGV[0];
############################################################
# Check command line
############################################################
if(!($host)) {
print "You must specify a host\n";
print "./updateAgent.pl host\n";
exit;
}
############################################################
# Windows Administrative Credentials
############################################################
$adaccount = "username";
$adpassword = "password";
$addomain = "domain";
############################################################
# Generate the following key if needed with:
# ssh-keygen -t dsa -b 1024
#
# Accept the default prompts and leave it without a password
############################################################
$linuxKey = "/root/.ssh/id_dsa.pub";
############################################################
# ZabbixAgentVersion - Agent versions lower then this
# will be automatically upgraded
############################################################
$zabbixAgentVersion = '1.8';
$zabbixDebPackage = "zabbix_1.8.5-1_i386.deb";
$zabbixDebStartup = "zabbix-1.8.5/misc/init.d/debian/zabbix-agent";
$zabbixAgentLinuxConf = "zabbix-1.8.5/misc/conf/zabbix_agentd.conf";
$zabbixAgentWinConf = "zabbix-1.8.5/misc/conf/zabbix_agentd.win.conf";
$zabbixAgentWinDefaultDir = "\\\"\\program files\\zabbix agent\\\"";
############################################################
# 32 bit and 64 bit Windows Agent directories
############################################################
%zabbixWinFilesDir = (
32 => "zabbix-1.8.5/bin/win32",
64 => "zabbix-1.8.5/bin/win64",
);
############################################################
# Directories to check for Windows Zabbix Agent install
############################################################
@zabbixAgentDirs = (
"\\\"\\program files (x86)\\zabbix agent\\\"",
"\\\"\\program files\\zabbix agent\\\"",
"\\\"\\program files\\zabbix\\\"",
);
############################################################
# Windows Drives to look for Zabbix Agent install
############################################################
@windowsDrives = (
"c",
"d",
"e",
);
############################################################
# Default Windows install drive
############################################################
$windowsAgentDrive = "c";
############################################################
# Zabbix Agent Conf Changes
#
# Any change listed in this hash will be add/updated
# to the Zabbix Agent conf file.
############################################################
%zabbixAgentConfChanges = (
Server => 'zabbix-server-1.domain.tld',
EnableRemoteCommands => '1',
Hostname=> $host,
);
############################################################
# Log file
############################################################
$LOG = "/var/log/zabbix-update-agent.log";
############################################################
# Debug level
############################################################
$debugLevel = 2;
############################################################
# Available debugging levels - Do not modify
############################################################
%debugLevels = (
DEBUG => "1",
INFO => "2",
SUCCESS => "3",
ERROR => "4",
);
############################################################
# Check requirements
############################################################
checkRequirements();
############################################################
# Main start
#
# Check if SSH is open on port 22. If it is then we
# assume we are working with a Linux system. If it's not
# then assume it's a Windows system.
############################################################
if (checkHost($host) == 0) {
updateLinux($host);
} else {
updateWindows($host);
}
############################################################
# Update a Windows Host
############################################################
sub updateWindows {
($host) = @_;
debugMessage("INFO", "Updating Windows host ($host)");
############################################################
# Find the Zabbix Agent directory
############################################################
foreach $zabbixAgentDir (@zabbixAgentDirs) {
foreach $driveShare (@windowsDrives) {
debugMessage("INFO", "Checking for Zabbix Directory at $zabbixAgentDir on drive $driveShare");
$zabbixAgentDirListing = system("smbclient //$host/$driveShare\$ $adpassword -U $adaccount -W $addomain -c \"prompt;cd $zabbixAgentDir\" 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode == 0) {
debugMessage("INFO", "Found Zabbix Agent directory at $zabbixAgentDir on drive $driveShare");
$windowsAgentFound = 1;
$windowsAgentDir = $zabbixAgentDir;
$windowsAgentDrive = $driveShare;
}
}
}
############################################################
# Check agent version
############################################################
if ($windowsAgentFound) {
$version = checkWindowsVersion($host, $windowsAgentDrive, $windowsAgentDir);
############################################################
# Upgrade Zabbix Agent if it's not at the latest version
############################################################
if($version < $zabbixAgentVersion) {
debugMessage("INFO", "Zabbix agent version ($version) is older then current verison ($zabbixAgentVersion)");
upgradeWindowsAgent($host, $windowsAgentDrive, $winexeWindowsAgentDir);
}
############################################################
# If agent directory was not found check if the service
# is installed. If the service is not installed then
# install the agent.
############################################################
} else {
debugMessage("INFO", "Could not locate Zabbix agent directory on $host, checking Windows service listing");
@services = `net rpc service list -I $host -U $adaccount%$adpassword -W $addomain`;
foreach $service (@services) {
chomp($service);
if($service =~ /Zabbix/gi) {
my $serviceInstalled = 1;
}
}
if($serviceInstalled) {
debugMessage("ERROR", "Zabbix service is installed but could not find agent directory. Cannot check agent version.");
}
############################################################
# Install Zabbix Agent
############################################################
installWindowsAgent($host);
}
############################################################
# Allow Zabbix ports through firewall
############################################################
$tcpRule = `winexe -U $addomain/$adaccount --password=$adpassword //$host \"netsh advfirewall firewall add rule name=\\\”ZabbixAgentTCP\\\” dir=in action=allow protocol=TCP localport=10050\" 2>&1`;
$udpRule = `winexe -U $addomain/$adaccount --password=$adpassword //$host \"netsh advfirewall firewall add rule name=\\\”ZabbixAgentUDP\\\” dir=in action=allow protocol=UDP localport=10050\" 2>&1`;
############################################################
# If WindowsAgentDir is not set then assume this is a brand
# new install that completed and use the default directory
############################################################
if(!($windowsAgentDir)) {
$windowsAgentDir = $zabbixAgentWinDefaultDir;
}
############################################################
# Agent install found and at latest version.
#
# Download the Zabbix Agent conf and process any requested
# changes
############################################################
$downloadAgentConf = system("smbclient //$host/$windowsAgentDrive\$ $adpassword -U $adaccount -W $addomain -c \"prompt;cd $windowsAgentDir;get zabbix_agentd.conf\" 2>/dev/null");
$returnCode = $?;
if($returnCode == 0) {
debugMessage("INFO", "Downloaded Zabbix Agent conf from $windowsAgentDir to zabbix_agentd.conf-$host");
system("mv zabbix_agentd.conf zabbix_agentd.conf-$host");
############################################################
# Update changes in Zabbix Agent Conf
############################################################
processZabbixAgentConf($host);
############################################################
# Upload the updated Zabbix Agent conf
############################################################
$uploadAgentConf = system("smbclient //$host/$windowsAgentDrive\$ $adpassword -U $adaccount -W $addomain -c \"prompt;cd $windowsAgentDir;put zabbix_agentd.conf\" 2>/dev/null");
$returnCode = $?;
if($returnCode == 0) {
debugMessage("INFO", "Successfully uploaded updated zabbix_agentd.conf");
system("rm -f zabbix_agentd.conf");
restartZabbixService($host);
debugMessage("SUCCESS", "Updated Zabbix Agent config on $host");
exit;
} else {
debugMessage("ERROR", "Could not upload updated zabbix_agentd.conf");
}
} else {
debugMessage("ERROR", "Could not download Zabbix Agent conf from $host");
}
}
############################################################
# Install new Windows Agent
############################################################
sub installWindowsAgent {
($host) = @_;
debugMessage("INFO", "Starting Windows agent install procedure");
############################################################
# Check if system is 32bit or 64bit
############################################################
debugMessage("INFO", "Checking for 32bit or 64bit Windows install");
@lines = `smbclient //$host/c\$ $adpassword -U $adaccount -W $addomain -c \"prompt;dir \\windows\\system32\\ntvdm64.dll\" 2>/dev/null`;
$returnCode = $?;
if ($returnCode == 0) {
foreach $line (@lines) {
if($line =~ /NT_STATUS_NO_SUCH_FILE/gi) {
$installTypeFound = 1;
$installType = 32;
} elsif ($line =~ /ntvdm64.dll/gi) {
$installTypeFound = 1;
$installType = 64;
}
}
if(!($installTypeFound)) {
debugMessage("ERROR", "Examined Windows directory but could not determine if Windows install on $host was 32bit or 64 bit");
} else {
debugMessage("INFO", "Found " . $installType . "bit Windows install on $host");
}
} else {
debugMessage("ERROR", "Could not determine if Windows install on $host was 32bit or 64 bit");
}
############################################################
# Create Zabbix Directory
############################################################
$zabbixAgentDirListing = system("smbclient //$host/c\$ $adpassword -U $adaccount -W $addomain -c \"prompt;cd $zabbixAgentWinDefaultDir\" 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode == 0) {
debugMessage("INFO", "Found Zabbix Agent directory at $zabbixAgentWinDefaultDir on drive $driveShare");
} else {
debugMessage("INFO", "Zabbix agent directory not found on $host. Creating. . .");
$createZabbixAgentDir = system("smbclient //$host/c\$ $adpassword -U $adaccount -W $addomain -c \"prompt;mkdir $zabbixAgentWinDefaultDir;\" 2>/dev/null");
$returnCode = $?;
if($returnCode == 0) {
debugMessage("INFO", "Successfully created Zabbix Agent directory ($zabbixAgentWinDefaultDir)");
} else {
debugMessage("ERROR", "Could not create Zabbix Agent directory ($zabbixAgentWinDefaultDir). Return code was $returnCode");
}
}
############################################################
# Copy Agent Files
############################################################
$uploadAgentFiles = system("smbclient //$host/c\$ $adpassword -U $adaccount -W $addomain -c \"prompt;cd $zabbixAgentWinDefaultDir;lcd $zabbixWinFilesDir{$installType};mput *\" 2>/dev/null");
$returnCode = $?;
if($returnCode == 0) {
debugMessage("INFO", "Successfully uploaded Zabbix Agent files");
} else {
debugMessage("ERROR", "Could not upload updated Zabbent agent files. Return code was $returnCode");
}
############################################################
# Upload Windows Agent Config
############################################################
$uploadAgentConf = system("smbclient //$host/c\$ $adpassword -U $adaccount -W $addomain -c \"prompt;cd $zabbixAgentWinDefaultDir;put $zabbixAgentWinConf zabbix_agentd.conf\" 2>/dev/null");
$returnCode = $?;
if($returnCode == 0) {
debugMessage("INFO", "Successfully uploaded updated zabbix_agentd.conf");
} else {
debugMessage("ERROR", "Could not upload Windows agent configuration file ($zabbixAgentWinConf) to host. Return code was $returnCode");
}
############################################################
# Check verison
############################################################
$version = checkWindowsVersion($host, "c", $zabbixAgentWinDefaultDir);
if($version < $zabbixAgentVersion) {
debugMessage("ERROR", "Zabbix agent uploaded but version ($version) is less then defined version ($zabbixAgentVersion)");
}
############################################################
# Install Zabbix Agent
############################################################
$winexeWindowsAgentDir = $zabbixAgentWinDefaultDir;
$winexeWindowsAgentDir =~ s/^..//;
$winexeWindowsAgentDir =~ s/..$//;
debugMessage("INFO", "Installing Zabbix agent at $windowsAgentDrive:$winexeWindowsAgentDir");
@lines = `winexe -U $addomain/$adaccount --password=$adpassword //$host \"c:$winexeWindowsAgentDir\\zabbix_agentd.exe --config \\\"c:$winexeWindowsAgentDir\\zabbix_agentd.conf\\\" --install\" 2>&1`;
$returnCode = $?;
foreach $line (@lines) {
chomp($line);
if ($line =~ /installed successfully/gi) {
$statusFound = 1;
debugMessage("INFO", "Zabbix service installed successfully");
}
}
if(!($statusFound)) {
debugMessage("ERROR", "Could not determine if Zabbix agent was successfully installed");
}
}
############################################################
# Upgrade Windows Agent
#
# Removes the current version of the agent and then
# calls the install function.
############################################################
sub upgradeWindowsAgent {
($host, $windowsAgentDrive, $winexeWindowsAgentDir) = @_;
debugMessage("INFO", "Updating Windows host ($host)");
############################################################
# Check service status
############################################################
debugMessage("INFO", "Checking Windows service listing for Zabbix agent");
@services = `net rpc service list -I $host -U $adaccount%$adpassword -W $addomain`;
foreach $service (@services) {
chomp($service);
if($service =~ /Zabbix/gi) {
$serviceInstalledPreCheck = 1;
}
}
if(!($serviceInstalledPreCheck)) {
debugMessage("INFO", "Zabbix agent files exist but service is not installed.");
} else {
############################################################
# Stop Zabbix Agent
############################################################
debugMessage("INFO", "Stopping Zabbix agent at $windowsAgentDrive:$winexeWindowsAgentDir");
@lines = `winexe -U $addomain/$adaccount --password=$adpassword //$host \"$windowsAgentDrive:$winexeWindowsAgentDir\\zabbix_agentd.exe --config \\\"$windowsAgentDrive:$winexeWindowsAgentDir\\zabbix_agentd.conf\\\" --stop\" 2>&1`;
$returnCode = $?;
foreach $line (@lines) {
chomp($line);
if ($line =~ /stopped successfully/gi) {
$statusFound = 1;
debugMessage("INFO", "Zabbix service stopped successfully");
} elsif($line =~ /The service has not been started/gi) {
$statusFound = 1;
debugMessage("INFO", "Zabbix service was not running");
}
}
if(!($statusFound)) {
debugMessage("ERROR", "Could not determine if Zabbix agent process was successfully stopped");
}
############################################################
# Uninstall Zabbix Agent
############################################################
debugMessage("INFO", "Uninstalling Zabbix agent at $windowsAgentDrive:$winexeWindowsAgentDir");
@lines = `winexe -U $addomain/$adaccount --password=$adpassword //$host \"$windowsAgentDrive:$winexeWindowsAgentDir\\zabbix_agentd.exe --config \\\"$windowsAgentDrive:$winexeWindowsAgentDir\\zabbix_agentd.conf\\\" --uninstall\" 2>&1`;
$returnCode = $?;
foreach $line (@lines) {
chomp($line);
if ($line =~ /uninstalled successfullyy/gi) {
$statusFound = 1;
debugMessage("INFO", "Zabbix service uninstalled successfully");
}
}
if(!($statusFound)) {
debugMessage("ERROR", "Could not determine if Zabbix agent was successfully uninstalled");
}
############################################################
# Check service is gone
############################################################
debugMessage("INFO", "Checking Windows service is removed for Zabbix agent");
@services = `net rpc service list -I $host -U $adaccount%$adpassword -W $addomain`;
foreach $service (@services) {
chomp($service);
if($service =~ /Zabbix/gi) {
$serviceInstalledPostCheck = 1;
}
}
if($serviceInstalledPostCheck) {
debugMessage("ERROR", "Zabbix agent service was uninstalled but still exists in service listing");
} else {
debugMessage("INFO", "Zabbix service no longer exists");
}
}
############################################################
# Install new agent
############################################################
installWindowsAgent($host);
}
############################################################
# Check the verison of the Windows agent
############################################################
sub checkWindowsVersion {
my ($host, $windowsAgentDrive, $windowsAgentDir) = @_;
debugMessage("INFO", "Checking version of Windows Agent");
$winexeWindowsAgentDir = $windowsAgentDir;
$winexeWindowsAgentDir =~ s/^..//;
$winexeWindowsAgentDir =~ s/..$//;
@lines = `winexe -U $addomain/$adaccount --password=$adpassword //$host \"$windowsAgentDrive:$winexeWindowsAgentDir\\zabbix_agentd.exe --version\"`;
$returnCode = $?;
if ($returnCode == 65280) {
debugMessage("INFO", "Found Zabbix Agent version with winexe");
foreach $line (@lines) {
chomp($line);
if ($line =~ /v\d/g) {
$version = $line;
$version =~ s/(^.*?)(v)(\d.*)/\3/;
$version =~ s/\s.*//;
$versionFound = 1;
debugMessage("INFO", "Zabbix agent version is $version");
}
}
} else {
debugMessage("ERROR", "Could not determine Zabbix Agent version with winexe on $host. Return code was $returnCode");
}
if (!($versionFound)) {
debugMessage("ERROR", "Could not determine Zabbix Agent version with winexe on $host. Winexe returned content but could not find version string");
}
return $version;
}
############################################################
# updateLinux
#
# This script assumes that a passwordless SSH key
# is setup to administer the client systems.
#
# If the key is not in place it attempts to install it
# automatically using SSH and the default root credentials.
############################################################
sub updateLinux {
($host) = @_;
debugMessage("INFO", "Updating Linux host ($host)");
system("./ssh-scp-autologin.sh ssh root@" . $host . " id 1>/dev/null 2>/dev/null");
system("ssh -o PasswordAuthentication=no -o NumberOfPasswordPrompts=0 root@". $host . " id 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode == 0) {
debugMessage("INFO", "SSH Key found on $host. Continuing. . .");
############################################################
# Install SSH host key if needed using Expect script
# ./ssh-scp-autologin.sh
############################################################
} else {
debugMessage("INFO", "SSH Key not found on $host, attempting to install");
@lines = `./ssh-scp-autologin.sh scp $linuxKey root\@$host:/root/id_dsa-zabbix.pub 2>&1`;
foreach $line (@lines) {
chomp($line);
if($line =~ /denied/gi) {
$deniedFound = 1;
}
}
if($deniedFound) {
debugMessage("INFO", "Could not copy SSH host key to $host. Please enter root password to copy SSH key:");
system("scp -o NumberOfPasswordPrompts=1 $linuxKey root\@$host:/root/id_dsa-zabbix.pub");
$returnCode = $?;
if ($returnCode != 0) {
debugMessage("ERROR", "Could not logon to system with supplied password");
}
debugMessage("INFO", "SSH Key copied, installing. Please enter root password:");
system("ssh root\@$host \"cat /root/id_dsa-zabbix.pub >> /root/.ssh/authorized_keys\" 2>&1");
$returnCode = $?;
if ($returnCode != 0) {
debugMessage("ERROR", "Could not logon to system with supplied password");
}
} else {
system("./ssh-scp-autologin.sh ssh root@" . $host . " \"cat /root/id_dsa-zabbix.pub >> /root/.ssh/authorized_keys\" 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode != 0) {
debugMessage("ERROR", "SSH key was copied to system but could not install to /root/.ssh/authorized_keys");
}
}
system("ssh -o PasswordAuthentication=no -o NumberOfPasswordPrompts=0 root@". $host . " rm /root/id_dsa-zabbix.pub 1>/dev/null 2>/dev/null");
if ($returnCode != 0) {
debugMessage("ERROR", "Could not remove copied SSH key after it was installed to authorized_keys");
}
debugMessage("INFO", "SSH key was successfully installed on $host");
}
############################################################
# Check Zabbix Agent version
############################################################
($version, $versionFound) = checkLinuxVersion($host);
if($versionFound) {
############################################################
# Upgrade Zabbix Agent if it's not at the latest version
############################################################
if($version < $zabbixAgentVersion) {
debugMessage("INFO", "Zabbix agent version ($version) is older then current verison ($zabbixAgentVersion)");
upgradeLinuxAgent($host);
}
} else {
debugMessage("INFO", "Zabbix agent is not installed");
installLinuxAgent($host);
}
############################################################
# Agent install found and at latest version.
#
# Download the Zabbix Agent conf and process any requested
# changes
############################################################
$downloadAgentConf = system("scp root\@$host:/etc/zabbix/zabbix_agentd.conf zabbix_agentd.conf-$host 1>/dev/null 2>/dev/null");
$returnCode = $?;
if($returnCode == 0) {
debugMessage("INFO", "Downloaded Zabbix Agent conf from $host to zabbix_agentd.conf-$host");
############################################################
# Update changes in Zabbix Agent Conf
############################################################
processZabbixAgentConf($host);
############################################################
# Upload the updated Zabbix Agent conf
############################################################
$uploadAgentConf = system("scp zabbix_agentd.conf root\@$host:/etc/zabbix/zabbix_agentd.conf 1>/dev/null 2>/dev/null");
$returnCode = $?;
if($returnCode == 0) {
debugMessage("INFO", "Successfully uploaded updated zabbix_agentd.conf");
system("rm -f zabbix_agentd.conf");
restartZabbixService($host);
debugMessage("SUCCESS", "Updated Zabbix Agent config on $host");
exit;
} else {
debugMessage("ERROR", "Could not upload updated zabbix_agentd.conf");
}
} else {
debugMessage("ERROR", "Could not download Zabbix Agent conf from $host");
}
}
############################################################
# Upgrade/Install Linux Zabbix Agent
#
# This function will install/upgrade a Zabbix agent on a
# Linux system. Each distribution is slightly different
# and used a different package and init scripts.
#
############################################################
sub upgradeLinuxAgent {
($host) = @_;
debugMessage("INFO", "Starting Linux agent upgrade procedure");
############################################################
# Check distribution
############################################################
($distributionFound, $distribution, $distributionVersion, $ubuntuFound, $ubuntuVersion, $redhatFound, $redhatVersion, $debianFound, $debianVersion) = checkLinuxDistribution($host);
if($distributionFound != 1) {
debugMessage("ERROR", "Did not find distribution details for $host");
}
if($distribution =~ /ubuntu/ && $ubuntuVersion != "8.04" && $ubuntuVersion != "10.04") {
debugMessage("ERROR", "Can not handle Ubuntu $ubuntuVersion hosts");
} elsif( ($distribution =~ /ubuntu/gi && $ubuntuVersion =~ /8.04/g) || ($distribution =~ /debian/gi)) {
debugMessage("INFO", "Starting Ubuntu 8.04 / Debian Linux agent upgrade");
############################################################
# Copy package to system
############################################################
system("scp $zabbixDebPackage root\@$host:~ 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode != 0) {
debugMessage("ERROR", "Could not copy Zabbix package ($zabbixDebPackage) to $host. Return code was $returnCode");
} else {
debugMessage("INFO", "Zabbix package ($zabbixDebPackage) copied to $host");
}
############################################################
# Install Package
############################################################
system("ssh root\@$host dpkg -i ~/$zabbixDebPackage 1>/dev/null 2>/dev/null");
if ($returnCode != 0) {
debugMessage("ERROR", "Zabbix package install failed. Return code was $returnCode");
} else {
debugMessage("INFO", "Zabbix package ($zabbixDebPackage) installed on $host");
}
############################################################
# Copy startup script
############################################################
system("scp $zabbixDebStartup root\@$host:/etc/init.d/ 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode != 0) {
debugMessage("ERROR", "Could not copy Zabbix startup script ($zabbixDebStartup) to $host. Return code was $returnCode");
} else {
debugMessage("INFO", "Zabbix startup script ($zabbixDebStartup) copied to $host");
}
############################################################
# Create /etc/zabbix directory
############################################################
system("ssh root\@$host \"if [[ ! -d /etc/zabbix ]]; then mkdir /etc/zabbix; fi\"");
$returnCode = $?;
if ($returnCode != 0) {
debugMessage("ERROR", "Could create /etc/zabbix directory on $host. Return code was $returnCode");
} else {
debugMessage("INFO", "Zabbix directory created on $host");
}
############################################################
# Copy Agent Conf
############################################################
system("scp $zabbixAgentLinuxConf root\@$host:/etc/zabbix/ 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode != 0) {
debugMessage("ERROR", "Could not copy Zabbix agent configuration file ($zabbixAgentLinuxConf) to $host. Return code was $returnCode");
} else {
debugMessage("INFO", "Zabbix startup script ($zabbixAgentLinuxConf) copied to $host");
}
############################################################
# Add Zabbix User if one does not exist
############################################################
system("ssh root\@$host id zabbix 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode != 0) {
debugMessage("INFO", "Zabbix user does not exist on $host");
system("ssh root\@$host useradd zabbix");
$returnCode = $?;
if ($returnCode != 0) {
debugMessage("ERROR", "Could not add Zabbix user. Return code was $returnCode");
} else {
debugMessage("INFO", "Zabbix user created on $host");
}
} else {
debugMessage("INFO", "Zabbix user exists on $host");
}
############################################################
# Fix permissions
############################################################
system("ssh root\@$host chown -R zabbix /etc/zabbix 1>/dev/null 2>/dev/null");
if ($returnCode != 0) {
debugMessage("ERROR", "Owner changes to /etc/zabbix failed. Return code was $returnCode");
} else {
debugMessage("INFO", "Owner changed on /etc/zabbix on $host");
}
############################################################
# Enable startup script
############################################################
system("ssh root\@$host update-rc.d zabbix-agent defaults 1>/dev/null 2>/dev/null");
if ($returnCode != 0) {
debugMessage("ERROR", "Enabling zabbix-agent init script failed. Return code was $returnCode");
} else {
debugMessage("INFO", "Enabled zabbix-agent init script");
}
debugMessage("INFO", "Succesfully upgraded/installed Zabbix Agent on $host");
} elsif($distribution =~ /ubuntu/gi && $ubuntuVersion == "10.04") {
debugMessage("INFO", "Starting Ubuntu 10.04 Linux agent upgrade");
############################################################
# Install Zabbix from package on 10.04
############################################################
system("ssh root\@$host aptitude --assume-yes install zabbix-agent 1>/dev/null 2>/dev/null");
############################################################
# Check Zabbix Agent version after install
############################################################
($version, $versionFound) = checkLinuxVersion($host);
if($versionFound) {
############################################################
# Upgrade Zabbix Agent if it's not at the latest version
############################################################
if($version < $zabbixAgentVersion) {
debugMessage("ERROR", "Zabbix agent version ($version) was installed but is older then current verison ($zabbixAgentVersion)");
} else {
debugMessage("INFO", "Zabbix agent ($version) was successfully installed");
}
} else {
debugMessage("ERROR", "Zabbix agent install from package failed on $host");
}
} else {
debugMessage("ERROR", "Can not handle installs on $distribution $distributionVersion");
}
}
sub installLinuxAgent {
($host) = @_;
debugMessage("INFO", "Starting Linux agent install procedure");
upgradeLinuxAgent($host);
}
############################################################
# Check distribution details
############################################################
sub checkLinuxDistribution {
($host) = @_;
$distributionFound = 0;
@lines = `ssh root\@$host "cat /etc/*release" 2>/dev/null`;
foreach $line (@lines) {
chomp($line);
if($line =~ /ubuntu/gi && $ubuntuFound == 0) {
debugMessage("INFO", "Ubuntu distribution detected");
$distributionFound = 1;
$ubuntuFound = 1;
$distribution = "ubuntu";
}
if($line =~ /red hat/gi && $ubuntuFound == 0) {
debugMessage("INFO", "Red Hat distribution detected");
$distributionFound = 1;
$redhatFound = 1;
$distribution = "redhat";
$redhatVerison = $line;
$distributionVersion = $line;
}
if($ubuntuFound) {
if($line =~ /DISTRIB_RELEASE/g) {
$ubuntuVersion = $line;
$ubuntuVersion =~ s/^.*\=//;
$distributionVersion = $ubuntuVersion;
debugMessage("INFO", "Ubuntu version $ubuntuVersion");
}
}
}
if(!($distributionFound)) {
@lines = `ssh root\@$host "cat /etc/debian_version" 2>/dev/null`;
foreach $line (@lines) {
chomp($line);
if($line =~ /\d/) {
debugMessage("INFO", "Debian distribution detected");
$distributionFound = 1;
$distribution = "debian";
$debianVersion = $line;
$debianFound = 1;
$distributionVersion = $debianVersion;
}
}
}
return ($distributionFound, $distribution, $distributionVersion, $ubuntuFound, $ubuntuVersion, $redhatFound, $redhatVersion, $debianFound, $debianVersion);
}
############################################################
# checkLinuxVersion
#
# Returns the version of the Linux Zabbix Agent installed
# on the passed host
############################################################
sub checkLinuxVersion {
($host) = @_;
$versionFound = 0;
@lines = `ssh root\@$host "zabbix_agentd --version" 2>/dev/null`;
$returnCode = $?;
if ($returnCode == 0 || $returnCode == 65280) {
debugMessage("INFO", "Zabbix agent installed");
foreach $line (@lines) {
chomp($line);
if ($line =~ /v\d/g) {
$version = $line;
$version =~ s/(^.*?)(v)(\d.*)/\3/;
$version =~ s/\s.*//;
$versionFound = 1;
debugMessage("INFO", "Zabbix agent version is $version");
}
}
############################################################
# Check Zabbix Agent Process Status
############################################################
system("ssh root@" . $host . " \"ps aux | grep zabbix_agentd | grep -v grep\" 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode == 0) {
debugMessage("INFO", "Zabbix Agent running");
}
}
return ($version, $versionFound);
}
sub restartZabbixService {
($host) = @_;
############################################################
# Linux System
############################################################
if (checkHost($host) == 0) {
############################################################
# Check distribution details
############################################################
($distributionFound, $distribution, $distributionVersion, $ubuntuFound, $ubuntuVersion, $redhatFound, $redhatVersion, $debianFound, $debianVersion) = checkLinuxDistribution($host);
if($distribution =~ /ubuntu/ && $ubuntuVersion != "8.04" && $ubuntuVersion != "10.04") {
debugMessage("ERROR", "Can not handle Ubuntu $ubuntuVersion hosts");
} elsif( ($distribution =~ /ubuntu/gi && $ubuntuVersion == "8.04") || ($distribution =~ /debian/gi) ) {
$restartFound = 1;
$restartCommand = "/etc/init.d/zabbix-agent restart";
} elsif($distribution =~ /ubuntu/gi && $ubuntuVersion == "10.04") {
$restartFound = 1;
$restartCommand = "service zabbix-agent restart";
} else {
debugMessage("INFO", "Can not handle service restarts on $distribution $distributionVersion");
}
if($restartFound) {
system("ssh root\@$host $restartCommand 1>/dev/null 2>/dev/null");
if ($returnCode != 0) {
debugMessage("ERROR", "Zabbix agent service restart failed. Return code was $returnCode");
} else {
debugMessage("INFO", "Zabbix agent service restarted");
}
}
############################################################
# Windows System
############################################################
} else {
@services = `net rpc service list -I $host -U $adaccount%$adpassword -W $addomain`;
foreach $service (@services) {
chomp($service);
if($service =~ /Zabbix/gi) {
$serviceMatch = 1;
}
}
if ($serviceMatch == 1) {
debugMessage("INFO", "Zabbix service found, restarting. . .");
system("net rpc service stop \"Zabbix Agent\" -I $host -U $adaccount%$adpassword -W $addomain 1>/dev/null 2>/dev/null");
system("net rpc service start \"Zabbix Agent\" -I $host -U $adaccount%$adpassword -W $addomain 1>/dev/null 2>/dev/null");
} else {
debugMessage("ERROR", "Zabbix service not found on $host");
}
}
}
############################################################
# Process Changes to Zabbix Agent Configuration File
############################################################
sub processZabbixAgentConf {
($host) = @_;
if (!(-f "zabbix_agentd.conf-$host")) {
debugMessage("ERROR", "Could not find Zabbix Agent conf file");
}
############################################################
# Put the right end line for Linux/Windows
############################################################
if(checkHost($host) == 0) {
$endline = "\n";
} else {
$endline = "\r\n";
}
open(AGENTCONF,"zabbix_agentd.conf-$host") or die("ERROR - Could not open zabbix_agentd.conf-$host");
open(NEWAGENTCONF,">zabbix_agentd.conf-$host-updated") or die("ERROR - Could not open zabbix_agentd.conf-$host-updated");
while(<AGENTCONF>) {
$line = $_;
foreach $zabbixConfVar (keys %zabbixAgentConfChanges) {
if($line =~ /^$zabbixConfVar/i) {
if($match{$zabbixConfVar} < 1) {
$match{$zabbixConfVar}++;
debugMessage("INFO", "Setting $zabbixConfVar variable to $zabbixAgentConfChanges{$zabbixConfVar}");
$line = $zabbixConfVar . "=" . $zabbixAgentConfChanges{$zabbixConfVar} . $endline;
} else {
debugMessage("INFO", "Found line that matched requested change ($zabbixConfVar) but variable was already set. Discarding line.");
$line = "";
}
}
}
print NEWAGENTCONF $line;
}
############################################################
# Check each request change has happened once
#
# If the line change has not occurred then append to the
# file
############################################################
foreach $zabbixConfVar (keys %zabbixAgentConfChanges) {
if($match{$zabbixConfVar} == 1) {
debugMessage("INFO", "$zabbixConfVar set successfully");
} elsif($match{$zabbixConfVar} > 1) {
debugMessage("ERROR", "$zabbixConfVar was found and set $match{$zabbixConfVar} times");
} elsif($match{$zabbixConfVar} == 0) {
debugMessage("INFO", "$zabbixConfVar was not set to $zabbixAgentConfChanges{$zabbixConfVar}, appending to file");
$line = $zabbixConfVar . "=" . $zabbixAgentConfChanges{$zabbixConfVar} . $endline;
print NEWAGENTCONF $line;
}
}
close(AGENTCONF);
close(NEWAGENTCONF);
system("rm -f zabbix_agentd.conf-$host");
system("mv zabbix_agentd.conf-$host-updated zabbix_agentd.conf");
}
sub checkRequirements {
debugMessage("DEBUG", "Checking requirements. . .");
if(-r $linuxKey) {
debugMessage("DEBUG", "SSH Key ($linuxKey) found");
} else {
debugMessage("ERROR", "Could not find SSH key ($linuxKey). Has it been generated with ssh-keygen?");
}
if(-r $zabbixDebPackage) {
debugMessage("DEBUG", "Debian package ($zabbixDebPackage) found");
} else {
debugMessage("ERROR", "Could not find Debian package ($zabbixDebPackage)");
}
if(-r $zabbixDebStartup) {
debugMessage("DEBUG", "Debian startup script ($zabbixDebStartup) found");
} else {
debugMessage("ERROR", "Could not find Debian startup script ($zabbixDebStartup)");
}
if(-r $zabbixAgentLinuxConf) {
debugMessage("DEBUG", "Linux agent config ($zabbixAgentLinuxConf) found");
} else {
debugMessage("ERROR", "Could not find Linux agent config ($zabbixAgentLinuxConf)");
}
if(-r $zabbixAgentWinConf) {
debugMessage("DEBUG", "Windows agent config ($zabbixAgentWinConf) found");
} else {
debugMessage("ERROR", "Could not find Windows agent config ($zabbixAgentWinConf)");
}
foreach $bitkey (keys %zabbixWinFilesDir) {
$directory = $zabbixWinFilesDir{$bitkey};
if (-d $directory) {
debugMessage("DEBUG", "$bitkey directory ($zabbixWinFilesDir{$bitkey}) found");
} else {
debugMessage("ERROR", "$bitkey directory ($zabbixWinFilesDir{$bitkey}) not found");
}
}
$currentUser = `whoami`;
chomp($currentUser);
if($currentUser =~ /root/) {
debugMessage("DEBUG", "Currently running as root user, continuing. . .");
} else {
debugMessage("ERROR", "This script must be run as the root user. Exiting.");
}
if(-x "./ssh-scp-autologin.sh") {
debugMessage("DEBUG", "Found required expect script (ssh-scp-autologin.sh)");
} else {
debugMessage("ERROR", "Could not find required expect script (ssh-scp-autologin.sh)");
}
if(`grep ROOTPASS ssh-scp-autologin.sh`) {
debugMessage("ERROR", "Root password has not been set in place of ROOTPASS in ssh-scp-autologin.sh");
} else {
debugMessage("DEBUG", "Password has been changed in ssh-scp-autologin.sh");
}
@checkBins = ("smbclient", "net", "winexe", "ssh", "scp", "ping");
foreach $bin (@checkBins) {
$bin = `which $bin`;
chomp($bin);
if(-x $bin) {
debugMessage("DEBUG", "Found required bin ($bin)");
} else {
debugMessage("ERROR", "Could not find required program ($bin)");
}
}
}
sub debugMessage{
my ($level, $message) = @_;
$entry = returndate() . " - $host - $level - $message";
appendfile($LOG, $entry);
if($debugLevels{$level} >= $debugLevel) {
print $entry . "\n";
}
if($level eq "ERROR") {
die();
}
}
sub checkHost {
($host) = @_;
system("ping -qc1 $host 1>/dev/null 2>/dev/null");
$returnCode = $?;
if ($returnCode == 0) {
my $sock = new IO::Socket::INET (
PeerAddr => $host,
PeerPort => '22',
Proto => 'tcp',
);
$returnCode = 1337 unless $sock;
close($sock);
}
return $returnCode;
}
sub returndate {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
$date = sprintf "%4d-%02d-%02d %02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec;
return($date);
}
sub appendfile {
my ($fp, $msg) = @_;
if (open(FILE, ">>$fp")) {
print FILE ("$msg\n");
close FILE;
}
}

Comment