Question

I am trying to execute a few PostgreSQL DB commands from a web interface. I use proc_open() to pipe to the Windows command prompt. Because psql (and all other postgres command) do not accept the password as an option, I must send the password to the write stream. The code below causes the browser to hang. Either the resource is not be created, or the password is not being piped properly. Any suggestions are welcome at this point.

$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);                         
}

[You'll notice the crazy double-double-quoting in the command -- this is apparently needed for windows for some reason.]

Work-arounds to this problem are welcome:

  • I previously tried using system() and exec() but gave up since they don't handle interactive prompt. Is there a better option in php for interactive?
  • pg_query() is the main command for interacting with the postgres DB, but pg_dump and pg_restore operations are not supported. Is there another way to backup and restore from binary postgres .backup files that can be accomplished with php?
Was it helpful?

Solution 2

As @c-ramseyer suggested, messing around with simulating an interactive prompt via proc_open() was a non-starter. PostgreSQL offers two methods to get around providing the password through the interactive prompt. Method (1) is to provide it as environment variables, as suggested by the other answer. Method (2) is to create a pgpass.conf file in the DB user's %appinfo% directiory. (To find that directory do echo %appinfo% from windows command prompt.) See postgresql for how to make this one-liner conf file. Neither of these methods worked for me, for reasons I still don't understand.

To solve the problem, I had to modify the ph_hda.conf file (PostgreSQL Client Authentication Configuration File) to disable authentication. That file is located in the postgresql/data directory. I commented out the 2 lines of default settings at the bottom and replaced them with

#TYPE  DATABASE     USER        CIDR-ADDRESS       METHOD
host    all         all         127.0.0.1/32       trust     
host    all         all         ::1/128            trust

Now if I call postgres from php I include the --no-password option and the sucker works. Note that this solution is not secure, and only makes sense in my case because it is being used for an internal company application, with machines running offline. This method should not be used for a production site, your DB will get hacked. Here's the php code.

$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 );
}

It took me close to 2 weeks to solve this, so I hope it helps someone.

OTHER TIPS

Don't mess around with the password prompt, better put an entry into %APPDATA%\postgresql\pgpass.conf. Format is

hostname:port:database:username:password

Make sure to pick the %APPDATA% of the user running the webserver process.

If you're really set on interacting with the prompt, you could try the Expect library which people often use for such tasks... disclaimer: I've never used it on windows and have no idea how well it works there, or if it really is necessary. Maybe your fwrite is just missing a terminating newline.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top