PHP 日本會議 2024

從命令列使用 PHP

目錄

簡介

CLI SAPI 的主要重點是使用 PHP 開發 shell 應用程式。 CLI SAPI 與其他 SAPI 之間存在許多差異,本章將對此進行說明。 值得一提的是,CLICGI 是不同的 SAPI,儘管它們確實具有許多相同的行為。

CLI SAPI 預設使用 --enable-cli 啟用,但在執行 ./configure 時可以使用 --disable-cli 選項停用。

CLI/CGI 二進位檔的名稱、位置和存在與否將取決於 PHP 在您的系統上的安裝方式。 預設情況下,在執行 make 時,CGICLI 都會建置,並分別放置在您的 PHP 來源目錄中的 sapi/cgi/php-cgisapi/cli/php。 您會注意到兩者都命名為 php。 在 make install 期間會發生什麼情況,取決於您的設定行。 如果在設定期間選擇了模組 SAPI(例如 apxs),或使用了 --disable-cgi 選項,則在 make install 期間,CLI 會複製到 {PREFIX}/bin/php,否則 CGI 會放置在那裡。 因此,舉例來說,如果您的設定行中有 --with-apxs,則在 make install 期間,CLI 會複製到 {PREFIX}/bin/php 。 如果您想覆寫 CGI 二進位檔的安裝,請在 make install 之後使用 make install-cli。 或者,您可以在設定行中指定 --disable-cgi

注意:

由於預設同時啟用 --enable-cli--enable-cgi,因此僅僅在您的設定行中加入 --enable-cli 並不一定表示在 make install 期間,CLI 會被複製為 {PREFIX}/bin/php

在 Windows 上,CLI 二進位檔在主資料夾中以 php.exe 的形式散發。 CGI 版本以 php-cgi.exe 的形式散發。 此外,如果使用 --enable-cli-win32 設定 PHP,則會散發 php-win.exe。 此版本的行為與 CLI 版本相同,但它不會輸出任何內容,因此不會提供主控台。

注意我使用的是哪個 SAPI?

從 shell 輸入 php -v 將告訴您 phpCGI 還是 CLI。 另請參閱函數 php_sapi_name() 和常數 PHP_SAPI

注意:

在 shell 環境中輸入 man php 即可取得 Unix man 手冊頁面。

新增筆記

使用者貢獻的筆記 33 則筆記

109
sep16 at psu dot edu
12 年前
您可以使用 parse_str() 函數輕鬆將命令列引數剖析到 $_GET 變數中。

<?php

parse_str
(implode('&', array_slice($argv, 1)), $_GET);

?>

它的行為就像您對 cgi-php 的預期一樣。

$ php -f somefile.php a=1 b[]=2 b[]=3

這會將 $_GET['a'] 設定為 '1',並將 $_GET['b'] 設定為陣列('2', '3')。

更棒的是,您可以利用 PHP 的 auto_prepend_file 指令,而不要將該行放在每個檔案中。 將該行放在其自己的檔案中,並在您的 cli 特定的 php.ini 中設定 auto_prepend_file 指令,如下所示

auto_prepend_file = "/etc/php/cli-php5.3/local.prepend.php"

它會自動前置於從命令列執行的任何 PHP 檔案。
22
apmuthu at usa dot net
7 年前
將 pause() 函數新增至 PHP,以等待任何使用者輸入並傳回該輸入

<?php
function pause() {
$handle = fopen ("php://stdin","r");
do {
$line = fgets($handle); } while ($line == '');
fclose($handle);
return
$line;
}
?>
23
frankNospamwanted at. toppoint dot. de
10 年前
剖析命令列引數 GET 字串,而不變更 PHP 指令碼 (linux shell)
URL:index.php?a=1&b=2
結果:output.html

echo "" | php -R 'include("index.php");' -B 'parse_str($argv[1], $_GET);' 'a=1&b=2' >output.html

(無需變更 php.ini)

您可以將此
echo "" | php -R 'include("'$1'");' -B 'parse_str($argv[1], $_GET);' "$2"
放在 bash 指令碼 "php_get" 中,以如下方式使用
php_get index.php 'a=1&b=2' >output.html
或導向文字瀏覽器...
php_get index.php 'a=1&b=2' |w3m -T text/html
16
PSIKYO at mail dot dlut dot edu dot cn
11 年前
如果您在 Windows 中編輯 php 檔案,並使用命令列方法上傳並在 Linux 上執行它。 您可能會遇到類似這樣的執行問題

