允许其他用户控制该过程

时间:2012-11-23 08:26:46

标签: bash sh

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

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

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

但是由于应用程序是由我启动的,否则其他任何人(除了root)都不能停止已经运行的实例或重新启动它。

所以我在考虑将所有者更改为nobody。这有帮助吗?如果是,那怎么办呢?

5 个答案:

答案 0 :(得分:4)

设置脚本以关闭某些事件,而不是直到被杀死。然后让主脚本在--stop触发该事件(事件可以像创建特定文件一样简单,或者更复杂的事情,比如将命令写入脚本定期读取的fifo)。这样,无论是谁启动了脚本,其他用户都应该能够关闭脚本。

如何执行此操作取决于脚本的详细信息。如果它没有可以检查关闭条件本身的循环,那么你可以做一些事情,比如它会产生一个后台进程来定期检查条件并在遇到时杀死它的父pid。

答案 1 :(得分:2)

特别为运行此脚本设置用户。

使用以下命令运行脚本:

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

<强>更新

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

答案 2 :(得分: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(假设此处名称为launcher.c,我们决定以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 --start./launcher --stop。这会将有效用户更改为nobody(或您选择设置程序的任何内容),并执行将执行所需原始操作的./daemon.sh --start-the-real-thing./daemon.sh --stop-the-real-thing

因为简单的启动程序只允许运行命名脚本,所以安全性很容易控制(只是为了确保,您可以在启动程序中检查argv[1]确实是--start或{{ 1}},然后可以运行两个命令行组合作为)。

答案 3 :(得分:-1)

您可以尝试以下选项:

  1. 在您的进程中创建一个TCP套接字,其他用户启动的客户端进程可以与之通信。
  2. 从您的用户,启动单独的TCP服务器,它可以通过TCP接受一些有限的命令集。该服务器可以接受来自任何用户的daemon-shutdown命令。然后,该进程可以为您的主进程发出kill命令。
  3. 创建一个名为fifo,可以由任何用户创建。创建一个子线程,尝试从该fifo读取。由于本质上,fifo读取调用是阻塞调用,该线程将保持休眠状态(并且不会占用CPU)。在其他一些用户向该fifo写入内容之后,该线程将被唤醒&amp;干净地终止父线程。
  4. 与上面相同,但是线程等待是另一个进程的一部分,由同一个用户启动。当这个过程醒来时,会杀死主要过程。
  5. 在我看来,第三种方法是三种方法中最干净的方法。

    编辑:由于'主进程'实际上是一个shell脚本,'thread'将更改为子shell。 &安培;要等待的子线程将是简单的'cat fifo'。

答案 4 :(得分:-2)

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