今天我們來談一談 PHP 的 pty 擴展。Pty 指的是 pseudo-terminal(偽終端),在我們使用終端界面時,我們就是在使用 pty。而 PHP 的 pty 擴展可以讓我們在 PHP 代碼中通過偽終端來執行 shell 命令。這個擴展的使用場景很多,比如說我們在開發一個 Web 應用,在 Web 界面上提供一個終端,供用戶直接執行 Linux 命令,或者我們需要編寫一個類似 SSH 的程序。下面我們來看一下 pty 擴展的用法和一些示例。
首先,我們需要確保我們已經安裝了 pty 擴展。如果您使用的是 PHP 7.1 以下版本的 PHP,那么 pty 已經默認開啟了,無需再安裝。如果您使用的是 PHP 7.1 或以上版本的 PHP,那么您需要在編譯 PHP 時指定--enable-pty 才能開啟 pty。
下面是一個簡單的示例:
這段代碼會生成一個偽終端,啟動一個
需要注意的是,這個示例僅僅是演示使用,實際使用時可能需要更復雜的邏輯。
下面我們再來看一下如何向偽終端輸入數據:
這段代碼會向偽終端輸入
最后,我們再來看一下如何獲取偽終端的大小:
這段代碼會使用
總結一下,PHP 的 pty 擴展可以讓我們在 PHP 代碼中通過偽終端來執行 shell 命令,適用于很多場景,可以讓我們更方便地處理一些命令行任務。當然,這個擴展的使用場景不限于此,您可以根據自己的需求靈活使用。
首先,我們需要確保我們已經安裝了 pty 擴展。如果您使用的是 PHP 7.1 以下版本的 PHP,那么 pty 已經默認開啟了,無需再安裝。如果您使用的是 PHP 7.1 或以上版本的 PHP,那么您需要在編譯 PHP 時指定--enable-pty 才能開啟 pty。
下面是一個簡單的示例:
php
$master = posix_openpt();
echo posix_ttyname($master);
echo "\n";
<br>
$slave = rtrim(ptsname $master
);
if (! file_exists($slave)) {
posix_mkfifo($slave, 0600);
}
<br>
stream_set_blocking($master, 0);
stream_set_blocking($slave, 0);
<br>
$pid = pcntl_fork();
if ($pid == -1) {
die('fork() failed');
} elseif ($pid == 0) {
posix_setsid();
posix_setpgid(0, 0);
$slave = posix_openpt(O_RDWR);
posix_unlockpt($slave);
$slave_name = rtrim(posix_ttyname($slave), "\n");
$slave_fh = fopen($slave_name, 'r+');
<br>
if (! posix_setgid(posix_getgid())) {
die('setgid failed');
}
if (! posix_setuid(posix_getuid())) {
die('setuid failed');
}
<br>
$exec = ['/bin/bash', '-i'];
pcntl_exec($exec[0], $exec);
} else {
$max_execution_time = ini_get('max_execution_time');
while (true) {
$start_time = time();
if ($max_execution_time > 0 && time() - $start_time > $max_execution_time) {
die(sprintf('Execution aborted after %d seconds.', $max_execution_time));
}
<br>
$read = [$master];
$write = [$master];
$except = null;
$tv_sec = 60;
$tv_usec = 0;
$num_changed_streams = stream_select($read, $write, $except, $tv_sec, $tv_usec);
if ($num_changed_streams === false) {
die('stream_select failed');
} elseif ($num_changed_streams === 0) { // Timed out
continue;
}
<br>
foreach ($read as $r) {
$data = fread($r, 8192);
if (strlen($data) == 0) { // eof
die();
}
echo $data;
}
}
}
這段代碼會生成一個偽終端,啟動一個
/bin/bash -i
進程,并將輸入輸出重定向到偽終端上。這個示例不但可以在命令行下執行,也可以在 Web 環境下使用。需要注意的是,這個示例僅僅是演示使用,實際使用時可能需要更復雜的邏輯。
下面我們再來看一下如何向偽終端輸入數據:
php if (fwrite($master, "ls\n") === false) { die('fwrite() failed'); } <br> //Sleep to ensure the command was executed sleep(1); <br> $data = ''; while ($line = fgets($master)) { if ($line == "\n" || $line == "\r\n") { break; } $data .= $line; } <br> echo $data;
這段代碼會向偽終端輸入
ls
命令并讀取輸出。最后,我們再來看一下如何獲取偽終端的大小:
php $rows = exec('tput lines'); $cols = exec('tput cols'); <br> echo "Terminal size: {$rows} rows x {$cols} columns";
這段代碼會使用
tput
命令獲取終端的大小。總結一下,PHP 的 pty 擴展可以讓我們在 PHP 代碼中通過偽終端來執行 shell 命令,適用于很多場景,可以讓我們更方便地處理一些命令行任務。當然,這個擴展的使用場景不限于此,您可以根據自己的需求靈活使用。
上一篇php psr4中文