Гость
Map
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / PHP: Перенаправить вывод для одной функции / 10 сообщений из 10, страница 1 из 1
22.04.2021, 14:01
    #40064732
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
Есть PHP-скрипт, который может запускаться как интерактивно (с выводом в терминал), так и планировщиком (с выводом в log-файл).
В скрипте последовательно вызывается несколько функций.
Можно ли сделать так, перед вызовом stdout менялся на конкретный файл, а после возврата функции stdout восстанавливался?

Я пробовал делать fopen перед вызовом функции, в результате вывод перенаправлялся в файл.
Но при этом после возврата функции не получалось восстановить stdout, несмотря на то, что я сохранял posix_ttyname и после возврата пробовал сделать fopen на сохраненное значение.
...
Рейтинг: 0 / 0
22.04.2021, 16:24
    #40064815
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
Alibek B.
не получалось восстановить stdout, несмотря на то, что я сохранял posix_ttyname и после возврата пробовал сделать fopen на сохраненное значение.
А если стандарно, 'php://output' задать?
https://www.php.net/manual/ru/wrappers.php.php
...
Рейтинг: 0 / 0
22.04.2021, 19:51
    #40064906
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
На примере не покажите?

Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
if (...) {
  proc('p1');
  proc('p2');
  ...
}

function proc($proc)
{
  //перенаправить stdout в $proc.log
  $proc();
  //вернуть stdout
}

function p1()
{
  ...
}
...
...
Рейтинг: 0 / 0
22.04.2021, 20:14
    #40064913
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
Сделал так:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
function proc($source)
{
	global $script;
	$proc = "proc_{$source}";
	$log = "{$script}_{$source}.log";
	if (!function_exists($proc)) return;
	print PHP_EOL;
	$fh = fopen($log,'w');
	$rc = ob_start(function($buffer) use($fh) { fwrite($fh, $buffer); return ''; });
	$proc();
	ob_end_clean();
	fclose($fh);
}


В принципе работает именно так, как мне нужно.
Но мне не нравится буферизация и ее особенности/ограничения.
Я бы предпочел перенаправление вывода.
...
Рейтинг: 0 / 0
22.04.2021, 23:52
    #40064970
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
Alibek B.
На примере не покажите?
Так покажите свой реально нерабочий тестовый пример, где fopen делаете и потом вернуть пытаетесь, но не получается. Или за Вас я должен придумать пример, показывающий, что Вам надо?
Давайте на Вашем примере посмотрим, что можно намутить.
Лишний код, не имеющий явного и прямого отношения к проблеме, в пример не включайте, но каменты, конечно же, приветствуются.
...
Рейтинг: 0 / 0
23.04.2021, 00:17
    #40064976
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
Вот исходная программа:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
print "*** START \n";

proc('p1');
proc('p2');

print "*** END \n";

function proc($proc)
{
        print "** PROC\n";
        $proc();
}

function p1()
{
        print "* P1\n";
}

function p2()
{
        print "* P2\n";
}



А вот пример:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
print "*** START \n";

proc('p1');
proc('p2');

print "*** END \n";

function proc($proc)
{
        global $STDOUT;
        print "** PROC\n";
        $old = posix_ttyname(STDOUT);
        print "#{$proc} old tty: {$old}\n";
        fclose(STDOUT);
        $STDOUT = fopen("{$proc}.log", 'wb');
        print "#{$proc} new tty: $STDOUT\n";
        $proc();
        fclose($STDOUT);
        $STDOUT = fopen($old, 'wb');
        print "#{$proc} def tty: $STDOUT\n";
}

function p1()
{
        print "* P1\n";
}

function p2()
{
        print "* P2\n";
}



При запуске должен написать в консоль START, PROC и END, а P1 и P2 должны быть выведены в файлы p1.log и p2.log соответственно.
Но в данном примере в консоль выводится START и PROC, в файл p1.log выводится P1, а остальное пропадает.
...
Рейтинг: 0 / 0
23.04.2021, 02:27
    #40064987
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
Занятно. Ошибки в консоль не вываливаются?
Мне напечатало:
Код: php
1.
PHP Warning:  posix_ttyname(): supplied resource is not a valid stream resource in /home/vk/t.php on line 14

Это строка
Код: php
1.
        $old = posix_ttyname(STDOUT);



Ладно, глядим значение константы
Код: php
1.
2.
$ php -r 'echo STDOUT;'
Resource id #2


Это наводит на мысль, что поток вывода явно привязан к константе. Закрыли его - гуд бай, константа осталась, но уже не указывает на ресурс.

Что видим.
Код: php
1.
2.
3.
4.
5.
6.
$ php -r 'var_dump(STDOUT); /*fclose(STDOUT);*/ var_dump(STDOUT);'
Command line code:1:
resource(2) of type (stream)
Command line code:1:
resource(2) of type (stream)
$ 


А так... Гхм...
Код: php
1.
2.
3.
4.
$ php -r 'var_dump(STDOUT); fclose(STDOUT); var_dump(STDOUT);'
Command line code:1:
resource(2) of type (stream)
$ 



Видимо, потому, как Вы и пишите:
Alibek B.
не получалось восстановить stdout
Ресурс закрыт, а переопределить константу с вновь открытым ресурсом... ну, понимаете.


Вероятно, остается делать какой-то приблизительно такого плана веселый замут, избавившись от дефолтового stdout и определить поток вывода явно (впрочем, это можно заметно упростить):
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
<?php

$fdOUT = fopen('php://stdout', 'wb');
fwrite($fdOUT,  "*** START \n");

proc('p1');
proc('p2');

fwrite($fdOUT,  "*** END \n");


function proc($proc)
{
        global $fdOUT;
        fwrite($fdOUT, "** PROC\n");
        fwrite($fdOUT, "#{$proc} old tty: {$fdOUT}\n");
        fclose($fdOUT);
        $fdOUT = fopen("{$proc}.log", 'wb');
        fwrite($fdOUT, "#{$proc} new tty: $fdOUT\n");
        $proc();
        fclose($fdOUT);
        $fdOUT = fopen('php://stdout', 'wb');
        fwrite($fdOUT, "#{$proc} def tty: $fdOUT\n");
}

function p1()
{
        global $fdOUT;
        fwrite($fdOUT, "* P1\n");
}

function p2()
{
        global $fdOUT;
        fwrite($fdOUT, "* P2\n");
}


Или, вообще, пересмотреть концепцию вывода. Например, в скрипте выводить всё в один поток, а в среде вызова разделять, направляя часть вывода по маркерам в файл. Ну это на уровне идеи. Не пробовал, может быть можно (а может и нет) определить в пхп четвертый, пятый и т.д. потоки и ими играть в среде вызова (в командной строке).
...
Рейтинг: 0 / 0
23.04.2021, 10:15
    #40065077
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
vkle
Вероятно, остается делать какой-то приблизительно такого плана веселый замут, избавившись от дефолтового stdout и определить поток вывода явно (впрочем, это можно заметно упростить)

Выглядит криво и неудобно. Уж лучше буферизацию использовать.

vkle
Или, вообще, пересмотреть концепцию вывода. Например, в скрипте выводить всё в один поток, а в среде вызова разделять, направляя часть вывода по маркерам в файл. Ну это на уровне идеи. Не пробовал, может быть можно (а может и нет) определить в пхп четвертый, пятый и т.д. потоки и ими играть в среде вызова (в командной строке).

Это уже усложнение ради усложнения.
Я как раз хотел упростить и сделать скелет скрипта прозрачным.
Как в bash-скриптах, в которых можно вызвать подпрограмму и перенаправить ее вывод по конвейеру.
...
Рейтинг: 0 / 0
23.04.2021, 14:41
    #40065219
vkle
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
Alibek B.
Выглядит криво и неудобно.
Совершенно согласен. Плюс не быстро всякий раз открывать и закрывать файловый дескриптор. Однако, это исключительно из разряда "как-то приблизительно так" и столь же далеко до реальной реализации как от Луны до Нептуна.
...
Рейтинг: 0 / 0
22.02.2022, 18:06
    #40135953
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
PHP: Перенаправить вывод для одной функции
Не появилось ли в PHP 7 более удобного способа?
Вроде бы эта библиотека позволяет более гибко работать с потоками.
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / PHP: Перенаправить вывод для одной функции / 10 сообщений из 10, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]