IT井戸端会議

IT井戸端会議

インフラ、ネットワーク、アプリケーション開発、IT界隈の話等々を東京都千代田区界隈から発信します。

Perlスクリプトの汎用化+GUI化+exe化=アプリ誕生!(1)

みなさまこんにちは。

前回までに、次のような仕様のスクリプトを作成し、実行できることを確認しました。

 

■作業対象機器のIPアドレスリストを読み込む ■読み込んだIPアドレスに接続し、コマンドを実行 ■コマンドの実行結果をログとしてファイルに出力

そこで、せっかくですので、実行するコマンドリストも別ファイルから読み込むように改良すれば、色んな作業で使えるモノになりそうです。

加えて、普段CLIに慣れていない方用に、GUIを作ってみます。 さらに、実行環境構築の手間も省きたいのでexe化してみます。

 『exe』で起動する『GUI』のプログラムって、ソレ普通にアプリじゃね?

はい、つまり、誰でも使えるようにツールのアプリ化を目指します。

 

<今回やること>

スクリプトの改良 ・コマンドリストの読み込みとループ処理を追加する ・現在の日付を取得し出力するログファイル名の末尾に付加する ■GUIの機能を提供するモジュールをインストールする ■GUIを作りやすくする、GUIビルダをインストールする ■GUIを作り込む

では、行きます。

 

スクリプトの改良

汎用的に使えるように、前回まで書いたスクリプトに次の機能を追加します。

・コマンドリストの読み込みとループ処理を追加する ・現在の日付を取得し出力するログファイル名の末尾に付加する

ここまでは、そんなに難しくなく、すんなり作れます。 Perlの強力なテキスト処理機能と、Google先生のおかげです。

で、以下がコアな処理部分のコードです。これだけでも、動かせますね。

~~~~

#

                        

  Cisco機器用ログ取得用スクリプト       

  (パスワードは各機器共通を想定)       

                        

#

おまじない(構文チェック&警告表示)

use strict; use warnings;

Cisco-IOS用モジュールのロード

use Net::Telnet::Cisco::IOS;

念のための文字コード指定

use utf8; use open ':encoding(cp932)'; binmode STDIN, ':encoding(cp932)'; binmode STDOUT, ':encoding(cp932)'; binmode STDERR, ':encoding(cp932)';

作業フォルダの指定

my $folder = 'D:/ActivePerl_setup/';

対象ノードのIPアドレスを記載したリストを読み込む

our $file_in_node = $folder . "nodelist.txt"; open (NODELIST, "<", $file_in_node) or die ("error :$!");

