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
干杯!
我有一个带有对象服务器的数组,如下所示:
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()
.
更新 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
干杯!