Monitor client PC in Microsoft AD using Zabbix. Part 1 — Reinstalling

There are several hundred client machines on windows 7 in a domain microsoft AD, they want to monitor, and in addition to the usual cpu, mem, disk, etc. it would be nice to get information about the smart status drives, usb UPS, and everything must be set automatically, and, if necessary, updated. About the templates, settings and alert the script on the server I'll write later, bye, let's prepare the script for powershell to install agents. At the moment the current version of zabbix — 3.x.

the

External tools


Briefly describe what I use:

-smartmontools — SMART monitoring
-Network UPS Tools (NUT) is a monitoring upsov
-libusb driver, for NUT
-awk, grep for parsing,

Unfortunately, NUT+libusb earned is not so great as expected, had to distribute crutches, but still write about it, in case someone will need it.

the

Configuration of the installer and logging


I will have to update the agent, or its configuration or want to add something new, so we need to have a table(mssql) configuration with the versions of modules that we plan to update.

On local machines versions will be stored in files "ver" in the appropriate directories.

the
CREATE TABLE [dbo].[zabbix_cfg](
[zabbix_bin] [int] NULL, -- agent zabbix binaries
[zabbix_cmd] [int] NULL, -- grep, awk, additional scripts, etc.
[zabbix_conf] [int] NULL, -- config file zabbix_agentd
[zabbix_extra] [int] NULL, -- additional binaries, so far only smartctl
[nut_bin] [int] NULL, -- bin files NUT
[nut_conf] [int] NULL -- conf files NUT
) ON [PRIMARY]

And need somewhere to centrally store the results of the installation in case you need the diagnosis.

the
CREATE TABLE [dbo].[zabbix_log](
[machine] [nvarchar](100) NULL,
[osname] [nvarchar](100) NULL,
[osarch] [nvarchar](10) NULL,
[lastrun] [int] NULL,
[zab_inst_err] [int] NULL,
[zab_inst_run] [int] NULL,
[nut_inst_err] [int] NULL,
[nut_inst_run] [int] NULL,
[nut_upd_err] [int] NULL,
[nut_upd_run] [int] NULL,
[zab_upd_err] [int] NULL,
[zab_upd_run] [int] NULL
) ON [PRIMARY]

lastrun — date of last execution of script
*_run — date of last execution of a function
*_err respectively the result of running

The table is created, it is necessary to give read access to the cfg and write to a log group that includes the computers.

the

the Script


the
# Note!!
# Storage of logs I have used absolute path c:\temp that is already created on all machines of a different policy
# To use the %TMP%(this must be taken into account in the configuration of the zabbix agent, as I recall, he does not understand variables) 
# or create C:\temp you must  make  appropriate edits. 

