PHP 7.0.26 Released

Потоки ввода/вывода

Модуль CLI SAPI определяет несколько констант для потоков ввода/вывода для упрощения работы с командной строкой.

Константы, специфичные для модуля CLI
Константа Описание
STDIN

Уже открытый поток ввода (stdin). Он предотвращает необходимость его открывать следующим способом:

<?php
$stdin 
fopen('php://stdin''r');
?>
Если вы хотите прочесть одну строку из stdin, можно использовать следующий код:
<?php
$line 
trim(fgets(STDIN)); // читает одну строку из STDIN
fscanf(STDIN"%d\n"$number); // читает число из STDIN
?>

STDOUT

Уже открытый поток вывода (stdout). Он предотвращает необходимость его открывать следующим способом:

<?php
$stdout 
fopen('php://stdout''w');
?>

STDERR

Уже открытый поток ошибок (stderr). Он предотвращает необходимость его открывать следующим способом:

<?php
$stderr 
fopen('php://stderr''w');
?>

Учитывая вышесказанное, нет необходимости самому открывать поток, например, stderr, а можно просто использовать уже определенную константу ресурса потока:

php -r 'fwrite(STDERR, "stderr\n");'
Вам также не нужно их вручную закрывать, они будут закрыты PHP автоматически при окончании вашего скрипта.

Замечание:

Эти константы недоступны, если PHP считывает запускаемый скрипт из stdin.

add a note add a note

User Contributed Notes 4 notes

up
27
Aurelien Marchand
6 years ago
Please remember in multi-process applications (which are best suited under CLI), that I/O operations often will BLOCK signals from being processed.

For instance, if you have a parent waiting on fread(STDIN), it won't handle SIGCHLD, even if you defined a signal handler for it, until after the call to fread has returned.

Your solution in this case is to wait on stream_select() to find out whether reading will block. Waiting on stream_select(), critically, does NOT BLOCK signals from being processed.

Aurelien
up
6
ecrist at secure-computing dot net
6 years ago
The following code shows how to test for input on STDIN.  In this case, we were looking for CSV data, so we use fgetcsv to read STDIN, if it creates an array, we assume CVS input on STDIN, if no array was created, we assume there's no input from STDIN, and look, later, to an argument with a CSV file name.

Note, without the stream_set_blocking() call, fgetcsv() hangs on STDIN, awaiting input from the user, which isn't useful as we're looking for a piped file. If it isn't here already, it isn't going to be.

<?php
stream_set_blocking
(STDIN, 0);
$csv_ar = fgetcsv(STDIN);
if (
is_array($csv_ar)){
  print
"CVS on STDIN\n";
} else {
  print
"Look to ARGV for CSV file name.\n";
}
?>
up
-1
ayon at hyurl dot com
9 months ago
I find a BUG with the constant STDIN, I don't know if it si the Enter/Return key that make this proprem, when I use trim(fgets(STDIN)), that doesn't trim anything, when I detect the length of fgets(STDIN), in windows, it is 2 characters longer than what I input, in Linux, it makes 1. I tried to trim(fgets(STDIN), ' \r\n'), but it still does not work.
So I have to substr the input manually, it seems like this way:
<?php
$STDIN
= trim(substr(fgets(STDIN), 0, (PHP_OS == 'WINNT' ? 2 : 1)));
?>
then I get what I want really.
up
-41
James Zhu
6 years ago
Example:

<?php
function ReadStdin($prompt, $valid_inputs, $default = '') {
    while(!isset(
$input) || (is_array($valid_inputs) && !in_array($input, $valid_inputs)) || ($valid_inputs == 'is_file' && !is_file($input))) {
        echo
$prompt;
       
$input = strtolower(trim(fgets(STDIN)));
        if(empty(
$input) && !empty($default)) {
           
$input = $default;
        }
    }
    return
$input;
}

// you can input <Enter> or 1, 2, 3
$choice = ReadStdin('Please choose your answer or press Enter to continue: ', array('', '1', '2', '3'));

// check input is valid file name, use /var/path for input nothing
$file = ReadStdin('Please input the file name(/var/path):', 'is_file', '/var/path');
?>

you can add more functions if you want.
To Top