我正在尝试从Web界面执行一些PostgreSQL数据库命令。 我使用proc_open()来管道到Windows命令提示符。 因为psql(和所有其他postgres命令)不接受密码作为选项,我必须将密码发送到写入流。 下面的代码导致浏览器挂起。要么未创建资源,要么未正确管道密码。欢迎提出任何建议。
$cmd = '""C:\\Program files\\PostgreSQL\\9.0\\bin\\psql.exe" --host localhost --port 5432 -U postgres --dbname $database_name --command "$query""';
$p=proc_open($cmd,
array(array("pipe","r"), array("pipe","w"), array("pipe","w")),
$pipes);
if (is_resource($p)){
fwrite($pipes[0],"mypassword");
fclose($pipes[0]);
proc_terminate($p);
proc_close($p);
}
[你会注意到命令中疯狂的双重引用 - 出于某种原因显然需要Windows。]
欢迎解决这个问题的方法:
答案 0 :(得分:3)
不要乱用密码提示,最好在%APPDATA%\postgresql\pgpass.conf
中输入一个条目。格式为
hostname:port:database:username:password
确保选择运行网络服务器进程的用户的%APPDATA%
。
如果您真的开始与提示进行交互,您可以尝试人们经常用于执行此类任务的Expect库...免责声明:我从未在Windows上使用它不知道它在那里有多好,或者它是否真的有必要。也许你的fwrite只是缺少终止换行符。
答案 1 :(得分:0)
正如@ c-ramseyer建议的那样,通过proc_open()
来模拟交互式提示是不可取的。 PostgreSQL提供了两种方法来通过交互式提示来提供密码。方法(1)是将其作为环境变量提供,如另一个答案所示。方法(2)是在DB用户的pgpass.conf
directiory中创建%appinfo%
文件。 (要从Windows命令提示符处找到该目录,请执行echo %appinfo%
。)有关如何创建此单线程配置文件,请参阅postgresql。由于我仍然不理解的原因,这些方法都不适合我。
要解决此问题,我必须修改ph_hda.conf
文件(PostgreSQL客户端身份验证配置文件)以禁用身份验证。该文件位于postgresql/data
目录中。我在底部注释掉了2行默认设置,并用
#TYPE DATABASE USER CIDR-ADDRESS METHOD
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
现在,如果我从php调用postgres,我会包含--no-password
选项,并且吸盘工作正常。请注意,此解决方案并不安全,只有在我的情况下才有意义,因为它用于内部公司应用程序,并且计算机脱机运行。此方法不应用于生产站点,您的数据库将被黑客入侵。这是php代码。
$commande_restore = '""'.$postgres_bin_directory.'pg_restore" --host 127.0.0.1 --port 5432 -U postgres --no-password -d '.$database_name.' '.$restore_file.'"';
$this->execute($commande_restore);
function execute($cmd, $env = null){
$proc=proc_open($cmd,array(0=>array('pipe','r'),1=>array('pipe','w'),2=>array('pipe','w')),$pipes, null, $env = null);
//fwrite($pipes[0],$stdin); //add to argument if you want to pass stdin
fclose($pipes[0]);
$stdout=stream_get_contents($pipes[1]); fclose($pipes[1]);
$stderr=stream_get_contents($pipes[2]); fclose($pipes[2]);
$return=proc_close($proc);
return array( 'stdout'=>$stdout, 'stderr'=>$stderr, 'return'=>$return );
}
我花了将近2周的时间来解决这个问题,所以我希望它可以帮助别人。