PHP system() - 返回状态总是0

11

我需要让以下脚本运行。

// File: script_a.php
<?php exit(1); ?>

// File: script_b.php
<?php 
     system('php script_a.php', $return);
     var_dump($return);
?>

现在我的问题是:在我的Windows系统上运行script_b.php会正常显示int(1)。但是在我们的Unix服务器上,我总是得到int(0),这使我无法检查是否发生了某些故障在script_a.php内部。

有人知道这个问题的原因以及如何解决吗?


2
当从命令行运行 script_a.php 时,$? 包含什么内容? - Ignacio Vazquez-Abrams
2
$? 是在 bash 中的返回参数。php script_a.php; echo $? - Ignacio Vazquez-Abrams
如果您将 exit(1) 替换为 exit(2),每个操作系统的返回值是什么? - Evan Mulawski
谢谢你的回答。最终我找到了这个失败的原因。实际上,我一直在调用 php script_a.php | tee test.log 记录输出。如果我不使用 tee 进行日志记录,我可以得到预期的结果 int(1) - Sebastian Schmidt
原因是我总是得到tee命令的退出状态。有什么解决办法吗? - Sebastian Schmidt
显示剩余6条评论
11个回答

1

尝试使用PHP system调用绝对路径来执行脚本,例如:system('/usr/bin/php /path/to/script_a.php', $return);。也许这是一个路径问题。(您可以使用which php命令查找PHP可执行文件的绝对路径)。

另外,正如有人建议的那样,在UNIX服务器上通过运行php script_a.php; echo $?命令来调试script_a.php的实际返回值。该echo将输出最后一个返回值,即script_a.php返回的值。

无论如何,我建议按照include()文档中描述的示例#5进行include并带有return语句。如果您能够像这样调整您的脚本,这是一种更有效的通信方式。

// File: script_a.php
<?php return 1; ?>

// File: script_b.php
<?php 
     $return = (include 'script_a.php');
     var_dump($return);
?>

1

您可能需要检查它是否在Unix机器上调用了正确的php可执行文件。在许多UNIX系统中,您需要调用php-cli可执行文件而不是php可执行文件以在命令行上使用。 另一个要检查的事项是权限。也许执行script_b.php脚本的用户没有执行script_a的权限?


1

在编程中,是否能够检查到某处调用了 __halt_compiler() 呢?


@Ignacio - 当我嵌入__halt_compiler(); exit(1);时,我可以复制相同的输出,并且可能将PHP在Unix别名中转换为某些内容? - ajreal
在这种情况下,两个平台都会失败,是吗? - Ignacio Vazquez-Abrams
是的,在这两种情况下都会失败,但所有者只说了 php script_a.php,而 php 可能会有不同的行为。 - ajreal

0

我也无法重现它(PHP 5.3.3, Ubuntu)。

当我将退出值设置为更好的grep-able值,比如"666",跟踪脚本也返回了预期的结果:

strace -f php5 script_b.php 2>&1 | grep EXITSTATUS

[pid 18574] <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 666}], 0, NULL) = 18575
waitpid(18574, [{WIFEXITED(s) && WEXITSTATUS(s) == 666}], 0) = 18574

使用"-f"选项,strace将跟踪系统调用中的子进程。 "2>&1"将标准错误重定向到标准输出使grep覆盖所有内容。您还可以将其管道传输至"|less"进行筛选,但输出结果会很长且难以阅读。

0

在我的系统Ubuntu Hardy中,无法再现这种情况。以下是一个示例:

/tmp$ mkdir /tmp/sbuzz
/tmp$ cd /tmp/sbuzz
/tmp/sbuzz$ echo '<?php exit(1); ?>' >script_a.php  
/tmp/sbuzz$ cat >script_b.php
<?php 
     system('php script_a.php', $return);
     var_dump($return);
