2

我有一个sh在我们的服务器上运行的脚本。它nohup从另一个脚本开始,以便我可以轻松关闭会话并且它仍然运行

主脚本(将启动这个)也是一个sh脚本。它可以使用两个参数执行:

--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

设置一个用户,特别是运行这个脚本。

并使用以下命令运行脚本:

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

更新:

提出这种方法的前提是修改有问题的脚本不是一种选择。

于 2012-11-28T13:29:01.040 回答
2

将所有者更改nobody为当然会帮助您实现目标。下面描述了一种通过使用对用户不可见的专用帮助程序来执行此操作的方法。

解决方案:您可以使用 setuid 程序确保脚本始终以同一用户身份运行。出于安全原因,您可能不允许将 shell 脚本设置为 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 如下(假设这里是 namelauncher.c并且我们决定运行 as nobody):

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

您需要稍微修改一下您的 shell 脚本守护程序:

#!/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的函数是所有有趣的 funk 完成的地方,直到你通过调用stop函数杀死程序。从任何地方运行它都需要进行一些明显的更改,我希望您现有的kill逻辑更加优雅。

用法和以前一样:

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

说明:以上将分别执行./launcher --startor ./launcher --stop。这会将有效用户更改为nobody(或您选择设置程序的任何用户),并执行其中一个./daemon.sh --start-the-real-thing./daemon.sh --stop-the-real-thing哪个将执行所需的原始操作。

因为简单的启动器程序只允许运行命名脚本,所以安全性很容易控制(只是为了确保您可以检查启动器程序argv[1]确实是--start--stop,那么恰好两个命令行组合可以运行为 )。

于 2012-11-29T12:07:15.483 回答
-1

您可以尝试以下选项:

  1. 在您的进程中创建一个 TCP 套接字,由其他用户启动的客户端进程可以与之通信。
  2. 从您的用户开始,启动一个单独的 TCP 服务器,它可以通过 TCP 接受一些有限的命令集。该服务器可以接受来自任何用户的 daemon-shutdown 命令。然后,该进程可以为您的主进程发出 kill 命令。
  3. 创建一个命名的 fifo,任何用户都可以将其设为可写。创建一个子线程,它将尝试从该 fifo 中读取。由于本质上,fifo 读取调用是阻塞调用,因此该线程将继续休眠(并且不会消耗您的 CPU)。在其他用户向该 fifo 写入内容后,该线程将唤醒并干净地终止父线程。
  4. 与上面相同,但线程等待是由同一用户启动的另一个进程的一部分。该进程在唤醒时将杀死主进程。

在我看来,第三种方法是三种方法中最干净的一种。

编辑:由于“主进程”实际上是一个 shell 脚本,“线程”将变为子 shell。&要等待的子线程将是简单的'cat fifo'。

于 2012-11-29T09:09:56.543 回答
-2

如果您具有 root 访问权限,则可以使用sudo并配置它以允许--stop以 root 身份运行带有参数的脚本。

于 2012-11-23T16:41:50.340 回答