IT井戸端会議

IT井戸端会議

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

いまさら聞けないOpenStack

最近、OpenStack を学び始めたのですが、 リリース名やプロジェクトが多すぎるのと 日本語ですべてのプロジェクトについて説明しているサイトや書籍もなかったので、 勉強がてらスライドにまとめてみました。

OpenStack についてのまとめと 以下のサービスの概要について説明してます。

  • Nova
  • Swift
  • Glance
  • Horizon
  • Keystone
  • Neutron
  • Cinder
  • Heat
  • Ceilometer
  • Trove
  • Sahara
  • Ironic
  • Zaqar
  • Manila
  • Designate
  • Barbican
  • Searchlight
  • Murano
  • Magnum

www.slideshare.net

マシン・ネットワークの仮想化、ハイパーバイザー、コンテナ、PaaS、各種ストレージ、監視・課金、DNS全文検索ビッグデータ、ジョブ管理、ポリシーサービス、ベンチマーク、DevOps etc.

数年もたてば、OpenStack でできないことはなくなのではなかろうか。。

OSS版 Siri「Sirius」をインストール

sirius とは

公式サイトでは、以下の通り説明されています。 Sirius is an open-source end-to-end standalone intelligent personal assistant (IPA) service. Sirius receives queries in the form of speech or images and returns results in the form of natural language. Sirius implements the core functionalities of an IPA including speech recognition, image matching, natural language processing and a question-and-answer system.

翻訳すると、 Sirius は、エンドツーエンド スタンドアロン型の知的パーソナルアシスタント(IPA/intelligent personal assistant)サービスのオープンソース版です。 Sirius は、会話音声の型や画像から、クエリを受け取り、自然言語形式で結果を返します。 Sirius は、音声認識、画像マッチング、自然言語処理質疑応答システムを含むIPAのコア機能を実装しています。

簡単に言うと、音声入力と画像入力が可能な Siri のオープンソース版ですね。 画像入力をうまくつかえると可能性がひろがりそうです。

使用環境

公式サイトによると、Ubuntu のバージョン 12.04 および 14.04 でのみテストされているようですので、 以下のスペックでインストールしました。

CPU: 1vCPU RAM: 1GB OS: Ubuntu Server 14.04 (x86_64)

インストール

依存パッケージ

依存パッケージは以下の通りとのことです。 - Sphinx (sphinxbase and pocketsphinx) ・・・音声認識 - Kaldi ・・・音声認識 - Protobuf - OpenCV (v2.4.9) ・・・画像認識 - Java (v1.7.0_55)

git のセットアップ

$ sudo apt-get install git

Sirius のセットアップ

まずは、アプリケーションの準備をします。

$ cd /usr/local/
$ sudo mkdir sirius
$ sudo chown ubuntu.ubuntu sirius
$ git clone https://github.com/claritylab/sirius.git

$ cd sirius/sirius-application
$ tar xzf question-answer.tar.gz

依存アプリケーションをまとめてインストールします。 すでにインストール済みの場合は、自動でスキップされるようです。

$ sudo ./get-dependencies.sh
$ sudo ./get-opencv.sh

公式手順にそって、Kaldi をインストールします。

$ ./get-kaldi.sh

sirius サーバをコンパイルします。

$ ./compile-sirius-servers.sh

自動音声認識(ASR/Automatic Speech Recognition)

自動音声認識を実行するため、以下の3つのバックエンドシステムをサポートしています。 - Kaldi (DNN/HMM 版) - Pocketsphinx - Sphinx4 (GMM/HMM 版)

どうやって切り替えるんだろう..

AWR サーバ

デフォルトでは、Kaldi を使うようで、Kaldiソースコードを解凍しておかないとエラーが出るので、解凍しておきます。

$ cd /usr/local/sirius/sirius-application/speech-recognition/kaldi
$ tar xfz src.tar.gz

ASRサーバを起動します。

$ cd /usr/local/sirius/sirius-application/run-scripts
$ ./start-asr-server.sh
Starting server on localhost:8081, use <Ctrl-C> to stop
./server.sh: line 12: ..//src/online2bin/online2-wav-nnet2-latgen-faster: No such file or directory

No such file or directory..気になる..けど一旦無視w

$ ./start-asr-server.sh <kaldi|sphinx4|pocketsphinx> <ip> <port>

こんな感じでIPアドレスやポートが変更と記載されていましたが、うまく動きません..

$ ./start-asr-server.sh kaldi 54.178.143.52 8080
Traceback (most recent call last):
  File "./start-asr-dnn-server.py", line 74, in <module>
    server = ThreadedHTTPServer((host, port), Handler)
  File "/usr/lib/python2.7/SocketServer.py", line 419, in __init__
    self.server_bind()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 108, in server_bind
    SocketServer.TCPServer.server_bind(self)
  File "/usr/lib/python2.7/SocketServer.py", line 430, in server_bind
    self.socket.bind(self.server_address)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 99] Cannot assign requested address

