ユーザー境界を超えたシグナル送信
投稿: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)がシグナルを受信できます。