LoginSignup
1
2

More than 3 years have passed since last update.

【ネットワークエンジニアのプログラミング】アクセススイッチの空きポート確認(材料:Tera Termマクロ+VBA )

Posted at

ネットワークエンジニアのプログラミング ほっぷ・すってぷ・Tera Term

今回書いてあるTera TermマクロとexcelVBAをつかうと、アクセススイッチの空きポートが一覧できますので、良かったら使ってください。
例えば

「300台のアクセススイッチの空きポートを一覧にしろ!」と言われたとしても、秒でできます。

では、本文です。

ネットワークエンジニアはプログラミングが出来ません。
(もちろん出来る人はいるよ!!!)

ただ、前回のブログでも言いましたが、プログラミングができないとIoTの世界で生きていけないので、
ネットワークエンジニアもIoTに興味のある人も、
第一歩目としてお勧めなのがTera Termマクロです。
(嘘です、ネットワークエンジニアにはお勧めですが、WEB界隈の人はマイコン制御した方がいいです。ラズパイです)

今回は、こんな感じでやってみます。

料理の目的

ゴール:自動でアクセススイッチの空きポート確認をする
目的 :スキルの付かない反復単純作業の自動化
理由 :浮いた時間でTera Termマクロを覚え、更に自動化 → IoTエンジニアへ
時間 :2時間クッキング

クッキングの流れ

①Tera Termマクロを作成
 ・ASW(Access SWitchにログイン、コマンドを実行)
 ・ログ取得
②ログをexcelに貼り付ける
 ・excel上で少し成形する
 ・excel VBAで空きポートなのか判断する

材料

teratermマクロ.ttl
; 接続情報
JumpSwitch = 'ホスト名:訳合って踏み台SWにログインが必要'
HOSTADDR01 = 'ASWのホスト名'
HOSTADDR02 = 'ASWのホスト名'
HOSTADDR03 = 'ASWのホスト名'
SSH        = 'ssh '
EXECOMMAND1 = 'ter len 0'
EXECOMMAND2 = 'sh ip int bri'
EXECOMMAND3 = 'sh int status'
EXECOMMAND4 = 'sh int counters'
EXECOMMAND5 = 'sh ver'
USERNAME = 'ログイン時のユーザー名'
PASSWORD = 'パスワード'
;=====================================================================

;--- 踏み台スイッチへログイン
COMMAND = 'xxx.xxx.xxx.xxx' ;--- IP address
strconcat COMMAND ':22 /ssh /2 /auth=password /user='
strconcat COMMAND USERNAME
strconcat COMMAND ' /passwd='
strconcat COMMAND PASSWORD

; 接続
connect COMMAND
strconcat JumpSwitch '>'
strconcat SSH HOSTADDR01
wait JumpSwitch
sendln SSH
wait 'Password:'
sendln PASSWORD

; 接続
strconcat HOSTADDR01 '>'
wait HOSTADDR01
sendln EXECOMMAND1
wait HOSTADDR01
sendln EXECOMMAND2
wait HOSTADDR01
sendln EXECOMMAND3
wait HOSTADDR01
sendln EXECOMMAND4
wait HOSTADDR01
sendln EXECOMMAND5
wait HOSTADDR01
sendln 'exit'


;--------------------------------------------------

wait JumpSwitch
SSH = 'ssh '
strconcat SSH HOSTADDR02
sendln SSH
wait 'Password:'
sendln PASSWORD

; 接続
strconcat HOSTADDR02 '>'
wait HOSTADDR02
sendln EXECOMMAND1
wait HOSTADDR02
sendln EXECOMMAND2
wait HOSTADDR02
sendln EXECOMMAND3
wait HOSTADDR02
sendln EXECOMMAND4
wait HOSTADDR02
sendln EXECOMMAND5
wait HOSTADDR02
sendln 'exit'

;--------------------------------------------------

wait JumpSwitch
SSH = 'ssh '
strconcat SSH HOSTADDR03
sendln SSH
wait 'Password:'
sendln PASSWORD

; 接続
strconcat HOSTADDR03 '>'
wait HOSTADDR03
sendln EXECOMMAND1
wait HOSTADDR03
sendln EXECOMMAND2
wait HOSTADDR03
sendln EXECOMMAND3
wait HOSTADDR03
sendln EXECOMMAND4
wait HOSTADDR03
sendln EXECOMMAND5
wait HOSTADDR03
sendln 'exit'

;--- という感じで、ログインしたいスイッチを永遠に繋いでいきます。