[root@ItsCloud02 wsdl]# ./lnxcli.php
未顯示擴充功能 './lnxcli.php'。

或者您可能會遇到其他奇怪的問題。
注意 Enter 鍵。 在 Windows 環境中,Enter 鍵會產生兩個二進位字元 '0D0A'。 但是在 Linux 中,Enter 鍵只產生一個 '0A'。
如果您使用 Windows 編寫 php 程式碼,並在 Linux 上將其作為命令列程式執行,我希望它可以對某人有所幫助。
15
ohcc at 163 dot com
8 年前
在使用帶有 -r 的 cli 版本時,在 Windows 上使用 " 而不是 '

php -r "echo 1"
-- 正確

php -r 'echo 1'
PHP 剖析錯誤:語法錯誤,意外的 ''echo' (T_ENCAPSED_AND_WHITESPACE),在第 1 行的命令列程式碼中應為檔案結尾
18
drewish at katherinehouse dot com
19 年前
當您編寫單行 php 指令碼時,請記住 'php://stdin' 是您的好幫手。 這是我用來格式化 PHP 程式碼以包含在我的部落格上的簡單程式

UNIX
cat test.php | php -r "print htmlentities(file_get_contents('php://stdin'));"

DOS/Windows
type test.php | php -r "print htmlentities(file_get_contents('php://stdin'));"
21
Kodeart
13 年前
直接檢查,不需呼叫函式
<?php
if (PHP_SAPI === 'cli')
{
// ...
}
?>

你可以定義一個常數,以便在其他地方使用
<?php
define
('ISCLI', PHP_SAPI === 'cli');
?>
16
monte at ispi dot net
21 年前
當 $argv 的值包含加號 (+) 時,我遇到值被拆分的問題。請務必使用 CLI 版本,而不是 CGI 來解決此問題。

Monte
14
lucas dot vasconcelos at gmail dot com
17 年前
這只是先前腳本的另一個變體,可以將不以 '-' 或 '--' 開頭的參數分組。

<?php
function arguments($argv) {
$_ARG = array();
foreach (
$argv as $arg) {
if (
ereg('--([^=]+)=(.*)',$arg,$reg)) {
$_ARG[$reg[1]] = $reg[2];
} elseif(
ereg('^-([a-zA-Z0-9])',$arg,$reg)) {
$_ARG[$reg[1]] = 'true';
} else {
$_ARG['input'][]=$arg;
}
}
return
$_ARG;
}

print_r(arguments($argv));
?>

