PHP Exec Won';t启动可执行文件


PHP Exec Won't Launch Executables

作为无法启动SRCDS(源代码游戏引擎的专用服务器)的故障排除的一部分,我决定尝试启动其他一些可执行文件(特别是Chrome和Firefox)。然而,这两项计划都没有启动。页面已加载(不像SRCDS那样挂起),但在检查Windows任务管理器时,进程从未真正启动$输出是一个0长度的数组,$return_var是1(没有给出实际发生错误的信息。

我使用的代码是(使用systempassthru而不是exec时不会发生变化):

<?php
// Save the current working directory, then set it to SRCDS' directory
$old_path = getcwd();
chdir("C:/Users/Johan/Desktop/SteamCMD/tf2/");
// Launch SRCDS. Only the 3rd exec allows the page to load.
//$tmp = exec("srcds -console -game tf +map ctf_2fort 2>&1",$output,$output2);
//$tmp = exec("srcds -console -game tf +map ctf_2fort >> tmp.txt",$output,$output2);
$tmp = exec("srcds -console -game tf +map ctf_2fort 1>/dev/null/ 2/&1",$output,$output2);
echo "<p>SRCDS Output: ".sizeof($output)."</p>";
echo "<p>SRCDS Output2: ".$output2."</p>";
// Test execution of other files
// test.bat echoes %time%
$tmp2 = exec("test.bat");
echo $tmp2;
// Trying to launch another executable
chdir("C:'Program Files (x86)'Mozilla Firefox");
$tmp2 = exec("firefox", $output, $output2);
echo $tmp2;
echo "<p>FF Output:".sizeof($output)."</p>";
echo "<p>FF Output2:".$output2."</p>";
// End
chdir($old_path);
echo "Done.";
?>

该输出:

SRCDS Output: 0
SRCDS Output2: 1
0:47:59,79
FF Output:0
FF Output2:1
Done.

我的问题是,这有什么原因吗?我这样做不对吗?

看起来你是:

  • 在Windows上
  • 尝试异步启动外部程序

以下是允许您这样做的秘密酱汁:

function async_exec_win($cmd)
{
    $wshShell = new COM('WScript.Shell');
    $wshShell->Run($cmd, 0, false); // NB: the second argument is meaningless
                                    // It just has to be an int <= 10
}

这需要COM类可用于您的PHP实例,您可能需要在PHP.ini中启用extension=php_com_dotnet.dll(从PHP 5.3.15/5.4.5开始)才能使其可用。

还要注意的是,这将需要您希望执行的文件的完整文件名,因为扩展名搜索列表不会在cmd.exe之外使用。因此,您需要的不是srcds -console ...,而是srcds.exe -console ...-就我个人而言,我不喜欢chdir()方法,我宁愿将exe的完整路径传递到函数中-但如果您这样做,您需要确保目录分隔符的类型适合操作系统。PHP会让你在任何你喜欢的地方使用你喜欢的东西,操作系统不会那么宽容。

为了完整起见,以下是如何在*nix上执行类似操作。这实际上比Windows版本更好,因为它还返回创建的进程的PID:

function async_exec_unix($cmd)
{
    return (int) exec($cmd . ' > /dev/null 2>&1 & echo $!');
}

需要注意的是:您的命令必须正确转义。这两种实现都不对正在执行的命令执行任何验证,它们只是盲目地运行它Never将用户输入传递到外部程序,而不将其适当地转义到主机操作系统!