Introduction
The following script allows you to get disk metrics using an EXE/Script sensor. It will connect to the server, execute the given command and simply return the corresponding disks. Note that you may need to modify the command it executes. By default, it will execute the following:
df -k | tail -n +2
...which is suitable for for AIX distributions. The tail command will omit the translated table header, making it look like this:
/dev/root 29316584 4593144 23211172 17% / devtmpfs 469688 0 469688 0% /dev tmpfs 474004 0 474004 0% /dev/shm tmpfs 474004 47972 426032 11% /run tmpfs 5120 4 5116 1% /run/lock tmpfs 474004 0 474004 0% /sys/fs/cgroup /dev/mmcblk0p6 64366 19974 44392 32% /boot tmpfs 94804 0 94804 0% /run/user/1000
Requirements
- Configured Linux credentials in the given device
- Python installed on the target host
- PRTG can execute PowerShell scripts. Please have a look at our guide for installing PowerShell based sensors for installation details.
Parameters
Parameter | Description |
---|---|
ComputerName | The Linux host you want to connect to (can be set to %host) |
Username | The Linux user you want to use (can be set to %linuxuser) |
Password | The password of the above user (can be set to %linuxpassword) |
Command | The command you want to execute, including parameters. Or use the configured one (remember to base64 encode it) |
Includes | Only include these mounts. Example @('/root','/etc') |
AutoUpdateFingerPrint | Set this when calling the script to automatically update the SSH fingerprints of known devices. Careful, though! |
Version History
Date | Version | Notes |
---|---|---|
April 12th, 2018 | 1.1 | - More generalistic approach - Automated module setup - Support for keyfiles - Better debug output |
July 23rd, 2015 | 1.0 | Initial Release |
Script
# ___ ___ _____ ___ #| _ \ _ \_ _/ __| #| _/ / | || (_ | #|_| |_|_\ |_| \___| # NETWORK MONITOR #------------------- # Description: This sensor will parse through the volumes mounted on the target device # Parameters: # -Computername: The linux host you want to connect to # -Username Your linux username # -Password Your linux password # -Command The line to execute on your host # -Includes Only include these drives if you don't want all of them. Use the exact filesystem path! # # # # # # # # # # # # # # Comments: # The comment used here is base64 encoded, since it's turning the output of df into a nice JSON object array, making it easier to evaluate the output: # df -Ph | awk '/^\// {print $1"\t"$2"\t"$4}' | python -c 'import json, fileinput; print json.dumps({"diskarray":[dict(zip(("mount", "spacetotal", "spaceavail"), l.split())) for l in fileinput.input()]}, indent=2)' # Note that it requires python installed on the target host. Courtesy of user "dawg" via stackoverflow (https://stackoverflow.com/a/35212442) # # # # # # # # # # # # # # # Note: If the SHA1 fingerprint of the server changes, please execute it with the following parameters: # -ComputerName <your-host> -UserName <username> -Password <password> -command "echo PRTG needs fingerprint update..." -UpdateFingerPrint # ------------------ # # # # # # # # # # # # # Version History # April 12th, 2018 - more generalistic approach, automated module setup, support for keyfiles, better debug output # July 23rd, 2015 - Initial Release # # # # # # # # # # # # # (c) 2017 Stephan Linke | Paessler AG # Parameters param( [string]$Computername = "", [string]$Username = "", [string]$Password = "", [string]$keyFile = "", [string]$Command = "ZGYgLVAgfCBhd2sgJy9eXC8vIHtwcmludCAkMSJcdCIkMiJcdCIkNH0nIHwgcHl0aG9uIC1jICdpbXBvcnQganNvbiwgZmlsZWlucHV0OyBwcmludCBqc29uLmR1bXBzKHsiZGlza2FycmF5IjpbZGljdCh6aXAoKCJtb3VudCIsICJzcGFjZXRvdGFsIiwgInNwYWNlYXZhaWwiKSwgbC5zcGxpdCgpKSkgZm9yIGwgaW4gZmlsZWlucHV0LmlucHV0KCldfSwgaW5kZW50PTIpJw==", [string]$Includes = @(), [switch]$UpdateFingerPrint = $False ) clear #region modules $requiredModules = @("Posh-SSH") #endregion #region configuration $numbers = @{ 2 = "two" 3 = "three" 4 = "four" 5 = "five" 6 = "six" 7 = "seven" 8 = "eight" 9 = "nine" } if(($requiredModules.Count -lt 10) -and ($requiredModules.Count -gt 1)){ $requiredModulesCount = $numbers[$requiredModules.Count]} if($requiredModules.Count -gt 9) { $requiredModulesCount = $requiredModules.Count } # channels per volume $resultTemplate = @" <result> <channel>{0} Free</channel> <value>{1}</value> <unit>BytesDisk</unit> <VolumeSize>KiloByte</VolumeSize> <float>0</float> </result> <result> <channel>{0} Used</channel> <value>{2}</value> <unit>BytesDisk</unit> <VolumeSize>KiloByte</VolumeSize> <float>0</float> </result> <result> <channel>{0} Used Percent</channel> <value>{3}</value> <unit>Percent</unit> </result> "@ #endregion #region function library # This will connect to the given host and execute the df command. function This-ShowMessage([string]$type,$message){ Write-Host ("[{0}] " -f (Get-Date)) -NoNewline; switch ($type){ "success" { Write-Host " success " -BackgroundColor Green -ForegroundColor White -NoNewline; } "information" { Write-Host " information " -BackgroundColor DarkCyan -ForegroundColor White -NoNewline; } "warning" { Write-Host " warning " -BackgroundColor DarkYellow -ForegroundColor White -NoNewline; } "error" { Write-Host " error " -BackgroundColor DarkRed -ForegroundColor White -NoNewline; } default { Write-Host " notes " -BackgroundColor DarkGray -ForegroundColor White -NoNewline; } } Write-Host (" {0}{1}" -f $message,$Global:blank) } function This-Setup { $installed = 0; Switch($requiredModules.Count){ {$_ -eq 1 } { This-ShowMessage -type information -message ([string]::Format("This sensor has one dependency: {0}", $requiredModules -join ", ")) } {$_ -gt 1 } { This-ShowMessage -type information -message ([string]::Format("This sensor has {0} dependencies: {1}", $requiredModulesCount, $requiredModules -join ", ")) } } foreach($requiredModule in $requiredModules){ # Check if our module loaded properly This-ShowMessage -type information -message "Checking for module $($requiredModule)" if (Get-Module -ListAvailable -Name $requiredModule) { try { Import-Module $requiredModule -Verbose:$false; This-ShowMessage -type success -message "$($requiredModule) loaded."; $installed++} catch { This-ShowMessage -type error -message "There was a problem loading $($requiredModule). Details of the error:`n$($_.Exception.Message)"} } else { This-ShowMessage -type information "$($requiredModule) not installed yet. Installing now..." try { Install-Module $requiredModule -Force -Verbose:$false; } catch { This-ShowMessage -type error -message "There was a problem installing $($requiredModule). Details of the error:`n$($_.Exception.Message)"} } } if($installed -eq $requiredModules.Count) { This-ShowMessage -type success -message "All dependencies loaded."} else { This-ShowMessage -type error -message "At least one dependency was not met. Exiting..."; This-Exit("At least one dependency was not met. Please run the sensor manually with the same parameters and check the error log.") } } function This-Exit([string]$message){ Write-Host @" <prtg> <error>1</error> <text>$($message)</text> </prtg> "@ } function This-GetSSHCommandOutput(){ # if we don't have a keyfile, use the password if($keyFile.Length -eq 0){ # Generate credentials object for authentication $SecPasswd = ConvertTo-SecureString $Password -AsPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential ($Username, $secpasswd) } # If AutoUpdateFingerprint is enabled, the script will always remove the fingerprint saved for the host. # It's recommended to set it to false and only call the script manually with # -ComputerName <your-host> -UserName <username> -Password <password> -command "echo PRTG needs fingerprint update..." -UpdateFingerPrint if($UpdateFingerprint){ Remove-SSHTrustedHost $Computername } # Create new session and execute the command given if($keyFile.Length -ne 0){ This-ShowMessage -type information -message "Using keyfile ($($keyFile))."; $SessionId = (New-SSHSession -Computername $Computername -Acceptkey -KeyFile $keyFile).SessionId } else { This-ShowMessage -type information -message "Using username/password."; $SessionId = (New-SSHSession -Computername $Computername -Credential $Credentials -Acceptkey).SessionId } # store output of the above command $Output = (Invoke-SSHCommand -SSHSession $SshSessions[$SessionId] -Command ( [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Command)))) # disconnect the host $SshSessions[$SessionId].Disconnect(); # remove from the session list Remove-SSHSession($SessionId) return ($Output.Output | ConvertFrom-Json) } # This will retrieve the volume table and output it into the proper XML format function This-EvaluteCommandResult(){ $Volumes = (This-GetSSHCommandOutput).diskarray This-ShowMessage information "Found $($Volumes.Count) volumes on $($Computername)." Foreach ($Volume in $Volumes){ try{ # $Bytes = [System.Math]::Round(($Volume.spacetotal / $Multiplicator),2) # $FreeBytes = [System.Math]::Round(($Volume.spaceavail / $Multiplicator),2) $Bytes = [int32]$Volume.spacetotal * 1024 $FreeBytes = [int32]$Volume.spaceavail * 1024 $UsedBytes = [System.Math]::Round(($Bytes - $FreeBytes),2) $FreePercent = [System.Math]::Round(100-(($Volume.spaceavail / $Volume.spacetotal)*100),0) $Volume | Add-Member "FreeReadable" $FreeBytes $Volume | Add-Member "SizeReadable" $Bytes $Volume | Add-Member "UsedReadable" $UsedBytes $Volume | Add-Member "FreePercent" $FreePercent } catch{ Write-Host "Failed." } } # output the XML structure according to the includes list (or output everything, in case it's empty) Write-Host "<?xml version='1.0' encoding='UTF-8' ?><prtg>"; Foreach ($Volume in $Volumes){ # check the include list if($Includes.Length -eq 0){ $placeholders = @($Volume.mount, $Volume.FreeReadable, $Volume.UsedReadable, $Volume.FreePercent) Write-Host ([string]::Format($resultTemplate, ($placeholders -replace ",","."))) } else{ if($Includes.Contains($volume.mount)){ $placeholders = @($Volume.mount, $Volume.FreeReadable, $Volume.UsedReadable, $Volume.FreePercent) Write-Host ([string]::Format($resultTemplate, ($placeholders -replace ",","."))) } } } Write-Host "</prtg>"; } This-Setup This-EvaluteCommandResult
The script is provided as is and may or may not work with your installation. If you need any further customizations for your environment, feel free to implement them. If you encounter any bugs, feel free to share them :)
Add comment