ASRのテストをします。

$ cd /usr/local/sirius/sirius-application/run-scripts
$ ./sirius-asr-test.sh ../inputs/questions/what.is.the.speed.of.light.wav

なんかエラーが出続ける..ということで心が折れましたww

スクリプト読むしかなさそうです..

$ ./start-asr-server.sh 
Starting server on localhost:8081, use <Ctrl-C> to stop
./server.sh: line 12: ..//src/online2bin/online2-wav-nnet2-latgen-faster: No such file or directory
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 48248)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 593, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 649, in __init__
    self.handle()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
    method()
  File "./start-asr-dnn-server.py", line 59, in do_POST
    res = shcin(filename, server_process)
  File "./start-asr-dnn-server.py", line 26, in shcin
    server.stdin.write(stdin_data)
IOError: [Errno 32] Broken pipe
----------------------------------------
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 48249)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 593, in process_request_thread
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 649, in __init__
    self.handle()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 328, in handle_one_request
    method()
  File "./start-asr-dnn-server.py", line 59, in do_POST
    res = shcin(filename, server_process)
  File "./start-asr-dnn-server.py", line 26, in shcin
    server.stdin.write(stdin_data)
IOError: [Errno 32] Broken pipe

これ以降は、一旦、公式手順からコピーだけ

(未実施です..)

画像マッチング(IM/Image Matching)

Image Matching uses SURF to match query images to a stored database.

In image-matching/ first build and store a database of descriptors in protobuf format where the arguments are the name of the database and the directory containing the images:

$ ./make-db.py landmarks matching/landmarks/db/

To change the database used by the IMM service, change the name in start-imm-server.py.

In run-scripts/, open the IMM server:

$ ./start-imm-server.sh

In a separate terminal, test IMM using:

$ ./sirius-imm-test.sh ../image-matching/matching/landmarks/query/query.jpg

Question-Answering System (QA)

The Question-Answering system uses OpenEphyra and a Wikipedia database stored in Lemur’s Indri format.

Extract the Wikipedia database (after untaring and building question-answer):

$ wget http://web.eecs.umich.edu/~jahausw/download/wiki_indri_index.tar.gz
$ tar xzvf wiki_indri_index.tar.gz -C question-answer/

In run-scripts/, open the QA server:

$ ./start-qa-server.sh

In a separate terminal, test QA using:

$ ./sirius-qa-test.sh "what is the speed of light"

Combining Services

It is very easy with Sirius to combine ASR and QA to create the full intelligent personal assistant pipeline. After opening multiple servers using ./start--server.sh, test an ASR-QA query using:

$ ./sirius-asr-qa-test.sh ../inputs/real/what.is.the.capital.of.italy.wav

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

みなさまこんにちは。

前回より間があいてしまいましたが、忘れないうちに今回、Perlスクリプトをパッケージ化するお話を書きたいと思います。

 

<今回やること>

■「PAR::Packer」のインストール ■コマンド「pp」によるスクリプトのExe化

まず最初に、結果的に上記2つのために必要だと判明した手順のみ書いておくと、次のようになります。 た っ た 5 行 です。 (ただし、この辺の手順は依存関係にある全てのモジュールのバージョンやメンテナンス状況により変わるため、あくまで参考です)

~~~~ cd C:/perl/bin Set http_proxy=~ cpan install PAR::Packer copy C:/Perl/site/lib/auto/MinGW/bin/windres.exe C:/Perl/site/bin/windres.exe pp -o CiscoCmdTool.exe CiscoCmdTool.pl ~~~~

これまで、ActivePerlの導入からGUIの作成まで、途中で行き詰まったり試行錯誤したりした過程というのはあまり書いてこず、「結果こうなりました」的に、サラッと書いてきました。 まぁ実際、スクリプト自体は割とすんなりと書けましたし、GUI化の時はPerl/Tk以外にGUI::Loftというのも試したけどうまく導入できなかったので結果的にPerl/Tkでイケましたし、Perl/Tkもcpanじゃうまくいかずppmから入れたり、ZooZのインストールも最初はコマンドひとつでは使えなかったのでフォルダコピーして直接実行してみたらイケた、程度の試行錯誤で済んでいました。

