Snmpホストリソースデータ収集（Windows）

## CPU、メモリー、ディスク使用率 VBスクリプト編

## はじめに

Mrtgグラフを作成する場合、SNMPのOIDを使うの方法が一般的ですが、加工した情報を採るスクリプトを作成してグラフを作成する機会がありましたので書き残します。スクリプトはVBScriptで記述しmrtg.cfgのTargetに設定します。Linuxのシェルスクリプト編は<a href="https://qiita.com/ossiansunny/items/72de1d05eb4f9a8c2743">こちら</a>にあります。


### CPU使用率取得OID

```DOC
監視対象エージェントホストがWindowsまたはLinuxの場合

* OID .1.3.6.1.2.1.25.3.3.1.2　をsnmpwalkし、
HOST-RESOURCES-MIB::hrProcessorLoad.xの最大値を取得
```

### Memory使用率取得OID

```DOC
監視対象エージェントホストがWindowsの場合

* OID .1.3.6.1.2.1.25.2.3.1　をsnmpwalkし、
HOST-RESOURCES-MIB::hrStorageDescr.5 = STRING: Physical Memory
のPhysical Memoryのxの数値を取得、この数値同じSizeとUsedを探し
HOST-RESOURCES-MIB::hrStorageSize.5 = INTEGER: 260240
HOST-RESOURCES-MIB::hrStorageUsed.5 = INTEGER: 79706
Used/Sizex100で使用率を算出する（上記例 79706/260240x100=30%）

監視対象エージェントホストがLinuxの場合

* OID .1.3.6.1.2.1.25.2.3.1　をsnmpwalkし、
HOST-RESOURCES-MIB::hrStorageDescr.1 = STRING: Physical Memory
のPhysical Memoryのyの数値を取得、この数値同じSizeとUsedを探し
HOST-RESOURCES-MIB::hrStorageSize.1 = INTEGER: 3715376
HOST-RESOURCES-MIB::hrStorageUsed.1 = INTEGER: 1104480
Used/Sizex100で使用率を算出する（上記例 1104480/3715376x100=29%）
```

### Disk使用率取得OID

```DOC
監視対象エージェントホストがWindowsの場合

* OID .1.3.6.1.2.1.25.2.3.1　をsnmpwalkし、
HOST-RESOURCES-MIB::hrStorageDescr.1 = STRING: **C:\\ Label**
のC:\\ Labelのxの数値を取得、この数値同じSizeとUsedを探し
HOST-RESOURCES-MIB::hrStorageSize.1 = INTEGER: 60721838
HOST-RESOURCES-MIB::hrStorageUsed.1 = INTEGER: 28520672
Used/Sizex100で使用率を算出する（上記例 28520672/60721838x100=46%）

監視対象エージェントホストがLinuxの場合

* OID .1.3.6.1.2.1.25.2.3.1　をsnmpwalkし、
HOST-RESOURCES-MIB::hrStorageDescr.x = STRING: /
の/(root directory)のyの数値を取得、この数値同じSizeとUsedを探し
HOST-RESOURCES-MIB::hrStorageSize.x = INTEGER: 36682240
HOST-RESOURCES-MIB::hrStorageUsed.x = INTEGER: 2096449
Used/Sizex100で使用率を算出する（上記例 2096449/36682240x100=6%）
```

### 使用パッケージ

- mrtg
- perl
- Windows Snmp (snmp Agent)
- Net-snmp (snmpコマンド)


### スクリプト概要

1. Cpu、Memory、Diskの使用率をsnmpで取得し、加工するBashスクリプトを作成します
2. スクリプトはホスト、OS、コミュニティの引数を受け入れ、２つの値を返します
3. ２つのうち、最初に返す値を使用し、２つ目はグラフの上限100%を返します
4. 以下のサンプルスクリプトはチェックおよびエラー処理等省略しています

### Cpu使用率取得のVBScript（snmpcpuget.vbs）

