Archive for 5月, 2009
TextAreaにタブをキーボードから入力したいのであるが、これがまた何もしないとできないのだ。
プログラムやらを書いているとタブが入らず、結構ストレス。
このブログの記入もタブが記入できないのですが・・・・
というわけで今回はTextAreaにタブ(Tab、いわゆる”\t” ) を記入したいということです。
TextAreaのマニュアル見ましたよ。じーーくり。
そこで気になったイベントが3つ。
- KeyDown
- KeyFocusChange
- FocusOut
もちろんタブキーが押されたら、って考えたらKewDownが素直な考えですよね。
KeyCode == 9 なら、って考えましたよ。でも、タブを入れることができても、フォーカスがなくなってしまうのですよ!!
イベントをキャンセルしても関係がないですし・・・
結局、組み合わせなければいけないのかなーーーと。マニュアルと格闘。
そしたら、KeyFocusChange
「ユーザーがキーボード操作によってフォーカスを変更しようとすると送出されます。」
と書いてあります。
あれ!?、キーボード操作によってフォーカスが変わる時って、TAB以外にあるのかな?
つまり、タブが入力されたとき?
じゃ、これだけでいいんだ。あれ、思ったより簡単!?
後は、今いるカーソル(キャレット)にタブを差し込めばいい。
あとは、TextAreaのTextFieldを操作すればよい。
この辺は、ちょうどこの問題がRichTextEditorが不満なのでつくりかえていたところなので、
そのソースを解析中だったのでわかりました。
でも、RichTextEditorで textArea.getTextField()ってやっているのに、なぜできない?
mx_internal function getTextField():IUITextField
こういうことでした。
ここで、mx_internalのNamespaceを使ってしまってもいいのですが、
ここはTextAreaの継承クラスを作成することにしました。
できた、ソースはこんな感じ
public class CustomTextArea extends TextArea
{
public function CustomTextArea()
{
super();
this.addEventListener(FocusEvent.KEY_FOCUS_CHANGE,handleKeyFocusChange);
}
private function handleKeyFocusChange(e:FocusEvent):void{
e.preventDefault();
var str1:String = textField.text.substr(0,textField.selectionBeginIndex);
var str2:String = textField.text.substr(textField.selectionBeginIndex);
textField.text = str1 + "\t" + str2;
textField.setSelection(textField.selectionBeginIndex + 1,textField.selectionEndIndex + 1);
}
}
実際にタブが押された時には、半角スペースで埋めるなんてのも後でできるようにしよと、解決できて満足です。
今から書くことは決して、メールサーバ(Postfix)を運用するためのノウハウではないのであしからず。
ただし、開発者がメール関係の開発をするときにテストとして知っておいたほうがいいとは思います。
また、サーバ系のミドルウェアに全くタッチしない人も、このような内容をしっているとちょっとはいいかもと思うこともあるかも知れません。
さて、今回のお題は「社外にメールを配信しても、実際には飛ばないようにしたい」という話です。
メールアドレスを適当に作ってしまい、それをもとにテスト配信したいのですが、実際飛んでしまっても困りますし、
でも、そのメール捨てられても困るんですよね。
さらに、贅沢なことに、一部のメールはほんとに飛んでほしいですよ。
ってことで、Postfixを使って、docomo.ne.jpとかにメールを出しても、そのサーバで受取る。ということをしたいと思います。
余談ですが・・・
その前に、あなたのLinuxにはPostfixはもしかしたら入っていないかもしれません。
でも、Redhat系ならばRPMで入っているでしょうから、sendmail を削除し、postfixをインストールしてください。
あなたが既にsendmail使いならいいのですが、postfixのほうがプログラマには向いていると思いますよ。
また、高速配信ならqmailだー!って人もいますが、あなたの高速配信ってどのレベルですか?
秒間数百通送りたい!!って人ならいいのですが、通常、日本でそんな需要はないですよ。
ちなみに高速配信するには、サーバの並列稼働が必要なのでアプリケーションレベルのみで解決はほぼできません。
だって、受け取り側が受け取ってくれないのですから・・・・
したがって、使いやすいMTAが一番。
さて、話をもどして、postfixで指定したドメインの受信をするには、
/etc/postfix/main.cf
のファイルを修正します。
| mydestination |
The mydestination parameter specifies the list of domains that this machine considers itself the final destination for. |
って、設定ファイルには書いてあります。
要するに、このパラメータで指定したドメインは、このマシンが受け取るよ。ってことです。
なので、ここの設定に、
mydestination = $myhostname, localhost.$mydomain, localhost,
ezweb.ne.jp, softbank.ne.jp, docomo.ne.jp
こんな感じに記述してしまえば、このサーバからのezwebや、docomo、softbank向けのメールはぜーーーんぶ、このサーバが受け取ってしまうということ。
あとは、
/etc/init.d/postfix restart
を忘れないでください。
じゃないと、ほんとに飛んでしまいますよ。
念のために、自分の携帯アドレスで確認してから実行してくださいね。失敗しても責任は負えませんので・・・
どうにかして、Flexで日本語フォントのみを抽出するということができないのでしょうか?
調べたのですが、どうしてもわかりませんでした。
でも、やたらと使わないフォントの一覧があってもこまります。
(ちなみに、フォント一覧をみるにはこちらから)
んー、考えたあげく、フォント名が日本語のフォントという考え方にすることにしました。
まあ、日本語フォントが日本語名になっていないということはまれでしょう。多分。
さらに、たいていの人は、複数の言語のフォントなんてないでしょうということで、
さらに、マルチバイトのフォント名は、「日本語フォント」だー。という強引な結論にしました。
まあ、ほとんどこれで大丈夫でしょう。
だめになったときに、それはそれで考えるということで、マルチバイトのフォント名一覧を作成するという命題です。
[AS]
var fontArray:Array = Font.enumerateFonts(true);
var janList:Array = new Array();
var ba:ByteArray = new ByteArray();
var cnt:Number = 0;
for(var i:Number = 0; i
ba.writeUTFBytes(ft.fontName);
if(ba.length > ft.fontName.length){
janList.push(ft);
}
ba.clear();
}
ba = null;
[/AS]
ちょっと注意点ですが、ここでbytearray.clear()を使っています。
これは、バージョンが10からですので、ご了承を。。。
私自身、なぜと思ってしまったので・・・
もっと、スマートなやり方を知っている方がいたら教えてください。
久々のflex mx:Treeのネタです。といっても、非常に基本的なことです。
Treeのアイテムを開いたり、閉じたりするには?
これ、開くには以前、flex:Treeで自動的にフォルダを展開させるには でTreeのアイテムにドラッグ&ドロップでドロップしようとしたときに、
自動的に開くようにするということで述べましたが、今回は閉じるには?を調べました。
久々のflex mx:Treeのネタです。といっても、非常に基本的なことです。
というのも、デフォルトで「閉じる」「開く」は矢印をクリックすればできるのですが、やっぱり、フォルダとして機能している場合、つまり、他のアイテムの親としてしか機能しないアイテムをクリックすると、開いたり、閉じたりしてほしいなーと思ったのがきっかけです。
だって、矢印が小さいんですもん。
最近、できるとはわかっているよりも、できるのか?できないのか?
のほうを優先してしまい、結構、基本的な部分がはて?どうやるんだ???のままでほったらかしなので。
さて、話は戻って、Treeで、「閉じる」、「開く」を実装するためには、
もちろん、「開く」、「閉じる」のメソッドが必要ですが、「今は開いているの?、閉じているの?」がわからないといけないですよね。
さて、それでは、クリックのイベントで処理をおこなうようにしましょう。
[AS]
tree.addEventListener(ListEvent.ITEM_CLICK,_fireClickItem);
[/AS]
次に、クリックされた時の処理は
[AS]
protected function _fireClickItem(e:ListEvent):void{
var tree:Tree = e.currentTarget as Tree;
var obj:Object = tree.selectedItem;
if(!tree.isItemOpen(item.selectedItem)){
tree.expandItem(obj,true,true);
}
else{
tree.expandChildrenOf(obj,false);
}
}
[/AS]
さて、閉じるときと、開くときでことなったメソッドを使っています。
expandChidrenOf(item,boolean)のドキュメントをみると
“指定したアイテムの配下にあるすべてのツリーを開くか、または閉じます。”
とあります。
すべて、開かれても困るので、開くときは、expandItemを使っていまし、
閉じるならすべて閉じたほうがいいかなと使い分けています。
この辺の動作は好みかもしれませんが、深ーいツリーで、やっぱり浅い階層のものを見るときに「閉じて」、「開く」ってことを私自身やってしまうので・・・
でも、ふつうは両方ともexpandItemでいいのでしょうね。
Windowsのエクスプローラもそうなっていることですし・・・・
AIRでアプリケーションを作成していると、アプリケーションのサイズを指定するわけだが、でも起動後にサイズを変更するわけだ。
私なんかは、ノートの場合、たいてい最大化してしまう。
しかし、大きなディスプレイのときにはそうでもなかったする。
要するにアプリケーションのサイズは前回閉じたときの大きさで再現できればより親切だろう。
こうなるとAIRのアプリケーションで閉じるときに値を保存しておかなければいけない。
保存しておくデータは、サイズと状態(最大?通常?)というデータだ。
理屈は、閉じるときに保存し、起動時に読み込み、そのサイズ、もしくは状態に変更させればいいわけだ。
さて、こうなると、サイズの取得と、状態の取得をする必要がある。
サイズの取得はWindowedApplicationのオブジェクトのwidthとheightをとればいいわけだが、状態を取るのはどうすればいいのだろうか?
実は、状態と記述しているところに訳がある。私ははじめ、「最大にした時」というのを探してしまった。こう考えてしまったために、たどり着くまでに時間がかかってしまったが、状態の変化は、以下のようにイベントでとれるのだ。
以下のように、状態が変わったときと、アプリケーションが閉じるときのイベントで処理をするようにする。
[AS]
// thisはWindowedApplicationのインスタンス
this.addEventListener(NativeWindowDisplayStateEvent.DISPLAY_STATE_CHANGE,windowStateChange);
this.addEventListener(Event.CLOSING,windowClosing);
[/AS]
これで、状態が変わったときにその状態を変数に保存しておき、アプリケーションが閉じるときに保存すればいい。というわけだ。
具体的にはこんな感じだ。
[AS]
private function windowStateChange(e:NativeWindowDisplayStateEvent):void{
this.windowState = e.afterDisplayState;
}
[/AS]
次にをアプリケーションが閉じるときのイベントだが、
[AS]
private function windowClosing(e:Event):void{
props.saveValue(“window.height”,String(this.height));
props.saveValue(“window.width”,String(this.width));
props.saveValue(“window.state”,this.windowState);
}
[/AS]
上のprops.saveValueというメソッドは私が作ったもので、実際にはここでプロパティ情報を管理するDB(sqlite)に値を保存している。
ここでは、どのような方法を使ってもいいのでローカルに保存できればいいのだが、後で値が簡単に見えるのと、変更も可能なのでテストしやすいために私はそうしただけだ。
ここまでできれば、今度は次回の起動時にこれを再現するだけだ。
再現は、WindowedApplicationにcreationComplete=”createEnd()”のように関数を登録し、
[AS]
private function createEnd():void{
this.windowState = props.getValue(“window.state”);
if(this.windowState == NativeWindowDisplayState.MAXIMIZED){
this.maximize();
}
else{
saveWidth = props.getNumberValue(“window.width”);
if(saveWidth > 0 ){
this.width = saveWidth;
}
saveHeight = props.getNumberValue(“window.height”);
if(saveHeight > 0 ){
this.height = saveHeight;
}
}
}
[/AS]
ここででも、props.getValueとprops.getNumberValueがあるが、これは保存した値を読むように私が作ったものなので、ここは各自にあった実装をしてほしい。
また、ここでは状態が最大しか考慮していないが、状態には、通常、最小、最大がある。
しかし、最小にしたいということはありえないと思うので、最大の場合だけ最大にし、それ以外は前回のサイズにしている。
これを応用すれば、それ以外にもアプリケーション特有の再現はできるとおもいますので、ますます、AIRとしての(クライアントアプリケーションとして)メリットが出せるのではないでしょうか?
GmailにPOPで接続するActionScriptを作成しているのですが、SSLではなくてはならないと知り、
Socketで作っていた部分を対応しなくては・・・と、SSLで接続できるAs3のライブラリを探しました。
as3cryptoというライブラリがありました。
まえまえから知ってはいたのですが、やっと使ってみようとおもいつかいました。
そしたら簡単です。
今まで、
[AS]
socket = new Socket();
[/AS]
としていた部分を
[AS]
socket = new TLSSocket();
[/AS]
とすれば、それで終わりです。
ただし、Socketの継承クラスではないので、御注意。
私の場合、
[AS]
private var socket:Socket;
[/AS]
としていたので、そこを
[AS]
private var socket:Object;
[/AS]
に変えました。でも、使えるイベント等の処理は同じようにかけるので大丈夫です。
前回、phpでシグナルと名前付きパイプは有用だということを書きましたが、
もうちょっと調べてみました。
やりたいことは、
1) 同時に複数の処理依頼プロセスがある。
また、処理は大量のトランザクションがあり、バッチ的に処理されるものである。
2) 処理をするのは複数ではなく1つのプロセスで行いたい。
システムの負荷やら、そのあとの処理の関係上。。。。
3) 1は、2に対して処理を名前付きパイプで依頼する。
ここで依頼方法は1行テキストで依頼します。
さて、単純に行うには問題がなかったのですが、処理の中断を考えなければいけなくなりました。
そこで、シグナルの登場です。
1のプロセスも2のプロセスも、シグナルを受け取って中断。
そこまでは簡単にできるのですが、2が中断されたことを1(依頼プロセス)が把握できなければなりません。
そこで、依頼プロセスは、以下のようにプロセスIDを処理プロセスに伝えてあげます。
こんな感じです。
[PID] < 処理開始合図>
[POD] < 処理命令>
[PID] < 処理終了合図>
これで、2(処理プロセス)も、中断したときに依頼プロセスを知ることができるので、依頼側にシグナルを投げられるというわけです。
シグナルを受け付けるのはpcntl_signalで受け付けますが、シグナルを投げるのはposix_killです。
これらを組み合わせれば、処理を投げたら、処理完了のシグナルを受け付けるまで待つということができます。
さらにPHP5.3からはpcntl_sigtimedwaitという関数があるのでそれで待つことももできるようです。
ちなみに私はPHP5.1だったので、usleepを使ってループさせましたが・・・・
ちょっとWEBプログラムをやっているだけでは使わないとおもいますが、PHPではこのようなこともできるのです。
ちなみに、このようなことをやっても秒間1000ぐらいの処理はできました。
まあ、今回逆に秒間20程度に抑えたいので同期の機能もつけたかったのですが・・・・
あっ、そうそう、処理側で名前付きpipeを読むのにstream_selectをつかいました。
これもsocketを受け付けるサーバを作っていると使うのですが、PHPでもこのような処理が作れるようになったのを実感すると、
だいぶいろいろなシーンで使えるなと実感します。
サイトのデザインを変えてみました。今まで、どこかに落ちていたテーマを使わせてもらっていましたが、
自分で作成してみました。
ちょっとスタイルが見にくいなーと思っていたのですが、ちょっとWordPressのことも勉強と思い、変えました。
とは言っても実は簡単にできました。
WordPressのテーマが作成できるソフトを使ったのです。
http://www.artisteer.com/で、いろいろな部品やらスタイルやら組み合わせれば、いいというわけです。
作ったといえば、ヘッダー画像くらい。
デザインセンスがない人や、簡単に作りたい人にはお勧めのソフトですね。
DataGridを使ってリストをカラムがうまく変更されないので、その調整をするようなクラスを作成しました。
具体的には、拡大、縮小すると一部のフィールドだけ拡大、縮小してしまうのです。
この再現方法がわからないのですが、たまに発生するのです。
あとはminWidthを設定していても、縮小するとたまに、その指定以下になってしまうと気があります。
さらに、私はその部分にresiable=”false”を指定しているので、そうなってしまうともう拡大することができないのです。
なので、この部分を強制的に再度、サイズを調整するクラスを作成しました。
動きとしては、拡大、縮小するときにそれまでの比率を保ったまま拡大、縮小されるのですが、その調整が終わった後にminWidthの指定があるものに関しては、そのサイズに再度調整しています。
実際にこの処理が行われるのは、サイズがユーザにより変更されたときと、全体のサイズ(更新が必要な時)の変更があったときのイベントを利用しています。
DataGridのカラムのサイズがユーザにより変更された時のイベントは
dataGrid.addEventListener(DataGridEvent.COLUMN_STRETCH,changeColumnWidth);
です。
はじめ、DataGridColumnのソースを見たらset width()でイベントを発行していたので、それを使えばと思いましたが、あっ、widthを変えているのだからそれじゃ、どうすれば・・とDataGridのソースを見ました。
そしたら、DataGridEvent.COLUMN_STRETCHがあったので、おお、それだと。
そして、とりあえずこんな感じ。
[AS]
package com.coltware.cise.ui.helper
{
import flash.utils.Dictionary;
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.events.DataGridEvent;
import mx.events.FlexEvent;
public class DataGridResizeController
{
private var dataGrid:DataGrid = null;
private var oldWidth:Number = -1;
private var oldColNum:Number = -1;
private var invalidateDisplayList:Boolean = false;
private var cols:Dictionary;
private var _enable:Boolean = true;
public function DataGridResizeController(dg:DataGrid)
{
cols = new Dictionary();
dataGrid = dg;
enable = true;
}
public function get enable():Boolean{
return _enable;
}
public function set enable(b:Boolean):void{
if(b){
_enable = true;
dataGrid.addEventListener(FlexEvent.CREATION_COMPLETE,create);
dataGrid.addEventListener(FlexEvent.UPDATE_COMPLETE,update);
dataGrid.addEventListener(DataGridEvent.COLUMN_STRETCH,changeColumnWidth);
}
else{
_enable = false;
dataGrid.removeEventListener(FlexEvent.CREATION_COMPLETE,create);
dataGrid.removeEventListener(FlexEvent.UPDATE_COMPLETE,update);
dataGrid.removeEventListener(DataGridEvent.COLUMN_STRETCH,changeColumnWidth);
}
}
private function create(e:FlexEvent):void{
oldWidth = dataGrid.width;
}
private function update(e:FlexEvent):void{
trace(“update …”);
if(oldWidth != dataGrid.width){
invalidateDisplayList = true;
}
if(invalidateDisplayList){
oldWidth = dataGrid.width;
for(var key:Object in cols){
var p:Number = cols[key] as Number;
var w:Number = Math.floor(oldWidth * p);
var c:DataGridColumn = key as DataGridColumn;
if(c && c.minWidth > w){
trace(“no resize col ” + c.minWidth + “>” + w );
}
else{
c.width = w;
}
}
// 最後に小さくなりすぎた resize = false のオブジェクトを戻す
for each(var col:DataGridColumn in dataGrid.columns){
if(!col.resizable && col.minWidth){
col.width = col.minWidth;
}
}
invalidateDisplayList = false;
}
else{
}
}
/**
* カラムのサイズがユーザにより変更された時の処理
*
*/
private function changeColumnWidth(e:DataGridEvent):void{
computePercent();
}
private function computePercent():void{
var w:Number = dataGrid.width;
cols = new Dictionary();
var arr:Array = new Array();
for each(var col:DataGridColumn in dataGrid.columns){
if(col.visible){
if(col.resizable){
arr.push(col);
}
else{
w = w – col.width;
}
}
}
for each(var col2:DataGridColumn in arr){
var p:Number = col2.width / w;
cols[col2] = p;
}
}
}
}
[/AS]
結構、ASDocの結果ってわかりにくいなーと思いますね。
というか、プロパティやらイベントやら、1つのクラスに多すぎるのかもしれません。
最近、見えるんだったらソースを見てしまえと、見てしまいます。
余談ですが、ここで、Flex Builderの「定義へ移動」のメニューはいいですね。
でも、それでもある程度見当が付いているときには、だらだらとみているのは面倒なのでFlex Linux版をインストールして、それで、grepを使って思いの処理がありそうか調べています。
ただ、おおよそうまくいくようになったのですが、それでもたまに最後のカラムだけが拡大・縮小してもサイズ変更されない場合があるのです。
これまた、なぜ発生するのはわからないのです。
こんな問題も、サイズ固定にしてしまえば問題ないのですが・・・
それでは使い勝手が悪いので。
でも、よくVBとかでできた製品でサイズ変更してしまうとレイアウトが崩れるのがありますが、かっこ悪いですよね。大変なのはわかりますが・・・
(と言うと、今後自分の首もしめることに・・・)
この問題はEclipseのプラグインでアプリケーションを作成していたときにはあまり遭遇しなかったのですが・・
よりUIを自由にやろうとすると、このあたりの制御がプログラマに戻ってしまい大変ですね。
さらにFlexも、ActionScriptもはじめて半年もたっていない私には基本部分の理解不足を思い知らされます。
久々にphpでサーバもどきのプログラムを作成することになった。
ここから書くことは別にphpに限ったことではないのだが、phpのプログラマたちはよく知らないことがあるので書いてみた。
ここでサーバもどきと言っているのは、WEBサーバのようにデーモンとして起動し負荷なども十二分に考えなくてはならないものでもないが、かといって、バッチよりもリアルタイムの処理をしたい場合という場合のプログラムだ。
たとえば、あるトランザクション処理があるが、それを来た順に処理をしていきたいという場合。でも、サーバが忙しければ時間がかかってもいいし、でも、なるはやで処理してなんて場合。
たとえば、レポートシステムなんかはそれに値するだろう。はじめは、WEBでリクエストがあった時にその場で記録・計算をするのだが、リクエストが多くなるとそうもいかない。
また、サーバの役割の分担なんかも考えるとレポートシステムだけ別サーバでひたすら計算、レポート作成をやらせるなんて感じかな。
このときに、よく見かけるのが、CSVファイルを作成してそれをレポートサーバに送り、cronで計算なんて感じだ。
これだと、レポートに時間がかかりすぎた場合などに重複して処理がされないようにとか・・・・
CSVファイルをどうやって転送するか( SCP,FTP ? )。でも一番多いのがNFSなのかな。などなど、いろいろと考えることが出てくる。
こんな時に使えるunixな環境は・・・
名前付きpipe
と
syslog
だ。
phpでは名前付きpipeはposix_mkfifoで作れる。
別に最初に作ってしまえば、プログラムで作るほどでもないが、読み書きはいつもどおりfopenだ。
これが結構使える。
まず、作成した名前付きパイプ(プログラマからは単なるファイル)に対してプログラムで、書き込むほうと読み込むほうを作成する。
そうすれば、それらのプログラム間の通信ができる。
しかも、だいたい読み手は一つにし、書き手を複数にしても排他ができているのでさらに便利だ。
キュー型のトランザクションを簡易的にすぐに作れる。
これで、cronで処理をしなくてもずーーと処理を回していればいい。
書き込みがなければ、まっているだけだ・・・
さて、書き込みのほうだが、WEBのレポートをする情報をphpでsyslogに書けばいい。
syslogでレポートサーバに飛ばせば、scpも、ftpもいらない。
さて、先ほどの名前付きパイプとsyslogを挙げたのは、この2つを連携することにある。
syslogではsyslog-ngという別のsyslogデーモンがあり、これは出力を名前付きpipeに書き込めるのだ。
これで、あるサーバが出力したトランザクション処理をべつのサーバが受け取って処理をしていくというサービスが簡単に作れる。
しかも、ほぼリアルタイムだ。
この「ほぼ」というのがシステム運用をするようになると非常に助かる。
だって、忙しい時はサーバの負荷を高めず、遅れるということができるのだから。
さらに、入力ファイル名が1つでいいということは非常に重要だ。
これのおかげでよりプログラムが単純になるのだ。
余談だが、ある会社のシステムを見たら、なぜかsystemのCPU負荷が90%を超えるようなプログラムを作っていたが、
こんなプログラムは売らないでほしい。しかも、原因を言っても理解できないと来ている。
(言語はJavaを使っていたのだが、Javaのせいじゃないかといってきかない。だから、Javaでおかしなことをしているからだろーー!。
動かぬ証拠を突きつけても、その証拠の意味が理解できない会社があるので要注意だ。こういうエンジニアがいるせいでJavaエンジニアは信用できないという人がでてきてしまうのだ・・・)
さて、 次はシグナルだ。
プログラムを途中で中断したい場合があるが、安全に中断したい。
メール配信などを作っていればよりそんな必要性がある。
これもプログラムしか知らない人がつくったものをみると、中断ファイルなどを作って、それを見る仕様になってしまっている。
Apacheだって他のプログラムだってシグナルで処理に対して安全に停止、再起動などをするのはシステム運用者から見れば普通だ。
だったら、その普通に合わせるのがいいプログラムってものだろう。
phpのシグナルの処理のしかたはマニュアルを見ればわかると思う。
while文でループしているところに、シグナルでループを止めるようにすれば安全に止まるように作れる。
これであれば、中断ファイルが消せなかったらとか、排他処理とか・・・も考えなくていいだろう。
さらに、シグナルを使うのであれば、そのプログラムが動いたときのプロセスIDファイルを作ったほうがいい。
だいたいのサービスはこのプロセスIDファイルがあるのに、プロセスがない状態ならばおかしな状態で落ちたよ!って起動時に出力され、
問題なければ、このファイルを消して起動して!ってメッセージが出てくる。
こんな感じで環境全体を考えよりサービスレベルにあったプログラムを作っていきましょう。


