The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



Вариант для распечатки  
Пред. тема | След. тема 
Форум Разговоры, обсуждение новостей
Режим отображения отдельной подветви беседы [ Отслеживать ]

Оглавление

Предварительный выпуск проекта PXP, развивающего расширенный диалект языка PHP, opennews (??), 16-Май-23, (0) [смотреть все]

Сообщения [Сортировка по времени | RSS]


87. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +/
Сообщение от Golangdev (?), 18-Май-23, 01:39 
Ну значит вы не во что (пока) не упёрлись, вестимо.

Читаем внимательно:

> когда не хватает возможностей

Я же не говорю что PHP плохой %)

Ответить | Правка | Наверх | Cообщить модератору

88. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +/
Сообщение от Ilya Indigo (ok), 18-Май-23, 02:20 
У меня недавно возникла проблема в том, что php многопоточность возможна только через вызов exec('... &'), после которой процесс живёт своей жизнью и не то что его судьба, его pid мне не известен!
Проблема возникла в отслеживании запущенных процессов и пробивания их при необходимости.
Решил передачей в exec уникального или определённого аргумента, по которому, в савокупности со всей командной строкой вызываю killall через exec() при необходимости (для снятия блокировки, которая долго весит).
А если нужно чтобы процесс, с такими же аргумертами не дублировался, можно в начале скрипта, который будет вызываться через exec('... &') такое прописать, и он не запустит новый процесс если старый выполняется.

#!/usr/bin/php
<?php
if(empty($_SERVER['argv'][3]))
{
    echo 'No arg1, arg2 and arg3 parameters passed!', "\n";
    exit(1);
}
elseif(exec('pgrep -cf '.escapeshellarg(implode(' ', $_SERVER['argv']))) > 1)
    exit(0);

Проблема хоть и кастыльно, через внешние вызовы, но решена.
Как с эти в пайтоне дела обстоят?
И как это в го решается и не возникнет ли там других проблем?
Го с nginx вообще можно использовать?

Если бы меня припёрло, я бы первым делом попробовал бы написать Си-расширение, но ни как не что-то на го.

Ответить | Правка | Наверх | Cообщить модератору

89. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +1 +/
Сообщение от Golangdev (?), 18-Май-23, 02:39 
> Как с эти в пайтоне дела обстоят?

Хоть я Golangdev, но отправной точкой может быть https://docs.python.org/3/library/threading.html

> И как это в го решается

С помощью горутин(если упростить донельзя, то можно считать за поток).

> вызываю killall через exec() при необходимости

для "убийства" горутины в Go используют контекст и cancel https://www.sohamkamani.com/golang/context-cancellation-and-.../ (привет, культура кэнселинга %) )

> Го с nginx вообще можно использовать?

можно, но в отличие от PHP на Go в самом рантайме есть полноценный HTTP-сервак, так что нгинкс, строго говоря, не особо нужен

> не возникнет ли там других проблем?

Конечно же возникнут. Другой вопрос, насколько в перспективе пользы принесёт переезд на Go по ставнению с остальными решениями (костыли, Си-расширения, и проч). Судя по популярности Go, можно считать что он окупается.

Ответить | Правка | Наверх | Cообщить модератору

91. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +/
Сообщение от Хухрымухры (ok), 18-Май-23, 11:00 
В linux есть flock для защиты от повторного запуска комманды...

> php многопоточность возможна только через вызов exec('... &')

Я как мигрировавший с пыхи голанг раб скажу что в пыхе есть для многопоточки файберы...

Так же у вас упадёт сервер если вы запустити 100500 комманд через `exec`, тогда как гошечка отработает их и даже не заметит.

Ответить | Правка | К родителю #88 | Наверх | Cообщить модератору

93. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +1 +/
Сообщение от Бздительный поцыент (?), 18-Май-23, 11:58 
Файберы - это таки не нормальная многопоточка с разнесением по тредам, а просто возможность прыгать между корутинами в пределах одного процесса/треда, самая-самая базовая. Впрочем, обвязка над таковой делается легко и ненавязчиво - и появляется достаточно удобная асинхронность. Но это таки не многопоточность. Есть какой-то навесной костыль для трединга, даже местами работает, но в продакшн такое страшно.
Ответить | Правка | Наверх | Cообщить модератору

95. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +/
Сообщение от Ilya Indigo (ok), 18-Май-23, 12:05 
> В linux есть flock для защиты от повторного запуска комманды...

И толку от этого?
Мне нужно ограничить не повторный запуск всего скрипта, а ограничить запуск скрипта с точно такими же аргументами, и никак не ограничивать запуск этого скрипта, но с другими аргументами, при условии что они уже НЕ запущены.
pgrep -cf для этого подходит идеально!