ところが今回、パッケージ化用のツールキットである「PAR::Packer」の導入には、相当手こずりました…。 これは「PAR」という単なるアーカイバと、自作スクリプトスタンドアロンなExeとして動作させるのに必要な諸々をやってくれる「PAR::Packer」の両方があって機能します。調べてみるとこれが以前は「PAR」と一緒にインストールされていたものを、現在は分離して個別にインストールしなければならなくなった経緯のあるツールのようでした。 この辺は、使いたいモジュールのメンテナンス状況によっても事情は様々に変化するでしょうし、自分のした苦労が他の人はまったくせずに済むケースもあろうかと思います。 ベースのActivePerlに含まれる諸々のバージョンや、その時にセットアップされていたコンパイラのバージョンとの相性みたいなところもありましたしね。 ただ逆に言えば、もしパッケージ化によるスタンドアロンアプリ化に一度成功してしまえば、いちいち自分のしたような環境構築の苦労をせずに、望む機能だけが使えるようになる…ということでもあります。やってみる価値は充分にあるでしょう。

という訳で、人によっては面白い、人によっては全然面白くもなんともないであろう、苦労話を書いてみます。たまにはこういうのもいいかと。前置きが長くなりましたが、本編も長いです(笑)全八章構成です。 では、行きます。

 

■「PAR::Packer」のインストール

 

~第一章 CPANがNG!?~

 

いつも通り、コマンドプロンプトからcd c:\perl\bin、プロキシ設定の後に

cpan install PAR::Packer

というコマンド一行で済むはず…でした。本来は。 ところが、コマンドプロンプト流れる膨大な量のコンソールログを眺めていると、しばらくして処理が中断しました。 出ていたメッセージは、

~~~~ 'windres' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。 ~~~~

今思えば、この意味を素直に解釈していればよかったのですが…。 訳が分からず、何回かコマンドを打ち直してみるも同じ。

 

~第二章 CPANがダメならPPMがあるじゃない~

 

Perl/Tkの時のように、cpanでNGだったのでppmでのインストールを試します。

ppm install PAR-Packer

をやってみました。すると、今度は一発ですんなり入って、ビルド完了してくれました。 「なーんだこっちならよかったのか」とぬか喜びします。浅はかでしたわ…。

早速自作スクリプトを使って、パッケージ化のコマンド

pp -o CiscoCmdTool.exe CiscoCmdTool.pl

と打ち込んでみました。すると

「実行してるPerlのバージョンがちげーよ!」 「おめーのは5.20.2、俺のは5.20.1だよボケェ!」

と怒られます…。 Exe化する仕組みとしては、ppコマンドに指定した自作スクリプト以外に、スクリプトを解釈するPerlインタプリタ、使うモジュール、そのモジュールが依存する別のモジュール…などなどを芋づる式に全部ひっくるめてzip形式で1ファイルに圧縮し、そのバイナリをゴニョゴニョしてブートストラップしてしまうというものです。その辺はExe化の方法を調べた時に知っていたので、 「あーなるほど、インストールしていたActivePerlは最新版だったから、パックするインタプリタの更新が追いついていないんだな」と原因に思い込みあたりをつけます。

 

~第三章 ActivePerl過去版探しの旅~

 

ということで、ActivePerlの過去版を探します。 せっかくここまで構築してきた実行環境を泣く泣くアンインストールし、公式ページから落とした過去版をインストールし直します。

そしてppmからPAR::Packerをインストール。エラーはありません。 ppコマンドを実行してみると、今度も落とした方のバージョンで 「実行してるPerlのバージョンがちげーよ!」 と同じように怒られます…。バージョン末尾の数字がひとつふたつ違うだけなんですが…そんなにPerlってバージョンに厳しいのか? 気を取り直して、さらにActivePerlのアンインストール→別バージョンのインストールを試すも、またも同じく怒られます…。

「そもそもこれ、バージョン一致させるの無理なんじゃね?」 そんな絶望的な想いがよぎり、ActivePerlを再び5.20.2に戻します。

 

~第四章 CPANのメッセージを見つめ直す~

 

さて、戻したはいいものの、状況は変わらない訳です。 ここで、ppmからのインストールとバージョン一致させる線は捨てて、CPANからインストールする線に戻ってみます。

改めてCPANからインストールしてみると、その処理は大きく次のようなステップで行われているようでした。

1.リソースのダウンロード 2.設定されたコンパイラを使ってコンパイル 3.コンパイルした結果のモジュールを動作させてテスト

今回直面しているエラーはこの3で、テスト中に発生しているようです。テストで発生する細かなエラーは、cpanに -f (強制のforce )オプションをつけることで無視してインストールできるらしいことも調べるうちに分かってきましたが、それを試しても、問題は解決しません。問題はテスト結果のエラーではなく、テスト中に使用されているらしい、「windres」コマンドがないこと。 なんとかしてこのコマンドを実行させねばなりません。

 

~第五章 binutils過去版探しの旅~

 

Google大先生によれば、本来windresはコンパイラであるMinGWbinutilsの中にあるものらしい。しかも、最近のバージョンだとwindresが入っていないらしい。なんじゃそりゃ!?と思いながらも、実際ないんだからしょうがない。入れてやるしかない。

でも、どこから?ということで、今度はMinGWbinutilsを探します。

