ルモーリン
ホーム更新Perlサービス雑談ランドナーコースガイド鉄ゲタ自転車リンク連絡先

ユーザー境界を超えたシグナル送信

概要

サイトのCGIから常駐プログラムへ素早く連絡したい。 ウチの場合、CGIのユーザー(Apache)と常駐プログラムのユーザーが異なり普通にシグナルを送信してもLinuxがブロックする(そりゃそうだ)。 そいつを手を替え品を替えてなんとかした。

説明

処理の流れと共に説明していきます。

CGIからSignalToTarget(シグナル送信プログラム)を起動

CGIからLinuxのコマンドを実行できるような奴、例えばPerlならsystem関数とか、そういうものでSignalToTargetを起動します。 例えば「system "./SignalToTarget";」といった感じです。

SignalToTargetのコード

これで全部です。
#include <unistd.h>

void main(void) {
        execl("/usr/bin/pkill", "/usr/bin/pkill", "-SIGUSR1", "-f", "perl target.pl", NULL);

        return;
}
関数execlの第5パラメタは、ターゲットを「ps -Af」で表示した際のコマンドラインです。 これをgccでコンパイルして「Hello, world.」のような実行プログラムにします。 試しに「ターゲットと同じユーザーで」実行してターゲットのプロセスがSIGUSR1を受信するか確認してみましょう。

SignalToTargetの設置場所とユーザー

CGIから呼べる所にコピーしてください。 え、ユーザーが違うからCGIのそばに置けない? そう、これが肝なんです。 ユーザー間を超えて移動できるのはスーパーユーザーくらいだと思うのでスーパーユーザーで移動させてください。 今時のLinuxなら他にも方法がありそう。 ややこしいのですけれど、プログラムのユーザーはターゲットのユーザーと同じです。 でも、プログラムを置く場所はCGIから呼べる所なので、パスはCGIのユーザーです。

SignalToTargetのファイルモードとsetuidビット

CGIから呼んだ時に実行できるよう「chmod 505 SignalToTarget」でファイルモードを変更してください。 あれ?ユーザーの所も5にする必要あったっけ? 最後に「chmod u+s SignalToTarget」でもってターゲットのユーザー権限で実行できるようにsetuidビットを設定してください。

ターゲットのユーザー権限でSignalToTargetが起動

SignalToTargetが起動されると、ソースの通りpkillを起動してターゲットのプログラムを見つけ、シグナルSIGUSR1を送信します。

ターゲットがSIGUSR1を受信

ターゲットと同じユーザー権限からシグナルが送信されていますのでLinuxはブロックしません。 これでターゲット(例ではPerlスクリプトのtarget.pl)がシグナルを受信できます。