2013年11月28日木曜日

rsyslog へのログ出力:ログファイルを変更して出力

rsyslog に対するログファイルを変更してログを出力する例題です。

syslog.h (ref. http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/syslog.3.html) に記載されている LOG_USER での出力は通常コメントアウトされている場合があります(/etc/rsyslog.d/50-default.conf 内)。 これを有効化するにはコメントを外し、以下のコメントを実行します。 こうすることにより、/var/log/user.log へ openlog/syslog 関数によりログが出力されるようになります(facility にて LOG_USER を指定した場合)。

一方、別のファイルとして出力したい場合には別の設定を追加する必要があります。
openlog で設定できるログのタイプにはローカルで利用できる facility が LOG_LOCAL0 から LOG_LOCAL7 まで用意されているので、そのいずれかを利用することによりカスタムのログファイルを利用することができます(他に利用されていないことが前提)。
LOCAL5 を利用する場合には rsyslog の設定ファイルに下記の行を追加し、rsyslog を再起動します(/var/log/custom.log へログ出力する設定)。 以下の例題では、LOCAL5 へとログ出力を行い /var/log/custom.log へログを出力するための例題です。
ログの出力を細かく制御する際には、/etc/rsyslog.d/50-default.conf にさらに追加のルールの記述が必要となりますが、今回の例題では全ての出力が同じように出力される結果となります。 実行結果

2013年11月27日水曜日

ネットワークインターフェースからのIPアドレスの取得

ネットワークインターフェースを指定して IP アドレスを取得する例題です。

Linux/Android では ifconfig/netcfg というコマンドがあり popen からその出力を取得する方法も考えられますが、例題ではネットワークインターフェースを指定して、必要なIPアドレスを直接取得しています。

また、192.168.x.x などの文字列ではなく、16進数の値としてアドレスを取得しています。 実行結果

2013年11月26日火曜日

設定ファイルの入出力

適当な区切り文字(「:」、「=」 etc.)で区切られて保存されている設定ファイルを入出力する例題です。

設定ファイルから読み込まれた値は全てメモリ内に動的に確保され、設定の変更後(キーによる検索、更新、追加)、元の設定ファイルに書き出すことができる例題となっています。

区切り文字の値(例題では「 = 」)を適宜変更して利用できます。

設定ファイルは値を書き込んだものを予め準備していますが、無い場合にはファイルを作成し、SetSettings にて設定した値が SaveSettings にてファイルに書き込まれます。 実行結果

2013年11月13日水曜日

libudev による USB デバイスのモニタリング

libudev により USB に接続されているデバイスをモニターする例題です。
※ テスト環境 Linux picuntu 3.0.8+:ディストリビューションによる動作の差異はあるかもしれませんが、Ubuntu 系なら問題なく動作するかと思います。

Linux では udevd というデーモンが起動しており、/etc/udev/rules.d/ 内に記述された udev ルールに応じて、USB に接続されたデバイス毎のプロセス起動やマウント等の処理を行うことができます。

USB メモリを挿入した際に実行する処理の記述例: 一方、挿入された際の処理(ACTION=add)に対して抜かれた際の処理に関しては(ACTION=remove)、デバイスの情報が取得できず処理が実行されない可能性があります(デバイスノードからデバイスディスクリプタが取得されないのが原因かと思われる)。

そこで、挿入された際のイベントに対して起動するプロセスに対して、終了する際のイベントに関してはデバイスが抜かれた際のデバイスへのノード(/dev/usbdev2.4 etc..)を調べ、挿された際のノードと一致するかによって目的のデバイスが抜かれたかを監視する方が無難な監視方法になるかとは思います。

以下の例題では、アプリ起動時に接続されているデバイスの一覧を表示し、目的のデバイスが挿入されているかを監視しています。
目的のデバイスが挿入された際に記憶しておいたノードの情報により、デバイスが抜かれたことを検知し、デバイスが挿入されていない状態になればアプリを終了しています。

この例題をそのままアプリ化して udev ルールから実行してデバイスが抜かれた際に終了するようにしても、上手く終了されない可能性があります(exit コマンドを行ってもアプリが終了しない)。
※ 原因はよく分からないのですが、デーモン用のプロセスとして実行しないと挿入されている間は常時プロセスが起動するような形で再実行されているのかもしれません。
その場合、start-stop-daemon コマンドを利用して下記のようなシェルスクリプトにて実行するようにすれば上手くアプリを終了させることができます。
パスやユーザーを適当に編集した上、udev ルールに下記スクリプトへのパスを設定した後に udevd をリスタートしてください。
※ [/path/udevMonitor.sh start] を RUN+= に追加
start-stop-daemon はアプリをデーモン化するためのコマンドですが、インストールされていない場合にはソースが配布されていますので、そちらをコンパイルしてインストールすることもできます。
start-stop-daemon

udevMonitor.sh コンパイルには libudev を利用しますが、インストールされていない場合には apt-get から libudev-dev をインストールしてください。 実行結果

シグナルハンドラによるプロセス終了時の処理

シグナルハンドラを設定することにより、アプリに対して SIGINT/SIGHUP/SIGTERM(キーボードからの割り込み/端末との切断/終了)などのプロセス終了のシグナルが送られた際、そのままアプリを終了するのではなく、終了前の片付け処理などを行うことができます。

普通にアプリを書いていれば何らかの判定処理によって終了を行うと思いますが、デーモン用のプロセスとして処理を記述する場合などでは、kill コマンドからプロセス終了が行われるためこのような処理が必要になる場合があります。

例題では、シグナルを受け取った後メッセージを表示し(daemon stopped.)、アプリを終了させています。
コマンドラインからは kill コマンドを送っていますが、この時点ではアプリは終了せず、アプリ内で明示的にアプリを終了しない限りはアプリは継続して動作します。
一方、kill -KILL にてアプリを強制終了させた場合にはシグナルの通知に関係なくアプリが終了されます。 実行結果