投稿

ラベル(perl)が付いた投稿を表示しています

メールサーバの移行

イメージ
 自前のメールサーバを停止 これまで、自ドメインのメールサーバはVPS上に構築していた。 ・Ubuntu Server ・Postfix ・Dovecot ・spamAssassinと、BlackListの利用 Spam対策を行ってきたし、サーバ上でメールをトリガーにして各種プログラムを動かしたりしてきた。 メールサーバのメンテナンスは結構面倒くさくて、  ・Disk容量のチェック  ・不正アクセスのチェック  ・各種セキュリティパッチの適用 など、手間がかかる。 そこで、外部のサーバを利用することに…。 結構安くて使い勝手の良さそうなのが、「さくらのメールボックス」 3年契約で、3070円とな…。  メールアドレスは自分のだけなので、20GBまで利用可能!  (Gmailより大きいねぇ) ということで、早速契約。 アカウント設定を行って、既存のDNSを書き換える。WHOISも書き換えて完了。 SMTPとIMAPが利用できればOK。 ちょうど、GoogleがSPF設定していないと受信しないし、DKIMおよびDMARCに対応していないメールを弾くようになったので、対応しているのを確認。 さくらサーバ自体は、これまでお客さんのサーバとして何件も利用しているので、利用方法も難しくはない。  Webメールにも対応しているので、いざという場合にもありがたい。 ということで、各メールソフトの設定を変更。  PC(常時使用する3台)とタブレット、スマートフォンと台数は多いがそれ程手間はかからない。 問題は、旧サーバで送受信したメールの履歴だけれど、これはThunderbrdを使ってローカルに保存することで回避。  本当は、サーバtoサーバでMailboxに残そうとも考えたんだけど、古いメールはそれ程必要ないし、ローカルにバックアップしてあれば凌げるので、良しとする。 移行時にDNSの反映で若干時間がかかったものの、問題なく送受信できるのを確認して、作業完了。  これでメンテナンスの手間が減るので、安いもんです。

Perl ScriptのEXE化で苦戦

イメージ
exeの生成が必要 以前(随分前だけど)やったことが、あったので楽勝と思ったら、意外なところで躓いたのでちゃんと記録しておく。 基本的にスクリプト言語であるPerlのコードはテキストファイル。 Perlの実行環境さえあれば、ほぼ動く。  LinuxやMacなら最初からperlが入っているので、何も考えることはない。 じゃ、windowsのように実行環境がない場合はどうするかというと、 Perlを動かせるようにインストールする(ActivePerlで簡単に入る) exeファイルにして、実行する。(ファイルが巨大になる) 諦める と、これくらいしか選択肢がない。 今回は、作成したスクリプトを、Perl実行環境のない端末で何台も動かすことになりそう。 でもって、それぞれの端末にPerlをインストールして、pmなどのライブラリを揃えてというのが、メンテナンス上大変になりそう。 となると、2.のexe化を検討するしかない。 環境準備1 まずは、新しいVMを用意して、ActivePerlのインストールから始める。 ActiveStateに行くと、 ActivePerl-5.20.2.2002-MSWin32-x86-64int-299195.msi が最新らしい。随分とバージョンが上がってるなぁ…。 早速インストール→数分で完了。 コマンドプロンプトから、 cpan install PAR::Packer で、exe化に必要なモジュールをインストール。 まっさらな状態からのインストールなので、若干時間がかかるけれど、無事終了…。 あれ?無事終了しない。Error吐いてる。 main.c: In function 'main': main.c:121:23: warning: assignment discards 'const' qualifier from pointer target type [enabled by default] windres -i winres/pp.rc -o ppresource.coff --input-format=rc --output-format=coff --target=pe-i386 '

perlで不要なタグを削除