$ php myscript.php --user=nobody /etc/apache2/*
Array
(
[input] => Array
(
[0] => myscript.php
[1] => /etc/apache2/apache2.conf
[2] => /etc/apache2/conf.d
[3] => /etc/apache2/envvars
[4] => /etc/apache2/httpd.conf
[5] => /etc/apache2/mods-available
[6] => /etc/apache2/mods-enabled
[7] => /etc/apache2/ports.conf
[8] => /etc/apache2/sites-available
[9] => /etc/apache2/sites-enabled
)

[user] => nobody
)
15
Anonymous
3 年前
我們可以將許多參數直接傳遞到 shebang 行。
例如,透過 php 的 -d 參數設定許多 ini 設定。
---
#!/usr/bin/php -d memory_limit=2048M -d post_max_size=0
phpinfo();
exit;
---
./script | grep memory
memory_limit => 2048M => 2048M
---
但我們也可以在第二個腳本中使用此行為,因此透過 shebang 將第一個腳本作為直譯器調用。
---
#!./script arg1 arg2 arg3
---
然而,參數會以不同的方式分派到 $argv 中

所有參數都在 $argv[1] 中,$argv[0] 是直譯器腳本名稱,$argv[1] 是調用者的腳本名稱。

要將參數返回到 $argv 中,我們可以簡單地測試 $argv[1] 是否包含空格,然後像平常一樣重新分派。

#!/usr/bin/php -d memory_limit=2048M -d post_max_size=0
<?php
var_dump
($argv);
if (
strpos($argv[1], ' ') !== false){
$argw = explode(" ", $argv[1]);
array_unshift($argw, $argv[2]);
$argv = $argw;
}
var_dump($argv); ?>
---
array(3) {
[0]=>
string(8) "./script"
[1]=>
string(15) "arg1 arg2 arg3 "
[2]=>
string(14) "./other_script"
}
array(4) {
[0]=>
string(8) "./other_script"
[1]=>
string(4) "arg1"
[2]=>
string(4) "arg2"
[3]=>
string(4) "arg3"
}
---
這將在所有情況下保持相同的行為,並允許雙擊腳本來調用另一個腳本的兩個參數,甚至建立一個完整的直譯器語言層。另一個腳本不必是 php。請注意路徑。
26
ben at slax0rnet dot com
20 年前
只是給想從命令列使用互動模式的人的注意事項。

互動模式的目的是解析程式碼片段,而無需實際離開 php,它的工作方式如下

[root@localhost php-4.3.4]# php -a
已啟用互動模式

<?php echo "hi!"; ?>
<注意,這裡我們會按下 CTRL-D 來解析到目前為止輸入的所有內容>
hi!
<?php exit(); ?>
<再次按下 ctrl-d 這裡>
[root@localhost php-4.3.4]#

我注意到這不知何故從文件中省略了,希望對某人有所幫助!
20
notreallyanaddress at somerandomaddr dot com
15 年前
如果你想與使用者互動並接收使用者輸入,你所需要做的就是從 stdin 讀取。

<?php
echo "你確定要執行此操作嗎?輸入 'yes' 繼續: ";
$handle = fopen ("php://stdin","r");
$line = fgets($handle);
if(
trim($line) != 'yes'){
echo
"正在中止!\n";
exit;
}
echo
"\n";
echo
"謝謝,繼續...\n";
?>
15
OverFlow636 at gmail dot com
19 年前
我需要這個,但你可能不需要。
將執行參數放入 $_GET
<?php
if ($argv) {
foreach (
$argv as $k=>$v)
{
if (
$k==0) continue;
$it = explode("=",$argv[$i]);
if (isset(
$it[1])) $_GET[$it[0]] = $it[1];
}
}
?>
16
thomas dot harding at laposte dot net
16 年前
解析命令列:最佳化是邪惡的!

此頁面上的所有貢獻者都忘記了一件事,你可以用單引號或雙引號包圍 argv。因此,join 與 preg_match_all 結合在一起始終會破壞這一點 :)

這是一個建議

#!/usr/bin/php
<?php
print_r
(arguments($argv));

function
arguments ( $args )
{
array_shift( $args );
$endofoptions = false;

$ret = array
(
'commands' => array(),
'options' => array(),
'flags' => array(),
'arguments' => array(),
);

while (
$arg = array_shift($args) )
{

// 如果已達到選項的結尾,
// 我們將所有剩餘的 argv 視為參數
if ($endofoptions)
{
$ret['arguments'][] = $arg;
continue;
}

// 它是命令嗎? (以 -- 為前綴)
if ( substr( $arg, 0, 2 ) === '--' )
{

// 它是選項結尾的旗標嗎?
if (!isset ($arg[3]))
{
$endofoptions = true;; // 選項結尾;
continue;
}

$value = "";
$com = substr( $arg, 2 );

// 它是 '--option=argument' 的語法嗎?
if (strpos($com,'='))
list(
$com,$value) = split("=",$com,2);

// 此選項後面沒有其他選項,而是接著參數
elseif (strpos($args[0],'-') !== 0)
{
while (
strpos($args[0],'-') !== 0)
$value .= array_shift($args).' ';
$value = rtrim($value,' ');
}

$ret['options'][$com] = !empty($value) ? $value : true;
continue;

}

// 它是旗標或一系列旗標嗎?(以 - 為前綴)
if ( substr( $arg, 0, 1 ) === '-' )
{
for (
$i = 1; isset($arg[$i]) ; $i++)
$ret['flags'][] = $arg[$i];
continue;
}

// 最後,它不是選項、不是旗標、也不是參數
$ret['commands'][] = $arg;
continue;
}

if (!
count($ret['options']) && !count($ret['flags']))
{
$ret['arguments'] = array_merge($ret['commands'], $ret['arguments']);
$ret['commands'] = array();
}
return
$ret;
}

exit (
0)

/* vim: set expandtab tabstop=2 shiftwidth=2: */
?>
11
rob
17 年前
我使用 emacs 的 c-mode 進行編輯。在 4.3 版本中,像這樣啟動一個 cli 腳本

