3

我有一个非常奇怪的情况,Java 进程在通过 Apache/PHP 调用时似乎挂起,但从命令行调用时可以。我花了几个小时调试这个,无济于事。欢迎任何和所有想法!

情况:我有一个 .class 文件(没有原始 Java 代码),它读取输入文件、处理读取信息并在标准输出上写入报告。Java 代码不读取标准输入,只写入标准输出。我将它包装在一个很小的 ​​Perl 脚本中,该脚本基本上只执行“java -cp /path/to/classfile MyJavaProgram /path/to/inputfile/to/process”。这样我就可以从命令行调用它进行测试,这就像一个魅力。接下来,我尝试使用 popen() 从 PHP 调用它,而 Java 只是挂起。我在 ps 列表中看到 Perl 进程和 Java;但是Java进程永远等待。一旦我杀死它,网络服务器页面将继续加载(但当然没有 Java 进程将生成的预期输出)。

到目前为止我尝试了什么:

  • 将 Java 进程包装在 shell 脚本中,行为相同。Java只是挂起。
  • 使用没有包装器的 popen() 从 PHP 运行它,行为相同。
  • 使用 system() 或 passthru() 从 PHP 启动它,行为相同。
  • 在 Perl 包装器中,为 /dev/null 重新打开 STDIN(以便读取 stdin 立即返回 EOF),行为相同。
  • 在 Perl 包装器中,为 /dev/null 重新打开 STDERR,行为相同。
  • 在 Perl 包装器中,为 /dev/null 重新打开 STDOUT。在这里,我希望没有输出(因为它被丢弃),但 Java 进程仍然挂起。
  • 在 Perl 包装器中,重新打开 /dev/null 的所有 3 个流。Java 仍然挂起。
  • 用简单的“ls -l /bin”替换 Perl 包装器中的 Java 调用。这按预期工作;网页被“ls”列表填充。所以问题不在于 PHP 或 Perl。
  • 使用“/bin/sh -c 'java .....'”启动 Java 进程。同样的行为,Java 挂起。
  • 在 Perl 包装器中,我也转储环境变量以检查它们。环境似乎还可以。
  • 当 Java 进程运行时,我在 ps 列表中查找 Perl 包装器调用,并将其复制/粘贴到命令行。奇迹般有效。
  • 同样,当 Java 进程挂起时,我在 ps 列表中查找调用,并将其复制/粘贴到命令行。奇迹般有效。
  • 我还验证了输入文件在从 Web 服务器调用时是可读的。以上所有使用命令行的测试都是使用与 Apache 用户相同的用户 ID 运行的。

不幸的是,我无法用我可以控制的东西替换 Java 代码。我只有 .class 文件可以使用。我还没有尝试过在 Linux 下运行它,所以这仍然可能是 OSX 特定的问题(这会让我感到惊讶)。

这到底是怎么回事?任何和所有“狂野”的想法都值得赞赏..谢谢!

4

1 回答 1

0

从 apache 和 cmd 行检查所有环境,包括路径、UID 等。

当从两个地方(apache和cmdline)包装它时,还要检查java进程在挂起时做了什么(使用truss/tusc/strace -f java xxxxxxxxxxx 2>/tmp/trace.$$),然后比较结果。

此外,当从 perl 包装时,在执行 java 之前将 stdin、stdout、stderr 的 autoflush 设置为 1。

于 2013-04-30T16:10:46.243 回答