素人すぎですよ 製作途中で放置されているサイトの依頼を受けて、少し前からチェック等していましたが…。 確かに、それなりに表示されているものの、中身がひどくてメンテナンスをどうやるか悩むレベル。 いろんな情報を提供する目的なんだろうけど、元のファイルをコピーして書きなおしている感じで、DBも使わず、サーバサイドで処理もせず、CSSもほぼなし。 ざっと300ファイル(全部html)で、やたらと全角スペースでレイアウトされているstaticなページ。 これを直すのは正直嫌です。 しかも、各ファイルの先頭に <script type="text/javascript"> if ((navigator.userAgent.indexOf('iPhone') > 0 && navigator.userAgent.indexOf('iPad') == -1) || navigator.userAgent.indexOf('iPod') > 0 || navigator.userAgent.indexOf('Android') > 0) { location.href = '/smartphone/'; }</script> そして、smartphoneフォルダには何もない。 だから、PCと同じページを見に来るとNot Found多発地帯という地雷まで完備。 この設計意味が分かりません。変更が発生した場合は、どうするつもりだったんでしょう??? 1つずつ直すのか?それとも、何かジェネレータプログラムが作ってあって、ガシガシと吐き出しているのだろうか? スマートフォンでも見えるように修正 まずは、現状のhtmlを見せれば、not foundは解決するので、scriptを無効にしたい。 とはいっても、300も1つ1つ直すのはコンピュータ使いのやることじゃない。 ここはperlでサクッと処理したい所。 調べてみると、TreeBuilderが良さそう。こんなことがなきゃ、この手のライブラリを使うことも無いだろうなんて思いながら、テストコードを書いてみる。  # perl -MCPA

久しぶりで、使い方を忘れてた…(Perl)

Perlでプログラムをガシガシと 昨年納品したプログラムの、追加機能の要求が上がったので、見直しを行っていた。 今回は、DBを使うほど件数が増えそうにもない。 履歴を見て登録されているユーザか、そうでないかを判別するだけなので、ハッシュをファイルに紐付けて、簡易のDBとして使うことにする。  昔なら、メモリがパンクするんじゃ?とかディスク遅いっすとか思ったりして躊躇するんだろうけど、今どきはドンドンメモリ使っちゃおう!ファイル使っちゃおう!なんて思ったりもする。 さて、前回利用したモジュールは Jcode; MIME::Parser; MIME::WordDecoder; File::Basename; File::Path; Fcntl; File::Temp; 書き出してみるとこんなにもあった。 でもって、今回新たに Storable; 当然、稼働しているプログラムなので、直接いじるわけにはいかない。 とりあえず、ローカルでテストをする。 ソースを取り出して、修正内容を細かく分割。 それぞれテストして、組み立て…。 と、最初のテストで躓いた。 ローカルの環境が、この春に14.04で準備したNewマシンなので、モジュールが入っていない! モジュールのインストール そもそも、最初のuse Jcode;でエラー吐いているし… ということで、インストールしようとしたが、コマンドを全く思い出せない。 あれれ? どうやら老化と共にやってくるアレか? # perl -MCPAN -e shell これが思い出せずに、仕方なくググりました。 いやぁ、外部記憶に入れておいて良かったゎ(泣) というか、内部記憶から消去されている模様。 忘れないように、自分を戒めるために記録しておく。 作業自体は、コマンド入力して完了するのに1分もかからないというのに、思い出そうとした時間の方が長いとは…。 root@X200:~# perl -MCPAN -e shell CPAN.pm requires configuration, but most of it can be done automaticall

さくらサーバでLynxが…

イメージ
自動化するのにPerlを検討 ある案件で、あるサイトのフォームへ手入力しているものを、自動化するという処理を構築することに。 当初、メールでデータを流しこみ、Perlで解析し、POSTする方法を検討。 ところが、何度もページを遷移したあとで入力フォームにたどり着くのだけれど、SSLなページが、LWPではどうも上手くいかない。 まあWebブラウザを作るのと同じような内容になってしまうので、面倒すぎる。 どうもHiddenでデータ渡しているし、セッションを使っているのでCookieまわりの処理とかがダメっぽい。ひょっとするとReferer等も見ている感じ ふ〜む、そうだ! WWW::Mechanizeを使おうと考えた。データを作るのに手入力はやっていられないので、HTTP::RecorderでProxyさせて、記録することに。 でもSSL通すと記録してくれない…。 はぁ…。 テキストブラウザLynxが使えないレベル ならば、いっその事テキストブラウザを制御する方向で検討。 メールで受けて、解析し、テキストブラウザをスクリプトで動作させる。 スクリプトには解析した内容から、フォームに入力させるようにPerlで生成する。 よし。これならOKそう。 まずは手元のUbuntu上で簡単な動作確認を行う。 Lynxには、マニュアルに載っていないコマンドラインオプションがあって、 $ lynx -cmd_log ファイル名 とすると、操作を記録してくれる。 この記録されたファイルを編集してやれば思い通りに動かせるはず。 実行するには、 $ lynx -cmd_script ファイル名 でOKだ。 実際には、 lynx -cmd_script log.txt -accept_all_cookies URL なんて指示してやる。 どうやら、日本語もちょっとうまく処理してやるとフォームに流し込めることが判明。 SSLもモジュールさえ入っていれば動作するのを確認。 本番環境の調査 お客さんの借りているのが「さくらのレンタルサーバ スタンダード」。契約内容からSSHがOK。Lynxも入っている。PerlもOK。 ここまでは、事前の調査で分かっているので、最