もうこの辺から記憶が曖昧なのですが、MinGWインストーラと思ってダウンロードし実行したものは、実は単なるダウンローダで、そいつ自身がさらにパッケージをダウンロードしようとするも、古いもののせいかどこにもなくてストップする…という悪夢の中でさらに悪夢をみるような思いも味わいます。

 

~第六章 まさに灯台下暗し…~

 

で、絶望に打ちひしがれて、どこにあるんだwindres~と何を思ったかローカルフォルダの中を彷徨いだす自分。あれば苦労はしないはず…なんですが、やぶれかぶれでローカルの中を「windres」で検索してみます。すると!

C:/Perl/site/lib/auto/MinGW/bin

に「windres.exe」というファイルがあるのを発見します! これこれ、これではないですか! で、試しにここのフォルダにPATHを通してみますが症状は変わらず。で、「windres.exe」をC:\Perl\site\binへコピーしたら、今度はインストール成功! 「C:\Perl\site\bin」はActivePerlインストール時に、環境変数へPATHが通してあるので MinGWに入ってたってことは、たぶんPAR::Packerのインストールバッチ、またはテスト用のバッチの中でコピーし忘れたのでしょうかね…?

最初から素直に、エラーメッセージの内容に従ってwindresを探していればよかったのですね…。 膨大な量のテスト項目らしきものが、無事に自動実行完了しました。

 

■コマンド「pp」によるスクリプトのExe化

 

祈るような気持ちで、ppコマンドを実行します。 今度は、バージョンちげーよ!と怒られることもなく、指定したExeファイルが出来上がってくれました。 ついにパッケージ化成功か!?

 

~第七章 ソーススクリプトにモジュール記述追加~

 

祈るような気持ちで、出来上がったExeファイルをダブルクリックします。 すると、コマンドプロンプトらしきウィンドウが一瞬だけ開いては消えました。失敗…。仕方なく、一瞬で消えるメッセージを確認すべく、予め開いておいたコマンドプロンプトから、Exeファイルのフルパスを指定して実行します。 すると今度は、「Win32を配置できねーよ、カス!」とお怒りになっておられました…。

確かに、GUI用にWin32::GUIというモジュールはロードしないといけないものの、そもそもなぜPerlスクリプトとして実行している時には怒らない起こらないことがExeだと怒る起こるのでしょうかね。 とはいえ、ないものは仕方ないので、自作スクリプトにuse Win32を追加してコンパイルし直します。Exe叩くと、また落ちます。またメッセージ確認します。今度は 「Arybaseを配置できねーよ、カス!」と…はいはい。名前からして、配列を扱うモジュールですかね。で、またuse Arybaseを追加してコンパイルし直します。 どうせまた何か言ってくるんだろ…と、思いきや。

 

~第八章 始まりの終わり~

 

ついに起動しました!前回自分の書いたGUI画面が! フォルダ選択ダイアログも、きちんと動きます。 嬉しいはずなんですが、相当長いお使いゲーをクリアしたような、微妙な気分でしたわ、えぇ。

という訳で、この過程で丸2日かけました(笑) 無駄な工数長い長い旅路の果てに、ついにExe化を実現したのでした。 つまり、単なるスクリプトキディが、GUIつきのスタンドアロンアプリ開発者に進化した!! という気分を味わった瞬間です。気分だけ。

めでたし、めでたし?

でもまぁ、動いたら動いたで、また色々と課題は出てくるのです…。

OSS のオンライン会議システム「BigBlueButton」を試す

OSS を使って、リモートで作業できないかと探していたところ、 BigBuleButton というものがあるということで試しにインストールしてみました。

似たようなものとして、Apache OpenMeetings(※1)というものもあるようですが、 ユーザビリティが悪そうだったので、 今回はBigBuleButtonを採用しました。

※ 1 Apache OpenMeetings

http://openmeetings.apache.org/index.html

スペック要件

公式サイトによると、以下のスペックが求められています。

  • Ubuntu 14.04 64-bit のサーバ
  • 4GB のメモリ、およびswap 領域 (8GB推奨)
  • Quad-core 2.6 GHZ CPU (またはそれ以上)
  • TCPポート 80番、1935番、9123番の解放
  • UDPポート 16384〜32768番の解放
  • 80番ポートが他のアプリケーションで使用されていないこと
  • 書き込み可能な500GB以上のディスク空き領域があること
  • 双方向帯域幅 100 Mbits/sec
  • ベアメタル(仮想マシン以外)

検証環境

  • Ubuntu 14.04.3 LT (x86_64) (Ubuntu Server 14.04 LTS (HVM), SSD Volume Type)

  • AWS EC2

    • m4.large (2vCPU、8GB RAM)

インストール手順

インストール方法は、こちらの公式手順書を参考にしています。

http://docs.bigbluebutton.org/install/install.html

準備

ロケールを以下のとおり変更します。

