运行 通过 PHP 的两个 linux 命令,不要等待第一个命令结束后再执行第二个
Running two linux commands via PHP, don't wait for first to end before executing second
这很奇怪,我搜索并尝试了所有方法,但我认为我只是犯了一个愚蠢的语法错误。
我正在尝试 运行 对 CPU 进行压力测试,然后立即将其 cpu 使用率限制在 30%,所有这些都通过 PHP。该测试也在另一个用户下 运行 并具有指定的名称,因此可以对其进行限制。压力测试开始正常,但我可以看到 PHP 文件仍在加载,并在压力测试结束时结束。
这是我尝试过的一些方法
$output = exec('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30"');
$output = exec('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s > /dev/null & cpulimit -e MyUniqueProcessName -l 30"');
这样做的全部目的是因为我正在为一个游戏托管网站编写脚本,我想限制每台服务器的资源消耗以提高质量,而不是让任何人霸占所有资源。
基本上,游戏服务器将 运行.
而不是压力测试
编辑::
这是我现在拥有的:
我需要 运行 强调 "test" ,但 cpu 限制在 sudo apache 或 root 下,因为它需要特殊权限。压力仍然开始正常,但它吃掉了 99.9%
passthru('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s &" & sudo cpulimit -e MyUniqueProcessName -l 30 -i -z');
执行此操作后我在进程列表中看不到 cpulimit http://i.imgur.com/iK2nL43.png
不幸的是,&&
或多或少与您想要的相反。 :-) 当您在 Bash 中执行 A && B
时,这意味着 "Run command A and wait until it's done; if it succeeded, then run command B."
相比之下,A & B
表示,"Run command A and then immediately run command B."
所以你的命令几乎是正确的,但只是被两个 bash
命令(应该只需要一个)和 &&
.
绊倒了
此外,您是否在 PHP 之外尝试在两个终端中分别 运行 执行每个命令?我刚刚分别下载并构建了 stress and cpulimit(我假设这些是您正在使用的?)、运行 命令,并发现了一个问题:cpulimit
仍然没有限制百分比。
查看 stress
的文档,我发现它是通过分叉子进程来工作的,所以你试图 CPU-limit 的是父进程,但不是使用的那个CPU。 cpulimit --help
显示有选项 -i
,其中包括受限的子进程。
这让我能够在一个终端中输入它(第一行在提示符处显示输入;随后显示输出):
$> exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30 -i
[1] 20229
MyUniqueProcessName: info: [20229] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
Process 20229 found
然后,在另一个终端 运行ning top
,我看到:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20237 stackov+ 20 0 7164 100 0 R 30.2 0.0 0:04.38 stress
好多了。 (请注意,在 Bash shell 之外,您将其别名为 exec -a
,您将看到进程名称为 stress
。)不幸的是,我还看到了另一个问题,即cpulimit
剩余 "listening" 个具有该名称的进程。返回 cpulimit --help
,其中显示了 -z
选项。
为了稍微降低复杂性,您可以关闭别名并使用 stress
进程的 PID,通过特殊的 Bash 变量 $!
,它指的是最后启动的进程的 PID。 运行 终端中的以下内容似乎可以满足您的所有需求:
stress -c 1 -t 60s & cpulimit -p $! -l 30 -i -z
现在,只需将 PHP 脚本更改为我们学到的内容即可:
exec('bash -c "exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30 -i -z"');
...或者,更简单的版本:
exec('bash -c "stress -c 1 -t 60s & cpulimit -p $! -l 30 -i -z"');
(注意 $!
中的 $ 必须用反斜杠转义,$!
,因为它在传递给 bash -c
时的引用方式。)
最终答案:
根据你修改问题的最后一个例子,你会想要这样的东西:
passthru('bash -c "sudo -u test stress -c 1 -t 60s & sudo -u root cpulimit -p $! -l 30 -i -z"');
当我 运行 使用 php Whosebug-question.php
时,它输出以下内容:
stress: info: [3374] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: info: [3374] successful run completed in 60s
Process 3371 found
(后两行仅出现在PHP脚本完成后,所以不要被误导。使用top
检查。)
运行 top
在 60 秒内在另一个终端中 PHP 脚本是 运行ning,我看到:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3472 test 20 0 7160 92 0 R 29.5 0.0 0:07.50 stress
3470 root 9 -11 4236 712 580 S 9.0 0.0 0:02.28 cpulimit
这正是您所描述的想要的:stress
运行ning 在用户 test
下,cpulimit
运行ning 在用户 运行ning 下用户 root
(如果需要,您可以在命令中更改两者)。 stress
限制在 30% 左右。
我不熟悉 runuser
并且看不到适用性,因为 sudo
是作为另一个用户 运行 进程的标准方式。要让它工作,您可能需要在 /etc/sudoers 中调整您的设置(这将需要 root 访问权限,但您显然已经拥有了)。这完全超出了本次讨论的范围,但作为示例,我添加了以下规则:
my-user ALL=(test) NOPASSWD:NOEXEC: /home/my-user/development/Whosebug/stress
my-user ALL=(root) NOPASSWD:NOEXEC: /home/my-user/development/Whosebug/cpulimit
这很奇怪,我搜索并尝试了所有方法,但我认为我只是犯了一个愚蠢的语法错误。
我正在尝试 运行 对 CPU 进行压力测试,然后立即将其 cpu 使用率限制在 30%,所有这些都通过 PHP。该测试也在另一个用户下 运行 并具有指定的名称,因此可以对其进行限制。压力测试开始正常,但我可以看到 PHP 文件仍在加载,并在压力测试结束时结束。
这是我尝试过的一些方法
$output = exec('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30"');
$output = exec('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s > /dev/null & cpulimit -e MyUniqueProcessName -l 30"');
这样做的全部目的是因为我正在为一个游戏托管网站编写脚本,我想限制每台服务器的资源消耗以提高质量,而不是让任何人霸占所有资源。 基本上,游戏服务器将 运行.
而不是压力测试编辑::
这是我现在拥有的:
我需要 运行 强调 "test" ,但 cpu 限制在 sudo apache 或 root 下,因为它需要特殊权限。压力仍然开始正常,但它吃掉了 99.9%
passthru('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s &" & sudo cpulimit -e MyUniqueProcessName -l 30 -i -z');
执行此操作后我在进程列表中看不到 cpulimit http://i.imgur.com/iK2nL43.png
不幸的是,&&
或多或少与您想要的相反。 :-) 当您在 Bash 中执行 A && B
时,这意味着 "Run command A and wait until it's done; if it succeeded, then run command B."
相比之下,A & B
表示,"Run command A and then immediately run command B."
所以你的命令几乎是正确的,但只是被两个 bash
命令(应该只需要一个)和 &&
.
此外,您是否在 PHP 之外尝试在两个终端中分别 运行 执行每个命令?我刚刚分别下载并构建了 stress and cpulimit(我假设这些是您正在使用的?)、运行 命令,并发现了一个问题:cpulimit
仍然没有限制百分比。
查看 stress
的文档,我发现它是通过分叉子进程来工作的,所以你试图 CPU-limit 的是父进程,但不是使用的那个CPU。 cpulimit --help
显示有选项 -i
,其中包括受限的子进程。
这让我能够在一个终端中输入它(第一行在提示符处显示输入;随后显示输出):
$> exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30 -i
[1] 20229
MyUniqueProcessName: info: [20229] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
Process 20229 found
然后,在另一个终端 运行ning top
,我看到:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
20237 stackov+ 20 0 7164 100 0 R 30.2 0.0 0:04.38 stress
好多了。 (请注意,在 Bash shell 之外,您将其别名为 exec -a
,您将看到进程名称为 stress
。)不幸的是,我还看到了另一个问题,即cpulimit
剩余 "listening" 个具有该名称的进程。返回 cpulimit --help
,其中显示了 -z
选项。
为了稍微降低复杂性,您可以关闭别名并使用 stress
进程的 PID,通过特殊的 Bash 变量 $!
,它指的是最后启动的进程的 PID。 运行 终端中的以下内容似乎可以满足您的所有需求:
stress -c 1 -t 60s & cpulimit -p $! -l 30 -i -z
现在,只需将 PHP 脚本更改为我们学到的内容即可:
exec('bash -c "exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30 -i -z"');
...或者,更简单的版本:
exec('bash -c "stress -c 1 -t 60s & cpulimit -p $! -l 30 -i -z"');
(注意 $!
中的 $ 必须用反斜杠转义,$!
,因为它在传递给 bash -c
时的引用方式。)
最终答案:
根据你修改问题的最后一个例子,你会想要这样的东西:
passthru('bash -c "sudo -u test stress -c 1 -t 60s & sudo -u root cpulimit -p $! -l 30 -i -z"');
当我 运行 使用 php Whosebug-question.php
时,它输出以下内容:
stress: info: [3374] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
stress: info: [3374] successful run completed in 60s
Process 3371 found
(后两行仅出现在PHP脚本完成后,所以不要被误导。使用top
检查。)
运行 top
在 60 秒内在另一个终端中 PHP 脚本是 运行ning,我看到:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
3472 test 20 0 7160 92 0 R 29.5 0.0 0:07.50 stress
3470 root 9 -11 4236 712 580 S 9.0 0.0 0:02.28 cpulimit
这正是您所描述的想要的:stress
运行ning 在用户 test
下,cpulimit
运行ning 在用户 运行ning 下用户 root
(如果需要,您可以在命令中更改两者)。 stress
限制在 30% 左右。
我不熟悉 runuser
并且看不到适用性,因为 sudo
是作为另一个用户 运行 进程的标准方式。要让它工作,您可能需要在 /etc/sudoers 中调整您的设置(这将需要 root 访问权限,但您显然已经拥有了)。这完全超出了本次讨论的范围,但作为示例,我添加了以下规则:
my-user ALL=(test) NOPASSWD:NOEXEC: /home/my-user/development/Whosebug/stress
my-user ALL=(root) NOPASSWD:NOEXEC: /home/my-user/development/Whosebug/cpulimit