dongqun5769 2015-03-15 00:43
浏览 127
已采纳

通过PHP运行两个linux命令,在执行第二个之前不要等待第一个结束

This is pretty weird, and I searched and tried everything, but I think I'm just making a dumb syntax error here.

I'm trying to run a stress test on the CPU , then immediately limit it's cpu usage to 30% , all this via PHP. The test is also run under another user and with a specified name so it can be limited. The stress test starts fine, but I can see the PHP file still loading, and it ends the second the stress test ends.

Here's some of the ways I tried doing it

$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"');

The whole purpose of this is because I am writing a script for a game hosting website, and I want to limit the resource consumption of each server to improve quality and not let someone hog all the resources. Basically, instead of the stress test, a game server will run.

edit::

here's what I have now:

I need to run the stress under "test" , but the cpulimit under either sudo apache or root, because it requires special permissions. The stress still starts fine but it eats 99.9%

passthru('sudo runuser -l test -c "exec -a MyUniqueProcessName stress -c 1 -t 60s &" & sudo cpulimit -e MyUniqueProcessName -l 30 -i -z');

I can't see the cpulimit in the process list after doing this http://i.imgur.com/iK2nL43.png

  • 写回答

1条回答 默认 最新

  • dongxing4196 2015-03-15 06:28
    关注

    Unfortunately, the && does more or less the opposite of what you want. :-) When you do A && B in Bash, that means, "Run command A and wait until it's done; if it succeeded, then run command B."

    By contrast, A & B means, "Run command A and then immediately run command B."

    So you're close to right in your command, but just getting tripped up by using two bash commands (should only need one) and the &&.

    Also, did you try running each command separately, outside PHP, in two terminals? I just downloaded and built both stress and cpulimit (I assume these are the ones you're using?), ran the commands separately, and spotted a problem: cpulimit still isn't limiting the percentage.

    Looking at the docs for stress, I see it works by forking child processes, so the one you're trying to CPU-limit is the parent, but that's not the one using the CPU. cpulimit --help reveals there's option -i, which includes child processes in what is limited.

    This gets me to the point of being able to enter this in one terminal (first line shows input at the prompt; subsequent show output):

    $> 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
    

    Then, in another terminal running top, I see:

      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
    

    Much better. (Notice that outside the Bash shell where you aliased it with exec -a, you will see the process name as stress.) Unfortunately, I also see another issue, which is cpulimit remaining "listening" for more processes with that name. Back to cpulimit --help, which reveals the -z option.

    Just to reduce the complexity a bit, you could leave the alias off and use the PID of the stress process, via the special Bash variable $!, which refers to the PID of the last process launched. Running the following in a terminal seems to do everything you want:

    stress -c 1 -t 60s & cpulimit -p $! -l 30 -i -z
    

    So now, just change the PHP script with what we've learned:

    exec('bash -c "exec -a MyUniqueProcessName stress -c 1 -t 60s & cpulimit -e MyUniqueProcessName -l 30 -i -z"');
    

    ...or, simpler version:

    exec('bash -c "stress -c 1 -t 60s & cpulimit -p \$! -l 30 -i -z"');
    

    (Notice the $ in the $! had to be escaped with a backslash, \$!, because of the way it's quoted when passed to bash -c.)

    Final Answer:

    Based on the last example you amended to your question, you'll want something like this:

    passthru('bash -c "sudo -u test stress -c 1 -t 60s & sudo -u root cpulimit -p \$! -l 30 -i -z"');
    

    When I run this with php stackoverflow-question.php, it outputs the following:

    stress: info: [3374] dispatching hogs: 1 cpu, 0 io, 0 vm, 0 hdd
    stress: info: [3374] successful run completed in 60s
    Process 3371 found
    

    (The second two lines only appear after the PHP script finishes, so don't be mislead. Use top to check.)

    Running top in another terminal during the 60 seconds the PHP script is running, I see:

      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
    

    This is exactly what you've described wanting: stress is running under the user test, and cpulimit is running under the user root (both of which you can change in the command, if desired). stress is limited to around 30%.

    I'm not familiar with runuser and don't see the applicability, since sudo is the standard way to run a process as another user. To get this to work, you may have to adjust your settings in /etc/sudoers (which will require root access, but you obviously already have that). That's entirely outside the scope of this discussion, but as an example, I added the following rules:

    my-user ALL=(test) NOPASSWD:NOEXEC: /home/my-user/development/stackoverflow/stress 
    my-user ALL=(root) NOPASSWD:NOEXEC: /home/my-user/development/stackoverflow/cpulimit 
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 Revit2020下载问题
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大
  • ¥15 单片机无法进入HAL_TIM_PWM_PulseFinishedCallback回调函数
  • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
  • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 seatunnel 怎么配置Elasticsearch