ロケールを変更?と思いましたが、小心者なので、素直にしたがいました。

$ sudo vi /etc/default/locale
LANG="en_US.UTF-8"

パッケージのダウンロード元設定ファイルの初期状態を確認します。

$ grep "multiverse" /etc/apt/sources.list
## multiverse WILL NOT receive any review or updates from the Ubuntu
# deb http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty multiverse
# deb-src http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty multiverse
# deb http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty-updates multiverse
# deb-src http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty-updates multiverse
# deb http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse
# deb-src http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse
# deb http://security.ubuntu.com/ubuntu trusty-security multiverse
# deb-src http://security.ubuntu.com/ubuntu trusty-security multiverse

以下の通りコマンドを実行し、リストに追加します。

$ echo "deb http://us.archive.ubuntu.com/ubuntu/ trusty multiverse" | sudo tee -a /etc/apt/sources.list
deb http://us.archive.ubuntu.com/ubuntu/ trusty multiverse

リストにdeb http://us.archive.ubuntu.com/ubuntu/ trusty multiverseという行が追加されたことを確認します。

$ grep "multiverse" /etc/apt/sources.list
## multiverse WILL NOT receive any review or updates from the Ubuntu
# deb http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty multiverse
# deb-src http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty multiverse
# deb http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty-updates multiverse
# deb-src http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty-updates multiverse
# deb http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse
# deb-src http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu/ trusty-backports main restricted universe multiverse
# deb http://security.ubuntu.com/ubuntu trusty-security multiverse
# deb-src http://security.ubuntu.com/ubuntu trusty-security multiverse
deb http://us.archive.ubuntu.com/ubuntu/ trusty multiverse

パッケージを更新します。

$ sudo apt-get update

$ sudo apt-get dist-upgrade

libreoffice セットアップ

Ubuntu 14.04 デフォルトの libreoffice 4.2.x ではなく、4.4を使用するとのことで、 libreoffice 4.4 インストールできるようにリポジトリを追加します。

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:libreoffice/libreoffice-4-4

BigBlueButton セットアップ

BigBlueButton パッケージのリポジトリにアクセスできるよう、キーをインストールします。

$ wget http://ubuntu.bigbluebutton.org/bigbluebutton.asc -O- | sudo apt-key add -

BigBuleButton リポジトリを追加し、更新します。

$ echo "deb http://ubuntu.bigbluebutton.org/trusty-090/ bigbluebutton-trusty main" | sudo tee /etc/apt/sources.list.d/bigbluebutton.listdeb http://ubuntu.bigbluebutton.org/trusty-090/ bigbluebutton-trusty main

$ sudo apt-get update

ffmpeg インストール

メディアファイル(音声、動画、デスクトップ共有)を使用するため、ffmpeg をインストールします。

インストールするためのスクリプトを作成します。

$ vi install-ffmpeg.sh

$ cat install-ffmpeg.sh
sudo apt-get install build-essential git-core checkinstall yasm texi2html libvorbis-dev libx11-dev libvpx-dev libxfixes-dev zlib1g-dev pkg-config netcat libncurses5-dev

FFMPEG_VERSION=2.3.3

cd /usr/local/src
if [ ! -d "/usr/local/src/ffmpeg-${FFMPEG_VERSION}" ]; then
  sudo wget "http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2"
  sudo tar -xjf "ffmpeg-${FFMPEG_VERSION}.tar.bz2"
fi

cd "ffmpeg-${FFMPEG_VERSION}"
sudo ./configure --enable-version3 --enable-postproc --enable-libvorbis --enable-libvpx
sudo make
sudo checkinstall --pkgname=ffmpeg --pkgversion="5:${FFMPEG_VERSION}" --backup=no --deldoc=yes --default

先ほど作成したスクリプトを実行して、ffmpeg をインストールします。

$ chmod +x install-ffmpeg.sh
$ ./install-ffmpeg.sh

インストール後に ffmpeg バージョンが表示されるか確認します。

$ ffmpeg -version
ffmpeg version 2.3.3 Copyright (c) 2000-2014 the FFmpeg developers
built on Aug 21 2015 23:11:44 with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04)
configuration: --enable-version3 --enable-postproc --enable-libvorbis --enable-libvpx
libavutil      52. 92.100 / 52. 92.100
libavcodec     55. 69.100 / 55. 69.100
libavformat    55. 48.100 / 55. 48.100
libavdevice    55. 13.102 / 55. 13.102
libavfilter     4. 11.100 /  4. 11.100
libswscale      2.  6.100 /  2.  6.100
libswresample   0. 19.100 /  0. 19.100

BigBlueButton インストール

BigBlueButton パッケージをインストールします。

$ sudo apt-get install bigbluebutton

BigBlueButton デモパッケージのインストール

BigBlueButton のデモをインストールします。 今回は、使ってみるのが目的なので、インストールしました。

