2

サーバー上で実行されるshスクリプトがあります。別のスクリプトから開始するnohupので、セッションを簡単に閉じることができ、それでも実行されます

メインスクリプト(これを開始します)もshスクリプトです。そしてそれは2つのパラメータで実行することができます:

--start (will start application)
--stop (will stop it using kill PID)

ただし、アプリケーションは私が起動するため、他の(rootを除く)インスタンスの実行を停止したり、再起動したりすることはできません。

だから私は所有者をに変更することについてもっと考えていましたnobody。それはそれを助けますか?はいの場合、どのようにそれを行うことができますか?

4

5 に答える 5

4

殺されるまで実行するのではなく、何らかのイベントでスクリプトをシャットダウンするようにスクリプトを設定します。次に、メイン スクリプトがそのイベントをトリガーするようにし--stopます (イベントは、特定のファイルを作成するような単純なものでも、スクリプトが定期的に読み取る fifo にコマンドを書き込むような複雑なものでもかまいません)。このようにして、他のユーザーは、誰がスクリプトを開始したかに関係なく、スクリプトをシャットダウンできるはずです。

これを行う方法は、スクリプトの詳細によって異なります。シャットダウン条件自体をチェックできるループがない場合は、定期的に条件をチェックし、満たされたときにその親 pid を強制終了するバックグラウンド プロセスを生成するようなことができる場合があります。

于 2012-11-28T14:19:06.083 に答える
2

所有者をに変更するnobodyことはもちろんあなたの目的に役立ちます。以下に、ユーザーには見えない専用のヘルパープログラムを使用してこれを行う1つの方法を説明します。

解決策: setuidプログラムを使用して、スクリプトが常に同じユーザーとして実行されるようにすることができます。セキュリティ上の理由から、シェルスクリプトをsetuidにすることはおそらく許可されていませんが、Cで簡単なランチャープログラムを作成することはできます。

#include <stdio.h>
#include <unistd.h>

#define PROG "./daemon.sh"

int main(int argc, char** argv)
{
    char action[32];

    if (argc < 2) {
            fprintf(stderr, "Usage: %s { --start | --stop }n", argv[0]);
            return 0;
    }

    snprintf(action, sizeof(action), "%s-the-real-thing", argv[1]);
    return execl(PROG, PROG, action, (char *)0);
}

ここでは、スクリプトに名前が付けられdaemon.shており、スクリプトを実行するのと同じディレクトリにあると想定しています。フルパスを使用することも、必要に応じて他の明白な方法で変更することもできます。

次のようにsetuidをコンパイルして作成します(ここで名前launcher.cを想定し、として実行することにしましたnobody):

$ gcc -Wall launcher.c -o launcher
$ sudo chown nobody launcher
$ sudo chmod u+s launcher

シェルスクリプトデーモンプログラムを少し変更する必要があります。

#!/bin/sh

prog=$(basename $0)

start()
{
    i=0
    while :; do
        i=$(expr $i + 1)
        echo "Daemon working like a mad horse... ($i)"
        sleep 1
    done
}

stop()
{
    pids=$(ps axu | grep "$prog.*--start" | grep -v grep | awk '{print $2}')
    echo "Killing [$pids]"
    [ -n "$pids" ] && exec /bin/kill -KILL $pids
}

case "$1" in
    --start|--stop)         exec ./launcher $1;;
    --start-the-real-thing) start;;
    --stop-the-real-thing)  stop;;
    *)                      echo "Bad argument \"$1\"";;
esac

ここでstart関数は、関数を呼び出してプログラムを強制終了するまで、すべての興味深いファンクが実行される場所stopです。killこれをどこからでも実行するには明らかな変更が必要です。既存のロジックがより洗練されていることを願っています。

使用法は以前のようです:

./daemon.sh --start
./daemon.sh --stop

説明:上記は、./launcher --startまたは./launcher --stop、それぞれ実行されます。これにより、有効なユーザーがnobody(またはプログラムをsetuidするために選択したもの)に変更され、またはいずれ./daemon.sh --start-the-real-thing./daemon.sh --stop-the-real-thingを実行して、目的の元のアクションを実行します。

単純なランチャープログラムでは名前付きスクリプトの実行しか許可されていないため、セキュリティの制御は簡単です(念のため、ランチャープログラムがargv[1]実際に--startまたはであるかどうかを確認して--stopから、正確に2つのコマンドラインの組み合わせをとして実行できます)。

于 2012-11-29T12:07:15.483 に答える
2

特にこのスクリプトを実行するためのユーザーをセットアップします。

そして、次を使用してスクリプトを実行します。

su -l <user> -c "<command>"

アップデート:

この種のアプローチを提案することは、問題のスクリプトを変更することはオプションではないことを前提としています。

于 2012-11-28T13:29:01.040 に答える
-1

以下のオプションを試すことができます:

  1. 他のユーザーによって開始されたクライアント プロセスが通信できるTCP ソケットをプロセスに作成します。
  2. ユーザーから、別の TCP サーバーを起動します。このサーバーは、TCP 経由でいくつかの限定されたコマンド セットを受け入れることができます。そのサーバーは、任意のユーザーからの daemon-shutdown コマンドを受け入れることができます。そのプロセスは、メイン プロセスに対して kill コマンドを発行できます。
  3. すべてのユーザーが書き込み可能にすることができる名前付き fifo を作成します。その fifo から読み取ろうとする子スレッドを作成します。本質的に、fifo 読み取り呼び出しは呼び出しをブロックしているため、そのスレッドはスリープ状態を維持します (& は CPU を消費しません)。他のユーザーがその fifo に何かを書き込んだ後、スレッドが起動し、親スレッドを正常に終了します。
  4. 上記と同じですが、待機しているスレッドは、同じユーザーによって開始された別のプロセスの一部です。そのプロセスは、ウェイクアップすると、メインプロセスを強制終了します。

私の意見では、3 番目のアプローチは 3 つの中で最もクリーンなアプローチです。

編集:「メイン プロセス」は実際にはシェル スクリプトであるため、「スレッド」はサブシェルに変更されます。&待機する子スレッドは単純な「cat fifo」になります。

于 2012-11-29T09:09:56.543 に答える
-2

root アクセス権がある場合は、root として引数sudoを使用してスクリプトを実行できるようにそれを使用および構成できます。--stop

于 2012-11-23T16:41:50.340 に答える