>> php многопоточность возможна только через вызов exec('... &')
> Я как мигрировавший с пыхи голанг раб скажу что в пыхе есть
> для многопоточки файберы...

Файберы появились недавно, в php 8.1 и на момент появления было не понятно как ими пользоваться.
https://www.php.net/manual/ru/language.fibers.php
https://habr.com/ru/companies/vk/articles/551240/
Судя по этой статье Файберы - это лютые костыли, которые даже не могут выполнятся одновременно, но при этом хорошо управляемы.
Мне метод с exec('... &>>/path/to/log/or/dev/null &'); гораздо больше нравится, тут управляемость костыльная, но я получаю реальный многопоток!

> Так же у вас упадёт сервер если вы запустити 100500 комманд через
> `exec`, тогда как гошечка отработает их и даже не заметит.

Во первых cli-скрипты и не предназначены чтобы их 100500 штук запускали, для этого есть php-fpm и он должен обрабатывать основную нагрузку, а cli-скрипты выполнять какие-то служебные действия. Если у вас не так, то у вас (были) проблема в архитектуре приложения.
Если всё-таки зачем-то и нужно запускать 100500 cli-скриптов, то нужно их самостоятельно ставить в очередь и обрабатывать порциями, в зависимости от ресурсов сервака.

Ответить | Правка | К родителю #91 | Наверх | Cообщить модератору

97. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +/
Сообщение от Ilya Indigo (ok), 18-Май-23, 16:54 
> вызываю killall через exec()

Поправляюсь, killall НЕ умеет работать с полным именем процесса (командой запуска), так что нужно использовать связку 'pgrep -f ...' + 'kill -9 ...'.


unset($pids, $exit);
exec('pgrep -f '.escapeshellarg('...'), $pids, $exit);
if($exit == 0 && count($pids))
{
    foreach($pids as $pid)
    {
        if(is_int($pid))
        {
            unset($out, $exit);
            exec('kill -9 '.$pid, $out, $exit);
            if($exit == 0)
                error_log(date_now().' - Процесс '.$pid.' завершён.'."\n", 3, LOG);
        }
    }
}

Ответить | Правка | К родителю #88 | Наверх | Cообщить модератору

102. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +1 +/
Сообщение от Аноним (102), 21-Май-23, 17:34 
> так что нужно использовать связку 'pgrep -f ...' + 'kill -9 ...'

Вроде там где есть pgrep - есть и pkill, так что связка обычно не нужна.

Ответить | Правка | Наверх | Cообщить модератору

104. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +/
Сообщение от Ilya Indigo (ok), 22-Май-23, 03:54 
Благодарю, да в этом примере 'pkill -9 -f ...' достаточно, не знал про него.
В реальном примере упростил, используя связку 'pgrep -cf ...' + 'pkill -9 -f ...', так как мне нужно знать есть ли вообще эти процессы или нет.
Ответить | Правка | Наверх | Cообщить модератору

107. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +/
Сообщение от Аноним (102), 22-Май-23, 14:30 
> так как мне нужно знать есть ли вообще эти процессы или нет.

Если нужно знать - _были_ или нет, то можно проверять код возврата pkill. А для более сложной логики - да, нужна ваша связка.

Ответить | Правка | Наверх | Cообщить модератору

101. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +1 +/
Сообщение от Аноним (102), 21-Май-23, 17:27 
> У меня недавно возникла проблема в том, что php многопоточность возможна только через вызов exec('... &'),

pcntl_fork чем не устроил?

> после которой процесс живёт своей жизнью и не то что его судьба, его pid мне не известен!

php -r '$res=proc_open("php -r \"sleep(5);\" >/dev/null 2>&1 &", array(["pipe","r"], ["pipe","w"], ["pipe","w"]), $p); echo implode("\n",proc_get_status($res)), "\n";'

Ответить | Правка | К родителю #88 | Наверх | Cообщить модератору

103. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +1 +/
Сообщение от Аноним (102), 21-Май-23, 18:20 
Т.е. даже вот так:
php -r '$res=proc_open("php -r \"sleep(15);\"", array(["pipe","r"], ["pipe","w"], ["pipe","w"]), $p); echo implode("\n",proc_get_status($res)), "\n";'

А то рефлекторно лишнего написал.

Ответить | Правка | Наверх | Cообщить модератору

105. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +/
Сообщение от Ilya Indigo (ok), 22-Май-23, 04:26 
>> У меня недавно возникла проблема в том, что php многопоточность возможна только через вызов exec('... &'),
> pcntl_fork чем не устроил?

