i am new to stackoverflow and i'm not really a powershell crack. Maybe you can help me with my problem. For monitoring reasons i want to get a ssh result from "vmstat 1 10" on an Linux-Server. I need to get the Avarage Values of the 10 Values i have. A Usual "vmstat 1 10" result looks like this:
procs -----------memory---------- ---swap-- -----io---- -system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 42352 599980 315860 2488096 0 0 2606 794 5 2 3 0 94 2 0
0 0 42352 600044 315860 2488096 0 0 64 84 1107 2107 0 1 99 1 0
0 0 42352 596820 315860 2488096 0 0 280 4 1218 2179 7 1 91 2 0
0 0 42352 589240 315860 2488096 0 0 32 7 1322 2366 1 1 95 3 0
0 0 42352 588620 315860 2488096 0 0 144 37 1161 2181 1 0 96 3 0
0 0 42352 588620 315860 2488096 0 0 0 24 1074 2075 0 0 100 0 0
0 0 42352 588620 315860 2488096 0 0 0 0 1081 2081 0 1 100 0 0
0 0 42352 588628 315860 2488096 0 0 128 32 1133 2091 1 0 96 3 0
0 0 42352 588652 315860 2488100 0 0 0 0 1077 2058 0 0 100 0 0
0 0 42352 588528 315860 2488100 0 0 0 5 1137 2147 0 0 99 0 0
So to get the AVG of the Values like swpd, free, buff, etc. my plan was to get the whole values in an Object an then make something like $tab.swpd | Measure-Object -avg
but i get an error.
Here is my Script to get the values in the Object. (I know that this is not very nice - sorry for that. I'm still learning...):
$runs = 10
#Get the Values via plink (putty)
$vmstat = .\plink.exe -ssh USER@SERVER -batch -pw "PASSWORD-YES-I-KNOW-THIS-IS-BAD" vmstat 1 $runs
$vmstat
##########################
#Get the Values in somthing like a csv
$vmstat = $vmstat.replace(" ", ";")
#replace alle double ";;" with single ";"
while ($vmstat -match ";;"){
$vmstat = $vmstat.replace(";;", ";")
}
#Delete ";" at the beginning (and at the end. Just to be sure. normally there arent ";" 's)
$vmstat = $vmstat.Trim(";")
#Save Columnames
$tabhead = $vmstat[1].split(";")
#Delete first and second row
$vmstat = $vmstat[2..($runs+1)]
##########################
#Split Values and Store it in an two-dimensional array
$values = New-Object system.Array[][] $tabhead.Length, $runs
for ($i=0;$i -lt ($vmstat.Length); $i++){
$tmp = $vmstat[$i].split(";")
for ($j=0;$j -lt ($tmp.Length); $j++){
$values[$j][$i] = $tmp[$j]
}
}
##########################
# Make an Object for Measurement!
$tab = New-Object System.Object
for ($i=0;$i -lt $tabhead.Length; $i++){
$tab | Add-Member -type NoteProperty -name $tabhead[$i] -Value $values[$i]
}
so after that all my Values are like i want in the Array or in the Object. I am Able to do select Values i want to see:
PS C:\> $tab
r : {1, 0, 0, 0...}
b : {0, 0, 0, 0...}
swpd : {42352, 42352, 42352, 42352...}
free : {599980, 600044, 596820, 589240...}
buff : {315860, 315860, 315860, 315860...}
cache : {2488096, 2488096, 2488096, 2488096...}
si : {0, 0, 0, 0...}
so : {0, 0, 0, 0...}
bi : {2606, 64, 280, 32...}
bo : {794, 84, 4, 7...}
in : {5, 1107, 1218, 1322...}
cs : {2, 2107, 2179, 2366...}
us : {3, 0, 7, 1...}
sy : {0, 1, 1, 1...}
id : {94, 99, 91, 95...}
wa : {2, 1, 2, 3...}
st : {0, 0, 0, 0...}
PS C:\> $tab.in
5
1107
1218
1322
1161
1074
1081
1133
1077
1137
But when i try somthing like: $tab.swpd | Measure-Object -Average
i get the following error:
Measure-Object : Das Eingabeobjekt "System.Object[]" ist nicht numerisch.
In Zeile:1 Zeichen:13
+ $tab.swpd | Measure-Object -Average
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (System.Object[]:Object[]) [Measure-Object], PSInvalidOperationException
+ FullyQualifiedErrorId : NonNumericInputObject,Microsoft.PowerShell.Commands.MeasureObjectCommand
i think i even would not need the Object, i think it must also be posible to do something like $values[0] | Measure-Object -Average
but there is the same error. I know the Problem is that the values arent int values. But i dont know how to convert them so i can make my measurements.
I dont have access to the same resources so I was not able to perfectly recreate the problem. You are right. Measure-Object
is trying to tell you that it cannot work with non-numerical values. I think newer versions of powershell handle this better but a cast might do you just fine.
[int[]]($tab.swpd) | Measure-Object -Average
That should cast the System.Object[]
array to System.Int32[]
For efficiency
You are splitting the empty space with semicolons and cosolidating those until you have one. Regex might save that whole loop. This will take groups of whitespace and convert them to a semicolon. That might save your issue towards the end. This might address the issue with you Measure-Object since that should remove all whitespace assuming you are not adding any somewhere else along the way. You would still have to address the leading and trailing semi colons created by this like you already do.
$vmstat = $vmstat.replace("\s+", ";")
Edit from comments
So I see the cast failed. You have whitespace in your array values i didnt notice at first. Perhaps that is why you are having and issue. You have an array of strings it seems. I will look at your code again and find out where these are coming from. There are other ways to address this but a simple one might be to update this line at the bottom of your code
$tab | Add-Member -type NoteProperty -name $tabhead[$i] -Value $values[$i].Trim()