Crypt::SSLeayが入らない

Perlでの作業中 ちょっとスクリプトからWebページをゲロってこようと思い、LWP::UserAgentなどを使って、取得していた。 ちょっとhttpsあたりも必要に迫られ、getしようとしたらエラーを吐いてくる。 ふむふむ。 ぐぐってみると、Crypt::SSLeayを入れろとな。 ちうことで、 $ sudo perl -MCPAN -e shell で、CPANから入れることに。 cpan[1]> install Crypt::SSLeay 通常は、これでOKなはずなのに…。エラー吐いてくれます。 でもなぁ、CPANから自動で入れているのにmakeで転けられても…。 でも、昔の出来事を思い出してテストして見ることに。 「接続を拒否されました」というメッセージが気になる。 Linuxの初期に良くあったのだけれど、これってLANG=Cでないと動かないんじゃ? ちゅうことで、再度やり直してみる。 英語モードで再度実行! 一旦、抜けてcpanの起動から。 $ LANG=C sudo perl -MCPAN -e shell 表示はもともと英語だし、何も問題ないはず。 同様に、Crypt::SSLeayを入れてみる。 全てのテストに合格して、無事インストール完了!! やはりな!って感じです。 はっ!! インストールが目的ではなかった…。 さて、SSLが使えるようになっているはずなので、テストする。 500 Can't verify SSL peers without knowning which Certificate Authorities to trust orz... SSL証明書と一致しないらしい…。 もうひと踏ん張り。 SSL 証明書のエラー時の対応  どうやら、良く発生するようで…。あちこちに対応策が書かれていた。 [Perl] LWP::UserAgent で SSL 証明書のエラーへの対応 の記述がわかり易かった。 ホスト名の検証をしない CAを明示する いやいや、1はまずいんでは?という思うので、2の方針で。 Mozilla::CAを入れれば良さそう。 さっそく、cpanでMozilla::CAをイン

PerlでMIME処理

イメージ
いろいろとCPANで遊んでいて PerlでMIMEの処理をさせようと、モジュールをインストールして試してみる。 今まで、自前処理で行うことが多かったので、勉強がてら検索&TRY。 メール解析には「MIME::Parser」が便利そう。 ということで、入れてみる。 $ sudo perl -MCPAN -e shell cpan[1]> install MIME::Parser たったこれだけで、入るんだから楽なもんだ。 my $parse=MIME::Parser->new(); my $message = $parse->parse(*STDIN); my $head = $message->head();  なんて処理を書いて、マルチパートなデータを食わせて、いろいろとテストしていたら、読み込んだメールデータをパースするたびに、ファイルを生成してくれる…。 txtとhtmlがわさわさと増えているじゃないか…。 つうことで、何かオプションが有るはずと思いつつ、探してみる。 「 MIME::Parser インスタンス設定 output_to_core 」なんて記録を見つけた。 1をセットすると、parseデータをメモリ上に保持する。デフォルトでは解析結果のうちbody部(本文やマルチパートの添付ファイル)は即時ディスクに書き出し。 (perldoc では、巨大ファイルが添付された場合などでちょっとriskyとさ) ということらしいので、セットしてテストしてみる。 $parse->output_to_core(1); $parse->tmp_to_core(1); $parse->tmp_recycling(1); $parse->use_inner_files(1); こんな感じで、書いておけば、オンメモリで作業してくれるらしい。 昔、メモリが少ない時の実装なんだろうな…なんて思いながら、現在の大量にメモリが使える時代に感謝!! で、output_to_core(1)をセットして、テストすると作業ファイル等全く作らなくなった。 まあ、どでかいメールを食わせる予定はないので、メモリで処理してくれた方がありがたい。ファイルがディスクを食いつぶ