?>
/tmp/sbuzz$ php script_b.php 
int(1)
/tmp/sbuzz$ echo '<?php exit(2); ?>' >script_a.php  
/tmp/sbuzz$ php script_b.php
int(2)
/tmp/sbuzz$ 

退出代码0表示程序成功执行,所以它听起来像是您可能正在运行错误的script_a.php或者"php"可执行文件没有按照您的期望工作?也许您有一个名为"php"的脚本在解释器之前的路径中?"which php"报告了什么?在我的系统上,它说"/usr/bin/php"。

如果PHP找不到脚本,它将以1退出,例如:

/tmp/sbuzz$ cat script_b.php 
<?php
     system('php doesnt_exist_script_a.php', $return);
     var_dump($return);
?>
/tmp/sbuzz$ php script_b.php 
Could not open input file: doesnt_exist_script_a.php
int(1)
/tmp/sbuzz$

在这种情况下,我将script_b.php更改为尝试运行一个不存在的脚本,并且我得到了退出代码1(如果成功完成,则应该是2,因为我更改了上面的script_a),但它还显示了无法运行程序的错误。
您可能希望尝试更改为明确运行PHP可执行文件的完整路径:
system('/usr/bin/php script_a.php')

或者也可以返回脚本的完整路径:

system('/usr/bin/php /tmp/sbuzz/script_a.php')

你也可以尝试执行一个特定的程序,返回1,作为另一个数据点,例如:

system('false')
system('bash -c "exit 69"')

你可能想尝试使用除了1以外的退出代码,因为1是常见的失败代码。这就是为什么我在上面使用了“exit 69”的原因。“false”会退出并返回1。

当然,还可以直接运行script_a.php脚本:

/tmp/sbuzz$ php script_a.php 
/tmp/sbuzz$ echo $?
2
/tmp/sbuzz$ 

"

"$?"是上一个运行命令的退出代码,在shell提示符下。

"

0

尝试:

<?php
    die(1);
?>

如果那也失败了,检查一下以下标准输出:
strace php script_a.php

0

我知道这是一个旧的帖子,但我刚遇到了类似的问题。

当我将脚本在后台运行时,退出状态被设置为0,类似于:

system('php script_a.php &', $return);

你是不是为了可读性而进行泛化处理?


0

你有检查 Unix 服务器上是否启用了 safe_mode 吗?

PHP 注意事项:

注意:当启用 safe_mode 时,您只能在 safe_mode_exec_dir 中执行文件。出于实际原因,目前不允许在可执行文件的路径中使用 .. 组件。

或者系统函数被禁止执行了吗?


安全模式已关闭,并且允许调用系统。如果我在脚本_a中添加一些echo语句然后退出,我可以正常获取输出,但退出状态仍然为0。 - Sebastian Schmidt
你尝试过其他的执行方法吗?也许exec()或passthru()会起作用。 - Rod
我尝试了exec()和passthru()。在命令行上,结果如预期,但在Web服务器上执行时,$return的值为0。 - Sebastian Schmidt
如果你执行的是“echo 1”而不是“exit(1)”,会怎样? 根据PHP文档,使用一个数字退出只会发送一个退出信号,而不会打印任何内容,也许这就是问题所在。 - Rod

0

不确定这些问题是否相关,但你可以看一下exec always returns -1 (or 127),因为我过去也遇到过类似的问题...即使我没有真正解决它。

在你的情况下,可能是另一个问题,不确定如何重现,但我见过一些情况,未知命令的返回字符串将是bash的返回字符串(bash:command not found)。在大多数服务器上,我没有发现任何问题。您可以尝试检查当前用户(我假设是www-data)的shell设置。


0

考虑到您的评论,即在UNIX系统中当script_b为以下形式时出现问题

system('php script_a.php | tee myLogFile', $return);

您可以使用以下语法

system("bash -c 'php script_a.php | tee log.txt ; exit \${PIPESTATUS[0]}'", $return);

请查阅“man bash”并搜索“PIPESTATUS”以获取更多详细信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接