closett
end

さぁ、これでエンドレスに入りたいスイッチにログインし、ポートステータスが取得できるようになりましたね。

因みに企業環境下では以下の制約があるケースが多いので、上記のような書き方をしています。
・スイッチへの直接ログインができない
 →踏み台サーバーやスイッチを経由してる書き方をしている。
・スイッチへのenableモードでのログインが制限されている
 →userモードで実行できるコマンドで記述している

--- 実行コマンドの説明 ---
"sh int status"や"sh ip int bri"
 → ポートのdown/upが判断します。
"sh int counters"
 → そのポートの累積通信量が表示される

上記2つで以下が分かります。(マトリックスを書きたいが文章で・・・)
ポートがup且つ、通信量があるポート
 → 利用しているポートと判断。
ポートがup且つ、通信量の無いポート
 → デバイス接続があるが、通信はしてないポート。
ポートがdown且つ、通信量のあるポート
 → 今は接続がない(もしくは結線ありだがエンド端末が電源off)が、
   過去に通信していたポート
   (このポートはケーブル結線があれば、
    利用しているポートにカテゴライズされるべき)
ポートがdown且つ、通信量の無いポート
 → 利用していないポートと判断。

今回は空きポートを知りたいので、
最後のパターン、「ポートがdown且つ、通信量の無いポート」をリストアップするようなマクロを書きます。

最後に"sh ver"についてですが、
このコマンドで機器のuptime(連続稼働時間)を見ます。
理由は、データの信頼性の確認です。

"sh int counters"の表示される通信量は、スイッチの電源が切れるとリセットされます。
よって、uptimeが1週間未満である場合は、sh int countersで取得した値はただの参考値とします。
(1週間未満だと、通信量が0であっても、たまたまこの一週間使ってなかっただけ。という可能性があるからです)

実際の利用状況は、(しょうがないので)、実地(オンサイト)で確認する事。としておきます。

さて、Tera Termマクロはこれで完成したので、今度はexcel側の成型作業とexcel VBAを作ります。
こんな感じで書きました。


②ログをexcelに貼り付ける
 ・excel上で少し成形する
 ・excel VBAで空きポートなのか判断する

このフローを実行するマクロを作成します。
1 uptimeの確認
  対象端末が20台くらいの場合:
   excelにログを貼り付けた時点で「uptime」で検索します。
   マクロ書きません。ただの検索です。その方が早いです。
   そこで、uptimeが1 week未満だったスイッチは今回の処理から除外しましょう。
  
  対象端末が300台を超える場合:
   マクロ化しましょう。
   マクロにより「やっぱり、1 week未満だったよ印」を付ける事にします。

2 ポートのup/downの確認
  やってみて分かったんですが、"sh int status"の方の結果を使いましょう。
  今回は、"sh ip int bri"は使いません。
  理由はポート名の表記です。
  "sh ip int bri" = GigabitEthernet1/0/1
  "sh int status" = Gi1/0/1
  "sh int counters" = Gi1/0/1
  この3つの中だと、sh ip int briだけ、フルでポート名が表示されるんですね。
  表示名が合ってる"sh int status"の方を使ってあげましょう。

3 ポートの通信量のチェック
  これは、ポートのup/down確認の時に、downだったポートのみ確認するように
  書いてみたいと思います。

4 ホスト名と、空きポートの書き出し
  ポートがdownステータス且つ、通信量が0だったもののみ書き出し(リストアップ)します。
  1の処理でuptimeが1 week未満だったものは、1 week未満だったよ印をつけます。

  こんな感じのVBAにしました。
  基本の骨組みはこれです。
  どんな言語でも似てるともいますが、
  機能別にモジュール分けしておくと、
  トラシューの時や再利用時に楽です。

Private Sub main()
  '処理①
  checkUPtime
 '処理②と③
  checkNonUsedPorts
  '処理④
  listNonUsedPorts
End Sub

Function checkUPtime() As String
   処理①
End Function

Function checkNonUsedPorts() As String
   処理②と③
End Function

Function listNonUsedPorts() As String
   処理④
End Function

