[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
YouTubeでピタゴラスイッチのピタゴラ装置やアルゴリズム行進がワールドワイド。
フランス語で字幕のついたアルゴリズム行進とか、1000人弱の囚人(フィリピンセブ島?)によるアルゴリズム行進とか。
百科おじさんの声が名古屋章だった頃から録画で見ているワタシ的にはちょっと嬉しい。
「何してるの?おじさん」コーナーも好きだったが、無くなってしまった。ラーメンズを起用するあたり、NHKもなかなかやるな。と思った次第。
さて、
年末年始中にバックアップジョブが失敗し、Oracleが停止したままになっていたのは問題なので、ColdFusionでOracleの死活を通知させることにしました。
ColdFusionのスケジュールタスク機能を使って、下記のテンプレートを1時間ごとに呼ぶことで実現します。
ColdFusionAdministratorのタスクスケジューリング画面
<!---
スケジュールタスクとして呼ばれ、Oracleへの接続を確認する。
呼ばれるのは、AM7:00からPM22:30の間、1時間ごと。
メールで通知する。
復旧も通知する。
--->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Oracleへの接続確認をする</title>
</head>
<!--- 初期設定 --->
<cfset orastop = false>
<cfset mailto="cfif@hoge.co.jp,cfif@hoge.ne.jp"><!---メール通知先--->
<cffile action="read" file="d:\Inetpub\wwwroot\CF\pingOracle.txt" variable="oracleStatus"><!--- ファイルから前回の状態を読む。"stop" or "open" --->
<!--- 接続確認 --->
<cftry>
<cfquery datasource="tip" name="pin">
select litemid from techmstl
</cfquery>
<cfcatch type="database">
<cfset orastop = true>
</cfcatch>
</cftry>
<cfif orastop>
<!--- 停止している場合 --->
<!--- ファイルにstopを書く --->
<cfif oracleStatus is "open">
<cffile action="write" file="d:\Inetpub\wwwroot\CF\pingOracle.txt" addnewline="no" output="stop">
</cfif>
<!--- メール通知 --->
<cfmail subject="STOP Oracle" from="server@hoge.co.jp" to="#mailto#">
Oracleが停止しています。
</cfmail>
<cfelse>
<!--- 起動している場合 --->
<!--- 復旧かどうかの確認 --->
<cfif oracleStatus is "stop">
<!--- 復旧通知 --->
<cfmail subject="OPEN Oracle" from="server@hoge.co.jp" to="#mailto#">
Oracleが復旧しました。
</cfmail>
<!--- ファイルにopenを書く --->
<cffile action="write" file="d:\Inetpub\wwwroot\CF\pingOracle.txt" addnewline="no" output="open">
</cfif>
</cfif>
<body>
</body>
</html>
1時間に1回、データーベースに接続を行い、エラーが帰ってきた場合は、指定されたメールアドレスに通知を行います。また、前回エラーで今回正常だった場合は、「復旧」を通知します。
クエリを発行してデータベースのエラーをcfcatchするわけですが、「復旧」を通知するために、状態をファイルに書き込んでいます。application変数を使ってもいいのですが、ColdFusionやサーバーの再起動があった場合には保持できなくなるので、ファイルに書いています。
cffileで読み書きをしていますが、action="write"のaddnewlineプロパティはデフォルトで"yes" つまり追記になります。日時も含めて書き込み、ログ的に使うなら"yes"ですが、今回は"no"でやってます。
ややこしくならないし。f(^^;)
ColdFusionAdministratorの設定では、7:00 - 22:50 をスケジューリングの範囲にしています。
夜中に携帯が鳴るのも鬱陶しい(というか、夜中止まっても支障ないシステムだ)し、週末の23時からバックアップのためデーターベースを停止させているので。
ということで、今年最初のコードを書きました。
乗っていた電車で痴漢騒ぎがありました。
誤解だと言ってましたが・・・・・大変だな。
さて、
aspxメインで動いているシステムで、複数ファイルをzipに圧縮して落とす仕組みを追加(外注)しました。
Chestysoft(http://www.chestysoft.com)というところのcsASPZipFileというASPコンポーネントで実装してもらったのですが、ダウンロードがとても遅い・・・・・
ダウンロード中の速度を見ていると、200KB/sくらいで始まり、だんだん遅くなって50KB/sくらいになってしまいます。
100MBくらいのボリュームになる場合も多いので、これでは使い物になりません。
調べると、zipファイル作成はサックリ終わっているのに、csASPZipFileコンポーネントのStreamZipメソッドが遅い模様。
Basp21のストリームを使ってみたりしてもらったのですが、外注先のSEさん曰く、『・・・手詰まりです』とのこと。
そのシステムのサーバーにはColdFusionMX7が載っているので、ColdFusionでzipファイル作る方法はないのかなぁ・・・・と調べ始めたところ、csASPZipFileのマニュアルにColdFusionの文字がっ!
Using csASPZipFile With ColdFusion
そもそも名前にASPとついていたので、ColdFusionで使えるとは思ってもいませんでした。
早速テスト。サンプルコードもあったので、あっという間にテスト完了。
Goodです。イントラレベルのダウンロードスピードが出てると思います。
テストソースはこんな感じ。
※select.cfm makezip.cfmを同じパスに置いて、その下にdatafilesフォルダを作ってダウンロード対象ファイルを入れます。
<html>
<head>
<title>Make selection</title>
</head>
<body>
<p>Select the files for download</p>
<form action=makezip.cfm method=post>
<cfset dir = ExpandPath(".") & "\datafiles\">
<cfdirectory directory="#dir#" name="datafiles">
<cfset I = 0>
<cfoutput query="datafiles">
<cfif (#name# NEQ ".") and (#name# NEQ "..")>
<input type=checkbox value=true name=#I#>#name#<br>
</cfif>
<cfset I = I + 1>
</cfoutput>
<input type=hidden name=directory value="<cfoutput>#HTMLEditFormat(dir)#</cfoutput>">
<input type=reset value=Clear><input type=submit value=Download>
</form>
</body>
</html>
======================== makezip.cfm ======================
<cfcache action="flush">
<cfset dir=form["directory"]>
<cfset filename=ExpandPath(".") & "\" & CreateUUID() & ".zip">
<!-- use the appropriate version of the component -->
<!---<cfobject action="create" name="zip" class="csASPZipFileTrial.MakeZip">--->
<cfobject action="create" name="zip" class="csASPZipFile.MakeZip">
<cfset I=0>
<cfdirectory directory=#dir# name="datafiles">
<cfoutput query="datafiles">
<cftry>
<cfif form["#I#"] EQ "true">
<cfset zip.ZipAdd(dir & #name#)>
</cfif>
<cfcatch>
</cfcatch>
</cftry>
<cfset I = I + 1>
</cfoutput>
<cfset zip.SaveZip(#filename#)>
<cfcontent type="application/x-zip-compressed" deletefile="yes" file=#filename#>
う~ん。やっぱりColdFusionが好き。
データーベースを停止する直前になって、ColdFusionのシステムにエラー処理を仕込みました。
やっぱり今週は時間がとれなかった・・・・
さて、
エラー処理といっても、基本中の基本と思われる、データーベースが停止しているときの処理です。
ColdFusion MX7 なので、Application.cfcでやるのが王道でしょう。
拡張子 cfc は、コールドフュージョンコンポーネントです。その中でもApplication.cfcだけは特別扱いのコンポーネント。どの辺が特別かというと、どのcfmを実行するときでも必ず読み込まれるのです。(そのcfmと同一ディレクトリか上位ディレクトリにApplication.cfcが存在すれば ですが) あ、それとApplicationのAは必ず大文字で。
必ず読み込まれるので、そこで<cfquery>を発行して、エラーが出ない事を確認させれば、全部のcfmにチェックするコードを入れる手間は省けるわけです。
ColdFusionでセッション管理をする場合にもApplication.cfcで定義するのですが、ちょっとそれは置いといて、エラー処理について。
======== Application.cfc のソース===========
<cfcomponent>
<cfprocessingdirective pageencoding="UTF-8">
<cfscript>
This.name="genba_ph";
This.clientManagement="False";
This.sessionmanagement="True";
This.Sessiontimeout="#createtimespan(0,0,60,0)#";
</cfscript>
<cffunction name="onApplicationStart">
<!---アプリケーション変数設定--->
</cffunction>
<cffunction name="onRequestStart">
<!--- データーベース確認 --->
<cftry>
<cfquery name="check" datasource="tip">
SELECT COUNT(HONSTNCD) FROM HONSITENMST
</cfquery>
<cfcatch type="database">
<cfoutput><h1>データーベースが停止しているため、システムは現在利用できません</h1></cfoutput>
<cfreturn false>
</cfcatch>
</cftry>
<!--- ログインチェック --->
<!--- session.login があればログイン済
無ければクッキーを調べる。cookie.shimei_cdはポータルと同じクッキー --->
</cffunction>
<cffunction name="onSessionStart">
<!---セッション開始をログ記録--->
</cffunction>
<cffunction name="onSessionEnd">
<!---ディレクトリを作成したなら消す--->
</cffunction>
</cfcomponent>
====================================
Application.cfc は、だいたいこんな構成が多いんだと思います。
エラー処理をしてるのは、<!---データーベース確認--->と書いてあるところ。
<cftry>
エラーが発生する可能性がある処理(クエリ発行)
<cfcatch>
発生しちゃったときの処理
</cfcatch>
</cftry>
このパターンが普通ですね。
ところでApplication.cfc は、ColdFusionMX7から使えるようになったコンポーネント。以前はApplication.cfmでした。
cfcになってから、必ず読み込まれるだけでなく、<cffunction name="どんなときに実行する?">というファンクションがつきました。
<cffunction name="onApplicationStart">は、アプリケーションが開始したとき。
<cffunction name="onRequestStart">は、cfmページが呼ばれたときに最初に必ず。
<cffunction name="onRequestEnd">は、cfmページの最後に必ず。
<cffunction name="onSessionStart">は、セッションが開始したときに必ず。
<cffunction name="onSessionEnd">は、セッションが終了したときに必ず。
今回のデーターベースの稼働確認は、ページを表示する時に毎回チェックさせてます。
その他、注釈のような処理をさせたりしてます。
さて、明日はシステムの引っ越しです。
無事引っ越せるか、結構不安・・・・
裏金燃やすってさ、みんな信じてるんだろうか・・・・・
冷静に考えると、燃やすわけねーだろ! って思う。
さて、
ColdFusionを使って、お気楽にディレクトリ内のファイルをweb公開する例です。
ぶっちゃけwebサーバーの機能だけでスグできるわけですが、あえてColdFusionを使います。はい。
最近のコピー機はいわゆるネットワーク複合機で、いろんなことができます。
ワタシもよく使う機能に、スキャンしてPDFにしてメールで送ってくれる機能があります。
当たり前ですがオートフィーダーもついているので、数十枚のペーパーをさくっとPDFにすることができます。
メールアドレスを登録しておけば、メール送信してくれたり、ユーザー名パスワードを設定して、サーバーのフォルダに直接保存したりできます。
この機能は、総務系うっかり課長(イメージ右図)レベルでも使えるので、「ペーパーレス化」とか「業務効率化」とか、耳障りのいいコトバと共にじゃんじゃんPDFが生成されるわけです。
すると当然総務系うっかり課長(イメージ右図)なんかは、「おい!回覧したりFAXしてる訃報なんぞは、PDFで送れば通信費削減だな!」 などと言い出すのは、たぶん何処の企業でも同じだと想像します。
すると今度は総務系オツボネーゼが「課長!そんなこと言ったって、メールでみんなに送るなんてめんどくさくてありえなーい!」と反論。で、じゃぁホームページで公開すれば・・・・・ となりオハチが廻ってくるしくみです。
そんな背景でサクッと。
webサーバーに公開用フォルダを用意します。アクセス制限をして、総務系オツボネーゼに書き込み権限を与えて、オツボネーゼのデスクトップにショートカットを仕込みます。
この公開用フォルダにPDFを保存すれば、そのまんま公開されるしくみを作ります。
オツボネーゼの仕事は、「コピー機でPDFを作り、ファイル名を整えて保存する」となり、このくらいなら「えーファイル名変えるのめんどくさーい」程度のイヤミを聞かされる程度で業務に組み込めますね。
<cfdirectory directory="/var/www/html/fuho" action="list" name="spf" filter="*.pdf" sort="name DESC"/>
<cfoutput>
<h3>訃報</h3>
<cfloop query="spf">
<div class="items">
<cfif (IsNumeric(ListGetAt(name,1,'.')) is false) or (Len(ListGetAt(name,1,'.')) neq 8)>
[#name#]←ファイル名がyyyymmdd.pdfでは無いようです....
<cfelse>
<h3><a href="./kyu/sambaweb/newspaper/#name#" target="_PDF">#left(name,4)#年 #mid(name,5,2)#月 #mid(name,7,2)#日</a> (#NumberFormat(size/1024/1024,'__._')#MB)</h3>
</cfif>
</div>
</cfloop>
</cfoutput>
ソースです。fuho フォルダにyyyymmdd.pdf 形式でpdfを保存すると、
2006年 09月 07日 ( 2.1MB)
2006年 09月 06日 ( 1.1MB)
2006年 09月 05日 ( 2.3MB)
といった感じで日付にpdfへのリンクが張られ、サイズが表示されます。
== 解説 ==
1行目の<cfdirectory>(→LiveDocs)で指定したフォルダ内のリストを取得しています。
directory="/var/www/html/fuho" は絶対パスで。Linuxなのでこう書いてますが、windowsなら directory="d:\inetpub\wwwroot\hogehoge" などと、ドライブレターからですね。
他のパラメータの意味は、
action="list" 欲しいのはリストだよ
name="spf" 取得した一覧はspf っていう変数に入れてね
filter="*.pdf" 取得するのは、拡張子がpdfのファイルだけでいいよ
sort="name DESC" ファイル名降順で並べ替えておくれ
という意味です。
ここで文字化けの問題に遭遇することがあります。
linuxのCFサーバーから、sambaで公開している日本語ファイル名を読むと、バケバケです。
これを回避する方法は今のところ解りません。誰か教えて下さい!
ワタシの見つけた唯一の解決策は、windowsのCFサーバーから、linuxのsambaフォルダを読むと文字化けしない。ってことです。
cfdirectoryはネットワーク越しでも使えますから。(でもスッキリしない・・・・・誰か教えて!)
つづく
今朝、会社の女子トイレから「キャー!きゃー!」と何度も悲鳴が聞こえた。
あとで聞くと、「コオロギが出た!」と言う・・・・
ここは東京都中央区のビルの8階。
そいつは絶対コオロギじゃないと思うぞ。
さて、
MovabeType用のpingサーバーの作り方、その5です。
[その1] [その2] [その3] [その4]
1)pingが来たら、
2)postされたcontentの内容を読んで
3)XMLとして取り込み
4)URLを取り出したら
5)RSSを読みに行って
6)新着記事を入手し
7)データーベースに書く
の7) について。
DBにping用のテーブルを用意します。
とりあえず、SEQ,URL,PINGDATE,TITLE,CONTENTSといったフィールドにしました。
<cfquery datasource="etc" name="pingins">
INSERT INTO BLOG (SEQ,URL,PINGDATE,TITLE,CONTENTS) VALUES
(BLOG_SEQ.NEXTVAL,'#ping.methodCall.params.param[2].value.xmltext#','#xmlDoc["rdf:RDF"].item[1]["dc:date"].XmlText#','#xmlDoc["rdf:RDF"].channel.title.xmltext#','#xmlDoc["rdf:RDF"].item[1].title.XmlText#')
</cfquery>
SEQ以外は文字列型でそのまんま突っ込んでます。f(^^;)
ColdFusionのわかりやすさの一つが、この<cfquery>の書き方。
aspやphpなどは、SQL文を作るのがめんどくさいなぁ といつも思います。文字列変数を何度もつなげて・・・・。作るのがめんどくさいというより、実はワタシ的にはほとんどaspやphpでゼロから作ることは無いので、ソースから逆追いするのがメンドクサい・・・・・といつも思います。
検索用に条件がいろいろ変わるときなんかは特にそうです。
aspやphpだと、結局どんなSQL文になってるのか、デバッグ用にsqlを表示させながら確認するしか方法をしりません。
ColdFusionだと、SQL文をそのまま書けるから見た目にわかりやすい。
検索系で動的に条件が変わる場合は、CFCとして別出しすることが多いかな?
そのときはそれなりに複雑になってしまいますが・・・・
さて、DBに突っ込めばとりあえずおしまいな訳ですが、なにやらpingを受け取ると結果をxmlで返すルールのようなので(よくわかってない)見よう見まねで返しておきます。本来なら成功か失敗かで返すxmlが代わるわけですが、その辺はなんちゃってイントラpingサーバーなので、気にしない気にしない。
=======以下、実際に使ってるソース index.cfm ========
<cfprocessingdirective pageencoding="utf-8">
<cfset x = GetHttpRequestData()><!---httpリクエストを取る--->
<cfif x.method is "POST">
<cfset ping = XMLParse(x.content)><!---xml展開--->
<cfset Variable.url = "#ping.methodCall.params.param[2].value.xmltext#index.rdf">
<cfhttp url="#Variable.url#" method="GET" resolveurl="Yes" throwOnError="Yes" />
<cfset xmlDoc = XmlParse(CFHTTP.FileContent)>
<cfset resources=xmlDoc.xmlroot.xmlChildren>
<cfquery datasource="etc" name="pingins">
INSERT INTO BLOG (SEQ,URL,PINGDATE,TITLE,CONTENTS) VALUES
(BLOG_SEQ.NEXTVAL,'#ping.methodCall.params.param[2].value.xmltext#',#now()#,'#resources[1].title.xmltext#','#resources[2].title.xmltext#')
</cfquery>
<?xml version="1.0" encording="UTF-8"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>flerror</name>
<value>
<boolean>0</boolean>
</value>
</member>
<member>
<name>message</name>
<value>Thanks for the ping.</value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>
<cfelse>
<!---そうか GETだったら表示しよう--->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ブログ更新情報</title>
</head>
<cfquery name="blogs" datasource="etc">
SELECT
C.SEQ , B.URL , B.LASTUPDATE , C.TITLE , C.CONTENTS
FROM
(SELECT A.URL,MAX(A.PINGDATE) LASTUPDATE FROM BLOG A GROUP BY A.URL) B, BLOG C
WHERE
B.URL = C.URL AND B.LASTUPDATE = C.PINGDATE
ORDER BY B.LASTUPDATE DESC
</cfquery>
<body>
<div id="blogs">
<h3>Blogs</h3>
<ul>
<cfoutput query="blogs">
<li><a href="#url#">#TITLE#</a>(#dateformat(lastupdate,'m/d')# <cfif datediff('d',lastupdate,now()) lt 3><span style="color:red">New!</span></cfif>)<br>
#CONTENTS#
</li>
</cfoutput>
</ul>
</div>
</body>
</html>
</cfif>
以上でした。
情報通信を生業としない企業の、システム系でもない普通の社員なので、 ColdFusionは独学。参考書が少ないのがツライです・・・・なんだかんだ、ColdFusion4.xのシリウス時代から7年くらいのおつきあい?リンコムNextのソースが教科書かも。
外注するときはよく「できればColdFusionで・・・・」とお願いするのですが、ほとんどの場合「えっ!?」と驚かれてしまい、「SEのアサインが・・・」などと営業さんが困ってしまうことが多くて悲しいです。
ちょっとしたものなら自分でシステム構築しちゃいますが、一人でやるには時間が足りませんね・・・
FlashRemotingとかもやりますが、Flexには手を出してません。
と、最初の頃書きましたが、ついにFlexに手を出しました。Flex1.5はイマイチわかりませんでしたが、Flex2は別物ですね。これで6万円でイインデスカ?
そしてFlex2とColdFusionの組み合わせなら無敵な気がしますよ。ほんとに。
01 | 2025/02 | 03 |
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |