以其他用户身份启动脚本

Iva*_*vic 13 linux debian bash sudo init.d

我在 /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",对我有用。但我也试过没有拒绝 %1,结果是一样的。所以这就是我所期望的:

sudo -u <username> bash -c "<script_of_a_particular_user> &"
Run Code Online (Sandbox Code Playgroud)

我现在的另一个问题是,为什么它可以在没有拒绝的情况下工作?无论如何,对于某些潜在的特殊情况,我是否仍然应该离开拒绝电话?

更新 2

显然这也有效:

su <username> -c "<script_of_a_particular_user> &"
Run Code Online (Sandbox Code Playgroud)

这个调用和 sudo 调用有什么区别吗?我知道这可能是一个完全不同的问题。但由于我自己在这里找到答案,也许为了这个话题,有人可以在这里澄清这一点。

更新 3在我启动机器后
,这两种使用 su 或 sudo 的方法现在都会生成一个新的startpar进程(以 root 身份运行的单个进程)。在进程列表中可见:

startpar -f -- <name_of_my_init.d_script>
Run Code Online (Sandbox Code Playgroud)

为什么会产生这个进程?显然我做错了什么,因为没有其他 init.d 脚本运行这个进程。

更新 4
startpar 的问题已解决。我为此提出了另一个问题:
startpar 进程在从 rc.local 或 init.d 启动进程时挂起

另一个进一步讨论非特权用户启动机制的问题:
为普通用户(非root)提供初始化和关闭自动运行功能

Iva*_*vic 19

对此的正确答案是,为了正确的“守护进程”,标准输入、标准输出和标准错误需要重定向到 /dev/null (或一些真实文件):

su someuser -c "nohup some_script.sh >/dev/null 2>&1 &"
Run Code Online (Sandbox Code Playgroud)

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,例如:

su someuser -c "some_script.sh 0<&- 1>&- 2>&- &"
Run Code Online (Sandbox Code Playgroud)

0<&-关闭标准输入(0)
1>&-关闭标准输出(1)
2>&-关闭标准错误(2) 输出

< > 符号的方向无关紧要,因为指定了长文件描述符编号。所以这同样好:

su someuser -c "some_script.sh 0>&- 1>&- 2>&- &"
Run Code Online (Sandbox Code Playgroud)

或者

su someuser -c "some_script.sh 0<&- 1<&- 2<&- &"
Run Code Online (Sandbox Code Playgroud)

然而,有一种更短的写法,没有标准输入和标准输出的数字,方向很重要:

su someuser -c "some_script.sh <&- >&- 2>&- &" 
Run Code Online (Sandbox Code Playgroud)

当文件描述符关闭或重定向到 /dev/null(start-stop-daemon正在重定向到 /dev/null)时,进程可以安全地作为守护程序在后台运行。所以这就是避免在启动期间启动脚本出现问题(startpar)所需要的。

我已经根据最初的想法实现了整个解决方案,并将其放在 GitHub 上:
https //github.com/ivankovacevic/userspaceServices