```vbscript

Dim host, ostype, comm
host=WScript.Arguments(0)
ostype=WScript.Arguments(1)
comm=WScript.Arguments(2)
Dim objShell,objExec,cpuGet,cpuArr,maxCpu,line,errSw
cpuGet=""
Set objShell = CreateObject("WScript.Shell")
cpuGet = "snmpwalk -v1 -c" & comm & " " & host & " .1.3.6.1.2.1.25.3.3.1.2"
Set objExec = objShell.Exec(cpuGet)
maxCpu=0
errSw=0
Do While objExec.StdOut.AtEndOfStream = false
  line = objExec.Stdout.ReadLine
  cpuArr = Split(line, ": ")
  If Ubound(cpuArr) = -1 Then
    errSw=1
    Exit Do
  Else
    If CInt(cpuArr(1)) > CInt(maxCpu) Then
      maxCpu=cpuArr(1)
    End If
  End If
Loop
If errSw = 0 Then
  WScript.Echo maxCpu
  WScript.Echo 100
Else
  WScript.Echo 0
  WScript.Echo 100
End If
```

### Memory使用率取得のVBScript（snmpramget.vbs）

```vbscript

Dim host, ostype, comm
host=WScript.Arguments(0)
ostype=WScript.Arguments(1)
comm=WScript.Arguments(2)
Dim objShell,ramGet,line,ramArr,ramSize,ramUsed,ramPer
Set objShell = CreateObject("WScript.Shell")
If ostype = "windows" Then
  ramSize = "snmpget -v1 -c" & comm & " " & host & " .1.3.6.1.2.1.25.2.3.1.5.5"
  ramUsed = "snmpget -v1 -c" & comm & " " & host & " .1.3.6.1.2.1.25.2.3.1.6.5"
Else
  ramSize = "snmpget -v1 -c" & comm & " " & host & " .1.3.6.1.2.1.25.2.3.1.5.1"
  ramUsed = "snmpget -v1 -c" & comm & " " & host & " .1.3.6.1.2.1.25.2.3.1.6.1"
End If
Set objExec = objShell.exec(ramSize)
line = objExec.Stdout.ReadLine
ramarr = Split(line, ": ")
If Not (Ubound(ramArr) = -1) Then
  ramSize = ramArr(1)
  Set objExec = objShell.exec(ramUsed)
  line = objExec.Stdout.ReadLine
  ramArr = Split(line, ": ")
  ramUsed = ramArr(1)
  ramPer = Int(ramUsed * 100 / ramSize)
  WScript.echo ramPer
  WScript.echo 100
Else
  WScript.Echo 0
  WScript.Echo 100
End If
```

### Disk使用率取得のVBScript （snmpdiskget.vbs）

``` vbscript

Dim host, ostype, comm
host=WScript.Arguments(0)
ostype=WScript.Arguments(1)
comm=WScript.Arguments(2)
Dim objShell,diskSize,diskUsed,line,diskArr,diskArr2,diskId,userdOid,sizeOid 
Set objShell = CreateObject("WScript.Shell")
diskDscr = "snmpwalk -v1 -c" & comm & " " & host & " .1.3.6.1.2.1.25.2.3.1.3"
Set objExec = objShell.exec(diskDscr)
line = objExec.Stdout.ReadLine
diskArr = Split(line, ": ")
If Not (Ubound(diskArr) = -1) Then
  If ostype = "windows" Then
    diskSize = "snmpget -v1 -c" & comm & " " & host & " .1.3.6.1.2.1.25.2.3.1.5.1"
    diskUsed = "snmpget -v1 -c" & comm & " " & host & " .1.3.6.1.2.1.25.2.3.1.6.1"
  Else
    diskDscr = "snmpwalk -v1 -c" & comm & " " & host & " .1.3.6.1.2.1.25.2.3.1.3"
    Set objExec = objShell.exec(diskDscr)
    diskId=""
    Do While objExec.StdOut.AtEndOfStream = false
      line = objExec.Stdout.ReadLine
      diskArr = Split(line, ": ")
      If diskArr(1) = "/" Then
        diskArr2 = Split(diskArr(0), " = ")
        diskArr = Split(diskArr2(0), ".")
        diskId = diskArr(1)
        Exit Do
      End If
    Loop
    sizeOid=".1.3.6.1.2.1.25.2.3.1.5." & diskId
    usedOid=".1.3.6.1.2.1.25.2.3.1.6." & diskId
    diskSize = "snmpget -v1 -c" & comm & " " & host & " " & sizeOid
    diskUsed = "snmpget -v1 -c" & comm & " " & host & " " & usedOid
  End If 
  Set objExec = objShell.exec(diskSize)
  line = objExec.Stdout.ReadLine
  diskArr = Split(line, ": ")
  diskSize = diskArr(1)
  Set objExec = objShell.exec(diskUsed)
  line = objExec.Stdout.ReadLine
  diskArr = Split(line, ": ")
  diskUsed = diskArr(1)
  diskPer = int(diskUsed * 100 / diskSize)
  WScript.Echo diskPer
  WScript.Echo 100
Else
  WScript.Echo 0
  WScript.Echo 100
End If 
```