では、中身書いてみます。
(注意点:
  ①シートには列名を入れておく。
   B列:ホスト名
   C列:uptimeが1週間未満だったかどうか
   D列:未使用ポート
   E列:notconnectだったポート
   F列:流量0ポート
   G列:uptime
  ②取り急ぎ作成。そのため、アクティブセルに対して処理がいくようになってる。
   あとでシート指定に直す
  ③取り急ぎ作成。そのため、ファイルパスがハードコーディングになってる
   あとで選択できるように直す
  ④上記で計画したsubやfunctionの設計をCodingでは、いきなり度外視している。
   理由は、VBAではテキストファイルを一行ずつ読み込む技が通常らしく(office TANAKA先生)
   それに着想を得て、「一度excelに貼り付けて成型作業する必要ないじゃん」って思ったから。
  ⑤空きポートと判断して記載するのが上下逆になっているので、そこは後で直す。

  因みにQiitaを始めてから、VBAを10年ぶりに書いてみてます。
  動いたソースコードではあるので、利用はできるはずですが、何かあればぜひコメントください!
  

Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 'APIを宣言

    '---------------------------------------------------
    ' 基本情報
    ' シートは1つ
    '  シート名「outPut」: まぁシート名は何でもいいです。今はactive cellに対して処理してしまっているので。
    ' 大前提
    ' ①「uptime」という文字が、sh verの結果以外に含まれない。(基本 port descriptionに記載がなければOK)
    ' ②「notconnect」という文字が、sh int statusの結果以外に含まれない。(基本 port descriptionに記載がなければOK)
    ' ③ログがずれていたり、表記がバグって無い事。(よく時差が生まれちゃうからね)
    ' ④commands は右記の順に実行すること ter len 0, sh int status, sh int counters, sh ver
    '---------------------------------------------------

Private Sub main2()

    '①uptimeの確認:機器起動時間が1週間未満だった機器を分かるようにする
    writeINFOfromLOG

End Sub


'①uptimeの確認:機器起動時間が1週間未満だった機器を分かるようにする
Sub writeINFOfromLOG()

'ログファイルを読み込みながら、以下実行する

    'ログファイル選択
    '我らがオフィス田中
    'http://officetanaka.net/excel/vba/file/file08b.htm
    Dim buf As String, n As Long
    n = 1
    Dim startPointRow As Long
    Dim FlagOfcheckTraffic As Long 'start at "sh int couunters" as 1. end at "sh ver" as 0
    FlagOfcheckTraffic = 0
    Dim columnB As Long, columnE As Long, columnF As Long '
    Dim highestRow As Long


    Open "ファイル名込みのフルパス" For Input As #1
        Do Until EOF(1)
            Line Input #1, buf
        '●notconnectだったポートを記載する
            If InStr(buf, "notconnect") <> 0 Then
                startPointRow = Cells(1048576, 5).End(xlUp).Row + 1
                Cells(startPointRow, 5) = Mid(buf, InStr(buf, "Gi") - 1, 9)
            End If

        '●流量が0のみだった(1-9がなかった)ポートを記載する
            'sh int countersまでいく。
            If InStr(buf, "sh int counters") <> 0 Then
            '    MsgBox "detected sh int coutners"
                FlagOfcheckTraffic = 1
            End If

            'sh verが来たら終わりにする
            If InStr(buf, "sh ver") <> 0 Then
            '    MsgBox "detected sh ver"
                FlagOfcheckTraffic = 0
            End If

            If FlagOfcheckTraffic = 1 Then
            'MsgBox "この処理は入るよね"
            'MsgBox Mid(buf, 35)
            'Debug.Print Mid(buf, 35)
                If Mid(buf, 35) = "               0              0              0              0 " Then
                    startPointRow = Cells(1048576, 6).End(xlUp).Row + 1
            '        MsgBox buf
            '        MsgBox startPointRow
                    Cells(startPointRow, 6) = Mid(buf, InStr(buf, "Gi") - 1, 9)
                End If
            End If

        '●uptime&ホスト名の記載と1週間未満だったかどうか判断
            'uptime の文字列がある行の情報を取得
            If InStr(buf, "uptime") <> 0 Then

                'uptimeを記載する
                startPointRow = Cells(1048576, 7).End(xlUp).Row + 1
                Cells(startPointRow, 7) = Mid(buf, InStr(buf, "uptime") + 9, 50)

                'uptimeが1週間未満だったかどうか記載する
                If InStr(buf, "week") = 0 Then
                    startPointRow = Cells(1048576, 3).End(xlUp).Row + 1
                    Cells(startPointRow, 3) = "Yes"
                End If

                'ホスト名記載する
                Cells(startPointRow, 2) = Mid(buf, 27, 20)


                'ホスト毎の区切り文字「---」を列B~Gへ記載する
                    'まず、B・E・F列で一番行数の多い列を判定

                columnB = Cells(1048576, 2).End(xlUp).Row
                columnE = Cells(1048576, 5).End(xlUp).Row
                columnF = Cells(1048576, 6).End(xlUp).Row

                If columnB > columnE Then
                    If columnB > columnF Then
                        highestRow = columnB
                    Else
                        highestRow = columnF
                    End If
                ElseIf columnE > columnF Then
                        highestRow = columnE
                Else
                        highestRow = columnF
                End If

                    '実際にホスト毎の区切り文字「---」を列B~Gへ記載する
                Cells(highestRow + 1, 2) = "'---"
                Cells(highestRow + 1, 3) = "'---"
                Cells(highestRow + 1, 4) = "'---"
                Cells(highestRow + 1, 5) = "'---"
                Cells(highestRow + 1, 6) = "'---"
                Cells(highestRow + 1, 7) = "'---"

                '②空きポート(down/down且つ流量0ポート)を記載する(D列)
                checkNonUsedPorts

            End If



        Loop
    Close #1

End Sub

'②空きポート(down/down且つ流量0ポート)を記載する(D列)
Sub checkNonUsedPorts()
    Dim ddPort() As Variant 'E列の配列 dd = down/down ports
    Dim ffPort() As Variant 'F列の配列 ff = final fantasy

    Dim RowPoint As Long
    Dim startRowPoint As Long 'E列のスタートポイント 下から処理するので、行数は start > end
    Dim endRowPoint As Long   'E列のスタートポイント 下から処理するので、行数は start > end
    Dim FstartRowPoint As Long 'F列のスタートポイント 下から処理するので、行数は start > end
    Dim FendRowPoint As Long   'F列のスタートポイント 下から処理するので、行数は start > end
    Dim i As Long
    i = 0
    Dim r As Long
    r = 0
    Dim f As Long
    f = 0
    Dim numberOfPorts As Long
    Dim count As Long
    count = 0


    '●E列(down/down)を全部配列に入れる
        '★start地点を確認して取得する処理 = startRowPoint

    RowPoint = Cells(1048576, 5).End(xlUp).Row - 1
        '区切り文字の直ぐ上がデータなのか、空白なのかの確認
    If Cells(RowPoint, 5) = "" Then
        startRowPoint = Cells(RowPoint, 5).End(xlUp).Row
    Else
        startRowPoint = RowPoint
    End If

        '★end地点を確認して取得 = endRowPoint
    endRowPoint = Cells(startRowPoint, 5).End(xlUp).Row + 1
        '配列の数をポートの数と合わせる

    numberOfPorts = startRowPoint - endRowPoint
    ReDim ddPort(numberOfPorts)

        '配列の最後が来るまで繰り返す。
    r = startRowPoint
    For i = LBound(ddPort) To UBound(ddPort)
        ddPort(i) = Cells(r - i, 5).Value
    Next i

    '●F列と比べる。もしあれば空きポートと判断しちゃう
    ' 理由:本当はoutgoingとincomingの両方が0かどうか。が判断ポイントなんだけど
    ' 片方が0で、片方にデータがあるポートなんて、ほぼないだろ。
        '★F列のスタートとエンドを取って、F列も配列へ
    RowPoint = Cells(1048576, 6).End(xlUp).Row - 1
            '区切り文字の直ぐ上がデータなのか、空白なのかの確認
    If Cells(RowPoint, 6) = "" Then
        FstartRowPoint = Cells(RowPoint, 6).End(xlUp).Row
    Else
        FstartRowPoint = RowPoint
    End If

            '★end地点を確認して取得 = endRowPoint
    FendRowPoint = Cells(startRowPoint, 6).End(xlUp).Row + 1

        '配列の数をポートの数と合わせる

    numberOfPorts = FstartRowPoint - FendRowPoint
    ReDim ffPort(numberOfPorts)

        '配列の最後が来るまで繰り返す。
    r = FstartRowPoint
    For i = LBound(ffPort) To UBound(ffPort)
        ffPort(i) = Cells(r - i, 6).Value
    Next i

    i = 0
    f = 0

        '★★★比べましょう★★★
    For i = LBound(ddPort) To UBound(ddPort)
        For f = LBound(ffPort) To UBound(ffPort)
            If ddPort(i) = ffPort(f) Then
                Cells(endRowPoint + count, 4) = ddPort(i)
                count = count + 1
                Exit For
            End If
        Next f
    Next i



End Sub

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2