php 调用 sqlplus 的 system() 命令导致 php 挂起
php system() command that calls sqlplus causes php to hang
我有一个简单的 php 脚本,它调用 sqlplus sqlldr 文件并将数据转储到 oracle 中的 table。我已将问题缩小到我认为是我的 php 脚本挂起的原因......这是:
当我从 php CLI 运行 时,系统命令不会返回到 php,而是挂在 sqlplus 中。当 运行 来自浏览器时,脚本按预期执行,我得到了打印到浏览器的最终 echo 命令:我现在 运行ning.
<?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 脚本 运行ning?
SQLPLUS 中典型的退出命令很简单 'exit' 我已经试过了(正如你在上面看到的)...当 运行 手动导致以下结果时:
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 调用时,它就挂在它之前的这个方法中 returns。
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;
}
首先,您应该始终将动态输出转义为 shell 命令。其次,system()
不会return程序的输出,而是直接显示。第二个参数由程序中的 return 值填充,在成功执行的情况下通常为 0。要收集完整输出以用于日志文件 和 获取 return 值,请使用 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 文件中的实际 "EXIT" 语句指示程序退出,as you discovered!
我有一个简单的 php 脚本,它调用 sqlplus sqlldr 文件并将数据转储到 oracle 中的 table。我已将问题缩小到我认为是我的 php 脚本挂起的原因......这是: 当我从 php CLI 运行 时,系统命令不会返回到 php,而是挂在 sqlplus 中。当 运行 来自浏览器时,脚本按预期执行,我得到了打印到浏览器的最终 echo 命令:我现在 运行ning.
<?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 脚本 运行ning?
SQLPLUS 中典型的退出命令很简单 'exit' 我已经试过了(正如你在上面看到的)...当 运行 手动导致以下结果时:
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 调用时,它就挂在它之前的这个方法中 returns。
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;
}
首先,您应该始终将动态输出转义为 shell 命令。其次,system()
不会return程序的输出,而是直接显示。第二个参数由程序中的 return 值填充,在成功执行的情况下通常为 0。要收集完整输出以用于日志文件 和 获取 return 值,请使用 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 文件中的实际 "EXIT" 语句指示程序退出,as you discovered!