将所有者更改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,那么恰好两个命令行组合可以运行为 )。