Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : Filesystem Functions : popen

popen

Opens process file pointer (PHP 4, PHP 5)
resource popen ( string command, string mode )

Example 665. popen() example

<?php
$handle
= popen("/bin/ls", "r");
?>

Example 666. popen() example

<?php
error_reporting
(E_ALL);

/* Add redirection so we can get stderr. */
$handle = popen('/path/to/spooge 2>&1', 'r');
echo
"'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo
$read;
pclose($handle);
?>

Related Examples ( Source code ) » popen



Code Examples / Notes » popen

michel machado

Yet another workaround for not having bidirectional pipes in php.
$Cmd =
"bc 2>&1 << END\n" .
"100+221\n" .
"1+3*3\n" .
"quit\n" .
"END\n";
$fp = popen($Cmd, 'r');
$read = fread($fp, 1024);
echo $read;
pclose($fp);


erb

Writing and executing a bash script is as simple as that:
$f = popen ("/bin/bash","w");
fwrite($f, "export KRB5CCNAME=`tempfile`\n");
fwrite($f, "export KRBTKFILE=`tempfile`\n");
fwrite($f, "$KINIT --keytab=$GLOBALS["KADMIN_KEYFILE"] --use-keytab --afslog $GLOBALS["KADMIN_PRINC"]\n");
fwrite($f, "pts delete $uid\n");
fwrite($f, "fs rmmount $rwhome\n");
fwrite($f, "vos remove sanjo b user.$uid\n");
fwrite($f, "$KDESTROY\n");
pclose($f);


bevmo