グループを別のグループに追加

Linux上での話ですが… 友人より、相談のメールが。 すでにLinux上でユーザを幾つかのグループに分けて管理している。 今回整理統合したのでしょうか、GroupA、GroupBをGroupCに突っ込みたいけど、良い方法は?という質問がありました。 Linuxの場合、プライマリーグループがあってdefaultだとユーザ名と同じグループが作られ、運用しています。 それとは別に、ユーザは他のグループに所属するケースもあるわけで、複数のグループに所属することが可能になっています。 で、その操作を簡単にできるのではないか?ということでした。 結論から言うと、その手のコマンドは存在していないので、標準コマンドで作業を完結することはできないわけです。 じゃぁ、無理なのか?というと、そんなことはなく、ちょっとスクリプトを書けば可能です。 解決方法1 メールの中身を読んだのが、日付が変わる頃だったので、寝ぼけながらも何とか処理できました。 ユーザのグループは、/etc/groupに格納されていて、以下のような構成になっています。 test:x:1003: test1:x:1004:test2,test3 test2:x:1005: test3:x:1006: test4:x:1007:test5 test5:x:1008: あくまでもサンプルですが、test1グループにユーザtest2,test3がいます。さらにグループtest4にはtest5がいます。 このtest1,test4をグループtestに入れることにします。 最終的には、test=(test2,test3,test5)となればOKと。 ※本当は、test1にはユーザtest1、test4にはユーザtest4も入っているんだけど、今回は処理しない前提で行きます。一人くらいなら、手作業で変更できるので…。 考え方 まずは、test1のグループのメンバーを引っ張りだします。 これはgrepを利用すればOK。 $ grep test1 /etc/group すると test1:x:1004:test2,test3 という行を得ることができます。欲しいのはtest2,test3の部分なので、切り出します。

ログの整理 #3

PowerShellでは遅すぎて… 実際問題、ログからcsvに切り出すことは可能になったものの、10MBのログから200kb前後のcsvファイルを生成するのに前回のスクリプトだと約2時間かかるんですねぇ。 そりゃ、1レコードを生成するのに、ログオンIDで再度全部ログを舐めて、PCの名前とIPを拾っているわけで…。 単純に考えればO(n^2)というわけですね。 ログのローテーションというか上限を5MB(半分)にすれば、多分処理速度は1/4程度にまで下がるとは思われるけれど、120分が30分になって、ファイル数が倍なので実質1時間かかるわけで…。orz。 何が遅い? 実際、何に時間がかかっているのかを調べ始めたのだけれど、まずwhere-Objectが結構な時間を消費している。その後foreachで回す処理は激遅い。 結局、イベントログからオブジェクトとして扱っているのが、遅さの原因ぽい。 最適化しようにも、PowerShell自体の扱いに慣れていないので、とっても疲れるです。 他に良い方法は無いものだろうか?と思案し始めた時に、以前オライリーの本で見た記憶があったので、ちょいっと検索してみる。 方針変更! perlのモジュールにW32::EventLogが有るじゃないですか。 早速、マニュアルを参考にテスト用のコードを書いてみる。 さすがに、サーバ上での作業は心配なので、VM上のWindows7にActivePerlを入れてテストすることに。 細かい仕様を決めようか、汎用的に作ろうかと迷いつつも、現状の作業をサックリ行えることを目的に作成した。約1日かけて、コーディング終了。前回までのスクリプトと同じ結果を返すようにするところで、少々苦労したわ。 なので、若干コードは汚い(perlなのでさらに汚いww)とは思うのだけれど、これが素晴らしい性能を発揮してくれた。 コードは以下全体を載せておくので、もし万が一使いたい人は、自己責任にてお願いします。 さて、実際に同じデータを食わせてみると、なっなんと、2時間かかっていた処理を1分以内に終えてくれる!!! あぁ、これで今後のログの整理が快適になる。 1週間分、いや1ヶ月分まとめて処理だって怖くない! あとは、コマンドラインでイベントログを引数として渡せば良い仕様