Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/takuya/php-proc_open-wrapper

php proc_open wrapper class
https://github.com/takuya/php-proc_open-wrapper

Last synced: 9 days ago
JSON representation

php proc_open wrapper class

Awesome Lists containing this project

README

        

## Run Process.

Run process and run string by interpreter(ex.python,bash). and keep process long time task running.

`proc_open` is distinctive style. so I make `proc_open` EASY and friendly.

## Installing

from packagist.
```
composer require takuya/php-proc_open-wrapper
```
from GitHub repos.
```sh
name='php-proc_open-wrapper'
composer config repositories.$name \
vcs https://github.com/takuya/$name
composer require takuya/$name:master
composer install
```

check installation.

sample.php
```php
start();
$p->wait();

echo $output = stream_get_contents($p->getFd(1));
```
```shell
php sample.php
```
## Test

phpunit

```shell
composer install
vendor/bin/phpunit
vendor/bin/phpunit --filter ProcOpen
```
## examples

See [Examples](https://github.com/takuya/php-proc_open-wrapper/tree/master/examples).

## safer process call

This package directly exec command, not using 'shell'.

proc_open executes command directly, without shell ( fork then exec ).

Using proc_open correctly, `directory traversal` vulnerability , `shell injection` vulnerability will not be occurred. Shell escaping will not be needed. this can reduce risks.

Don't escape string , use array.

#### use cmd array. not escaping.
proc_open can accept cmd string, but cmd string may be danger(mal-escaping). exec cmd by array is more safe.

```php
start();
$p->wait();
//
$output = stream_get_contents($p->getFd(1));
```

you must check arguments.

To prevent directory traversal. you must check args in advance. cmd string cannot be checked, but array can check.
```php
start();

$p2 = new ProcOpen(['grep','pcntl'])
$p2->setInput($p1->getFd(1));//pipe p1->stdout to p2->stdin
$p2->start();
//
$p1->wait();
$p2->wait();
//
$output = stream_get_contents($p2->getFd(1));
```

pipe by pure php. It's very painful.
```php
'php']);
$proc->setInput('
for i in {0..4}; do
echo $i
done;
');
$proc->start();
$proc->wait();
//blocking io
echo fread($proc->getFd(1), 1024);
```

## Run string as python code.

run python code in proc_open

```php
setInput('
import os;
import sys
for i in range(5):
print(i);
print("end")
print(sys.path)
');
$proc->start();
$proc->wait();
//blocking io
echo fread($proc->getFd(ProcOpen::STDOUT), 1024);
```

## Run php interactive shell `php -a `

```php
start();

$fp = $proc->getFd(ProcOpen::STDIN);
fwrite($fp,'echo 0 ;'.PHP_EOL);
fwrite($fp,'echo 1 ;'.PHP_EOL);
fwrite($fp,'echo 2 ;'.PHP_EOL);
fwrite($fp,'echo 3 ;'.PHP_EOL);
fwrite($fp,'echo 4 ;'.PHP_EOL);
fclose($fp); // finish php interactive shell

// get output.
$output= stream_get_contents($proc->getFd(1));

```
## Linux pipe max.

Linux pipe will be blocked if left unread.

`LINUX_PIPE_SIZE` is `1024*64`.
so if you try to write one more byte (`1024*64+1`bytes) to `stdout`, process will be blocked by OS.

```php
setInput(<<<'EOS'
start();
// this will be blocked.

```

To avoid blocking, you should use tmp-io.

```php
setInput(<<<'EOS'
setStdout($tmp = fopen('php://temp','w'));
$proc->start();
// this will be successfully finished.
```

Or use `select syscall` and read the buffer.

```php
setInput(<<<'EOS'
start();
// use select not to be clogged.
$output = '';
$avail = stream_select( ...( $selected = [[$proc->getFd( 1 )], [], null, 0, 100] ) );
if ( $avail > 0 ) {
$output .= fread( $proc->getFd( 1 ), 1 );
}
```