Try this if you want to use sendmail...
$mailer = popen ("/usr/sbin/sendmail -t -i","w");
fwrite ($mailer,"Subject:
From:
To:
*insert text*
");
pclose ($mailer);


lexzeus

Try this (if you're familiar with vi editor) :
<?php
$f=popen("vi newfile.txt","w");
sleep(1);
fputs($f,"i");  // insert
sleep(1);
fputs($f,"Hello world\r"); // write the text to vi Editor
sleep(1);
fputs($f,chr(27));  // cancel action
sleep(1);
fputs($f,":wq\r");  // write and quit
pclose($f); // back to php
exit;
?>
heh heh heh,
LexZEUS


rjl

Truncated output from ps command?
The solution lies in the way ps displays it's info
specifically the -w option which:
'uses 132 columns to display information,
instead of the default which is your window size.'....
somehow with fgets in php that results in 74 characters
regardless off the init length parameter
a bit of code:
echo '<table width="99%"><tr><td>cron</td></tr>' . "\n";
$fp=popen("/bin/ps -waux","r");
while (!feof($fp)) {
$buffer = fgets($fp, 4096);
$croninf .= '<tr><td>' . $buffer . '</td></tr>' . "\n";
}
pclose($fp);
echo $croninf;
echo '</table>
' . "\n";
Ciao,
Rene =<>=


webmaster

This function send an email in html format.
function SendEmail($to,$asunto,$html,$from) {
$fd = popen("/usr/sbin/sendmail -t", "w");
fputs($fd, "Content-type: text/html\r\n");
fputs($fd, "To: $to\r\n");
fputs($fd, "From: TRYKE <" . $from . ">\r\n");
fputs($fd, "Subject: $asunto\r\n");
fputs($fd, "X-Mailer: PHP3\r\n\r\n");
fputs($fd, $html);
pclose($fd);
}
Examples:
SendEmail("tryke@hot.com","My Subject","<h1>Hi,
How are you?</h1>","miemail@midomain.com");
More:
http://tryke.blogcindario.com


cyberlot

The below code works for both way processing ;) Have fun folks
<?
   system("mkfifo pipeout");
  $pipe = popen("./nwserver -module Chapter1E > pipeout","w");
  $pipeout = fopen("pipeout", "r");
  while ($s = fgets($pipeout,1024)) {
echo $s;
  }
?>


christian

Thanks a lot to tr4nc3 at msn dot com..
when using apache on Windows XP, on 'console mode' commands work fine, but as a system service, commands like 'popen' stop functioning, to resolve this:
Start>Run>services.msc
Right click "Apache...", select properties.
Click on the "LOG ON" tab
Check the box "Allow this service to interact with desktop"
Click OK
Restart Apache


nospam

popen() seems to have problems dealing with binary data (piping audio data to the standard input of an encoding application). I changed to proc_open() instead and now everything is working fine.

eric dot liu dot yi

popen() can be used to directly communicate with tools like GNUplot. (And it is platform independent~). To facilitate my work, I made a PHP interface to GNUPlot here:
http://celeste.cn/PHP-GNUPlot/


rockytriton

Note, when using this with a batch file in windows, you must put an "exit" at the end of your batch file or you will get a new cmd.exe stuck in your process list every time you execute the page.

matthew

Note that your OS must support bi-direction pipes for popen to be bi-directional.  
FreeBSD and BSDI are known to support bi-pipes.  
Not sure about Linux.


nate

Note that under Windows, if you are trying to write data to be available to your pipe's STDIN, you may need to execute php directly, rather than depending on file associations.
<?
   // with $cmd set to 'foo.php', STDIN comes up blank.
   // with $cmd set to 'php foo.php', STDIN gets filled
   //     (assuming php.exe is in your path)
   $cmd = 'foo.php';
   if ( ($fh = popen($cmd, 'w')) === false )
       die("Open failed: ${php_errormsg}\n");
   fwrite($fh, "Line one\nLine two\n");
   pclose($fh);
?>


shaun

Note that there appears to be a limit to the amount of data that fread() will return from a handle opened with popen(). A call to fread() may not return as much as you ask for.
For example, suppose I have a file "myfile.txt" which is more than 10KB in size. The following code works as expected:
<?php
$fp = fopen('myfile.txt', 'r');
$data = fread($fp, 10240);
echo strlen($data);
?>
The output is '10240.' However, popen() behaves differently:
<?php
$fp = popen('/bin/cat myfile.txt', 'r');
$data = fread($fp, 10240);
echo strlen($data);
?>
On my system, this code prints out '8192' instead of the expected '10240.'


pgp dude

LinixDude010's srcipt did not work for me.  Seems wrong to read and write with popen, according to the manual.
The script produced pgp text, but there was something wrong with the text and I could not decode it.
This replacement script, using proc_open, which can read and write, DOES work:
<?php
function pgp_encrypt($keyring_location, $public_key_id, $plain_text) {
 $encrypted_text='';
 $key_id = EscapeShellArg($public_key_id);
 putenv("PGPPATH=$keyring_location");
 // encrypt the message
 $descriptorspec = array(
   0 => array("pipe", "r"),  // stdin
   1 => array("pipe", "w"),  // stdout
   2 => array("pipe", "w")   // stderr ?? instead of a file
 );
 $process = proc_open("pgpe -r $key_id -af", $descriptorspec, $pipes);
 if (is_resource($process)) {
   fwrite($pipes[0], $plain_text);
   fclose($pipes[0]);
   while($s= fgets($pipes[1], 1024)) {
         // read from the pipe
         $encrypted_text .= $s;
   }
   fclose($pipes[1]);
   // optional:
   while($s= fgets($pipes[2], 1024)) {
 $encrypted_text.= "\n

Error: $s\n";
   }
   fclose($pipes[2]);
 }
 return $encrypted_text;
}
$message = pgp_encrypt("/home/username/.pgp", "to@domain.com", "dummy text to be encrypted");
print nl2br($message);
?>


trevor

Just make sure that you check the user information being passed into the command (if any) before it executes.

kevin

Just a quick note about your environment. None of the apache specific environment variables are available to the called program.

nricciardi

ive tried using popen using bidirectional pipes without working for obvious reasons, but i managed to create a simple script that managed to take care of the problem.  This example is for gpg encryption.
<?
  $message = "this is the text to encrypt with gpg";
  $sendto = 'Dummy Key <another@fake.email>';
  system("mkfifo pipein");
  system("mkfifo pipeout");
  system("gpg --encrypt -a -r '$sendto' > pipeout < pipein &");
  $fo = fopen("pipeout", "r");
  $fi = fopen("pipein", "w");
  fwrite($fi, $message, strlen($message));
  fclose($fi);
  while (!feof($fo)) {
     $buf .= fread($fo, 1024);
  }
  echo $buf;
  unlink("pipein");
  unlink("pipeout");
?>
If anyone has a better way of doing this I would love to see it.


electronerd

In response to shaun at nospam dot phplabs dot com:
fread() does not guarantee that all the expected data is read. The length argument is only an upper limit. If there isn't more data immediately available, fread() may return early.


stevet

In PHP3, I could do:
$query = "echo hello world | mycmd"
$fp = ($query, "r");
Under PHP4, this just produces "hello world | mycmd" as the output - the pipe is not executed.
Instead, use:
$query = "hello world";
$cmd = "mycmd";
$fp = popen($cmd, "w+");
fwrite($fp, $query);


kalvinb602

If you're having trouble with the server (Apache) hanging when issuing system commands consider the following bug report:
http://bugs.php.net/bug.php?id=22526
basically, if you're using sessions issue a
session_write_close();
command before you execute your system command to keep the server from hanging.
This may also correct the problem when using other system command executing functions like exec.
Ben


atampone

If you want to fork a process under windows, this is the function to use.  I created a batch file called runcmd.bat with the following line
start %1 %2 %3 %4
then I have the folowing function
<?
define('RUNCMDPATH', 'c:\\htdocs\\nonwebspace\\runcmd.bat');
function runCmd($cmd) {
$externalProcess=popen(RUNCMDPATH.' '.$cmd, 'r');
pclose($externalProcess);
}
?>
with this, doing something like
<? runCmd('php.exe printWorkOrder.php 3498'); ?>
will launch php.exe outside of apache and allow the script calling the runCmd() function to continue without waiting for the command line process to return.  The process will run under the same user account that Apache (or whatever webserver you're running) is running under, so make sure it has permissions to do whatever you need to do.  Also, make sure that the batch file has enough %n s in order to pass all the command line variables that you might need to pass.
Special thanks to kicken from the devshed forums for coming up with the idea.


php dot net_manual

If you are going to allow data coming from user input to be passed to this function, then you should keep in mind the following warning that also applies to exec() and system():
http://www.php.net/manual/en/function.exec.php
http://www.php.net/manual/en/function.system.php
Warning:
If you are going to allow data coming from user input to be passed to this function, then you should be using escapeshellarg() or escapeshellcmd() to make sure that users cannot trick the system into executing arbitrary commands.


pgp dude

I should say, my host uses a modified form of safe mode, so I don't know if that might have caused a problem with "popen" as opposed to "proc_open".  The warning below does NOT appear on the proc_open page:
quote:
With safe mode enabled, all words following the initial command string are treated as a single argument. Thus, echo y | echo x becomes echo "y | echo x".


ajv-php

I noticed that some of the examples above seem to advocate passing unencrypted data to gpg via the pipe shell escape, in the absence of a bi-directional popen (on some OSes).
The approach I've taken is similar to:
 $prefix = 'example';
 $command = '/usr/local/bin/gpg --encrypt --armor --no-tty --batch --no-secmem-warning --recipient "joe.soap@example.com"';
 $tmpfile = tempnam('/tmp', $prefix);
 $pipe = popen("$command 2>&1 >$tmpfile", 'w');
 if (!$pipe) {
   unlink($tmpfile);
 } else {
   fwrite($pipe, $plaintxt, strlen($plaintxt));
   pclose($pipe);
   $fd = fopen($tmpfile, "rb");
   $output = fread($fd, filesize($tmpfile));
   fclose($fd);
   unlink($tmpfile);
 }
 return $output;
This means that unencrypted information is not passed via a (potentially readable) shell command, and only encrypted information gets stored on disc.


linuxdude010

I had all kinds of trouble encrypting a message with PGP, but I finanlly got it to work.  The trick was to 'chmod o+r pubring.pkr' so that the apache server could read the public keys!!!  Then, this function worked fine:
<?PHP
function pgp_encrypt($keyring_location, $public_key_id, $plain_text) {
       $key_id = EscapeShellArg($public_key_id);
       putenv("PGPPATH=$keyring_location");
       // encrypt the message
       $pipe = popen("pgpe -r $key_id -af", "r");              
       fwrite($pipe, $plain_text);
       $encrypted_text = '';
       while($s = fgets($pipe, 1024)) {
               // read from the pipe
               $encrypted_text .= $s;
       }
       pclose($pipe);
       return $encrypted_text;
}
$message = pgp_encrypt("/home/username/.pgp", "to@domain.com", "dummy text to be encrypted");
print nl2br($message);
?>


12-jul-2002 10:33

Here is a workaround for not having bidirectional pipes in php.
If you have bidirectional pipe support, don't bother with this.
The trick here is to send the input on the command line to the target application.  In particular I wanted to use openssl without using temp files or named pipes.  This solution should also be thread/process safe.
This does work on Linux (RedHat 7).
function filterThroughCmd($input, $commandLine) {
 $pipe = popen("echo \"$input\"|$commandLine" , 'r');
 if (!$pipe) {
   print "pipe failed.";
   return "";
 }
 $output = '';
 while(!feof($pipe)) {
   $output .= fread($pipe, 1024);
 }
 pclose($pipe);
 return $output;
}
# example:
print filterThroughCmd("hello", "cat");
# Piping to cat has the effect of echoing your input.


cride5

Here is a nice little script for monitoring your http access log.
<?php
$handle = popen("tail -f /etc/httpd/logs/access.log 2>&1", 'r');
while(!feof($handle)) {
$buffer = fgets($handle);
echo "$buffer<br/>\n";
ob_flush();
flush();
}
pclose($handle);
?>
----
www.eviltree.co.uk
www.solidsites.co.uk
www.mongbong.com


http://vmlinuz.nl/about/contact/

From the popen linux programmers manual:
<quote>The  command  argument  is  a pointer to a null-terminated string containing a shell command line.  This  command  is passed  to  /bin/sh  using the -c flag.</quote>
Since php uses this popen function, you need to be sure /bin/sh exists. This file may not exist in chroot()ed environments.


betchern0t

Care needs to be taken in the case of long running child processes. Say you want to run tail -f /var/log/messages or in my case burn dvds. If you have a busy wait, Apache2 can sit towards 100%cpu and steadily grow memory. In my case I crashed the server after about an hour and 90% of the dvd burned. During that time apache had consumed a gig of swap.
Offending code - don't copy:
       $ThisCommand = sprintf("%s %s",COMMAND,$ThisFile);
       $fp=popen($ThisCommand,"r");
       while (!feof($fp)) {
               set_time_limit (20);
               $results = fgets($fp, 4096);
               if (strlen($results) == 0) {
                  // stop the browser timing out
                  echo " ";
                  flush();
               } else {
                  $tok = strtok($results, "\n");
                  while ($tok !== false) {
                       echo htmlentities(sprintf("%s\n",$tok))."<br/>";
                       flush();
                       $tok = strtok("\n");
                  }
               }
       }
       pclose($fp);
to go from zero memory and 100% cpu  to negligible memory and negligible cpu add a sleep.
       while (!feof($fp)) {
               set_time_limit (20);
               $results = fgets($fp, 256);
               if (strlen($results) == 0) {
                  // stop the browser timing out
                  echo " ";
                  flush();
               } else {
                  $tok = strtok($results, "\n");
                  while ($tok !== false) {
                       echo htmlentities(sprintf("%s\n",$tok))."<br/>";
                       flush();
                       $tok = strtok("\n");
                  }
               }
               // avoid a busy wait
               sleep(1);
       }
I think the continued banging of the space to keep the browser awake triggered some issues in apache.


don

// The above import function can be easily extended using
// /usr/local/bin/xls2csv (part of catdoc ) and popen
// to read excell files directly.
// In our particular application the first line was the file heading.
function importxls($file,$head=true,$throwfirst=true,$delim=",",$len=1000) {
  $return = false;
  $handle = popen("/usr/local/bin/xls2csv $file", "r");
// or die if not there.
  if ($throwfirst) {
      $throw = fgetcsv($handle, $len, $delim);
  }
  if ($head) {
      $header = fgetcsv($handle, $len, $delim);
  }
  while (($data = fgetcsv($handle, $len, $delim)) !== FALSE) {
      if ($head AND isset($header)) {
          foreach ($header as $key=>$heading) {
              $row[$heading]=(isset($data[$key])) ? $data[$key] : '';
              print "<li>". $heading ."=>" . $row[$heading]."</li>";
          }
          $return[]=$row;
      } else {
          $return[]=$data;
      }
  }
  fclose($handle);
  return $return;
}


Change Language


Follow Navioo On Twitter
basename
chgrp
chmod
chown
clearstatcache
copy
delete
dirname
disk_free_space
disk_total_space
diskfreespace
fclose
feof
fflush
fgetc
fgetcsv
fgets
fgetss
file_exists
file_get_contents
file_put_contents
file
fileatime
filectime
filegroup
fileinode
filemtime
fileowner
fileperms
filesize
filetype
flock
fnmatch
fopen
fpassthru
fputcsv
fputs
fread
fscanf
fseek
fstat
ftell
ftruncate
fwrite
glob
is_dir
is_executable
is_file
is_link
is_readable
is_uploaded_file
is_writable
is_writeable
lchgrp
lchown
link
linkinfo
lstat
mkdir
move_uploaded_file
parse_ini_file
pathinfo
pclose
popen
readfile
readlink
realpath
rename
rewind
rmdir
set_file_buffer
stat
symlink
tempnam
tmpfile
touch
umask
unlink
eXTReMe Tracker