我在 /etc/init.d/ 中创建了一个脚本,它必须从其他(非 root 特权)用户的主目录运行其他几个脚本,就像他们启动它们一样。
我使用以下命令启动这些脚本:sudo -b -u <username> <script_of_a_particular_user>
它有效。但是对于每个继续运行的用户脚本(例如一些看门狗),我看到一个相应的父 sudo 进程,仍然活着并以 root 身份运行。这会在活动进程列表中造成混乱。
所以我的问题是:如何从现有的 bash 脚本作为另一个用户启动(fork)另一个脚本并将其保留为孤立(独立)进程?
更详细的解释:
我基本上试图通过运行在其主目录中的相应子目录中找到的可执行文件(名为 .startUp 和 .shutDown)来向机器上的其他用户提供一种在系统启动或系统关闭时运行东西的方法。因为我没有找到任何其他方法可以做到这一点,所以我编写了我的 bash 脚本,我已经将它配置为 /etc/init.d/ 中的服务脚本(通过遵循骨架示例),所以当它运行时使用 start 参数,它从 .startUp 目录启动所有内容,当它使用 stop 参数运行时,它从所有用户的 .shutDown 目录启动所有内容。
或者,如果我可以使用一些现有的解决方案来解决这个问题,我也很感兴趣。
更新
我环顾四周,发现了这个问题:
https ://unix.stackexchange.com/questions/22478/detach-a-daemon-using-sudo
那里接受的答案,使用:sudo -u user sh -c "daemon & disown %1"
,对我有用。但是我也尝试过没有disown %1并且是一样的。所以这就是我所期望的对我有用的东西:
sudo -u <username> bash -c "<script_of_a_particular_user> &"
我现在的另一个问题是,为什么它可以在没有否认的情况下工作?无论如何,对于某些潜在的特殊情况,我是否仍然应该留下disown电话?
更新 2
显然这也有效:
su <username> -c "<script_of_a_particular_user> &"
这个调用和 sudo 调用有什么区别吗?我知道这可能是一个完全不同的问题。但是,由于我自己在这里找到了答案,也许为了这个话题,有人可以在这里澄清这一点。
更新 3
在我启动机器后
,这两种使用 su 或 sudo 的方法现在都会生成一个新的startpar进程(以 root 身份运行的单个进程)。在进程列表中可见:
startpar -f -- <name_of_my_init.d_script>
为什么会产生这个过程?显然我做错了,因为没有其他 init.d 脚本运行此进程。
更新 4
startpar 的问题已解决。我为此提出了另一个问题:
从 rc.local 或 init.d 启动进程时 startpar 进程挂起
还有一个问题需要进一步讨论非特权用户的启动机制:
为普通用户(非root)提供初始化和关闭自动运行功能
对此的正确答案是,为了正确的“守护进程”,标准输入、标准输出和标准错误需要重定向到 /dev/null (或一些真实文件):
su - 将用户身份替换为someuser
-c - su 参数以运行指定的命令
nohup - 运行不受挂断影响的命令。防止父进程终止子进程的情况。在这里添加以防万一。但实际上对我的特定情况没有影响。是否需要取决于环境(检查shopt)
>/dev/null - 将标准输出重定向为空,基本上禁用它。
2>&1 - 将标准错误 (2) 输出重定向到标准输出 (1),它被重定向到 null
& - 分离到后台,这会将标准输入也重定向到 /dev/null。
这本质上正是Debian dpkg的 start-stop-daemon实用程序的核心。这就是为什么我更喜欢以这种方式启动脚本,而不是在我的代码中引入另一个外部实用程序调用。start-stop-daemon在您需要启动完整的守护程序并且您需要start-stop-daemon 提供的附加功能的情况下很有用(例如检查指定的进程是否已经在运行,以便它不会不要再次启动它)。
还值得注意的是,您还可以关闭进程的文件描述符,而不是将它们重定向到/dev/null,例如:
0<&-关闭标准输入(0)
1>&-关闭标准输出(1)
2>&-关闭标准错误(2) 输出
< > 符号的方向无关紧要,只要指定了长文件描述符编号。所以这同样好:
或者
然而,有一个更短的方法来写,没有标准输入和标准输出的数字,其中方向确实很重要:
当文件描述符关闭或重定向到 /dev/null (start-stop-daemon正在重定向到 /dev/null )时,该进程可以安全地作为守护进程在后台运行。这就是避免在启动期间启动脚本出现问题( startpar )所需要的。
我已经从我最初的想法中实现了整个解决方案并将其放在 GitHub 上:
https ://github.com/ivankovacevic/userspaceServices
您可以将 init.d 中的start-stop-daemon与该
--user
选项一起使用。我还没有完全测试过这个,但我认为是这样的:
在启动时,然后
关机时。
处理 .shutDown 脚本可以通过启动之类的东西来完成,但是您不能确定脚本运行到结束,因为无论如何都应该发生关闭:-)
应该可以解决问题,也许您应该进行一些输入重定向,但是您将不得不担心日志文件被填充。
你试过使用
su
吗?-c
告诉 su 执行命令,最后一个参数是执行它的用户。