# case function to SQL server
function Invoke-Sqlcmd($conn,$Query,[Int32]$QueryTimeout=30)
{
$cmd=new-object system.Data.SqlClient.SqlCommand($Query,$conn)
$cmd.CommandTimeout=$QueryTimeout
$ds=New-Object system.Data.DataSet
$da=New-Object system.Data.SqlClient.SqlDataAdapter($cmd)
[void]$da.fill($ds)
$ds.Tables[0]
}
#--------------------------------------------------------------------------------------------
report function-mail($CL) 
{
#E-Mail
$sender = 'ZabbixInstall@domain.local'
$recipient = 'admin@domain.local'
$SMTPserver = 'smtp'
$subject = "At $HostName PS_version = $CurrentPS_Version"
if ($CL -eq 1) {$subject = "p***a #powershell install zabbix deployment aborted"} 
$body = "$HostName't$OSName't$OSVersion't$OSLang't$OSArchitecture't$Date"
$msg = New-Object System.Net.Mail.MailMessage $sender, $recipient, $subject, $body
$client = New-Object System.Net.Mail.SmtpClient $SMTPserver
$client.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$client.Send($msg)
}
#--------------------------------------------------------------------------------------------
#function process is complete:
#Kill-Process "msiexec"
function Kill-Process([string[]]$ProcessNames) 
{
if ($ProcessNames -eq $null) 
{
Write-Error 'The parametre "ProcessNames" cannot be empty';
break
}
else
{
$pr=(Get-Process $ProcessNames -ErrorAction SilentlyContinue) 
$pr.kill()
}
}
#--------------------------------------------------------------------------------------------
#function Install NUT:
#NUT-Install-pth $pnut -pth2 $pnut2 -globalpath $globalpath
function NUT-Install() 
{
Param([string]$pth[string]$pth2,[string]$pth3,[string]$globalpath) 
$ErrorActionPreference="SilentlyContinue"
Copy-Item "$globalpath\driver\APC-UPS\InstallDriver.exe" Destination "c:\temp\InstallDriver.exe" -Force -Verbose
Start-process "c:\temp\InstallDriver.exe" #Put the driver for upsov. We have always used upsy APC, so the exe file alone.
$processid = (Start-process msiexec -args "/quiet /passive /norestart /log c:\temp\inst_nutlog.txt /I $globalpath\nut.msi" -PassThru).id
do 
# when the silent install a NUT falls out interactive exe, nailed. 
{
Write-Host "target_pid" $processid
[array]$msiexecid = Get-Process -Name ' msiexec | % {$_.id}
[array]$xer = Get-Process -Name wdi-simple 
if ($xer.count-gt 0) 

Write-Host "rem_proc" $msiexecid
Start-Sleep -Milliseconds 1000
[array]$proccount+=1
Write-Host "pcount" $proccount.count
Start-Sleep -Milliseconds 1000
} 

while(($msiexecid -contains $processid)-and($proccount.count-lt "90")) 
#different versions of the NUT crooked work different exe, so I take only the best. Files later I will upload to git. 
Copy-Item $globalpath\nut_sbin\* -Destination $pth3 -Force -Verbose
Copy-Item $globalpath\nut_etc\* -Destination $pth -Force -Verbose #config
Copy-Item $globalpath\nut_bin\* -Destination $pth2 -Force -Verbose
Start-Sleep -Milliseconds 15000
#Start the service and write the result to the log. All the logs will update with the MERGE, because the miles log is useless. 
$nut_inst_err=(Get-WmiObject Win32_Service -Filter "Name='Network UPS Tools'").InvokeMethod("StartService",$null)
Invoke-Sqlcmd $conn "MERGE [zabbix].[dbo].[zabbix_log]
USING (values('$HostName','$nut_inst_err','$today')) AS foo (machine,nut_inst_err,nut_inst_run)
ON (zabbix.dbo.zabbix_log.machine = foo.machine)
WHEN MATCHED THEN
UPDATE SET zabbix.dbo.zabbix_log.nut_inst_err = foo.nut_inst_err, zabbix.dbo.zabbix_log.nut_inst_run = foo.nut_inst_run;"
}
#--------------------------------------------------------------------------------------------
#update feature NUT:
function NUT-Update() 
{
Param([string]$pth[string]$pth2,[string]$pth3,[string]$globalpath) 
(Get-WmiObject Win32_Service -Filter "Name='Network UPS Tools'").InvokeMethod("StopService",$null)
Start-Sleep -Milliseconds 15000
Copy-Item $globalpath\nut_etc\* -Destination $pth -Force -Verbose
Copy-Item $globalpath\nut_bin\* -Destination $pth2 -Force -Verbose
Copy-Item $globalpath\nut_sbin\* -Destination $pth3 -Force -Verbose
Start-Sleep -Milliseconds 15000
$nut_upd_err=(Get-WmiObject Win32_Service -Filter "Name='Network UPS Tools'").InvokeMethod("StartService",$null)
Invoke-Sqlcmd $conn "MERGE [zabbix].[dbo].[zabbix_log]
USING (values('$HostName','$nut_upd_err','$today')) AS foo (machine,nut_upd_err,nut_upd_run)
ON (zabbix.dbo.zabbix_log.machine = foo.machine)
WHEN MATCHED THEN
UPDATE SET zabbix.dbo.zabbix_log.nut_upd_err = foo.nut_upd_err, zabbix.dbo.zabbix_log.nut_upd_run = foo.nut_upd_run;"
}
#--------------------------------------------------------------------------------------------
#function install zabbix:
function zabbix-inst($globalpath,$zbxbin)
{
Copy-Item $globalpath\Zabbix -Destination "C:\Program Files\" -Force -Recurse -Verbose
Start-Sleep -Milliseconds 15000
if ($zbxbin -eq "win32") {Copy-Item $globalpath\x86\Zabbix -Destination "C:\Program Files\" -Force -Recurse -Verbose}
Start-Sleep -Milliseconds 11000
$zconf = '"C:\Program Files\Zabbix\conf\zabbix_agentd.conf"'
Start-Process -FilePath "C:\Program Files\Zabbix\bin\$zbxbin\zabbix_agentd.exe" -args "--config $zconf -i"
Start-Sleep -Milliseconds 15000
$zab_inst_err=(Get-WmiObject Win32_Service -Filter "Name='Zabbix Agent'").InvokeMethod("StartService",$null)
Invoke-Sqlcmd $conn "MERGE [zabbix].[dbo].[zabbix_log]
USING (values('$HostName','$zab_inst_err','$today')) AS foo (machine,zab_inst_err,zab_inst_run)
ON (zabbix.dbo.zabbix_log.machine = foo.machine)
WHEN MATCHED THEN
UPDATE SET zabbix.dbo.zabbix_log.zab_inst_err = foo.zab_inst_err, zabbix.dbo.zabbix_log.zab_inst_run = foo.zab_inst_run;"
}

#--------------------------------------------------------------------------------------------
#update feature of zabbix:
function zabbix-update($globalpath,$zbxbin,$part)
{
(Get-WmiObject Win32_Service -Filter "Name='Zabbix Agent'").InvokeMethod("StopService",$null)
Start-Sleep -Milliseconds 15000
Copy-Item $globalpath\Zabbix\$part-Destination "C:\Program Files\Zabbix" -Force -Recurse -Verbose
Start-Sleep -Milliseconds 15000
if (($zbxbin -eq "win32") -and (($part-eq "conf") -or ($part-eq "cmd"))) {Copy-Item $globalpath\x86\Zabbix -Destination "C:\Program Files\" -Force -Recurse -Verbose}
Start-Sleep -Milliseconds 10000 
$zab_upd_err=(Get-WmiObject Win32_Service -Filter "Name='Zabbix Agent'").InvokeMethod("StartService",$null)
Invoke-Sqlcmd $conn "MERGE [zabbix].[dbo].[zabbix_log]
USING (values('$HostName','$zab_upd_err','$today')) AS foo (machine,zab_upd_err,zab_upd_run)
ON (zabbix.dbo.zabbix_log.machine = foo.machine)
WHEN MATCHED THEN
UPDATE SET zabbix.dbo.zabbix_log.zab_upd_err = foo.zab_upd_err, zabbix.dbo.zabbix_log.zab_upd_run = foo.zab_upd_run;"
}

## START
Start-Transcript -path c:\temp\zabbix_inst_debug.txt

$globalpath="\\domain.local\dfs\Zabbix_policy\zabbixinst" #the path where all our welcome, don't forget to give rights to a group, which includes computers. 
$today= get-date -Format "yyyyMMdd"
#
#Arch
$OSArchitecture = (Get-WmiObject -Class Win32_OperatingSystem -Namespace root/cimv2).OSArchitecture
if ($OSArchitecture -match "64-bit")
{
$zbxbin="win64"
$pnut="c:\Program Files (x86)\NUT\etc\"
$pnut2="c:\Program Files (x86)\NUT\bin\"
$pnut3="c:\Program Files (x86)\NUT\sbin\"
}
else 
{
$zbxbin="win32"
$pnut="c:\Program Files\NUT\etc\"
$pnut2="c:\Program Files\NUT\bin\"
$pnut3="c:\Program Files\NUT\sbin\"
}

#Connect to SQL
$conn=new-object System.Data.SqlClient.SQLConnection
$conn.ConnectionString="Server={0};Database={1};Integrated Security=True" -f "server","Zabbix" 
$conn.Open()



# define the name of the host on which you start the script.
$HostName = $env:COMPUTERNAME;

# collect information about the OS
$OperatingSystem = Get-WmiObject Win32_OperatingSystem;
# define other parameters of the OS
$OSName = $OperatingSystem.caption; # the name of the OS
$OSVersion = $OperatingSystem.version; # the version of the OS
$OSLang = $OperatingSystem.oslanguage; # language OS
# MinimalPS_Major_Version
$MinimalPS_Major_Version = 2
# Determine the version of PowerShell
$CurrentPS_Version = $host.version.major

# If versiya PS is right, the script further
If ($CurrentPS_Version -ge $MinimalPS_Major_Version)
{
#main

#log
Invoke-Sqlcmd $conn "MERGE [zabbix].[dbo].[zabbix_log]
USING (values('$HostName','$OSName','$zbxbin','$today')) AS foo (machine,osname,osarch,lastrun)
ON (zabbix.dbo.zabbix_log.machine = foo.machine)
WHEN MATCHED THEN
UPDATE SET zabbix.dbo.zabbix_log.osname = foo.osname, zabbix.dbo.zabbix_log.osarch = foo.osarch, zabbix.dbo.zabbix_log.lastrun = foo.lastrun
WHEN NOT MATCHED BY TARGET THEN
INSERT (machine,osname,osarch,lastrun)
values (machine,osname,osarch,lastrun);"
# 

$Query= 
"SELECT * FROM [zabbix].[dbo].[zabbix_cfg]" 

$result= Invoke-Sqlcmd $conn $Query
[array]$testresult= $result
if ($testresult.count-ne 1 ) { report-mail 1}

#get the local version
[int]$zabbix_bin = Get-Content -Path "C:\Program Files\Zabbix\bin\ver" -ErrorAction SilentlyContinue
[int]$zabbix_cmd = Get-Content -Path "C:\Program Files\Zabbix\cmd\ver" -ErrorAction SilentlyContinue
[int]$zabbix_conf = Get-Content -Path "C:\Program Files\Zabbix\conf\ver" -ErrorAction SilentlyContinue
[int]$zabbix_extra = Get-Content -Path "C:\Program Files\Zabbix\extra\ver" -ErrorAction SilentlyContinue
[int]$nut_bin = Get-Content -Path $pnut2"ver" -ErrorAction SilentlyContinue
[int]$nut_conf = Get-Content -Path $pnut"ver" -ErrorAction SilentlyContinue

#check version 
if (($zabbix_bin -lt 1) -and ($zabbix_cmd -lt 1) -and ($zabbix_conf -lt 1) -and ($zabbix_extra -lt 1) -and ($nut_bin -lt 1) -and ($nut_conf -lt 1) ) 
{
NUT-Install-pth $pnut -pth2 $pnut2 -pth3 $pnut3 -globalpath $globalpath
zabbix-inst $globalpath $zbxbin
}
else
{
if ($zabbix_bin -lt $result.zabbix_bin) {zabbix-update $globalpath $zbxbin "bin"}
if ($zabbix_cmd -lt $result.zabbix_cmd) {zabbix-update $globalpath $zbxbin "cmd"}
if ($zabbix_conf -lt $result.zabbix_conf) {zabbix-update $globalpath $zbxbin "conf"}
if ($zabbix_extra -lt $result.zabbix_extra) {zabbix-update $globalpath $zbxbin "extra"}
if ($nut_bin -lt $result.nut_bin) {NUT-Install-pth $pnut -pth2 $pnut2 -pth3 $pnut3 -globalpath $globalpath}
elseif ($nut_conf -lt $result.nut_conf) {NUT-Update-pth $pnut -pth2 $pnut2 -pth3 $pnut3 -globalpath $globalpath}
}

}
else {
report-mail
}
#end main

#close the connect 
$conn.Close()
Stop-Transcript

the

PostScript


I have a script placed in dfs and starts the job that is created by using group policy.
All the files posted on git.

Monitor client PC in Microsoft AD using Zabbix. Part 2 — the Template scripts and LLD
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

Address FIAS in the PostgreSQL environment. Part 4. EPILOGUE

PostgreSQL: Analytics for DBA

Audit Active Directory tools with Powershell releases. Part 1