https://www.php.net/manual/ru/function.pcntl-fork.php
Я не понял как это использовать и что мне это даёт.
Мне нужно чтобы скрипт выполняя какие-то синхронные действия, запустил несколько, в зависимости от условий, асинхронных процессов, затем продолжил свою синхронную работу и по окончании или завершился сразу, не завершая при этом асинхронные процессы или дождался завершения последнего асинхронного процесса и завершился.
Как это сделать с pcntl_fork() я не понял.

> Т.е. даже вот так:
> php -r '$res=proc_open("php -r \"sleep(15);\"", array(["pipe","r"], ["pipe","w"], ["pipe","w"]), $p); echo implode("\n",proc_get_status($res)), "\n";'

https://www.php.net/manual/ru/function.proc-open.php
С proc_open() не разобрался показалось слишком сложной и не понятно что такое pipe-ы и как с ними работать, если я предполагаю что процесс сам будет побочные действия выполнять и мне в него ничего передавать кроме аргументов вызова не нужно, а получить я от него хочу только pid или код возврата, когда он и подобные ему процессы завершаются. Но как это реализовать не совсем понял.
С proc_get_status($res) мне в конце скрипта в бесконечном цикле с секундной задержкой каждый запущенный процесс опрашивать что ли нужно перед выходом, чтобы получить код возврата?
Иначе $res я потеряю же после выхода?

Ответить | Правка | К родителю #101 | Наверх | Cообщить модератору

106. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +1 +/
Сообщение от Аноним (102), 22-Май-23, 14:22 
> https://www.php.net/manual/ru/function.pcntl-fork.php
> Я не понял как это использовать и что мне это даёт.

У вас была жалоба на отсутствие многопоточности в пхп, ну так это оно и есть. А нужно оно вам или нет - мне-то откуда знать? Вроде ещё треды есть, но там совсем как-то сложно, имхо.

> и по окончании или завершился сразу, не завершая при этом асинхронные процессы

С таким описанием вам нужен просто exec. Только зачем вам тогда pgrep, kill и всё остальное?...

> С proc_open() не разобрался показалось слишком сложной и не понятно что такое pipe-ы

Пайпы - это потоки STDIN, STDOUT и STDERR для запущенного процесса.

> и как с ними работать, если я предполагаю что процесс сам будет побочные действия выполнять и мне в него ничего передавать кроме аргументов вызова не нужно,

Если вам не нужно общаться с этим процессом, то и не работайте с этими пайпами, просто закройте их перед вызовом proc_close. Или вместо пайпов передайте константы [STDIN, STDOUT, STDOUT] - тогда и закрывать ничего не нужно будет. По вашей ссылке все примеры есть.

> а получить я от него хочу только pid или код возврата,

Ну вот тот же PID и можно получить через пайп:

php -r '$res=proc_open("php -r \"echo getmypid(), \\\"\n\\\"; sleep(15);\"", array(["pipe","r"], ["pipe","w"], ["pipe","w"]), $p); echo implode("\n",proc_get_status($res)), "\n\n"; echo fread($p[1], 10);';

> С proc_get_status($res) мне в конце скрипта в бесконечном цикле с секундной задержкой каждый запущенный процесс опрашивать что ли нужно перед выходом, чтобы получить код возврата?

А как вы это сейчас делаете с pgrep? Да, только так. Если через форк делать, то есть ещё pcntl_wait. Но судя по вашему 'kill -9' - дочерние процессы вам нужно прибивать принудительно, а значит wait вам не подойдёт.

> Иначе $res я потеряю же после выхода?

После выхода чего? При завершении родительского процесса? - Да, потеряете. Но тогда это уже и не мультипоточность, а просто запускалка процессов. Тогда вам опять же нужен exec, а не вот это вот всё.

Ответить | Правка | Наверх | Cообщить модератору

108. "Предварительный выпуск проекта PXP, развивающего расширенный..."  +/
Сообщение от Ilya Indigo (ok), 22-Май-23, 14:59 
Благодарю за разъяснения!

Если я правильно понял эти ф-ии предназначены для web-сервиса, который запускается через systemd, запускает несколько процессов и потом не закрывая их общается с ними передавая им новые задачи и получая от них новые результаты.
А пытался я это применить на cli-скрипт который запускается ежеминутно кроном и котороый, при необходимости, запускает параллельные асинхронные процессы, и понятно почему у меня не получилось.

Теперь немного больше понял как в принципе устроена многопоточность и понимаю что в php это работает, по крайней мере ф-ии для этого есть.

Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру