调用sqlplus的php system()命令导致php挂起

时间:2017-03-08 20:48:30

标签: php oracle command-line-interface sqlplus

我有一个简单的php脚本,它调用sqlplus sqlldr文件并将数据转储到oracle中的表中。我把问题缩小到我认为是我的PHP脚本挂起的原因...这是: 当我从php CLI运行时,系统命令不会返回到php,而是挂在sqlplus的土地上。当从浏览器运行时,脚本按预期执行,然后我到达打印到浏览器的最终echo命令:我现在正在运行

<?PHP
system('sqlplus username/password@tnsNameOfDatabase',$out);
echo $out;
system('exit',$out);
echo $out;
echo 'I am done running now';

从已加载sqlplus的命令行运行此脚本将正确连接到数据库,我从该连接的输出如下所示:

SQL*Plus: Release 12.1.0.2.0 Production on Wed Mar 8 15:37:34 2017

Copyright (c) 1982, 2014, Oracle.  All rights reserved.

Last Successful login time: Wed Mar 08 2017 15:37:18 -05:00

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning and Oracle Label Security options

现在......问题是这导致我的php程序挂起,我再也无法回到php脚本了。如何退出sqlplus CLI以返回运行的php脚本?

SQLPLUS中的典型退出命令只是“退出”,我已尝试过(如上所示)...当手动运行时会产生以下结果:

Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning and Oracle Label Security options

如何退出sqlplus并返回应该继续的脚本?非常感谢任何帮助!

再次调用此sqlplus脚本的实际方法 - 从浏览器调用时效果非常好,但是从CLI调用时它会在此方法中挂起,然后返回。

private function loadTempData($object) {
$this->getLog()->appendLogFile('Constructed Control File: '.$object->getTempData()->getQaveLoadControl()->getFullPathFileName());
$this->getLog()->appendLogFile('Result saved in: '.$object->getTempData()->getExportFile()->getFullPathFileName());
    $object->getInsertCommandFile()->appendContent('$ sqlldr '.$this->getPersistEnv()->getUserSlid().'/'.$this->getPersistEnv()->getPassword().'@'.$this->getPersistEnv()->getDatabase().' control='.$object->getTempData()->getQaveLoadControl()->getFullPathFileName().' log='.$object->getTempData()->getQaveLoadControl()->getFullPathFileName().'.log');
$this->getLog()->appendLogFile('Loading data to Temp Table');
    $command = 'sqlplus '.$this->getPersistEnv()->getUserSlid().'/'.$this->getPersistEnv()->getPassword().'@'.$this->getPersistEnv()->getDatabase().' @'.$object->insertCommandFile->getFullPathFileName();
$this->getLog()->appendLogFile($command);
    system($command,$output);
// this line does not make it into the log...
    $this->getLog()->appendLogFile($output);
// this method does not return when run from CLI
    return true;
}

1 个答案:

答案 0 :(得分:1)

首先,您应该始终将动态输出转义为shell命令。其次,system()不会返回程序的输出,而是直接显示它。第二个参数使用程序的返回值填充,在成功执行的情况下通常为0。要收集在日志文件中使用的完整输出获取返回值,请使用exec()

<?php
$credentials = escapeshellarg("username/password@tnsNameOfDatabase");
$scriptfile = escapeshellarg("@/my/sqlldr/file");
exec("sqlplus $credentials $scriptfile", $output, $return);
// $output contains every line of output from the program, as an array
// $return contains the numeric exit code from the program
echo 'I am done running now';

最后,确保您指示程序在SQL文件as you discovered中使用实际的“EXIT”语句退出!