【问题标题】:PHP exec, system or passthru all remove single or double quotesPHP exec、system 或 passthru 都删除单引号或双引号
【发布时间】:2011-12-15 22:58:50
【问题描述】:

当我尝试通过 php 的 exec/passthru/system 函数向 shell 执行命令时,它似乎会从命令中删除引号。

$str_file = '1323988284_700.csv';
exec("/usr/bin/lftp -e 'set ftp:passive-mode true; set ftp:ssl-protect-data yes; put /web/files/{$str_file}; bye;' -u user,pass ftp://ftp.site.com/uploaddir/");

这是检查过程的输出

ps faxxx | grep lftp
4486 ?        S      0:00  |       \_ /usr/bin/lftp -e set ftp:passive-mode true; set ftp:ssl-protect-data yes; put /web/files/1323988284_700.csv; bye; -u user,pass ftp://ftp.site.com/uploaddir/

如您所见,它显示了不带单引号运行的进程。这会导致 lftp 出错。

现在它只是挂起,直到我杀死它,我相信这是因为如果我将进程列表中显示的内容输入到命令中,它会出错并让你留在 lftp shell。

PHP 安全模式已关闭

我已经尝试了以下报价的

\'
\\'
\\\'
\\\\'
''
'''
''''

更新


我想在进一步测试时添加它.. 如果我创建一个 shell 脚本 (run_ftp.sh) 并通过 php 运行它,它也会从 run_ftp.sh 中删除引号.. 所以这让我认为它不是php 导致问题。

SELinux 已关闭.. linux/bash 是否有任何其他安全措施可能导致此问题?

【问题讨论】:

  • 你试过php.net/escapeshellarg吗?
  • 是的,我有,它也失败了。引号被删除,我留下了引号应该在的地方。

标签: php linux exec quote


【解决方案1】:

PHP 中的exec()system() 命令通过shell 传递。 shell 解析命令行并删除引号。然而,它将整个字符串保留为一个参数,并将其铲到实际的 execve() 系统调用等。

应用程序将接收单引号中的字符串作为一个参数ps 工具可能只是按原样列出它们。

不过,lftp 工具可能会自己进行一些解析(-e 标志听起来就是这样)。在这种情况下,两级引号可能会有所帮助:

exec("lftp -e '\'multiple; commands; for the lftp thingy\''");

【讨论】:

  • PHP中没有一个表单可以避免shell处理吗?贝壳真是善变的动物家园。
  • 不,它根本没有用户输入。
  • @pst:不在核心函数中,但我相信pcntl_exec() 映射到真正的系统调用。 (当然是不同的行为,替换当前进程。)
  • 我刚刚尝试了这个,有些引号仍然被剥离,我留下... -e \multipule;命令\ ...
  • @Antivanity:对此无能为力。然而,将它们剥离的不是 PHP。哪个$_SERVER["SHELL"] 类型在您的服务器上处于活动状态?
【解决方案2】:

有人读过 lftp 手册页吗?

它在“选项”下显示:

-e commands      执行给定的命令并且不退出

-c commands      执行给定的命令并退出

所以你的 lftp 挂起,因为你使用的是 -e 而不是 -c。

这与 PHP 或 shell 去掉引号无关。外壳总是这样做,它就是这样工作的。 PS 的输出并不意味着可以复制和粘贴。

【讨论】:

    【解决方案3】:

    我找到了使用 PHP 函数 proc_open 的解决方案。它更复杂,但对我来说效果很好。

    $command = "lftp -u $USER,$PASSWORD -e 'get /tmp/backup-2012-08-15.zip; bye' sftp://$HOST";
    
    $io = array();            
    $p = proc_open($command,
               array(1 => array('pipe', 'w'),
                     2 => array('pipe', 'w')), $io);
    
    /* Read output sent to stdout. */
    while (!feof($io[1])) {
        echo "STDOUT: ".fgets($io[1]);
    }
    /* Read output sent to stderr. */
    while (!feof($io[2])) {
        echo "STDERR: ".fgets($io[2]);
    }
    
    fclose($io[1]);
    fclose($io[2]);
    proc_close($p);
    

    此代码的灵感来自 PHP SHELL 工具。 PDT:对不起我的英语

    【讨论】:

      【解决方案4】:

      有一个自解释的UNIX SHELL Quote Tutorial,试试看!

      【讨论】:

      • 我不确定这是否有帮助,因为问题出在 php.ini 中。我可以通过命令行执行命令就好了。
      【解决方案5】:

      1) 将参数写入tmp 文件(这会保留单引号)。
      2)exec("/usr/bin/lftp<tmp");

      【讨论】:

        猜你喜欢
        • 2021-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-11
        • 2013-10-29
        • 2011-03-09
        相关资源
        最近更新 更多