2016-10-08 2 views
0

У меня есть скрипт php, который использует flock(), чтобы запретить запуск нескольких экземпляров, если скрипт уже запущен.php script - Перенаправить ввод в другой экземпляр

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

т.е.

test.php:

#!/usr/bin/env php 
<?php 

$lock_file = fopen (getcwd() . '/'. basename(__FILE__, '.php') . '.pid', 'c'); 
$got_lock = flock ($lock_file, LOCK_EX | LOCK_NB, $wouldblock); 
if ($lock_file === false || (! $got_lock && ! $wouldblock)) : 
    throw new Exception ("Error opening or locking lock file"); 
    error_log("execption thrown"); 
elseif (! $got_lock && $wouldblock) : 
    exit ("Another instance is already running; terminating.\n"); 
endif; 

while (true) : 
    $input = $argv; // or incomming datas from other script ? 
    unset($argv); 
    if (is_array($input)) : 
     foreach ($input as $a) : 
      echo $a; 
     endforeach; 
    else : 
     echo $input; 
    endif; 
endwhile; 

?> 

Теперь, если я бегу:

php -f test.php arg1 arg2

php -f test.php arg3 arg4

Второй вызов выхода, а также, но я хотел бы, чтобы arg3 и arg4 были отправлены на май n процесс.

Как я могу это сделать?

ответ

1

Другими словами, вы хотите установить связь с процессом, который уже существует? aka IPC, есть много способов сделать это. самым быстрым способом является разделяемая память. но использование базы данных или UNIX-сокетов было бы проще реализовать. вот пример использования SQLite:

в любом удобном для обработки сообщений, выполните следующие действия:

while(NULL!==($message=check_for_message())){//handle all messages 
echo "got a mesage!:"; 
var_dump($message); 
} 

и функция "check_for_message":

//returns string("message") if there is a message available. 
// else returns NULL 
//Warning, do not try to optimize this function with prepared statements, unless you know what you're doing, in SQLIte they will lock the database from writing. 
function check_for_message(){ 
static $db=false; 
if($db===false){ 
$db=new PDO('sqlite:ipc.db3','','',array(PDO::ATTR_EMULATE_PREPARES => false,PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)); 
$db->exec(
' 
CREATE TABLE IF NOT EXISTS messages (id INTEGER PRIMARY KEY AUTOINCREMENT, message TEXT); 

' 
); 
register_shutdown_function(function()use(&$db){ 
$db=NULL; 
unset($db); 
unlink("ipc.db3"); 
}); 
} 
$message=$db->query("SELECT id,message FROM messages LIMIT 1",PDO::FETCH_ASSOC); 

foreach($message as $ret){ 
$db->query("DELETE FROM messages WHERE id = ".$db->quote($ret['id'])); 
return $ret['message']; 
} 
return NULL; 
} 

и отправить сообщение:

пример использования:

foreach($argv as $arg){ 
sendmessage($arg); 
} 

функция:

function sendmessage(string $message){ 
$db=new PDO('sqlite:ipc.db3','','',array(
PDO::ATTR_EMULATE_PREPARES => false, 
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION 
)); 
$db->query('INSERT INTO messages (message) VALUES('.$db->quote($message).');'); 
} 

примечание: я думаю, что вы могли бы оптимизировать эту функцию с помощью WAL режима SQLite и подготовленных заявлений. Я думаю, вы могли бы оптимизировать его еще больше, поместив его в общую память, используя PDO :: ATTR_PERSISTENT, но afaik, это хакерство, используя недокументированные функции, и я бы не ожидал, что он будет работать на такие вещи, как HHVM PHP. на unixes (* BSD, Mac OS X, Linux и т. д.), использование сокета unix будет в любом случае быстрее. было бы еще быстрее использовать необработанную общую память, но реализация очередей сообщений в общей памяти несколько сложна .. вы также можете изучить установку обработчика сигналов, например, SIGUSR1, чтобы указать, что есть ожидание сообщения, см. http://php.net/manual/en/function.pcntl-signal.php

+0

Сначала я посмотрю IPC, я не знал этого, в противном случае подход sql кажется хорошим решением, однако, если он не вызывает слишком много проблем одновременного доступа. благодаря! – Khorwin

+0

@Khorwin, поэтому я использовал SQLite, скажем, простой текстовый файл или что-то в этом роде. SQLite-движок заботится о синхронизации между практически бесконечным количеством процессов, которые хотят писать/читать из него/удалять из него, в то же время :) нет условий гонки, нет случайных перезаписей, все необходимые блокировки позаботятся SQLite. – hanshenrik

+0

Полезно знать, спасибо @hanshenrik! – Khorwin

Смежные вопросы