本文目录导读:

在PHP中操作Linux命令有多种方式,以下是常用的方法和最佳实践:
基础函数(按推荐程度排序)
exec() - 执行命令并返回最后一行
<?php
// 返回最后一行输出
$lastLine = exec('ls -la', $output, $returnCode);
echo "最后一行: " . $lastLine . PHP_EOL;
echo "完整输出: " . implode("\n", $output) . PHP_EOL;
echo "返回码: " . $returnCode;
?>
shell_exec() - 执行命令并返回完整输出
<?php
$output = shell_exec('ls -la');
echo "<pre>$output</pre>";
?>
system() - 直接输出结果
<?php
// 直接输出到浏览器
system('pwd', $returnCode);
echo "返回码: " . $returnCode;
?>
passthru() - 执行外部程序并显示原始输出
<?php
// 适合二进制输出
passthru('cat image.jpg', $returnCode);
?>
使用反引号运算符
<?php $output = `ls -la`; echo $output; ?>
proc_open() - 高级操作(推荐)
<?php
$descriptors = [
0 => ["pipe", "r"], // stdin
1 => ["pipe", "w"], // stdout
2 => ["pipe", "w"] // stderr
];
$process = proc_open('ls -la', $descriptors, $pipes);
if (is_resource($process)) {
// 读取标准输出
$stdout = stream_get_contents($pipes[1]);
// 读取错误输出
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
$returnCode = proc_close($process);
echo "标准输出: " . $stdout;
echo "错误输出: " . $stderr;
echo "返回码: " . $returnCode;
}
?>
安全最佳实践
转义参数
<?php
// 使用 escapeshellcmd 转义整个命令
$cmd = escapeshellcmd('ls -la');
// 使用 escapeshellarg 转义每个参数
$filename = $_GET['file']; // 用户输入
$cmd = 'cat ' . escapeshellarg($filename);
?>
验证用户输入
<?php
function safeSystemCall($command, $allowedCommands = []) {
// 验证命令
if (!in_array($command, $allowedCommands)) {
throw new Exception("不允许执行此命令");
}
// 执行并返回结果
return shell_exec($command);
}
// 使用示例
$allowed = ['ls', 'pwd', 'date'];
try {
echo safeSystemCall($_GET['cmd'], $allowed);
} catch (Exception $e) {
echo "错误: " . $e->getMessage();
}
?>
完整示例 - 执行命令并处理错误
<?php
function executeCommand($command, $timeout = 30) {
$descriptors = [
0 => ["pipe", "r"],
1 => ["pipe", "w"],
2 => ["pipe", "w"]
];
$process = proc_open(
$command,
$descriptors,
$pipes,
null,
null,
['timeout' => $timeout]
);
if (!is_resource($process)) {
return ['success' => false, 'error' => "无法启动进程"];
}
// 关闭stdin
fclose($pipes[0]);
// 读取输出(设置流超时)
stream_set_blocking($pipes[1], false);
$stdout = '';
$start = time();
while (true) {
$stdout .= fgets($pipes[1]);
if (time() - $start > $timeout) {
proc_terminate($process);
return ['success' => false, 'error' => "命令执行超时"];
}
if (feof($pipes[1])) {
break;
}
usleep(100000); // 100ms
}
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$returnCode = proc_close($process);
return [
'success' => ($returnCode === 0),
'stdout' => $stdout,
'stderr' => $stderr,
'returnCode' => $returnCode
];
}
// 使用示例
$result = executeCommand('python3 script.py --input file.txt');
if ($result['success']) {
echo "执行成功:\n" . $result['stdout'];
} else {
echo "执行失败:\n" . $result['stderr'];
}
?>
使用 Symfony Process(推荐第三方库)
<?php
// 安装: composer require symfony/process
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
$process = new Process(['ls', '-la']);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
echo $process->getOutput();
?>
注意事项
-
安全警告:
- 永远不会直接执行用户输入的命令
- 使用白名单验证可执行命令
- 转义所有用户提供的参数
-
权限限制:
- Web服务器用户通常权限有限
- 使用sudo时需要配置NOPASSWD
-
错误处理:
- 始终检查返回码
- 处理stdout和stderr
-
性能考虑:
- 避免频繁执行系统命令
- 考虑使用缓存
-
环境问题:
- 某些PHP环境可能禁用exec类函数
- 检查php.ini中的disable_functions
根据具体需求选择合适的函数,推荐使用proc_open或Symfony Process以获得最佳控制。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播