ルモーリン
ホーム 更新 Perl Sample サービス 雑談 鉄ゲタ Linux リンク 連絡先

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

投稿:2018-03-22

サイトのCGIから常駐プログラムへ素早く連絡したい。 ウチの場合、CGIのユーザー(Apache)と常駐プログラムのユーザーが異なり普通にシグナルを送信してもLinuxがブロックする(そりゃそうだ)。 そいつを手を替え品を替えてなんとかした。
処理の流れと共に説明していきます。
CGIからLinuxのコマンドを実行できるような奴、例えばPerlならsystem関数とか、そういうものでSignalToTargetを起動します。 例えば「system "./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を受信するか確認してみましょう。
CGIから呼べる所にコピーしてください。 え、ユーザーが違うからCGIのそばに置けない? そう、これが肝なんです。 ユーザー間を超えて移動できるのはスーパーユーザーくらいだと思うのでスーパーユーザーで移動させてください。 今時のLinuxなら他にも方法がありそう。 ややこしいのですけれど、プログラムのユーザーはターゲットのユーザーと同じです。 でも、プログラムを置く場所はCGIから呼べる所なので、パスはCGIのユーザーです。
CGIから呼んだ時に実行できるよう「chmod 505 SignalToTarget」でファイルモードを変更してください。 あれ?ユーザーの所も5にする必要あったっけ? 最後に「chmod u+s SignalToTarget」でもってターゲットのユーザー権限で実行できるようにsetuidビットを設定してください。
SignalToTargetが起動されると、ソースの通りpkillを起動してターゲットのプログラムを見つけ、シグナルSIGUSR1を送信します。
ターゲットと同じユーザー権限からシグナルが送信されていますのでLinuxはブロックしません。 これでターゲット(例ではPerlスクリプトのtarget.pl)がシグナルを受信できます。