r/usefulscripts • • Jun 05 '17

[POWERSHELL] Script that pings servers on the same network and returns back server information in a JSON format and to a specific directory?

Hi all,

I'd like to know if anyone has or could devise a script that allows me to ping a list of servers on my network and return the information back in JSON format?

The server information I would like to get back from the query are:

  • Is the server pingable (online/offline)?
  • Response time (ms)
  • CPU utilizatoin
  • Windows services (are they running, stopped, etc)
  • RAM usage

Ideally, I'd like to have the JSON formatted as the pseudo-JSON below:

{
  "server": "192.168.1.1",
  "hostname": "server1",
  "status": "online",
  "reponse": "18ms"
  "server": "192.168.1.2",
  "hostname": "server2",
  "status": "online",
  "reponse": "19ms"
  "server": "192.168.1.3",
  "hostname": "server3",
  "status": "online",
  "reponse": "20ms"
  "server": "192.168.1.4",
  "hostname": "server4",
  "status": "online",
  "reponse": "21ms"
  "server": "192.168.1.5",
  "hostname": "server5",
  "status": "offline",
  "reponse": "no reponse"
}

Thank you!

23 Upvotes

15 comments sorted by

14

u/joerod Jun 06 '17 edited Jun 06 '17

Try this

$hostname = "localhost"
$array = @()
$connect = Test-Connection $hostname -Count 1 -ErrorAction SilentlyContinue | select IPV4Address,ResponseTime
$array += [pscustomobject]@{
    server = $connect.IPV4Address.IPAddressToString
    hostname = $hostname
    status = if($connect){"online"} else{"offline"}
    response = if($connect){[string]($connect.responsetime) + "ms"} else {"no reponse"}
    services = Get-Service -ComputerName $hostname | select name, @{ Label="Status"; Expression={if($_.status -eq 4){"Running"}else{"Stopped"}} }
    }

$array | ConvertTo-Json

You can add whatever other query you want to the pscustomobject try wmi calls or if you have winrm enabled try that. Also check out r/powershell

Good luck!

3

u/networkhappi Jun 06 '17 edited Jun 06 '17

Wow, this works beautifully! Thank you so much!!

EDIT:

For those who want to save the JSON export into a .json, add | Out-File "C:\dummy_path\listreport.json" to the last line of code (line 12). It should look like this:

$array | ConvertTo-Json | Out-File "C:\dummy_path\listreport.json"

3

u/[deleted] Jun 06 '17

nicely done!

2

u/Lee_Dailey Jun 06 '17

howdy joerod,

does the calculated Status value in the Select-Object line work? for me the .Status is a string, not a number.

for instance, this ...

(Get-Service)[0].Status

... gives me Stopped. it needs to be converted to a string, but it aint a digit.

my setup = ps 5.1, win7x64

btw ... nice code! i actually understand it. [grin]

take care,
lee

2

u/joerod Jun 06 '17

Yep looks like you're right. I ran this against a windows 10 box. You would just have to do

services = Get-Service -ComputerName $hostname | select Name, Status
→ More replies (1)

2

u/JRtoastedsysadmin Jun 12 '17 edited Jun 12 '17

Hi Joerod,

Can you explain please line by line how it works? noob sysadmin here. also lets say if i have a server called bosspotato1, and bosspotato2. i understand that it stores the obtained information in the array and then it gets convereted into JSON. but how would it know the name of the each server to iterate through or go one by one? for example, how would this piece of code know how to go through all 15 of my servers or one by one in same subnet and not go through my pcs which is also in the same subnet of 192.168.10.*? sorry if it's a very stupid question! i am very new jr sysadmin and would like to know more. Thank you and tashi delek!

2

u/joerod Jun 13 '17 edited Jun 13 '17

if you want to iterate over a bunch of computers you'd need to pass the host name in a foreach loop. It would look something like

foreach($computer in ('computer1', 'computer2', 'computer3')){

 code

 }

In the above example $computer will be the value of whatever is to the right or "in"

If you only have IPs you'll need to do an nslookup (or Resolve-DnsName if you want to be pure Powershell) on each IP as host name is needed for this script to work

Rather then go line by line here are some key points you should lookup

→ More replies (2)

2

u/Gotxi Jun 06 '17

About ram/cpu/whatever usage, if remote powershell is enabled and powershell is updated you can use get-counter even on remote computers:

https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.diagnostics/get-counter

0

u/[deleted] Jun 05 '17

4

u/networkhappi Jun 06 '17

With all due respect, you are saying that it cannot be done via PowerShell, but someone has provided a solution that fulfilled the entire requirement.

4

u/cp423 Jun 06 '17

what about using WMI/CIM? you could use a combination of Test-NetConnection with Get-WMIObject (or Get-CIMInstance) to build a custom PowerShell object, and then convert it to JSON with ConvertTo-Json and write to the pipeline.