Search code examples
phpcommand-linepipeproc-open

php how to use proc_open to pipe the content of a variable to the process


from a php script I am trying to run an external command which is taking its input from a previous command with a pipe (at os level). The command I want to use is pdftotext -nopgbrk -layout myfile.pdf -. I have been able to get proc_open working with a file to read for input.

But I getting my input from a variable not from a file. The main command accepts its input from a pipe (at os level) like this : cat myfile.pdf | pdftotext -nopgbrk -layout - - to give the same result.

I would like to directly send the content of this variable without having to create a temporary file.

Can it be done ? and how ?

Here is a working example of what I don't want to do:

$data = <<<EOD
    Hello
    world!
    EOD;
$tmpfname = tempnam("/tmp", "myPDF");

$handle = fopen($tmpfname, "w");
fwrite($handle, $data);
fclose($handle);

$cmd = "cat $tmpfname | grep -i hello";
$proc=proc_open($cmd,
array(
  array("pipe","r"), //stdin
  array("pipe","w"), //stdout
  array("pipe","w") //stderr
),
$pipes);

$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
var_dump($stdout);
var_dump($stderr);
fclose($pipes[1]);
fclose($pipes[2]);
$exit_status = proc_close($proc);
echo $exit_status;
unlink($tmpfname);

how to get rid of the file manipulation part ? how get it working with $cmd = "grep -i hello"; instead of $cmd = "cat $tmpfname | grep -i hello"; ? how to use $data with proc_open ? (please no comment about grep or alternative to it, it is not the final command I plan to use, it is only to provide a quite portable example)


Solution

  • What about using echo instead of cat? So your command will be like:

    $cmd = "echo $tmpfname | grep -i hello";
    #       ^^^^
    

    Update

    Or, why you don't simply pipe your data to your proc_open stdin? like the following:

    $file = file_get_contents('your/pdf/file.pdf'); // or whatever your variable is
    
    $pipes = [];
    $process = proc_open(
        "pdftotext -nopgbrk -layout - -",
        array(
            0 => array("pipe", 'r'),  // stdin is a pipe that the child will read from
            1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
         ),
        $pipes,
    );
    
    fwrite($pipes[0], $file);
    fclose($pipes[0]);
    
    echo stream_get_contents($pipes[1]);
    fclose($pipes[1]);
    echo "\n===========\n";