簡體   English   中英

從 PHP 調用沒有 Shell 的 PHP-CLI 腳本

[英]Call PHP-CLI script without Shell from PHP

我想從我的 PHP 腳本運行 Composer 的一些供應商腳本。

盡管命令本身很快完成,但調用每個命令都需要很長時間。 我假設通過shell_exec()創建一個新的 shell 需要一些時間。

我想通過require關鍵字直接調用 PHP 腳本,但更改全局$argv以包含腳本參數不適用於被調用的腳本。 $argv是跨腳本文件隱式不可變的還是我的思維方式有另一個錯誤?

下面是一些示例代碼(應通過 CLI 執行,未經測試):

namespace Foo;
class Bar
{
    public static function call_cs_fixer()
    {
        $GLOBALS['argv'] = [
            '/path/to/vendor/bin/php-cs-fixer',
            'fix',
            '--config',
            '"/path/to/.php-cs-fixer.php"',
            '"/path/to/project"',
        ];
        return require $GLOBALS['argv'][0];
    }
}
echo \Foo\Bar::call_cs_fixer();

$argv是跨腳本文件隱式不可變的還是我的思維方式有另一個錯誤?

這取決於您嘗試調用的腳本/實用程序的工作方式。 這意味着你不能指望它能穩定地工作,除非你知道它有這個界面,否則我會避免使用它。 因為你不知道——否則你不會那樣問這個問題——在這種情況下把這個想法扔進垃圾箱。

我假設通過shell_exec()創建一個新的 shell 需要一些時間。

這可能是(我們無法查看您的系統配置),但如果它是 linux 系統,則很可能不是這種情況

在實踐中,使用新的 shell 子流程來調用工具是更好的方法。 這也是composer(1)調用腳本的方式(請參閱腳本)——除非它們被綁定為(靜態)方法——並且對於composer exec命令始終如此。

原因是您不僅可以更好地控制命令行 arguments,還可以更好地控制工作目錄和環境參數(簡稱環境變量環境),比較proc_open(php) 標准流也可用。

當您在 composer 的上下文中運行時,如果您可以訪問它的源代碼(例如,您在 composer.json 配置中綁定了一個 composer 腳本或掛鈎),您可以使用 composer 本身附帶的流程組件(它的所有 PHP),它在那里有相當多的實用性。

如果你只是想輕松開始,我發現passthru(php) function 非常適合快速入門:

// the command you'd like to execute
$command = '/path/to/vendor/bin/php-cs-fixer';
$args = [
    'fix',
    '--config',
    '/path/to/.php-cs-fixer.php',
    '/path/to/project'
];


// build the command-line
$commandLine = sprintf(
   '%s %s',
   $command,
   implode(' ', array_map('escapeshellarg', $args))
);

// execute
$result = passthru($commandLine, $exitStatus);

// be verbose and give some debug info
fprintf(
    STDERR, 
    "debug: command %s exited with status %d\n", 
    $commandLine, 
    $exitStatus
);

// throw on exit status != 0, a convention only but you often want this
if (false === $result || $existStatus !== 0) {
    throw new \RuntimeException(sprintf(
        'command "%s" exited with non-zero status %d (result=%s).\n',
        addcslashes($commandLine, "\0..\37\"\\\177..\377"),
        $exitStatus,
        var_export($result, true)
    ), (int)$exitStatus);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM