You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP未切换当前目录时exec执行ghostscript命令失效问题

先澄清一个误区:exec()中执行的所有命令都运行在PHP拉起的独立子shell进程里,你在命令里写的cd只会修改这个子shell的工作目录,命令执行结束后子shell就销毁了,完全不会改动PHP主进程的当前工作目录,和你不想用chdir()修改PHP进程目录的需求没有冲突。

问题根因
  • 你第一段可运行的代码里,chdir('/user/bin/ghostscript')之后执行的是不带./前缀的gs命令,系统不会在当前切换的目录下找可执行文件,而是会从环境变量PATH定义的全局路径里搜索Ghostscript程序。也就是说你之前的chdir根本不是用来定位gs二进制的,只是刚好把工作目录切到了gs运行时默认读取配置/依赖的路径,才让命令跑通了。
  • 第二段失效的代码里,cd到目录后执行的是./gs,是强制调用/user/bin/ghostscript目录下的本地二进制文件,这个文件要么没有可执行权限、要么和主机系统架构不匹配、要么被主机的open_basedir安全限制拦截,才会执行失败。另外部分共享主机的PHP默认调用的受限shell不支持&&命令拼接符,也会导致整条命令解析失败。
修复方案

优先选第一种方案,稳定性最高:

  • 先找到全局可正常调用的gs路径
    把你第一段可运行的代码临时加一行调试,拿到全局gs的真实绝对路径:
    <?php
    chdir('/user/bin/ghostscript');
    exec('which gs', $pathInfo);
    print_r($pathInfo);
    
    一般输出的路径会是/usr/bin/gs或者/usr/local/bin/gs这类系统默认路径。
  • 直接用绝对路径调用gs,不需要切任何目录
    拿到路径后直接写全路径执行即可,既不需要调用PHP的chdir(),也不需要在命令里拼cd,完全不会修改PHP进程工作目录:
    <?php
    $a = '/home1/user/public_html/a.pdf';
    $b = '/home1/user/public_html/b.pdf';
    $gsBin = '/usr/bin/gs'; // 替换成你上一步打印出来的实际路径
    // 路径参数用escapeshellarg转义,避免特殊字符导致命令失败
    exec($gsBin . ' -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER -dFirstPage=1 -dLastPage=2 -sOutputFile=' . escapeshellarg($b) . ' ' . escapeshellarg($a), $cmdOutput, $returnCode);
    
    执行后如果$returnCode为0说明运行成功,非0可以打印$cmdOutput看具体报错信息。

如果你必须使用/user/bin/ghostscript目录下的特定版本gs,用下面的写法适配共享主机的受限shell:

<?php
$a = '/home1/user/public_html/a.pdf';
$b = '/home1/user/public_html/b.pdf';
// 用分号代替&&做命令分隔,兼容不支持&&的受限shell,同时给gs写全绝对路径避免解析错误
exec('cd /user/bin/ghostscript; /user/bin/ghostscript/gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER -dFirstPage=1 -dLastPage=2 -sOutputFile=' . escapeshellarg($b) . ' ' . escapeshellarg($a), $cmdOutput, $returnCode);

如果执行后返回码是126,说明该目录下的gs文件没有可执行权限,要么联系主机商开通权限,要么换用全局安装的gs版本即可。

内容的提问来源于stack exchange,提问作者TWolfe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:24:22