1

我编写了一个 PHP 小类,它基本上gm convert通过 exec() 从 GraphicksMagick 1.3.12 调用以调整图片大小。来自实时站点的用户正在报告问题,我也能够在我的开发框中重现一些问题。

相关代码如下所示:

<?php

define('GM_PATH', 'C:\\Archivos de programa\\GraphicsMagick-1.3.12-Q16\\gm.exe');

[...]

private function resize($width, $height, $do_not_upscale=TRUE){
    $source = escapeshellarg($this->source_file);
    $target = escapeshellarg($this->target_file);
    $command = escapeshellarg(GM_PATH) . ' convert ';
    $parameters = array();

    $parameters[] = $source;
    $parameters[] = sprintf('-resize "%dx%d%s"', round($width), round($height), $do_not_upscale ? '>' : '');
    $parameters[] = '+profile "*"';
    $parameters[] = $target;

    $execute = $command . ' ' . implode(' ', $parameters) . ' 2>&1';

    exec($execute, $output, $return);
    if( $return==0 ){
        return $this->target_file;
    }else{
        throw new Exception('Image resizing failed: return code ' . $return . ': ' . implode(PHP_EOL, $output));
    }
}

实时站点在 PHP/5.2.9-2 下运行,开发站点在 PHP/5.3.0 下运行。两个盒子都运行 Windows Server 2003、Apache/2.2 和 GraphicsMagick 1.3.112 Q16。

在实时站点中,我遇到了 return code 异常1。在开发站点中,我可以随机看到一个cmd.exe进程如何永远保持空闲,使用 0% CPU 直到我终止任务。

鉴于它是一个外部工具,我已经没有关于下一步做什么的想法了。如何解决此问题?

更新#1

我在一段不相关的代码中修复了一个小错误,并且我正在登录到一个文件,每一步我都能想到(包括gm.exe的活动-debug All),但我无处可去。PHP 到达 exec() 调用并 gm.exe保持永远运行,什么也不做。

更新#2

我已经通过两种方式执行了确切的命令。日志文件中的回显显示:

"C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe" convert  -debug All "\\SHARE\Project\tmp\mini_4d13465d4bc4b.jpg" -resize "1024x1024>" +profile "*" "\\SHARE\Project\tmp\mini_4d13465dafddd.jpg" 2>>"//SHARE/Project/Miniatura-01.log"

Process Explorer显示的进程属性中,命令行如下所示:

cmd.exe /c ""C:\Archivos de programa\GraphicsMagick-1.3.12-Q16\gm.exe" convert  -debug All "\\SHARE\Project\tmp\mini_4d13465d4bc4b.jpg" -resize "1024x1024>" +profile "*" "\\SHARE\Project\tmp\mini_4d13465dafddd.jpg" 2>>"//SHARE/Project/Miniatura-01.log""

我可以手动运行这两个命令,尽管第二个命令只能从 Start->Run (而不是从命令提示符)运行,除非我双引号整个表达式

无论如何,我有理由确定该命令会按预期执行,因为我确实得到了调整大小的图像,并且 gm 生成的调试日志看起来很正常。最后一行总是看起来像这样,当它停止时,当它没有时:

13:53:52 0:03 3.016u 2344 module.c/UnloadModule/2180/配置:卸载“JPEG”模块...

我怀疑有什么东西会阻止进程在完成后退出:病毒扫描程序、shell 扩展或其他东西......

整件事开始变得不值得修复。我会考虑切换到 ImageMagick 或普通的 PHP 函数图像。

更新#3

有趣...我已经切换到 ImageMagick 并且遇到了同样的问题!而且我总是可以重现它:我只需要打开两个浏览器选项卡。

很明显,我忘记了如何从 PHP 运行命令。我想我会尝试用纯 PHP 代码调整图片的大小。

4

2 回答 2

0

您是否打印出正在执行的确切命令?(并且您检查过打印的字符串是否有任何明显的错误?)

您是否尝试过直接从命令行运行该确切命令(即与 PHP 分开)?它在那种情况下有效,还是也锁定在那里?

如果完全相同的命令在单独运行时有效,那么您使用 PHP 调用外部命令的方式可能存在问题。

如果它不起作用,那么您可能在提供给 GM 的命令行参数中存在错误,或者您可能在 GM 本身中发现了错误。

无论哪种方式,这应该可以帮助您更好地处理发生错误的地方。

我建议的另一件事是将 GM 文件夹添加到您的系统路径中,这样您就可以gm自己调用该命令,而不必调用define整个路径。

哦,顺便说一句,你知道 PHP 有一个 GraphicsMagik 扩展,对吧?这意味着您不需要使用exec. 您需要从 PECL 安装它,但这可能是值得的……请参阅http://devzone.zend.com/article/10531

于 2010-12-23T13:40:56.667 回答
0

感谢一位同事,我找到了解决方案:

http://es2.php.net/manual/en/function.exec.php#99781

在 Windows-Apache-PHP 服务器上,同时多次使用 exec 命令会出现问题。如果同一用户在同一时间多次加载脚本(使用 exec 命令),则服务器将冻结。在我的例子中,使用 exec 命令的 PHP 脚本被用作图像标签的来源。一个 HTML 中的多个图像使服务器停止。此处(http://bugs.php.net/bug.php?id=44942)与解决方案一起描述了该问题 - 在 exec 命令之前停止会话并在其之后再次启动它。

<?php

session_write_close();
exec($cmd);
session_start();

?>
于 2010-12-23T18:03:36.900 回答