Log4cppでログファイルをローテーションする

プログラム開発でログの出力を行いたいと思います。
今回はC++のプログラムで実装してみます。

まず、なんで今更Log4cppについて記述しようと思ったか説明します。
log4cppのサンプルや記述はネット検索ですぐに見つかります。
でも、上位で検索されたサンプルには間違いがそのまま残されていて、実際に動かしてみるとローテーションは行われませんでした。
また、注意深く見てみると、設定のパラメタすら間違ったままになっているのです。
私は、そのWebサイトの間違いに過去引っかかり、無駄な時間を費やしました。なので、そんな無駄な時間を今後費やすことのないように、ここに記述します。
そちらのサイトを批判するつもりはありませんので、当該サイトのURL等については記述しません。
なお、ここの記載内容に間違いがあった場合には、お手数ですがご指摘して頂けますようお願いします。
こちらのサイトを参考にされる方には、コメント欄に指摘されている内容も含め参考にされることを期待します。
なるべく、修正は行っていくつもりですが・・・将来のことなので、ご注意ください。また、Web上の情報は参考情報です。ご利用に際しては、ご自身の責任でご利用ください。

環境

今回実装を試したのは以下の環境です。

OS:CentOS 7.4
gcc バージョン 4.8.5

 

パッケージインストール

 

プログラム

 

設定

ファイルサイズを102400バイトまでとする。
ログは最大8世代まで残す。

ざっとこんな感じ。

コンパイルは以下のコマンドで行う。

 

CentOS 7 NTP設定・・・ちょっと待て!?

こんな感じではじまった

CentOS 7で時刻同期を行おうとNTPの設定を行った。
デフォルトでインストールされているだろうと思い込んで進んだのだが、ntpdが無いではないか!?

