PHP远程执行两条SSH命令生成并读取HTML文件失败问题
问题描述
需要通过PHP在Linux服务器上执行两条有依赖关系的远程命令:
- 第一条命令:
/opt/IBM/ITM/JRE/lx8266/bin/java -Xmx3145728k -jar AggregationAnalyzer.jar /opt/IBM/ITM2/lx8263/to/bin/todata,执行后生成/opt/sw/db_viewer/todata_summary.html文件 - 第二条命令:
cat /opt/sw/db_viewer/todata_summary.html,需要在第一条命令执行完成后再运行
当前PHP代码中,单独执行第二条命令能正常读取文件,但同时执行两条命令时,读取到的内容为空。用户提供的代码如下:
<?php include('C:\Manutenzione\Analisi_TT\simple_html_dom.php'); $ip_soatt04='myIP'; $usr_soatt = 'root'; $pwd_soatt = 'pwd'; $dom = new DomDocument(); $connection_soatt04 = ssh2_connect($ip_soatt04, 22); if (!$connection_soatt04) { echo "impossibile connettersi a soatt04"; } ssh2_auth_password($connection_soatt04, $usr_soatt , $pwd_soatt); $exec=ssh2_exec($connection_soatt04,'/opt/IBM/ITM/JRE/lx8266/bin/java -Xmx3145728k -jar AggregationAnalyzer.jar /opt/IBM/ITM2/lx8263/to/bin/todata'); $stream = ssh2_exec($connection_soatt04,'cat /opt/sw/db_viewer/todata_summary.html'); stream_set_blocking($stream, true); $stream_out=stream_get_contents($stream); //$stream_out=file_get_html($stream,true); //echo $stream_out; $dom->loadHTML($stream_out); $xpath = new DOMXpath($dom); [...]
第一条命令执行时的输出为:
Reading /opt/IBM/ITM2/lx8263/to/bin/todata/topology/MetaData.xml Processing 864 records 0% 25% 50% 75% 100% |---------+---------+---------+---------| |.......................................| Found 864 records in 2.41s. There were 0 records with missing RecordIdentity.xml Writing HTML report to /opt/sw/db_viewer/todata_summary.html Writing CSV report to /opt/sw/db_viewer/todata_raw.csv
问题原因
ssh2_exec函数是异步执行的,调用后不会等待当前命令执行完成就会继续执行后续代码。因此第二条读取文件的命令会在第一条生成文件的命令还未完成时就执行,此时目标文件还未生成(或未写入完成),所以读取到的内容为空。
解决方案
有两种可靠的方法可以确保两条命令按顺序执行:
方法1:合并两条命令为一条(推荐)
使用&&连接两条命令,这样只有第一条命令执行成功后,第二条命令才会被执行。同时通过同一个流获取最终的文件内容:
<?php include('C:\Manutenzione\Analisi_TT\simple_html_dom.php'); $ip_soatt04='myIP'; $usr_soatt = 'root'; $pwd_soatt = 'pwd'; $dom = new DomDocument(); $connection_soatt04 = ssh2_connect($ip_soatt04, 22); if (!$connection_soatt04) { echo "impossibile connettersi a soatt04"; exit; } ssh2_auth_password($connection_soatt04, $usr_soatt, $pwd_soatt); // 合并两条命令,确保顺序执行 $stream = ssh2_exec($connection_soatt04, '/opt/IBM/ITM/JRE/lx8266/bin/java -Xmx3145728k -jar AggregationAnalyzer.jar /opt/IBM/ITM2/lx8263/to/bin/todata && cat /opt/sw/db_viewer/todata_summary.html'); stream_set_blocking($stream, true); $stream_out = stream_get_contents($stream); fclose($stream); // 关闭流 $dom->loadHTML($stream_out); $xpath = new DOMXpath($dom); [...]
方法2:等待第一条命令执行完成后再执行第二条
显式读取第一条命令的输出流直到结束,确保命令执行完毕,再执行第二条命令:
<?php include('C:\Manutenzione\Analisi_TT\simple_html_dom.php'); $ip_soatt04='myIP'; $usr_soatt = 'root'; $pwd_soatt = 'pwd'; $dom = new DomDocument(); $connection_soatt04 = ssh2_connect($ip_soatt04, 22); if (!$connection_soatt04) { echo "impossibile connettersi a soatt04"; exit; } ssh2_auth_password($connection_soatt04, $usr_soatt, $pwd_soatt); // 执行第一条命令并等待完成 $exec = ssh2_exec($connection_soatt04, '/opt/IBM/ITM/JRE/lx8266/bin/java -Xmx3145728k -jar AggregationAnalyzer.jar /opt/IBM/ITM2/lx8263/to/bin/todata'); stream_set_blocking($exec, true); // 读取第一条命令的输出,直到流结束,确保命令执行完成 $exec_output = stream_get_contents($exec); fclose($exec); // 关闭第一条命令的流 // 执行第二条命令读取文件 $stream = ssh2_exec($connection_soatt04, 'cat /opt/sw/db_viewer/todata_summary.html'); stream_set_blocking($stream, true); $stream_out = stream_get_contents($stream); fclose($stream); $dom->loadHTML($stream_out); $xpath = new DOMXpath($dom); [...]
注意事项
- 可以通过检查第一条命令的输出(如
$exec_output),确认是否包含Writing HTML report to /opt/sw/db_viewer/todata_summary.html内容,进一步验证文件是否成功生成。 - 如果第一条命令可能执行失败,建议在合并命令时添加错误处理逻辑,例如使用
||捕获错误。
内容的提问来源于stack exchange,提问作者Fabio
相关产品推荐
相关产品推荐