$ sudo apt-get install bbb-demo

BigBlueButton チェックパッケージのインストール

config等をチェックするツールでしょうか。 インストールしておきます。

$ sudo apt-get install bbb-check

WebRTC audio の有効化

必要であれば、ということですが、こちらもインストールしておきます。

$ sudo bbb-conf --enablewebrtc

セットアップ

config の初期化とセットアッップ、およびサービスの再起動を行います。

$ sudo bbb-conf --clean

$ sudo bbb-conf --check

BigBlueButton Server 0.9.1 (396)
                    Kernel version: 3.13.0-48-generic
                      Distribution: Ubuntu 14.04.3 LTS (64-bit)
                            Memory: 16047 MB

/var/www/bigbluebutton/client/conf/config.xml (bbb-client)
        Port test (tunnel): 172.31.8.229
                              Red5: 172.31.8.229
              useWebrtcIfAvailable: true

/opt/freeswitch/conf/sip_profiles/external.xml (FreeSWITCH)
                    websocket port: 5066
                    WebRTC enabled: true

/etc/nginx/sites-available/bigbluebutton (nginx)
                       server name: 172.31.8.229
                              port: 80
                    bbb-client dir: /var/www/bigbluebutton

/var/lib/tomcat7/webapps/bigbluebutton/WEB-INF/classes/bigbluebutton.properties (bbb-web)
                      bbb-web host: 172.31.8.229

/var/lib/tomcat7/webapps/demo/bbb_api_conf.jsp (API demos)
                           api url: 172.31.8.229

/var/www/bigbluebutton/check/conf/config.xml (client check)
                      client check: 172.31.8.229

/usr/share/red5/webapps/bigbluebutton/WEB-INF/red5-web.xml (red5)
                  voice conference: FreeSWITCH
                     capture video: true
                   capture desktop: true

/usr/local/bigbluebutton/core/scripts/bigbluebutton.yml (record and playback)
                     playback host: 172.31.8.229


** Potential problems described below **
# Warning: The API demos are installed and accessible from:
#
#    http://172.31.8.229/
#
# These API demos allow anyone to access your server without authentication
# to create/manage meetings and recordings. They are for testing purposes only.
# If you are running a production system, remove them by running:
#
#    sudo apt-get purge bbb-demo

# Warning: The client self check is installed and accessible from:
#
#    http://172.31.8.229/check
#

Webブラウザより、http://<サーバIP>にアクセスし、 BigBlueButton のトップページが表示されない場合、以下の通りIPアドレスをセットします。

$ sudo bbb-conf --setip <サーバIP>

以下の通り、ログイン画面が表示されれば、OKです。 f:id:candapc:20160117142108p:plain f:id:candapc:20160117142113p:plain

当初、Chrome で検証してましたが、 Webカメラとデスクトップ共有がうまく機能しなかった。

どうやら Firefox 推奨らしい.. Firefox を使うと正常に起動できた。

所感

作り込めば、e-leaning システムとか作れそうだけど、 ソースコードを見る限り やるならちょっと本腰入れて開発する必要がありそう..

https://github.com/bigbluebutton/bigbluebutton

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

みなさまこんにちは。

前回、GUIを作成したPerlスクリプトの続きです。

 

<今回やること>

GUIを表示させるのみのスクリプトに、コマンド(処理)を追加

Perlから実際にGUIを動かしてみる

 

では、行きます。

 

GUIを表示させるのみのスクリプトに、コマンド(処理)を追加

 

前回作成した、GUIが表示されるだけでボタンを押しても無反応なスクリプトに、ボタンクリック時の処理を紐付けていきます。

若干話が前後してしまいますが、そもそも、今回書いていたスクリプトの機能としては、次のようなものでした。

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

 

ですので、機能としては、次のようなGUI要素があればよいことになりますね。

IPアドレスリストをファイル選択するダイアログを表示→リストファイル名を取得するボタン ■コマンドリストをファイル選択するダイアログを表示→リストファイル名を取得するボタン ■ログの出力先フォルダを選択するダイアログを表示→フォルダ名を取得するボタン ■コマンド実行ボタン ■終了ボタン

 

また、各ファイル名、フォルダ名の取得結果を表示するフィールド(エントリ)があると、分かりやすいし手入力もできてよいので、ボタンの横に並べました。

 

Perl/Tkの世界では、ボタンやテキストラベル、入力フィールドのような各GUI要素を「ウィジェット」と呼びます。

ほとんどの種類のウィジェットには、共通するオプションが用意されています。処理を紐付ける、commandオプションもそのひとつです。

例として、1個目のボタンは次のように定義しています。

 

~~~~

Widget Button1 isa Button

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

~~~~

「$ZWIDGETS」というのは、GUIビルダであるZoozが定義したハッシュで、すべてのウィジェットがこのハッシュに格納されるようです。

