我有一个像这样的对象服务器的数组:
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 [ "$1" == "" ]
then
echo "To start monitor, please provide the server ip:"
read IP
else
IP=$1
fi
ssh root@$IP "date"
但是,对于5台服务器,整个过程需要10秒,而不到2秒则需要1台服务器。这是为什么?反正有减少时间吗?我的猜测是,在进入下一个循环之前,exec命令正在等待输出分配给变量?我尝试谷歌一点点,但大多数答案是没有返回任何输出...我需要输出
答案 0 :(得分:9)
您可以使用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的问题影响了你,这也可以显示哪个服务器拒绝了连接。
答案 1 :(得分:0)
我不知道如何让你的逻辑更快,但我可以告诉你如何在我有脚本时跟踪运行时间。在脚本的开头放置一些var $start = date('c');
,最后只是简单的echo ' start='.$start; echo ' end='.date(c);
答案 2 :(得分:0)
是的,你是对的:你的PHP脚本在继续前进之前等待每个响应。
我认为您希望同时向所有服务器运行请求,而不是等待每个服务器响应。在这种情况下,假设您运行的是线程安全的PHP版本,请查看pthreads。一种选择是使用cURL multi-exec来发出异步请求。然后还有pcntl_fork可能会帮助你。另见this& this线程用于可能的线程/异步方法。
除此之外,还要单独测试和测试shell脚本以查看瓶颈的位置,以及是否可以加快它们的速度。这可能比PHP中的线程/异步设置更容易。如果您遇到网络延迟问题,那么编写一个聚合器shell脚本来执行其他脚本,并在一个请求中返回结果,并且只在PHP脚本中调用它。
答案 3 :(得分:0)
你需要做的就是在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
干杯!