### mrtg.cfgと実行例

``` DOC
 1 EnableIPv6: no
 2 WorkDir: c:\mypath\mrtg
 3 #------------------------------------------------------#
 4 Target[sample.com.cpu]: `cscript //nologo c:\mypath\bin\snmpcpuget.vbs host ostype comm`
 5 MaxBytes[sample.com.cpu]: 100
 6 Options[sample.com.cpu]: gauge,growright
 7 YTicsFactor[sample.com.cpu]: 1
 8 Factor[sample.com.cpu]: 1
 9 Title[sample.com.cpu]: Maximum CPU Load per Hour
10 YLegend[sample.com.cpu]: CPU Load
11 #------------------------------------------------------#
12 Target[sample.com.disk]: `cscript //nologo c:￥mypath\bin\snmpdiskget.vbs host ostype comm`
13 MaxBytes[sample.com.disk]: 100
14 Options[sample.com.disk]: gauge,growright
15 YTicsFactor[sample.com.disk]: 1
16 Factor[sample.com.disk]: 1
17 Title[sample.com.disk]: Disk Usage
18 YLegend[sample.com.disk]: Disk Usage
19 #------------------------------------------------------#
20 Target[sample.com.ram]: `cscript //nologo c:\mypath\bin\snmpramget.vbs host ostype comm`
21 MaxBytes[sample.com.ram]: 100
22 Options[sample.com.ram]: gauge,growright
23 YTicsFactor[sample.com.ram]: 1
24 Factor[sample.com.ram]: 1
25 Title[sample.com.ram]: Memory Usage
26 YLegend[sample.com.ram]: Memory Usage
 2,4,12,20行目のパス、ホスト、コミュニティは、環境に合わせて変更が必要
Targetの snmpxxxget 引数 host:ホスト　ostype:{windows|unix} comm:コミュニティ
cscriptのロゴが標準出力に影響するので、nologoオプションを指定
```

```DOC
* Path構成
 
c:\mypath
    |__ \bin
    |     |__ snmpcpuget.vbs
    |     |__ snmpramget.vbs
    |     |__ snmpdiskget.vbs
    |__ \mrtg  
          |__ mrtg.cfgなど

```

```dos
* 実行例(単体テスト)
c:\mypath> bin\snmpcpuget.vbs host ostype comm
c:\mypath> bin\snmpramget.vbs host ostype comm
c:\mypath> bin\snmpdiskget.vbs host ostype comm  
注意：スクリプトは入力チェック、エラー処理等省略していますので、事前にsnmpコマンドでhost、ostype、commが実際に存在することを確認してから実行して下さい 

* 実行例(mrtg)
c:\mypath> perl mrtg c:\mypath\mrtg\mrtg.cfg
perl,mrtgは PATH環境変数にあること、実行はタスクスケジューラが利用できる
```

### ソースとサンプルデータ

<a href="https://github.com/ossiansunny/visualmonitor">ここの</a>graphsample/windowsにあります。

### サンプル画像
![mrtggraph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714448/b0a16cad-8202-c6f7-719d-c2751d1bc3ac.png)

## おわりに
グラフデータ収集スクリプトはグラフ作成以外に、サーバ監視システムの機能の中のCPU、Memory、Diask使用率の危険値、警告値超えをチェックする機能としても動作させています。興味ある方は<a href="https://github.com/ossiansunny/visualmonitor">ここから</a>どうぞ。