#!/usr/bin/php -q /* -*- c -*- */
<?php

告訴 emacs 在我載入檔案進行編輯時自動進入 c
-mode。`-q` 旗標實際上沒有任何作用(在較舊的 cgi 版本中,它會抑制腳本執行時的 html 輸出),但它導致 php 忽略註解的模式行。

在 5.2 版本中,
`-q` 顯然已被棄用。請將其替換為 `--` 以實現 4.3 版本與 emacs-mode-line 相同的行為:

#!/usr/bin/php -- /* -*- c -*- */
<?php

不要回到您的 4.3 系統並將
`-q` 替換為 `--`它似乎會導致 php 掛起並等待 STDIN...
11
goalain eat gmail dont com
18 年前
如果您的 php 腳本沒有使用 shebang (#!/usr/bin/php) 執行,
並且它發出了美妙且資訊豐富的錯誤訊息
「找不到命令。」,只需使用 dos2unix yourscript.php
瞧。

如果您仍然收到「找不到命令。」
請嘗試使用 ./myscript.php,加上 "./" 來執行
如果有效 - 這表示您目前所在的目錄不在可執行檔的搜尋路徑中。

如果您的 php 腳本沒有使用 shebang (#/usr/bin/php) 執行,
並且它發出了美妙且資訊豐富的訊息
「無效的空命令。」,這可能是因為 shebang 行中缺少「!」(如上面的範例)或該區域的其他問題。

\Alon
9
jeff at noSpam[] dot genhex dot net
22 年前
您也可以在 chmod 檔案後從命令列呼叫腳本 (例如:chmod 755 file.php)。

在檔案的第一行,輸入「#!/usr/bin/php」(或您的 php 可執行檔所在的位置)。如果您要抑制 PHP 標頭,請使用「#!/usr/bin/php -q」這行來指定您的路徑。
8
roberto dot dimas at gmail dot com
19 年前
我喜歡 perl 和 vbscript 的其中一點是,我可以將檔案命名為例如「test.pl」,並且只需在 Windows 命令列上輸入「test」,而無需使用 .pl 副檔名,命令處理器就會知道它是一個 perl 檔案,並使用 perl 命令直譯器執行它。

我對 .php3 檔案副檔名做了同樣的事情(我將專門使用 php3 來處理命令列 php 腳本,我這樣做是因為我的文字編輯器 VIM 6.3 已經針對 .php3 檔案提供了正確的語法突顯)。

我從「'系統' 控制台小程式 -> '進階' 標籤 -> '環境變數' 按鈕 -> '系統變數' 文字區域」修改了 Windows XP 中的 PATHEXT 環境變數。

然後從控制台「資料夾選項」小程式 -> '檔案類型' 標籤,我新增了一個新的檔案副檔名 (php3),使用 '新增' 按鈕並在彈出的視窗中輸入 php3。

然後在 'php3 副檔名詳細資訊' 區域中,我使用 '變更' 按鈕來尋找 Php.exe 可執行檔,以便 php3 檔案副檔名與 php 可執行檔關聯。

您還必須修改 'PATH' 環境變數,使其指向安裝 php 可執行檔的資料夾

希望這對某些人有所幫助
7
phpnotes at ssilk dot de
22 年前
若要在互動模式下傳遞 GET 變數,就像 HTTP 模式中一樣(例如,您的 URI 是 myprog.html?hugo=bla&bla=hugo),您必須呼叫

php myprog.html '&hugo=bla&bla=hugo'

(兩個 & 而不是 ? 和 &!)

在 $ARGC、$ARGV 值中只有一點點差異,但我認為在這些情況下這並不重要。
8
Anonymous
14 年前
使用 CLI (至少在 Windows 上) 時,某些 INI 路徑是相對於目前工作目錄的。例如,如果您的 error_log 設定為 "php_errors.log",那麼 php_errors.log 將會被建立 (或附加到現有檔案) 在您當下所在的任何目錄中 (如果您擁有寫入權限)。為了避免因為這種行為而導致錯誤日誌散落在各處,您可能會希望將 error_log 設定為完整路徑,或許設定到 php.exe 的目錄。
9
linn at backendmedia dot com
20 年前
對於那些想要使用會變更到腳本實際目錄的舊版 CGI 行為的人,請使用
chdir(dirname($_SERVER['argv'][0]));

在您的腳本開頭。
9
eric dot brison at anakeen dot com
17 年前
這是先前腳本的一個變體,也可以接受帶有 '=' 的參數
<?php
function arguments($argv) {
$_ARG = array();
foreach (
$argv as $arg) {
if (
ereg('--([^=]+)=(.*)',$arg,$reg)) {
$_ARG[$reg[1]] = $reg[2];
} elseif(
ereg('-([a-zA-Z0-9])',$arg,$reg)) {
$_ARG[$reg[1]] = 'true';
}

}
return
$_ARG;
}
?>
$ php myscript.php --user=nobody --password=secret -p --access="host=127.0.0.1 port=456"
Array
(
[user] => nobody
[password] => secret
[p] => true
[access] => host=127.0.0.1 port=456
)
4
sam marshall
5 年前
當使用 -R 旗標時,包含目前行內容的變數名稱 (不包括 LF) 是 $argn。

例如,您可以這樣寫程式碼

cat file.txt | php -R 'echo $argn . "\n";'

這只會輸出輸入檔案的每一行,而不會對其進行任何操作。
6
losbrutos at free dot fr
17 年前
另一個「變體」

<?php
function arguments($argv)
{
$_ARG = array();
foreach (
$argv as $arg)
{
if (
preg_match('#^-{1,2}([a-zA-Z0-9]*)=?(.*)$#', $arg, $matches))
{
$key = $matches[1];
switch (
$matches[2])
{
case
'':
case
'true':
$arg = true;
break;
case
'false':
$arg = false;
break;
default:
$arg = $matches[2];
}
$_ARG[$key] = $arg;
}
else
{
$_ARG['input'][] = $arg;
}
}
return
$_ARG;
}
?>

$php myscript.php arg1 -arg2=val2 --arg3=arg3 -arg4 --arg5 -arg6=false

Array
(
[input] => Array
(
[0] => myscript.php
[1] => arg1
)

[arg2] => val2
[arg3] => arg3
[arg4] => true
[arg5] => true
[arg5] => false
)
7
docey
19 年前
不知道這在 Linux 上是否相同,但在 Windows 上,每次
您將某些內容傳送到主控台螢幕時,PHP 都會等待
主控台返回。因此,如果您傳送大量小的
短字串文字,主控台開始使用
比 PHP 更多的 CPU 週期,從而減慢腳本速度。

請看這個示意圖
cpu 週期:1 ->php: print("a");
cpu 週期:2 ->cmd: output("a");
cpu 週期:3 ->php: print("b");
cpu 週期:4 ->cmd: output("b");
cpu 週期:5 ->php: print("c");
cpu 週期:6 ->cmd: output("c");
cpu 週期:7 ->php: print("d");
cpu 週期:8 ->cmd: output("d");
cpu 週期:9 ->php: print("e");
cpu 週期:0 ->cmd: output("e");

螢幕上只會出現 "abcde"。但是如果您這樣寫
您的腳本,它會快得多
cpu 週期:1 ->php: ob_start();
cpu 週期:2 ->php: print("abc");
cpu 週期:3 ->php: print("de");
cpu 週期:4 ->php: $data = ob_get_contents();
cpu 週期:5 ->php: ob_end_clean();
cpu 週期:6 ->php: print($data);
cpu 週期:7 ->cmd: output("abcde");

這只是一個小例子,但是如果您正在編寫一個
向主控台輸出大量內容的應用程式,例如文字
具有頻繁更新的螢幕,那麼最好
首先快取所有輸出,然後將其作為一大塊輸出
文字,而不是一次一個字元。

輸出緩衝非常適合這種情況。在我的腳本中,我輸出了
將近 4000 個字元的資訊,而且只是先快取它,就
速度提高了將近 400%,並且降低了 CPU 使用率。

因為顯示的內容並不重要,無論是 2
個字元還是 40,0000 個字元,都只是呼叫輸出
需要大量的時間。請記住這一點。

也許有人可以測試這在基於 Unix 的系統上是否相同
系統。似乎 STDOUT 流只是在等待
主控台回報就緒,然後繼續執行。
8
Adam, php(at)getwebspace.com
21 年前
好的,我在 PHP > 4.3.x 和是否使用 CLI 與 CGI 方面遇到了很多麻煩。4.3.2 的 CGI 版本會返回 (在瀏覽器中)
---
未指定輸入檔案。
---

而 CLI 版本會返回
---
500 內部伺服器錯誤
---

似乎在 CGI 模式下,PHP 會查看環境變數 PATH_TRANSLATED 來決定要執行的腳本,並忽略命令列。這就是為什麼在沒有此環境變數的情況下,您會收到「未指定輸入檔案」。但是,在 CLI 模式下,不會印出 HTTP 標頭。我相信這兩種情況都是預期的行為,但是當您的 CGI 包裝器傳送環境變數,卻在命令列上傳遞實際腳本名稱時,就會產生問題。

透過修改我的 CGI 包裝器來建立此 PATH_TRANSLATED 環境變數,解決了我的問題,並且我能夠執行 4.3.2 的 CGI 建置版本
5
obfuscated at emailaddress dot com
19 年前
這個貼文不僅是 PHP 的問題,但希望可以為某人節省幾個小時的頭痛。在 MacOS 上執行時 (儘管這可能發生在任何 *nix 上),我無法在不從命令列明確叫用 PHP 的情況下執行腳本

[macg4:valencia/jobs] tim% test.php
./test.php:找不到命令。

但是,當從命令列叫用 PHP 時,它可以正常運作

[macg4:valencia/jobs] tim% php test.php
好了,我們現在在這裡... 接下來呢?

檔案存取模式是否設定為可執行?是的。

[macg4:valencia/jobs] tim% ls -l
總計 16
-rwxr-xr-x 1 tim staff 242 2 月 24 17:23 test.php

當然,您記得將 PHP 命令新增為腳本的第一行,對吧?當然。

#!/usr/bin/php
<?php print "好了,我們現在在這裡... 接下來呢?\n"; ?>

那麼為什麼它不起作用呢?好吧,就像我說的... 在 Mac 上... 但是我也偶爾在我的 Windows 可攜式電腦上編輯檔案 (也就是說,當我在旅行並且沒有我可靠的 Mac 時)... 在 Windows 上使用 WordPad... 在 Mac 上使用 BBEdit...

啊... 在 BBEdit 中檢查檔案的儲存方式!Mac?Unix?還是 Dos?答對了。它以 Dos 格式儲存。將其變更為 Unix

[macg4:valencia/jobs] tim% ./test.php
好了,我們現在在這裡... 接下來呢?
[macg4:valencia/jobs] tim%

注意:如果您在多個平台上編輯您的 PHP 檔案 (也就是說,Windows 和 Linux),請確保您仔細檢查檔案是否以 Unix 格式儲存... 那些 \r 和 \n 會咬住您!
4
bluej100@gmail
17 年前
在 5.1.2 (以及其他版本,我假設) 中,-f 形式會從 $_SERVER['argv'] 中靜默捨棄腳本名稱後面的第一個參數。我建議除非您在特殊情況下需要它,否則請避免使用它。
4
Popeye at P-t-B dot com
21 年前
在 *nix 系統中,使用 WHICH 命令來顯示 PHP 二進位可執行檔的位置。這是在您的 PHP Shell 腳本檔案中用作第一行的路徑。(#!/path/to/php -q) 並從命令列執行帶有 -v 切換的 PHP,以查看您正在執行的版本。

範例

# which php
/usr/local/bin/php
# php -v
PHP 4.3.1 (cli) (build: 2003 年 3 月 27 日 14:41:51)
Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2002 Zend Technologies

在上面的範例中,您將使用: #!/usr/local/bin/php

另請注意,如果您的 PATH 中沒有目前/預設目錄 (.),您必須使用 ./scriptfilename 從命令列執行您的腳本檔案 (否則您將收到「找不到命令」錯誤)。使用 ENV 命令來顯示您的 PATH 環境變數值。
4
Alexander Plakidin
21 年前
當使用 PHP 4.3.0 從命令列執行時,如何將 PHP 腳本中的目前目錄變更為腳本的目錄?
(當在 PHP 4.3.0 下執行舊腳本時,您可能需要將此新增到這些腳本中,以實現向後相容性)

這是我正在使用的
chdir(preg_replace('/\\/[^\\/]+$/',"",$PHP_SELF));

注意:文件指出「PHP_SELF」在命令列 PHP 腳本中不可用。但是,它確實可用。這可能會在未來版本中變更,所以不要依賴這一行程式碼...

如果您的 register_globals=Off,請使用 $_SERVER['PHP_SELF'] 而不是 $PHP_SELF
4
stromdotcom at hotmail dot com
18 年前
在 Windows 應用程式中,將 php-win.exe 作為子程序產生以處理腳本時,會有一些怪異之處(都與 Windows 應用程式和主控台應用程式之間的管道有關)。

在 C++ 中執行此操作:

// 我們將在建立兩個管道並將它們附加到子程序的 stdin 和 stdout 之後,將 php.exe 作為子程序執行
// 建立兩個管道並將它們附加到子程序的 stdin 和 stdout
// 子程序會繼承我們的處理序,所以要定義 sa 結構
// 定義 sa 結構,以便子程序繼承我們的處理序

SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;

// 為我們的兩個管道建立處理序(每個管道兩個處理序,每個端點一個)
// 我們將會有一個用於 stdin 的管道和一個用於 stdout 的管道,每個管道都有一個讀取和一個寫入端點
HANDLE hStdoutRd, hStdoutWr, hStdinRd, hStdinWr;

// 現在建立管道,並使它們可繼承
CreatePipe (&hStdoutRd, &hStdoutWr, &sa, 0))
SetHandleInformation(hStdoutRd, HANDLE_FLAG_INHERIT, 0);
CreatePipe (&hStdinRd, &hStdinWr, &sa, 0)
SetHandleInformation(hStdinWr, HANDLE_FLAG_INHERIT, 0);

// 現在我們有兩個管道,我們可以建立進程
// 首先,填寫使用結構
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi;
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hStdoutWr;
si.hStdInput = hStdinRd;

// 最後,建立進程
CreateProcess (NULL, "c:\\php\\php-win.exe", NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);

// 關閉我們不使用的處理序
CloseHandle(hStdoutWr);
CloseHandle(hStdinRd);

// 現在我們已經啟動了進程,我們可以開始將 PHP 推送到它
WriteFile(hStdinWr, "<?php echo 'test'; ?>", 9, &dwWritten, NULL);

// 當我們完成寫入 stdin 後,我們關閉該管道
CloseHandle(hStdinWr);

// 從 stdout 讀取只稍微複雜一點
int i;

std::string processed("");
char buf[128];

while ( (ReadFile(hStdoutRd, buf, 128, &dwRead, NULL) && (dwRead != 0)) ) {
for (i = 0; i < dwRead; i++)
processed += buf[i];
}

// 完成讀取,所以也關閉這個處理序
CloseHandle(hStdoutRd);

完整的實作(以 C++ 類別實作)可在 http://www.stromcode.com 上找到
3
pyxl at jerrell dot com
22 年前
假設 --prefix=/usr/local/php,最好從 /usr/bin/php 或 /usr/local/bin/php 建立一個符號連結到 /usr/local/php/bin/php,這樣它就會在您的路徑中,並且每次重建時都會自動正確。如果您在重建後忘記複製二進制檔案,當發生問題時,您可能會陷入各種漫無目的的追逐。
2
james_s2010 at NOSPAM dot hotmail dot com
17 年前
我正在尋找一種方法來以互動方式從使用者獲取單個字元回應。 使用 STDIN 與 fread、fgets 等僅在按下 Enter 鍵後才會起作用。 因此,我提出了以下替代方案

#!/usr/bin/php -q
<?php
function inKey($vals) {
$inKey = "";
While(!
in_array($inKey,$vals)) {
$inKey = trim(`read -s -n1 valu;echo \$valu`);
}
return
$inKey;
}
function
echoAT($Row,$Col,$prompt="") {
// 在特定螢幕座標顯示提示
echo "\033[".$Row.";".$Col."H".$prompt;
}
// 在位置 10,10 顯示提示
echoAT(10,10,"Opt : ");

// 定義可接受的回應
$options = array("1","2","3","4","X");

// 獲取使用者回應
$key = inKey($options);

// 顯示使用者回應並結束
echoAT(12,10,"Pressed : $key\n");
?>

希望這對某些人有幫助。
To Top