允许 {USER} 对另一个用户拥有的进程运行命令

允许 {USER} 对另一个用户拥有的进程运行命令

我一直在论坛上搜索如何允许用户运行通常只由 root 或其自身允许的命令/进程。

这里有一些很好的资源,但没有一个能帮助我,我希望 Ubuntu 天才可以给我指明正确的方向。

我使用 apt-get install cpulimit 安装了 cpulimit,这是一个可以限制特定进程的 CPU 使用率的软件包。安装后,我可以在 /usr/bin/cpulimit 中看到安装。

我现在必须在运行用户处理的进程时运行 cpulimit,在该进程代码内。

我在 visudo 文件中添加了几次尝试,所有这些都是这样的:

{USER} ALL=(ALL:ALL) NOPASSWD:/usr/bin/cpulimit

但是,当我运行命令(限制=百分比)时:

cpulimit --pid 159845 --limit 60

响应是:

Error: Process 159845 detected, but you don't have permission to control it.

其中159845是正确的进程,它是mysqld。

我可以运行 top -i 并看到该进程由用户 mysql 运行:

PID 用户 公共关系 虚拟仿真测试系统 可再生能源 自发性高血压 年代 %中央处理器 %内存 时间+ 命令
159845 mysql 20 0 1460764 608076 3772 年代 15.6 29.9 862:34.15 mysqld

这让我认为没有必要添加允许 {USER} 运行 cpulimit 的初始 visudo 行,但更重要的是,当 {USER} 针对问题 159845 中的进程运行 cpulimit 时,这是不允许的,因为 {USER} 没有权限接触 mysql 的进程。

我作为 {USER} 如何在 mysql 的进程 mysql 上运行 cpulimit?

GENERIC:如何在不同“用户/帐户/角色”拥有的进程上以 {USER} 身份运行命令?

编辑:该命令正在 {USER} 的 crontab 中触发的脚本中运行。

编辑2:以 sudo 形式运行命令后,如下所示:

$limit_mysqld_cpu_usage = "sudo -u mysql cpulimit --pid " . $mysqld_id_exe_output[0] . " --limit " . $cpu_limit_as_perc_of_cpus;

// Run command
exec($limit_mysqld_cpu_usage, $limit_mysqld_cpu_usage_output, $limit_mysqld_cpu_usage_id);

脚本似乎冻结了,而之前它会继续执行脚本。经过尝试和测试,脚本在这一点之后运行良好,不会触发上述命令。

问:为什么这个脚本没有执行然后继续执行其余部分?

答:因为命令运行并且它开始监视该过程,阻止它按照我们期望的返回值执行代码,所以它会永远挂在这里。

问:如何在后台触发 cpulimit 命令的 exec(),或者无需观察并等待响应后再继续?

A:如果使用该函数启动程序,为了使其继续在后台运行,必须将程序的输出重定向到文件或其他输出流。如果不这样做,将导致 PHP 挂起,直到程序执行结束。

http://php.net/manual/en/function.exec.php

因此,本质上我们需要 > 到另一个空间(例如 /dev/null),并通过附加 & 在后台运行该进程。 在我的情况下,命令将需要如下所示:

sudo -u {用户} cpulimit --pid {ID} --limit 60 > /dev/null &"

我还用 exec() 代替了 shell_exec(),它似乎不需要所有参数,也不会产生那么大的响应:

shell_exec(sudo -u {USER} cpulimit --pid {ID} --limit 60 > /dev/null &");

答案1

在@steeldriver 的帮助下,我找到了解决问题的方法。

按时间顺序回答这个问题:

如何以 {USER} 身份在不同“用户/帐户/角色”拥有的进程上运行命令?

为了在以 {USER} 身份在 {ALTERNATIVE_USER} 上运行进程,我们必须使用 sudo,然后您可以指定哪个确切的用户应该运行该命令,如下所示:

sudo -u {ALTERNATIVE_USER} {COMMAND}

我如何触发 {COMMAND} 在后台运行以允许当前脚本继续?

当进程被触发时,脚本似乎冻结了,但它并没有冻结,只是在等待新触发的命令结束,但它不会结束,因为它正在作用于最初触发的进程,而该进程永远不会结束。

为了在启动挂起的命令时执行此操作,我们必须为其指定一个出口,以便它有地方挂起。这可以通过指向替代位置来完成,在我的例子中,我使用了> /dev/null

最后,我需要做的是在后台运行它,这可以通过附加来完成&

最后一点,具体来说,对我来说,我不希望收到回复,我只是希望命令运行并按照我说的做,所以我用 shell_exec() 替换了 exec()。

shell_exec(sudo -u {USER} cpulimit --pid {ID} --limit 60 /dev/null &");

相关内容