Search code examples
phpproc-open

Is there a way to make proc_open read input from a file if the file is dynamic?


I am trying to read input from a file as stdin for the process using proc_open . But this file is actually going to be dynamic i.e. User will enter something in another process into this file. What I want is that proc_open should wait until some new content is added in this file before considering this as STDIN.

Here's what I have tried.

<?php
$desc = array(
    0 => array('file', 'input.txt','r'),
    1 => array('pipe', 'w'), 
    2 => array('pipe', 'w')
);
//$cmd = "java Main";
$cmd="python sample.py";
$proc = proc_open($cmd, $desc, $pipes);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
//stream_set_blocking($pipes[0], 0);
if($proc === FALSE){
    throw new Exception('Cannot execute child process');
}
$status=proc_get_status($proc);
$pid = $status['pid'];
while(true) {
    $status = proc_get_status($proc);
    if($status === FALSE) {
        throw new Exception ("Failed to obtain status information for $pid");
    }
    if($status['running'] === FALSE) {
        $exitcode = $status['exitcode'];
        $pid = -1;
        echo "child exited with code: $exitcode\n";
        exit($exitcode);
    }
    $a=0;
    //fwrite($pipes[0],"10\n");
    foreach(array(1, 2) as $desc) {
        // check stdout for data
        $read = array($pipes[$desc]);
        $write = NULL;
        $except = NULL;
        $tv = 0;
        $utv = 50000;
        $n = stream_select($read, $write, $except, $tv, $utv);
        if($n > 0) {
            do {
                $data = fread($pipes[$desc], 8092);
                //echo "tp".$data;
               //$a=$a+1;
               //echo $a."\n";
                fwrite(STDOUT, $data);
            } while (strlen($data) > 0);
           // echo "Hey". $desc;
        }   
    }
   /* $read = array(STDIN);
    $n = stream_select($read, $write, $except, $tv, $utv);
    if($n > 0) {
        echo "Inside input stream";
        $input=10;
        fwrite($pipes[0], $input);
    }else{
        echo "Not working";
    }*/
}
?>

And when i run a sample program with file input.txt empty the output is this:

Sample python program

print("Hello world")
x=input("Enter a no: ")
print(x)
y=input("Enter any string: ")
print(y)
print(y+str(x))

Output: Output of running python program with php script above

As u can see in the output when input for variable y is expected there's an error because input.txt file does not yet have the value. I want it to wait for some time say 30 secs and then only read newly added content but if it is added before 30 secs then it should immediately resume. Thanks!!!


Solution

  • Wait for the file to be created before using it.

    while !file_exists("input.txt") {
        sleep(5)
        // code that uses input.txt
    }
    ...
    unlink("input.txt") # Remove file to prepare for next iteration
    

    To avoid seeing a partial file, the process that creates the file should write to a temporary name, then rename it to input.txt when it's done.