そして、メインウィンドウを表す $MW にButtonとして定義されて、その()の中に各オプションが書かれているつくりになっています。

多くは見た目に関する設定値なのはお分かりいただけると思いますが、各オプションの一番下に

-command => &amp;GetNodeListFile,

が書かれています。これが、ボタンクリック時に実行される処理になります。

「&GetNodeListFile」というのは、このボタン用に定義したサブルーティンで、次のように定義しています。

 

~~~~

「アドレスリストの選択」ボタンの実行コマンド

sub GetNodeListFile{ $NodeListFile = $MW->Win32::GUI::GetOpenFileName(); $NodeListFile = decode("CP932",$NodeListFile);

~~~~

「-command =>」の後に処理を実際に並べて書いてもよいのですが、ボタンによっても処理の量は変わるし、可読性も考えるとサブルーティン化するのがよいでしょうね。

このように、各ボタン毎に「-command =>(サブルーティン名)」、サブルーティンリストの中に実際の処理を書いていくことを繰り返して、ウィジェットスクリプトの処理を必要な分だけ紐付けていきます。前回書いた、コア処理部分は当然、「コマンド実行ボタン」に紐付けられます。

こうして出来上がったコードが、以下になります。

~~~~

!C:\perl/bin/

#

                        

 Cisco機器用連続コマンド実行スクリプト    

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

                        

   Written by Takeru Satoh at APCommunications 

                        

#
#

#

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;

GUI用モジュールのロード

use Tk 804; use Win32; use Win32::GUI; use arybase; use Encode;

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)';

#

Global variables

# my (

MainWindow

$MW,

Hash of all widgets

%ZWIDGETS,

IPAddress List File

$NodeListFile,

Command List File

$CmdListFile,

Log Output Folder

$LogFolder,

Telnet User Name

$UserName,

LineVTY Password

$vtyPasswd,

Enable Password

$enPasswd

);

$UserName = '(空欄可)';

#

User-defined variables (if any)

#

#

#

Create the MainWindow

#

#

$MW = MainWindow->new( -title => 'Cisco機器コマンド実行ツール Ver.1.0', -background => '#ffffff', -borderwidth => 2, -relief => 'groove', );

#

#

Load any images and fonts

#

#

ZloadFonts ();

以下、GUIの各要素(ウィジェット)を定義

Widget Label1 isa Label

$ZWIDGETS{'Label1'} = $MW->Label( -background => '#ffffff', -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, -width       => 12, -relief      => 'raised', -takefocus   => 0, -text        => 'アドレスリストの選択', -command => &amp;GetNodeListFile, )->grid( -row    => 1, -column => 0, );

Widget Button2 isa Button

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

Widget Button3 isa Button

$ZWIDGETS{'Button3'} = $MW->Button( -font => 'Meiryo_UI_8_normal_roman_', -padx => 20, -pady => 10, -width       => 12, -relief      => 'raised', -takefocus   => 0, -text => 'ログ出力フォルダの選択', -command => &amp;GetFolder, )->grid( -row    => 3, -column => 0, );

Widget Label2 isa Label

$ZWIDGETS{'Label2'} = $MW->Label( -background => '#ffffff', -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( -background => '#ffffff', -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( -background => '#ffffff', -font       => 'Meiryo_UI_8_normal_roman_', -padx       => 20, -pady       => 10, -takefocus  => 0, -text       => 'Enableパスワードの指定', )->grid( -row    => 6, -column => 0, );

Widget Label5 isa Label

$ZWIDGETS{'Label5'} = $MW->Label( -background => '#ffffff', -font       => 'Meiryo_UI_8_normal_roman_', -takefocus  => 0,

   -text       => 'Powered by :',

)->grid( -row    => 8, -column => 0, );

Widget Entry1 isa Entry

$ZWIDGETS{'Entry1'} = $MW->Entry( -font  => 'Meiryo_UI_8_normal_roman_', -width => 30, -textvariable => \$NodeListFile, )->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, -textvariable => \$CmdListFile, )->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, -textvariable => \$LogFolder, )->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, -textvariable => \$UserName, )->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, -textvariable => \$vtyPasswd, )->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, -textvariable => \$enPasswd, )->grid( -row        => 6, -column     => 1, -columnspan => 2, );

Widget Button4 isa Button

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

Widget Button5 isa Button

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

$MW->gridRowconfigure(0, -pad => 20, );

$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

#

#

GUI用フォント設定

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

「アドレスリストの選択」ボタンの実行コマンド

sub GetNodeListFile{ $NodeListFile = $MW->Win32::GUI::GetOpenFileName(); $NodeListFile = decode("CP932",$NodeListFile);

}

「コマンドリストの選択」ボタンの実行コマンド

