
こんにちは。ITサービス本部の松永です。
今回は、プログラミング言語Pythonとジョブ運行ツールA-AUTO50を使って、
手作業を自動で行うRPAツール[ AUTO Operator ]を作ってみましたので、ご紹介します。
0. きっかけ
私の所属するチームでは、お客様が利用するシステムの運用を行っています。
例えば、
- システムを構成する機器でアラートが発生したときの原因調査、対応
- お客様からの依頼対応(データ更新、ミドルウェア再起動、など)
など、[ システムを快適に利用いただくため ]の業務がメインです。
たくさんのシステムを限られたメンバーで運用しているため、[ 自動化 ][ 効率化 ]がチームの至上命題です。
・・・ということで、それに向けた第1歩[ AUTO Operator ]を作ってみることとなりました!
1. AUTO Operatorの姿(=今回作りたいもの)
名前は[ CHILED_OPE.py ]
A-AUTO50上で起動するジョブ[ AUTOOPE3 ]をトリガーとし、以下を自動で行います。
- お客様からgmailで受信した依頼メールの解析(差出人、件名、本文)
- お客様へ受付完了メール送信
- オペレーション実行可否判定(Linuxサーバで稼動するhttpdの再起動)
- オペレーション実行
- お客様へ完了メール送信
-4.にてオペレーションがNGだった場合-
- SEエスカレーションメール送信
-3.にて[ 否 ](オペレーション対象外)と判定された場合-
- SEエスカレーションメール送信
単純なつくりではありますが、実現に向け、頑張っていこうと思います!
2. 環境準備
まずは、AUTO Operatorを作るための環境を整えます。
尚、以下は用意されている前提でお話を進めます。ご了承ください。
- gmailが利用可能なWindowsパソコン
- httpdとSSHが稼動するLinuxサーバ
- WindowsパソコンとLinuxサーバ間のSSH通信
2-1. Python
2-1-1. Pythonのインストール
AUTO Operator[ CHILED_OPE.py ]を開発するために必要です。
以下サイトからダウンロードし、パソコンにインストールします。
https://www.python.org/
※トップページ[ Downloads ]タブにて、[ Downloads Python 3.5 ]ボタンをクリック
2-1-2. paramikoモジュールのインストール
こちらは、[ CHILED_OPE.py ]からLinuxサーバへSSHで接続、コマンド発行する際に必要なモジュールです。
Pythonインタープリタから以下コマンドを発行し、インストールします。
pip install paramiko
これで[ CHILED_OPE.py ]を作るための準備が整いました。
続いて、A-AUTO50の準備を進めます。
2-2. A-AUTO50
2-2-1. A-AUTO50のインストール
A-AUTO50はユニリタ社が提供する無償のジョブ運行ツールです。
同社のサイトからダウンロードし、パソコンにインストールします。
https://a-auto50.unirita.co.jp/downloads/
以上で準備完了です。
これで、AUTO Operatorを作る環境が整いました。
いよいよ開発をはじめます!
3. Pythonによる[ CHILED_OPE.py ]開発
Pythonインタープリタにて、前述の処理フローを実現するためのコードを記述していきます。
以下、コードの一部を紹介します。
<モジュールインポート>
import sys
import imaplib
import email
import smtplib
import paramiko
import base64
from email.header import decode_header, make_header
from email.mime.text import MIMEText
まず必要なモジュールをインポートします。
Pythonはデフォルトで備わっているモジュールが豊富(=paramikoのように追加でインストールするケースが少ない)なので便利ですね・・!
<変数セット>
UserName = 'xxxx@gmail.com' #お客様からの依頼メールを受信するgmailアカウント
PassName = 'xxxx' #gmailアカウントのパスワード
mail = imaplib.IMAP4_SSL('imap.gmail.com') #imap設定情報
sender = smtplib.SMTP_SSL('smtp.gmail.com') #smtp設定情報
keyword = 'httpd再起動' #オペレーション実行のトリガーとなるキーワード
client = paramiko.SSHClient() #LinuxサーバへのSSH接続情報①
client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #LinuxサーバへのSSH接続情報②
client.connect('192.xxx.xxx.xxx', username='xxxx', password='xxxx') #LinuxサーバへのSSH接続情報③
operation = 'service httpd restart' #オペレーション時の実行コマンド
各変数の設定値(=依頼要件)を変えれば、それに応じた自動オペレーションが可能・・!
といいたいのですが、まだ検証が足りてません。。。。
このあと頑張ります・・!
<依頼メールの解析>
msg_subject = email.header.decode_header(msg.get('Subject'))[0][0]
subject = str(msg_subject.decode(msg_encoding))
お客様からgmailで受領した依頼メールの件名を解析する際のコードです。(上述の処理フロー①)
同じ要領で差出人、本文も解析します。
<受付完了メール送信>
message = MIMEText('ご依頼を受け付けました。作業結果は追ってご連絡します。')
message['Subject'] = '【ご依頼受付のお知らせ】Re:'+subject
sender.login(UserName, PassName)
sender.sendmail(UserName, email_from, message.as_string())
お客様へ受付完了メールを送信する際のコードです。(上述の処理フロー②)
<オペレーション>
#お客様からの依頼メール本文に[ httpd再起動 ]が記述されていたら、LinuxサーバにSSH接続し、httpdを再起動。(上述の処理フロー④)
if keyword in body:
stdin,stdout,stderr = client.exec_command(operation)
buf = stderr.read()
#結果判定。失敗したら、SEへエスカレーションメールを送信する。(上述の処理フロー⑥)
if len(buf) > 0:
mail.copy(num,'operation-error')
mail.store(num, '+FLAGS','\\deleted')
message = MIMEText('オペレーションが失敗しました。対処ならびに完了後の依頼元への報告をお願いします。')
message['Subject'] = '【緊急】【エスカレーションのお知らせ】Re:'+subject
sender.login(UserName, PassName)
sender.sendmail(UserName, email_from, message.as_string())
sender.quit()
sys.exit(1)
#成功したら、お客様へ作業完了メールを送信する。(上述の処理フロー⑤)
else:
mail.copy(num,'operation-success')
mail.store(num, '+FLAGS','\\deleted')
message = MIMEText('ご依頼の作業が完了しましたので、ご報告します。')
message['Subject'] = '【ご依頼完了のお知らせ】Re:'+subject
sender.login(UserName, PassName)
sender.sendmail(UserName, email_from, message.as_string())
sender.quit()
sys.exit(0)
#依頼メール本文に[ httpd再起動 ]が記述されてなかったら、SEへエスカレーションメールを送信する。(上述の処理フロー⑦)
else:
mail.copy(num,'operation-success')
mail.store(num, '+FLAGS','\\deleted')
message = MIMEText(body)
message['Subject'] = '【エスカレーションのお知らせ】'+subject
sender.login(UserName, PassName)
sender.sendmail(UserName, email_from, message.as_string())
sender.quit()
sys.exit(0)
長い・・・ので、コード内にコメント(#)で説明を記載しました。
コーディングするのに一番苦労しました。。。
4. A-AUTO50による[CHILED_OPE.py]の起動設定
ここでは、前項で開発した[ CHILED_OPE.py ]を起動するための仕組みを開発していきます。
4-1. ジョブ設定
A-AUTO50は、ブラウザ経由で設定や操作・監視が行えます。
こちらでジョブを設定します。名前は[ AUTOOPE3 ]です。
4-2. 起動用バッチファイル作成
A-AUTO50のジョブからは[ CHILED_OPE.py ]を直接起動することができないため、
起動用のバッチファイルを作成します。
名前は [ AUTOOPE3.bat ]です。
@echo off
C:\Users\user\AppData\Local\Programs\Python\Python35-32\python.exe C:\BSP\AUW\INSTALL\PRIMSCRIPT\CHILED_AUTOOPE.py
IF %ERRORLEVEL%==0 GOTO SUCCESS
:ERROR
aexit 1
GOTO DONE
:SUCCESS
aexit 0
:DONE
exit
コードは単純で、[ CHILED_OPE.py ]を起動し、同プログラムから渡される終了コードをジョブに返値するだけです。
これでAUTO Operatorを作成できました。
業務フロー通りに稼動するか、試してみます。
5. テスト
テストは3ケース行います。まずは、オペレーションが成功するか、試してみます。。。
5-1. ケースA:httpd再起動成功
お客様から以下メールを受信しましたので、A-AUTO50でジョブ[ AUTOOPE3 ]を起動します。
(以降、AUTO Operatorがうまく動くかどうか見ていきます!)
↓ ↓ ↓ ↓ ↓
お客様へ依頼受付メールを送信
↓ ↓ ↓ ↓ ↓
httpdの再起動依頼であったため、Linuxサーバへ接続し、httpdを再起動
↓ ↓ ↓ ↓ ↓
お客様へ作業完了メールを送信
↓ ↓ ↓ ↓ ↓
A-AUTO50のジョブ[ AUTOOPE3 ]が正常終了
OKです、うまく稼動しました!
続いて、次のケースを試してみます。
5-2. ケースB:httpd再起動失敗。SEエスカレーション
お客様から以下メールを受信しましたので、ケースAと同様にジョブ[ AUTOOPE3 ]を起動します。
(さあ、うまくいくかどうか・・!?)
↓ ↓ ↓ ↓ ↓
お客様へ依頼受付メールを送信
↓ ↓ ↓ ↓ ↓
httpdの再起動依頼であったため、Linuxサーバへ接続し、httpdを再起動
・・・・しましたが、失敗。
※今回、[ CHILED_OPE.py ]内のhttpd再起動の記述を意図的に変えて失敗させました。
[service httpd restart ] → [ service httpd restartdddddd]
↓ ↓ ↓ ↓ ↓
SEへエスカレーションメールを送信
↓ ↓ ↓ ↓ ↓
A-AUTO50のジョブ[ AUTOOPE3 ]が異常終了
これもOKです!!想定通り稼動しました!
続いて最後のケースを試してみます。
5-3. ケースC:[ AUTO Operator ]対応不能。SEエスカレーション
これは、httpd再起動以外の依頼が発生した際の対応です。試してみます。
お客様から以下メールを受信しましたので、A-AUTO50でジョブ[ AUTOOPE3 ]を起動します。
(今回は、httpd再起動ではなく、データ更新の依頼です)
↓ ↓ ↓ ↓ ↓
お客様へ依頼受付メールを送信
↓ ↓ ↓ ↓ ↓
httpdの再起動でないため、SEへエスカレーションメールを送信
OKです!!
3ケース実行し、無事、処理フロー通りの稼動を確認することができました!
6. おわりに
今回、業務自動化に向けた第1歩として、AUTO Operatorを作ってみましたが、
まだまだ、バージョンアップできるな、と感じました。
例えば、
- 緊急エスカレーションの場合は、SEに電話をかけるようにする。
(Twilioなどを使用して) - 変数の設定値のような可変のものは、Pythonプログラムから外出しすることでプログラムを汎用化する。
(A-AUTOの[ ノーマル実行時のパラメータ ]機能を使用して)
などなど。
AUTO Operatorが便利になればなるほど、手作業を行っていた人の手を空けられます。
そして、空いた手で、更なる改善を進めていくことができますので、引き続きいろいろとチャレンジしていきたいと思います!