PHP 运行 多个脚本并发

PHP running multiple scripts concurrently

我有一个带有对象服务器的数组,如下所示:

Array
(
    [0](
                (
                    [id] => 1
                    [version] => 1
                    [server_addr] => 192.168.5.210
                    [server_name] => server1
                )
        )
    [1](
                (
                    [id] => 2
                    [server_addr] => 192.168.5.211
                    [server_name] => server2
                )
        )
)

通过运行下面的代码,我能够得到想要的输出

foreach ($model as $server) {
        $cpu_usage = shell_exec('sudo path/to/total_cpu_usage.sh '.$server->server_addr);
        $memory_usage = shell_exec('sudo path/to/total_memory_usage.sh '.$server->server_addr);
        $disk_space = shell_exec('sudo path/to/disk_space.sh '.$server->server_addr);
        $inode_space = shell_exec('sudo path/to/inode_space.sh '.$server->server_addr);
        $network = shell_exec('sudo path/to/network.sh '.$server->server_addr);
        exec('sudo path/to/process.sh '.$server->server_addr, $processString);
        $processArray = array();
        foreach ($processString as $i) {
          $row = explode(" ", preg_replace('/\s+/', ' ', $i));
          array_push($processArray,$row);
        }
        $datetime = shell_exec('sudo path/to/datetime.sh '.$server->server_addr);
        echo $cpu_usage;
        echo $mem_usage;
        echo $disk_space;
        ......
}

我的脚本类似于:

#!/bin/bash
if [ "" == "" ]
then
        echo "To start monitor, please provide the server ip:"
        read IP
else
        IP=
fi

ssh root@$IP "date"

但是 5 台服务器的整个过程花费了 10 秒,而 1 台服务器的时间不到 2 秒。这是为什么?有什么办法可以缩短时间吗?我的猜测是 exec 命令在进入下一个循环之前正在等待将输出分配给变量?我尝试 google 一点点,但大部分答案都是完全不返回任何输出...不过我需要输出

我不知道如何让你的逻辑更快,但我可以告诉你当我有脚本时我如何使用来跟踪 运行 的时间。在脚本的开头放一些 var $start = date('c');,最后放一些简单的 echo ' start='.$start; echo ' end='.date(c);

是的,你是对的:你的 PHP 脚本在继续之前等待每个响应。

我假设您希望 运行 同时向所有服务器发送请求,而不是等待每个服务器响应。在这种情况下,假设您运行正在使用 PHP 的线程安全版本,请查看 pthreads. One option is to use cURL multi-exec for making asynchronous requests. Then there's also pcntl_fork that may help you out. Also see this & this 线程以寻找可能的 thread/async 方法。

除此之外,单独测试和基准测试 shell 脚本,看看瓶颈在哪里,以及是否可以加快它们的速度。这可能比 PHP 中的 thread/async 设置更容易。如果您遇到网络延迟问题,请编写一个聚合器 shell 脚本来执行其他脚本,并在一个请求中 returns 结果,并且只在您的 PHP 脚本中调用它。

您可以 运行 您的脚本同时使用 popen() 并稍后使用 fread() 获取输出。

//execute
foreach ($model as $server) {
    $server->handles = [
        popen('sudo path/to/total_cpu_usage.sh '.$server->server_addr, 'r'),
        popen('sudo path/to/total_memory_usage.sh '.$server->server_addr, 'r'),
        popen('sudo path/to/disk_space.sh '.$server->server_addr, 'r'),
        popen('sudo path/to/inode_space.sh '.$server->server_addr, 'r'),
        popen('sudo path/to/network.sh '.$server->server_addr, 'r'),
    ];
}

//grab and store the output, then close the handles
foreach ($model as $server) {
    $server->cpu_usage = fread($server->handles[0], 4096);
    $server->mem_usage = fread($server->handles[1], 4096);
    $server->disk_space = fread($server->handles[2], 4096);
    $server->inode_space = fread($server->handles[3], 4096);
    $server->network = fread($server->handles[4], 4096);

    foreach($server->handles as $h) pclose($h);
}

//print everything
print_r($model);

我测试了一个类似的代码来执行 5 个休眠 2 秒的脚本,整个过程只用了 2.12 秒 而不是 shell_exec().

的 10.49 秒

更新 1: 非常感谢 Markus AO 指出优化潜力。

更新 2: 修改了代码以消除覆盖的可能性。 结果现在在 $model.

这还可以显示哪个服务器拒绝了连接,以防 sshd 的问题影响到您。

你需要做的就是在 Linux 的末尾添加一个 > /dev/null &,虽然你不会得到输出,但它会 运行 作为后台(异步)进程.

shell_exec('sudo path/to/datetime.sh '.$server->server_addr.'  > /dev/null &');

另请参阅我的 GitHub 中的后台进程脚本(它具有 windows 兼容的后台进程)

https://github.com/ArtisticPhoenix/MISC/blob/master/BgProcess.php

干杯!