そんじゃ・・・ということでyumにお願いしてインストールしてsystemctlをstartとenableやって、ntpqコマンドで動作確認。。。。おっ!動いた!OK(^^♪

と思ったよ!!俺でもこれくらいは出来るぞ!と、思ったよ!

しばらくして、マシンの再起動なんかもして、翌日ntpqで時刻同期はどうなってるかなぁ~なんて、楽しみに見てみたら・・・・

あれ?動いてない?systemctl enable ntpdを忘れてたの?
と再度実行して、再起動してみたものの同じ現象やん!?

やばい!いつも簡単な設定だから適当決め込んでいたのだが、不味い!!((((;゚Д゚))))ガクガクブルブル

ググったら出てきた。CentOS 7からntpdは標準ではなく、代わりにChronydが標準になったのが原因だった。
当然、デフォルトで設定されてたよw

と言うことで本題!

でもって、/etc/chrony.confを開いて以下の部分を適当に変更。

不要なサーバ設定を削除して、必要なサーバを指定(IPは適当なものに置き換えてください)して、再起動したらOKでした。

こんな感じで再起動

ちなみに、

確認はやらなくちゃ!

更に確認方法は・・・

こんな感じで表示されたらOKらしい。(表示されているのはデフォルトの状態で試した時です。)

ほんま焦りますわ(^^♪

ついでにちょっとだけコメント

ちなみに、サーバとして動作させるには、/etc/chrony.confの以下の部分を設定してあげる必要があります。

allowする相手のネットワークを必要に応じて記載することが必要です。

サーバとして動作させる必要が無ければ、この状態でOKです。

ちにみに設定変更を行ったら、サービスの再起動を行うこと!

自動機能もデフォルトで設定されている様ですが、どうしてもやりたい人は、systemctl enableで実施してください。

chronydは嫌だぁ~!って人は、chronydをdisableしてntpdを設定してあげれば良いそうです。

 

プロセスの監視と再起動(monitを使ってみる)

前回はdummyプログラムを用いたサービスの登録方法について説明しました。
今回は、その登録したサービスを監視し異常発生時の再起動を自動的に行いたいと思います。

dummyプログラムは、TCP/IPによる通信を行うサーバ側のプログラムです。
ポート番号10050を使用してクライアントからの接続を待っています。

そのdummyプログラムが異常終了しゴースト化してしまっていたり、プロセス自体が動作していない状態(psコマンドで見つからない時)に、自動的に再起動を行わせます。

準備

プロセスの監視には色々と方法がありますが、今回はmonitを使用します。

monitのインストール

まず最初に、epelリポジトリをインストールします。
デフォルトではインストールされていないので、準備します。

続けて、monitをインストールします。

これだけです。

monitの初期設定

色々と他のサイトでも紹介されている様なので、今回は細かな設定については割愛します。
私がやったことは、以下の通りです。

1)monit.confの設定変更

/etc/monit.confもしくは/etc/monitrcの記述内容を編集します。

当該ファイルの一番下にこんな記述があります。

このままでは、/etc/monit.d/にある全てのファイルがインクルードされることになります。
/etc/monit.d/には各監視対象毎の設定ファイルが置かれることになります。
そこで、以下の様に編集しました。

/etc/moni.d/*.confとすることで、拡張子が.confのファイルだけが対象となります。
この設定を行う場合には、以下の作業も忘れずに行って下さい。

初期状態では、/etc/monit.d/にあるファイルはloggingだけになっています。

loggingファイルをlogging.confにコピーします。ファイル名の変更でも構いません。

これでmonitが動作する環境設定は準備出来ました。
それでは、monitをサービスとして起動します。

OS起動時に自動起動させるためには更に以下のコマンドを実行する。

これで監視が行われる状態になっています。
でも、監視対象が何も指定されいませんので、以下でdummyサービスの監視を行います。

プロセスの監視

前回の設定ではサービスとして登録しましたが、ここでは敢えて単独のプロセスとして監視対象にしました。
サービスとして登録した場合の方法については、別途記載しています。
サービスと登録している状態で、この方法を取ることはお勧めできません。
方法が異なる起動方法によりプロセスが再起動する可能性が発生し、管理上良くないからです。
この方法を採用する場合には、サービスとしての登録は行わない方が賢明です。monit単独で利用されることが望ましいと判断します。この方法とサービスでの起動を両方採用することは、二重起動を引き起こす可能性を含んでいます。
多分、プログラムは正常に動作しますが、異常が発生した場合に何が原因なのか特定することが困難になる気がします。

/etc/monit.d/dummy.confを以下の内容で作成します。

1行目:監視対象を指定します。
2行目:起動方法を指定します。
3行目:終了方法を指定します。
4行目:異常時の処置を指定します。今回はポート10050を使用しており、10050ポートが開いているかどうかを確認しています。
5行目:10回再起動をトライしてダメだったら再起動を取止めるという内容で、再起動の試行回数を指定しています。

後は、monitに設定を読込ませれば完了です。以下のコマンドでmonitに設定内容を読込ませます。

以上で完了です。
監視状況を確認するには以下のコマンドで確認出来ます。

 

サービスの監視

サービスの監視も基本的には同じです。

設定ファイルが以下の通り変更になりますが、実際には同じでも大丈夫です。
サービスとして登録する方法は前回を参考にしてください。

プロセスと異なり、systemctlを使用して起動と停止を行っています。
起動時にsystemctlコマンドを使用することで、サービス側との二重起動が避けられます。PIDはSystemd側で管理されていますので、Systemdを経由した起動の方が都合が良いわけです。
dummyプログラムのPIDを調べれば解ることなので、pkillやkillを使用して停止させることも出来るのですが、Systemd側における管理が煩雑になることを避ける意味から、systemctlコマンドを使うことになります。

サービス登録をしてRestartによる再起動を行った場合は、ポートの状態までは監視してくれませんでしたが、monitを使うことでポートの監視を行える様になっています。
ただし、固定のポートアドレスをハードコーディングで行う必要があるため、ちょっと使い勝手が良いとは言えません。

尚、この場合にはサービス登録側の設定も少し変更した方が良いでしょう。

こんな感じになります。

 

プロセスとして登録した場合とサービスとして登録した場合を敢えて記載しましたが、monitだけで十分では無いか?と考えると思います。通常はmonitだけで十分だと私も思います。

サービスとして登録する意味があまりある様には思えません。

敢えてサービスとして登録する意味はと言えば、一意のファイル名でプログラムが作成されていれば良いのですが、同名の実行ファイル名でプロセスが起動する様な場合には、サービスにしておく意味がある・・・と言うことぐらいでしょうか?

更に突っ込んで!monitが死んだら?

サービスで登録した場合でもプロセスとして登録した場合でも同じことなのですが、monit自体が死んでしまったら、プロセスを再起動することが出来ません。

CentOS 7では、UpStartの設定に従来の/etc/initが使えません。

ということで、/usr/lib/systemd/system/monit.serviceを変更します。

Restart=alwaysを追加しただけです。

これで、自動的に再起動を行ってくれます。

 

 

独自コマンドのサービス登録(CentOS 7)

今回は、CentOS 7上で自分で作ったプログラムをサービスとして登録する方法について説明します。

CentOS 6までとは管理の方法が異なっているため、ご注意ください。

環境はCentOS 7です。

今回のお題は

独自に作成した常駐プログラムをサービスとして登録します。
仮に、dummyというプログラムをサービスとして登録します。
dummyプログラムは単体で動作する時、常に動作状態を維持し障害や何らかの人為的操作以外で停止することが無いプログラムであると仮定します。
なんか難しく書きましたが、要は異常がない限り動き続けるプログラムを準備します。
それをサービスとして登録します。

サービス登録内容の記述

サービス登録を行うためには、設定内容をファイルに記述する必要があります。
そのファイルは以下のフォルダーへ保存します。

試しにdummyプログラムをサービスとして登録する場合の記述内容を以下に記します。

[Unit]ではこのサービスに関する説明を記しています。
Descriptionで簡単な名前を登録します。

[Service]では、以下の内容を登録しています。
Restart:always・・・サービスが停止していた場合に自動的に再起動を行います。
StartLimitInterval=60・・・①
StartLimitBurst=5・・・・・②

StartLimitInterval中にStartLimitBurst回の再起動を試みますが、それが失敗した場合には、次のStartLimitInterva時間は再起動を試みません。という設定になります。

PIDFileはPIDを出力する先を示しています。
ExecStartはコマンドの起動方法です。
ExecStopはコマンドの終了方法です。

[Install]
WanterByでは、OSの起動のセッションを指定しています。
multi-user.targetはinit 3の起動時に相当します。
他にgraphical-user.targetなどを指定することが可能です。
multi-user.targetを指定した場合、graphical-user.target時にも起動されます。これは、graphical-user.targetがmulti-user.targeをベースにしているためです

上記の設定では、プロセスが起動できない状態が発生した場合、永遠に再起動が繰り返されることになります。

また、プロセスがゴースト(defunct)になってしまった場合に、プロセス自体が残るため再起動が行われない可能性が残ります。
そういう意味では、少し問題を抱えていると思っても良いでしょう。

この解決方法については、別途説明したいと思います。

サービスの起動と終了

サービスを起動するには、通常通り以下のコマンドでサービスを起動します。

終了させるには、以下のコマンドです。

startもstopも基本的に何もエコーバックされてこないのでstatusで確認を取るのが賢明でしょう。

startさせた後に、OS起動時の登録を行う場合には以下のコマンドを実行してください。

disableすれば起動時の登録は解除されます。

課題

Systemdで登録したサービスの再起動には、先に述べた通り、プロセスがゴースト化してしまったり、何らかの異常が発生して実際の動作を行っていない場合の対処法がありません。
そんな時には、サービスとしての登録だけは行い、monitなどのプロセス監視を併用すると良いかと思います。

次回は、このDummyサービスをmonitを併用したプロセスの自動再起動をやってみようと思います。

 

WordPressを更新したら、Adsenseが消えた( ゚Д゚)

一か月以上更新をさぼっていたブログ。。。。いつものことですが(^^ゞ

さてさて、見ていて解ると思いますが、ここのブログサイトはほとんど何も手を加えておらず、テーマもそのまま使っている状態です。

ということで、何も気にせずにデフォルトのテーマにAdsenseのコードだけを埋め込んで使っていたんですw

で、更新したら広告が出ていない・・・それもしばらく見ていなかったから、なんで?となっちゃうわけでwww

いや~お粗末!

ということで、同じようなことやってる人が居るだろうということで書いときます。

テーマをデフォルトのままカスタマイズして使っていると、テーマを更新した時にカスタマイズ内容が消えてしまうということです。

と言うことは、バックアップして・・・じゃなくて、コピーして使っておけば良いわけです。

と言うことで、コピーしちゃいましょう!

まずはWordPressをインストールしているディレクトリへ移動して、更に以下のコマンドでテーマが保存されているディレクトリへ移動します。

themesディレクトリには、各テーマのディレクトリが存在します。
その内、カスタマイズを行いたいテーマのコピーを作ります。

上記のコマンドのtheme_nameは対象となるテーマ名を指定してください。私の場合は「twentyfourteen」としました。コピー再帰には「twentyfourteen-clone」を指定しました。
-p は、コピー元の日時を維持してコピーします。
-rは、ディレクトリ毎再帰的にコピー素行います。

普通ならコピーはこれでおしまいなのですが、同じ内容のテーマが2つ存在してしまうことになって、少し面倒です。

そこで、テーマを管理している内容を少しだけカスタマイズしてしまいます。

先程作ったテーマのフォルダーにあるstyle.cssを編集します。

twentyfourteenのクローンを作ってみたのですが、内容はこんな感じです。(2行目と7行目だけ少し変更しました。)

一応、「Theme Name」だけでも変更しておくと良いでしょう。

これで終わりです。
テーマを見てみると新しく作成した「XXXX-clone」のテーマが選択できるようになっているはずです。

このクローンテーマを使ってカスタマイズしておけば、テーマの更新でカスタマイズ内容が消えてしまうことのないはずです。

私の場合は、再度Adsenseのコードを取得し直して、header.phpにコードを割り当てて完了でした!すでに承認が下りていますので、すぐに広告が表示されると思います。

ただ、クローンで作成したテーマは更新が行われないことに注意しましょう!
セキュリティ的な観点からも、そのままクローンを使い続けるのではなく、クローン元のテーマが更新された際には、そのテーマ元に更新を行うことが必要です。
テーマの更新が行われるたびに、毎回同じことを行わなければならないというのが課題です。
うーん・・・・何か良い手はないものだろうか?
何方か、良いアドバイスを頂けると幸いです。
私も気が付いたら、何かやってみようと思います。

以上

R 指数表示回避でoptions(scipen )は大丈夫か?

Rを使っていて、大きな数字が指数表示になってしまうことを避けたいということがあります。

今回遭遇したのは、13桁の整数値です。

実際に試したのは、9223372036854775807(19桁)の数字。

符号付き64ビット整数の最大値です。

結果はこんな感じです。

1の位が変ってしまっています。

試しに、scipen=1000とかにしてみました。

やっぱり駄目でした(^^ゞ

一けた削ってみたら。

おいおい(一一”)

ということで限界を確認することにしました。

2の53乗〜54乗の間に限界がありそうです。

2の53乗が限界なのかな?
double 64ビットで表現できる数値の限界は、

±5.0e−324 から ±1.7e308
ですが、有効桁数は15〜16桁となっています。

そこから類推すると、内部で64ビットのdoubleで数値を持っているからなのかも知れませんね。

ということで、options(scipen = ???)はとても大きな数字を扱う時には注意した方が良さそうです。

 

 

地図タイルの404エラーで文句を言われた時の対策

地図タイルを扱っていると、セキュリティ関係の方から、こんなことを言われることがある。

「大量のアクセスが発生していて、エラーがたくさん出ています。」
「攻撃されているんじゃないか?」

待て!
アクセスしている方向は、内部から外部への閲覧であり、そのエラーは外部のサーバへアクセスして、外部のサーバに存在しないファイルがたくさんあるということであり、方向が逆だろう!

と、まあこんなことです。

Web地図では、タイル配信されている場合に必要な領域だけタイル画像を作成ます。
例えば、日本の領域だけに限った地図タイルを作成した場合、日本以外の地域におけるタイル画像は存在しない為エラーが発生します。

地理院地図の西之島関係のレイヤを表示してみると、ほとんど404エラーが出っぱなしですw

プログラム上で404エラーは無視する設定を行っていますので、ブラウザで見る限りにおいてエラーは見掛け上発生していませんが、デバッガーで見てみると404エラーが大量発生しているのが解ります。

本題に戻ります。
セキュリティ担当者の勘違いも甚だしいと怒りを感じつつ、「このどド素人が!」と憤慨しても相手は遠い存在であり、面倒ですよね。

こんなこと遣りたくないんですよ。
理解してもらえる人はやらない方が良いのですが・・・・
でも、止むを得ず対策を講じなければならない時があったら、以下を参考にしてください。

画像が無いところは、透過状態な訳ですよね。
透過状態のファイルを無い時に送ってあげれば良いんですよね。

ということで、まずは透過画像を作成しました。
以下の画像を作成しました。

←ここに画像があります。

解らない人のために、ここからダウンロードできます。

そして、公開しているデータの存在しない番号に名前を変えてコピーしまくる・・・・・・嘘です(-_-メ)

次に、以下のファイルを作成します。

.htaccess

webmap_dirは、実際にalpha_plane.pngを保存した場所を指定してください。
ドメインは必ず指定してください。ドメインを指定しないと、代替画像へのリダイレクトを行いますが、404エラーは発生してしまいます。
ドメインを指定すると404エラーは発生しなくなります。

この.htaccessファイルを地図タイルのあるディレクトリの最上部においてあげることで404エラーを回避することが出来ます。

 

 

QTiles/QMetaTiles Pluginで作成したタイル画像の要らない部分を削除する

QGISでタイル作成したタイル画像で不要なタイル画像を削除する方法をまとめました。
透過のみのタイル画像というよりも、1カラーだけのタイル画像を削除する方法になっています。
厳密に透過画像のみを削除したい場合には、identifyの出力内容を調整する必要があります。

QGISで簡単にタイル画像を作成しようと思って、QTilesやQMetaTilesプラグインでタイルを作成したまでは良かった。

おぉ~!タイル画像が出来てるではないか!!

と、意気揚々で「次はこれ作ってぇ~!」とかお願いしていたら・・・・
やたら時間は掛かるんだけどねw

で、しばらくお願いして放置していたら・・・

「なんかエラーが出て、出来ません。」との連絡が。

なんで?

見てみると、ディスクがパンパン(爆)

よく見ると、タイル画像が重すぎて一杯やないですか!

でも部分的に削除すると言っても・・・・と悩みながらも、透過しているだけのタイル画像は必要ないわなw

どうやって判定しようかなぁ?

ちょうど、そのWindowsマシンには下記のツールが入っていた。

  • ImageMagick
    Linuxで画像弄るなら必須アイテム。Windows版も当然ある。
  • Gow
    Linux風のコマンドを使えるようにするツール。

で、使ったのがこんなコマンド

identify

今回扱った画像には以下の条件がある。

①PNG画像
②1つのタイル画像に含まれる色は、対象物があった場合は2色以上になる。
③対象物が無い場合は透過のみとなるため、1色のみになる。

上記を整理すると、「単色のpng画像は不要」ということになる。

で、どうやってそのリストを作って削除するか・・・・

まずはWindowsでやってみた。
以下のバッチファイルを準備する。

Gowを入れると、xargsやsedなどLinux標準のコマンド類が使える様になります。sedのみを使いました。
xargsを使って渡せば簡単じゃないか!と思われますが、これがWindows側の「|(パイプ)」とxargsの相性が悪く、受け渡す標準出力を溜めこんでします様です。
その為、大量のファイルを扱う場合には、ファイルのパスがバッファに積まてしまいエラーが発生するという問題を解決出来ませんでした。

使い方はこんな感じです。

タイル画像のあるフォルダーの根元に移動してから、この以下のコマンドを実行します。

①で削除対象ファイルの削除用コマンドをrun_del.batファイルへ書き出します。
それを②で実行する。

それだけですw

せっかくここまで読んで頂いたのに済みませんが、時間にメッチャ余裕のある方や、タイルファイル数がそれ程多くない方はこれでも全然OKです。
でも、タイル数が数十万とか数百万とかになってくると、Windowsのコマンドプロンプトは使い物になりません。
Power Shellを使え?とか言わないでください。信用してませんからw

で、仕方が無いのでLinuxにファイルをコピーしてから同じことをLinux上で実施して、結果をダウンロードしてくることにしました。

下手すりゃ、ファイル共有掛けて実行してもそこそこLinuxの方が速いかも知れないのですが・・・・

確実に速かったのでこれにした。

まずは、全てのファイルを圧縮しようと思うのですが、7zを使いました。

とは言え、数百万ファイルのファイルを圧縮するには相当な時間が掛かりますし、纏まったファイルの容量もデカくて取り扱いが不便です。
こまめに分けました。

それぞれのフォルダー毎に圧縮ファイルを作成します。

これでフォルダー単位の圧縮ファイルが作成されます。

圧縮ファイルをLinuxに転送します。

転送したファイルを今度はLinux上で解凍します。

次に、以下のコマンドで透過(1つのカラーだけ)のファイルを削除します。

Windows環境でやる何倍も速く実行できます。

 

 

 

OpenSceneGraph コンパイルエラー jas_math.h

OpenSceneGraphのコンパイル中にエラーが発生した。

エラー内容は以下の通り

調べてみると、どうも/usr/include/jasper/jas_math.hに問題があるらしい。

jas_math.hファイルを一部修正することで解決するらしい。

修正内容は以下の通り。

89行目あたりの以下の部分を修正する。

こちらが修正前

こちらが修正後

 

これでコンパイルが通るようになった。

焦った〜(^^;

OpenSceneGraph インストールのyumまとめ!

OpenSceneGraphのインストールで各種パッケージをインストールするのは大変です。
対象OSはCentOS 7です。

一つ一つパッケージを確認しながらインストールしていると、何時間掛かることでしょう?

ということで、私がインストールしたyumコマンドを以下に記録しておきます。

まとめてインストールする手順を以下に記します。
前提として、gccやqtが入っていることとしますが、入っていない人のためにこんな感じです。

epel リポジトリをインストールします。

つづいてnux-dextopをインストールします。
ffmpeg関連のインストールを行うための下準備です。

そして最後に以下のコマンドで一気にパッケージをインストールします。
個人個人の好みに合わせてインストール対象を調整してください。

概ね必要そうなライブラリは全てインストールしたつもりです。

これで大分楽になるはず!

あとは、OpenSeceneGraphのソースをダウンロードして、通常どおりにコンパイルとかやれば概ね大丈夫でしょう!

では、ソースをダウンロードします。
今回は、Stable Releaseを利用します。
下記URLでダウンロードします。

http://www.openscenegraph.org/index.php/download-section/stable-releases

gitでインストールするなら、適当なディレクトリへ移動してから以下のコマンドを実行します。今回は、/homeで作業を行うことを前提にします。(cd /home で移動してください)

これで/home/OpenSceneGraphが出来上がっています。
ccmake-guiを起動します。

ccmake-gui画面で、「Configure」やって「Generate」を行います。
※エラー内容には注意すること。
※EXSAMPLEを必要とする場合には「BUILD_OSG_EXAMPLES」をチェックすることを忘れずに。

これで準備は完了!山は越えました!!
構築に入ります。

これで構築は完了しました。
データなどを揃えてお試しください。

足りないライブラリとかパッケージがあれば、どなたかコメントしてください。

このコマンドを書き換えて楽になりたいです(^^;

インストールの詳細は以前に書いた下記の内容をご確認下さい。

OpenSceneGraphをLinuxへインストールする。

OpenSceneGraphをLinuxへインストールする。(2回目)

 

 

気になる技術の使い方を記録しています。マニアックなところもあると思いますので、ご利用は自己判断で。