php exec 执行 中文_PHP 调用 exec 执行中文命令的坑

写在之前

首先,我们的项目中有这么一个需求,就是需要在发送请求时,需要调用 java 写的一个加密库。所以不可避免的会使用到 php 的 exec 方法执行 shell 命令。

一切都很正常,直到,出现了中文。哎。具体的 case 如下:

样例代码:<?php

$cmd = 'java -jar sign-maker.jar mike messi';

exec($cmd, $ret, $out);

var_dump($ret);

$cmd = 'java -jar sign-maker.jar 麦克 梅西';

exec($cmd, $ret, $out);

var_dump($ret);

其中,sign-maker.jar 就是我们按照第三方的加密协议的一个签名包(虽然也是我写的),执行这段代码,我们可以得到如下的结果:php index.php

array(1) {

[0]=>

string(80) "495cc9e9269265cc0e7d58940367976571a1c4fdb90bf842ee4ba703fb1a554abf0772218e29d3d8"

}

array(2) {

[0]=>

string(80) "495cc9e9269265cc0e7d58940367976571a1c4fdb90bf842ee4ba703fb1a554abf0772218e29d3d8"

[1]=>

string(80) "e442a87d369a1a3c610bb2d18bd38fdad3b52644ab0ef86a21b57a5d0d75cb8dbf0772218e29d3d8"

}

可以看到,我们已经生成了两个 sign 值。但是,在传输过程中,对面居然报了 sign 无效的错误。觉得很奇怪,第一个 sign 是正确的,但是第二个就是败了。于是我们在终端中手动输入了这个命令:└─[$]> java -jar sign-maker.jar 麦克 梅西

92144a18e9f75ec2e257c9bb15a05825a706064445b9492efd065dfd6c8b38d0bf0772218e29d3d8

发现 sign 果然不同。所以第一反应是字符编码的问题,尝试了 utf8encode,iconv 等等方法转换字符,但是都是无功而返。最后定为到环境变量的问题上。

解决办法

解决办法先上,在 exec 的命令前首先指定字符集:<?php

$set_charset = 'export LANG=en_US.UTF-8;';

$cmd = 'java -jar sign-maker.jar mike messi';

exec($set_charset.$cmd, $ret, $out);

var_dump($ret);

$cmd = 'java -jar sign-maker.jar 麦克 梅西';

exec($set_charset.$cmd, $ret, $out);

var_dump($ret);

这样即可。

如何定位

在尝试了 php 的字符转化的方法之后,确实可以断定不是 PHP 的问题,所以最后转移到,php 中 exec 的环境上。我们直接使用如下代码确定 exec 时的环境变量:<?php

system('env | grep LANG');

结果在服务器上发现并没有返回值。而在终端中,执行 env | grep LANG 却有如下输出:➜ ~ env | grep LANG

LANG=en_US.UTF-8

所以即可断定,是环境中语言设置的问题,遂使用上述解决办法解决。

顺便说一下

exec 中的那个 $ret 的结果居然是 append 的。。。一开始还不知道,结果在一个循环中调用的时候,一直使用 $ret[0] 作为结果,哎。都是泪,这个 bug 调了好久才知道。

PS:感谢今天不请自来协助加班的兄弟们。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的示例代码,可以通过 AJAX 调用 PHP 文件,并将 shell_exec("ntpq -p") 的输出转换成 HTML 表格并返回到页面上: index.html: ```html <!DOCTYPE html> <html> <head> <title>PHP AJAX Shell Exec</title> <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script> <script> $(document).ready(function() { $("#btn").click(function() { $.ajax({ url: "shell_exec.php", type: "POST", data: {}, success: function(result) { $("#output").html(result); } }); }); }); </script> </head> <body> <button id="btn">Execute</button> <div id="output"></div> </body> </html> ``` shell_exec.php: ```php <?php $output = shell_exec("ntpq -p"); $table = "<table><thead><tr><th>Remote</th><th>Refid</th><th>St</th><th>T</th><th>When</th><th>Poll</th><th>Reach</th><th>Delay</th><th>Offset</th><th>Jitter</th></tr></thead><tbody>"; $rows = explode("\n", $output); foreach ($rows as $row) { $cols = explode(" ", preg_replace("/\s+/", " ", $row)); if (count($cols) >= 10) { $table .= "<tr>"; for ($i = 0; $i < 10; $i++) { $table .= "<td>" . $cols[$i] . "</td>"; } $table .= "</tr>"; } } $table .= "</tbody></table>"; echo $table; ?> ``` 这个示例使用 jQuery 发送 AJAX 请求到 shell_exec.php 文件,并在成功时将输出转换成 HTML 表格并将其插入到页面中的 div 元素中。在 PHP 文件中,我们使用 shell_exec 函数来执行 shell 命令并获取输出。然后我们将输出拆分成行和列,并将其转换为 HTML 表格。最后,我们将表格作为响应发送回页面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值