while (my $nlist = <NODELIST>){ chomp($nlist);

my $IPAddress = $nlist; my $vtyPasswd = "jfc"; my $enPasswd = "jfc"; my $hostname;

セッションの確立

my $conn= Net::Telnet::Cisco::IOS->new( Errmode => "return", Timeout => 20, HOST => $IPAddress);

vtyパスワードを用いてログイン

$conn->login( Name => "" , Password => $vtyPasswd );

ENABLEモードに昇格

$conn->enable( $enPasswd );

HOSTNAME取得

my @show_run = $conn->cmd('show run | inc hostname'); for my $i (@show_run){ if($i =~ /hostname/){ $hostname = $i; chomp($hostname); $hostname =~ s/(?:hostname )//g; last; } }

ログファイル名に付加する日付を"yyyymmdd"で生成

my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time); my $yyyymmdd = sprintf("%04d%02d%02d", $year + 1900, $mon + 1, $mday);

ログをファイルへ出力

my $file_out = $LogFolder ."/". $hostname . "_" . $yyyymmdd .".txt"; open (LOG, ">>", $file_out) or die "$!";

各ノードで実行するコマンドを記載したリストを読み込む

our $file_in_cmd = $folder . "cmdlist.txt"; open (CMDLIST, "<", $file_in_cmd) or die ("error :$!");

while (my $clist = <CMDLIST>){ chomp($clist);

my $Command = $clist; my @logging = "\n". $hostname .'>'. $Command . "\n"; @logging = $conn->cmd($Command);

print "\n\n\n\n\n". $hostname .'>'. $Command . "\n"; print @logging;

print ( LOG "\n\n\n\n\n". $hostname .'>'. $Command . "\n"); print ( LOG @logging );

}

close CMDLIST; close LOG;

} print "\nログ取得が完了しました。終了するにはEnterキーを押してください。\n"; my $input = <STDIN>;

~~~~

 

GUIの機能を提供するモジュールをインストールする

次に、上記のコードを動かすためのGUIを作りますが、作る前に、 GUIの機能を提供するモジュール、Perl/Tkをインストールします。

 

<Tkのインストールコマンド>

コマンドプロンプトで cd c:\perl\bin ・(必要なら)Set http_proxy=~ ※前々回を参照> ・ppm install Tk

 

GUIを作り込む

GUIというのは、ビルダがあると手軽に作れます。 だいたい、GUIは以下のような要素からできています。 これを、画面上で設定したり配置したりしながら作る訳です。

・ウィンドウを作る ・ラベルやボタンを作る ・値を入力するフィールドを作る ・作ったパーツを配置する

これらを、テキストエディタだけでコーディングするのは結構難しいです。 まぁ、グラフィカルなUIですから、グラフィカルに作成するGUIビルダがあった方が簡単なのは言うまでもないかのかもしれません。 そこで、Perl/Tk用のGUIビルダ、Zoozをインストールします。

 

<Zoozのインストール手順>

http://search.cpan.org/~aqumsieh/ZooZ-1.2/ から、「ZooZ-1.2.tar.gz」をダウンロード ・コマンドプロンプトで cd c:\perl\bin ・(必要なら)Set http_proxy=~ ※前々回を参照> ・cpan install Tk::ToolBar ・「ZooZ-1.2.tar.gz」を解凍し、出てきたフォルダの中の「ZooZ.pl」をperlで実行する。 C:\Perl\bin\perl.exe "(ZooZ.plへのフルパス)" としたショートカットを作っておくと便利。 f:id:candapc:20160117142950p:plain

これがZoozの画面↑。

Zoozの画面上で要素(ウィジェット)を配置したら.plファイルに書き出し、それをベースにスクリプトを作り込んでいきます。

 

で、以下がZoozから書き出したスクリプト+αです。

そのまま実行すると文字は化け化けでなんだか分からないので、

use Tk 804; の行の下に use utf8; を足してます。

これをperl で実行するとウィンドウは表示されますが、ボタンを押しても何も起きません。

はい、GUIのガワのみです(笑)

~~~~

!perl

#

#

This file was automatically generated by ZooZ.pl v1.2

on Thu Aug 20 10:17:47 2015.

Project: Project 1

File:    D:/ActivePerl_setup/CiscoCmdGUI.zooz

#

#

#

Headers

# use strict; use warnings;

use Tk 804; use utf8;

#

Global variables

# my (

MainWindow

$MW,

Hash of all widgets

%ZWIDGETS, );

#

User-defined variables (if any)

#

#

#

Create the MainWindow

#

#

$MW = MainWindow->new;

#

#

Load any images and fonts

#

#

ZloadFonts ();

Widget Label1 isa Label

$ZWIDGETS{'Label1'} = $MW->Label( -font       => 'Meiryo_UI_8_normal_roman_', -takefocus  => 0, -text       => '下記のパラメータを指定し、「ログ取得の実行」ボタンをクリックしてください。', )->grid( -row        => 0, -column     => 0, -columnspan => 3, );

Widget Button1 isa Button

$ZWIDGETS{'Button1'} = $MW->Button( -borderwidth => 2, -font        => 'Meiryo_UI_8_normal_roman_', -padx        => 20, -pady        => 10, -takefocus   => 0, -text        => 'アドレスリストの選択', -width       => 0, )->grid( -row    => 1, -column => 0, );

Widget Button2 isa Button

$ZWIDGETS{'Button2'} = $MW->Button( -font => 'Meiryo_UI_8_normal_roman_', -padx => 20, -pady => 10, -text => 'コマンドリストの選択', )->grid( -row    => 2, -column => 0, );

Widget Button3 isa Button

$ZWIDGETS{'Button3'} = $MW->Button( -font => 'Meiryo_UI_8_normal_roman_', -padx => 20, -pady => 10, -text => 'ログフォルダの選択', )->grid( -row    => 3, -column => 0, );

Widget Label2 isa Label

$ZWIDGETS{'Label2'} = $MW->Label( -font       => 'Meiryo_UI_8_normal_roman_', -padx       => 20, -pady       => 10, -takefocus  => 0, -text       => 'Telnetユーザー名の指定', )->grid( -row    => 4, -column => 0, );

Widget Label3 isa Label

$ZWIDGETS{'Label3'} = $MW->Label( -font       => 'Meiryo_UI_8_normal_roman_', -padx       => 20, -pady       => 10, -takefocus  => 0, -text       => 'Line VTYパスワードの指定', )->grid( -row    => 5, -column => 0, );

Widget Label4 isa Label

$ZWIDGETS{'Label4'} = $MW->Label( -font       => 'Meiryo_UI_8_normal_roman_', -padx       => 20, -pady       => 10, -takefocus  => 0, -text       => 'Enableパスワードの指定', )->grid( -row    => 6, -column => 0, );

Widget Entry1 isa Entry

$ZWIDGETS{'Entry1'} = $MW->Entry( -font  => 'Meiryo_UI_8_normal_roman_', -width => 30, )->grid( -row        => 1, -column     => 1, -columnspan => 2, );

Widget Entry2 isa Entry

$ZWIDGETS{'Entry2'} = $MW->Entry( -exportselection => 1, -font            => 'Meiryo_UI_8_normal_roman_', -width           => 30, )->grid( -row        => 2, -column     => 1, -columnspan => 2, );

Widget Entry3 isa Entry

$ZWIDGETS{'Entry3'} = $MW->Entry( -exportselection => 1, -font            => 'Meiryo_UI_8_normal_roman_', -width           => 30, )->grid( -row        => 3, -column     => 1, -columnspan => 2, );

Widget Entry4 isa Entry

$ZWIDGETS{'Entry4'} = $MW->Entry( -exportselection => 1, -font            => 'Meiryo_UI_8_normal_roman_', -width           => 30, )->grid( -row        => 4, -column     => 1, -columnspan => 2, );

Widget Entry5 isa Entry

$ZWIDGETS{'Entry5'} = $MW->Entry( -exportselection => 1, -font            => 'Meiryo_UI_8_normal_roman_', -width           => 30, )->grid( -row        => 5, -column     => 1, -columnspan => 2, );

Widget Entry6 isa Entry

$ZWIDGETS{'Entry6'} = $MW->Entry( -exportselection => 1, -font            => 'Meiryo_UI_8_normal_roman_', -width           => 30, )->grid( -row        => 6, -column     => 1, -columnspan => 2, );

Widget Button4 isa Button

$ZWIDGETS{'Button4'} = $MW->Button( -font    => 'Meiryo_UI_8_normal_roman_', -padx    => 20, -pady    => 10, -text    => 'コマンド実行の開始', )->grid( -row    => 7, -column => 1, );

Widget Button5 isa Button

$ZWIDGETS{'Button5'} = $MW->Button( -font => 'Meiryo_UI_8_normal_roman_', -padx => 20, -pady => 10, -text => '終了', )->grid( -row    => 7, -column => 2, );

$MW->gridRowconfigure(1, -pad => 10, );

$MW->gridRowconfigure(2, -pad => 10, );

$MW->gridRowconfigure(3, -pad => 10, );

$MW->gridRowconfigure(4, -pad => 10, );

$MW->gridRowconfigure(5, -pad => 10, );

$MW->gridRowconfigure(6, -pad => 10, );

$MW->gridRowconfigure(7, -pad => 40, );

#

#

MainLoop

#

#

MainLoop;

#

#

Subroutines

#

#

sub ZloadFonts { $MW->fontCreate('Meiryo_UI_8_normal_roman_', -slant      => 'roman', -underline  => 0, -weight     => 'normal', -size       => -11, -overstrike => 0, -family     => 'Meiryo UI', ); }

~~~~

  f:id:candapc:20160117143039p:plain このGUIスクリプトを実行したところ↑。

このガワをアプリとして機能させるためには、各ボタンにコマンドを割り当ててやります。 もちろん、各ボタンから呼び出されるコマンドの処理内容も、書いてやらねばなりません。

ボリューム多くなってきたので、今回はこの辺で。