sub GetCmdListFile{ $CmdListFile = $MW->Win32::GUI::GetOpenFileName(); $CmdListFile = decode("CP932",$CmdListFile);

}

「ログ出力フォルダの選択」ボタンの実行コマンド

sub GetFolder{ $LogFolder = $MW->Win32::GUI::BrowseForFolder(); $LogFolder = decode("CP932",$LogFolder); }

「コマンド実行の開始」ボタンの実行コマンド

sub GetLog{

対象ノードのIPアドレスを読み込む

open (NODELIST, "<", $NodeListFile) or die ("error :$!");

IPアドレスひとつずつに対し以下の処理を実行

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

my $IPAddress = $nlist; my $hostname;

セッションの確立

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

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

$conn->login( Name => $UserName , 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 "$!";

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

open (CMDLIST, "<", $CmdListFile) 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ログ取得が完了しました。\n"; print "終了するにはEnterキーを押してから、アプリ「終了」ボタンをクリックしてください。\n"; my $input = <STDIN>;

}

「終了」ボタンの実行コマンド

sub DestroyWindow{ $MW->destroy;

}

~~~~

ここで注意というか、理解が必要なのが、次の2つです。

GUIから取得する値はグローバル変数に格納すること。

各ボタンからは「-command」オプションで紐付けられたサブルーティンを呼び出します。しかし、サブルーティン中で定義された変数はそのサブルーティン内でしか使えず、例えばIPアドレスのリストファイル名を取得しても、コマンド実行処理にファイル名を渡せない…ということになってしまいます。

そこで、どのサブルーティンからもアクセスできるグローバル変数にリストファイル名を格納することで、どのサブルーティンからも共通にアクセスできるように書いてあります。GUIから入力される値は、全てそのようにしました。処理の中で頻繁に値が変わったり参照される場合は、グローバル変数で横着しない方がいいのかもしれませんが、今回はそれほど複雑な処理でもありませんしね。

GUIを使うために必要なモジュールを追加でロードしていること。

下記の各モジュールは、スクリプトとして動作させるだけなら不要なのですが、GUIを動作させるのには必要になります。

use Win32; → 下記Win32::GUIを使うのに必要(らしい) ※パッケージ化で改めて触れます。 use Win32::GUI; → OS標準のファイル・フォルダ選択ダイアログを呼び出すのに必要 use arybase; → 配列を使うのに必要(らしい) ※パッケージ化で改めて触れます。 use Encode; →PerlのコードはUTF8で書かれるが、WindowsはShiftJIS(CP932)の世界なので、Windowsから取得したファイル・フォルダ名を扱うのに必要。

 

Perlから実際にGUIを動かしてみる

コマンドプロンプトから、上記のコードを保存した「CiscoCmdTool-ver1.0.pl」を指定して、次の構文で実行します。

コマンドプロンプトで cd c:\perl\bin/ ・C:\Perl\bin\perl.exe "(CiscoCmdTool-ver1.0.pl へのフルパス)"

前回同様のGUIが開き、各ボタンも今度はクリックするとちゃんとダイアログを開いてくれて、動作しているのが分かると思います。

 

またボリュームが多くなってきたので、この辺で。

次回は、いよいよパッケージャのお話です。

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スクリプトを実行したところ↑。

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

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

GitLab CE をたった10分でインストール

GitHub のような環境が無料で構築できる GitLab CE (Community Edition) というものがあるということで、早速試してみた。 GitLab CE は、MITライセンスのようです。

使用環境

Ubuntu 14.04.2 LTS (x86_64)

CPU: 1vCPU RAM: 2GB ※ 1GBの場合、ActionView::Template::Error (Cannot allocate memory - node):とエラーログが出力されて、一部機能が使用できませんでした。。

手順

公式ページの手順を参考にインストールしていきます。

https://about.gitlab.com/downloads/

まずは、必要なパッケージを事前にインストールします。

$ sudo apt-get install curl openssh-server ca-certificates postfix

GitLab パッケージをオンラインでインストールします。

$ curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
$ sudo apt-get install gitlab-ce

GitLab の初期設定をして、起動します。

$ sudo gitlab-ctl reconfigure

ブラウザで、http://<サーバURL>/にアクセスし、以下のユーザでログインします。

ユーザ名root
パスワード5iveL!fe

f:id:candapc:20160117143341p:plain

パスワードを変更画面が表示されるので、パスワードを変更します。 f:id:candapc:20160117143351p:plain

先ほど設定したパスワードで再度ログインします。 f:id:candapc:20160117143345p:plain

トップ画面が表示されました。 ここまで約10分、あっという間でした。 f:id:candapc:20160117143633p:plain

試しにプルリクを出してマージしてみました。 f:id:candapc:20160117143857p:plain f:id:candapc:20160117143728p:plain

機能については、GitHub と同等くらいに見えましたが、 見栄えが違う分、慣れるまで少し手こずりそうです。