php script - 将输入重定向到另一个实例

I have a php script who use flock() to deny multiple instance if script already running.

I would like the arguments provided in the script call are transferred to the existing process who would be able to handle them.

ie :

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.
" );
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;

?>

Now, if i run :

php -f test.php arg1 arg2

php -f test.php arg3 arg4

The second call exiting as well, but i would like the arg3 and arg4 are piped to the main process.

How can i do that ?

展开翻译

译文

我有一个php脚本,如果脚本已经使用 flock()</ code>来拒绝多个实例 运行。</ p>

我希望脚本调用中提供的参数转移到能够处理它们的现有进程。</ p>

ie: </ p>

test.php:</ p>

 #!/ usr / bin / env php 
&lt;?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&amp;&amp;!$ wouldblock)):
抛出新的异常(“错误打开或锁定锁定文件”);
error_log(“execption thrown”); \ nelseif(!$ got_lock&amp;&amp; $ wouldblock):
exit(“另一个实例已经在运行;终止。
”);
endif;

而(true):
$ input = $ argv; //或者从其他脚本中输入数据?
unset($ argv);
if(is_array($ input)):
foreach($ input as a a):
echo $ a;
endforeach; \ 否则:
echo $ input;
endif;
endwhile;

?&gt;
</ code> </ pre>

现在,如果我运行:</ p>

php -f test.php arg1 arg2 </ code> </ p>

php -f test.php arg3 arg4 </ code> </ p>

第二个调用也退出了,但我希望arg3和arg4通过管道输送到主进程。</ p>

我该怎么做?</ p>
</ div>

1个回答

in other words, you want a way to communicate with the process that already exists? aka IPC, there are a lot of ways to do this. the absolute fastest way being shared memory. but using a database, or unix sockets, would be easier to implement. here's an example using SQLite:

whenever convenient to process messages, do this:

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

and the "check_for_message" function:

//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;
}

and to send a message:

example usage:

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

function:

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).');');
}

notes: i think you could optimize that function by using WAL-mode sqlite and prepared statements. i think you could optimize it even more by putting it in shared memory by using PDO::ATTR_PERSISTENT , but afaik, that's hackish using undocumented features and i wouldn't expect it to work for things like HHVM PHP. on unixes (*BSD, Mac OS X, Linux, etc), using a unix socket would be faster anyway. it'd be even faster to use raw shared memory, but implementing message queues in shared memory is somewhat tricky.. you could also look into installing a signal handler, for instance, SIGUSR1 to indicate that there's a message waiting, see http://php.net/manual/en/function.pcntl-signal.php

douaoj0994
douaoj0994 很高兴知道,谢谢@hanshenrik!
3 年多之前 回复
dsfg3241
dsfg3241 这就是我使用SQLite而不是纯文本文件的原因。 SQLite引擎负责在几乎无限数量的进程之间进行同步,这些进程想要写入/从中读取/从中删除,同时:)没有竞争条件,没有意外覆盖,所需的所有锁定都由 SQLite的。
3 年多之前 回复
duandou8457
duandou8457 我会首先看看IPC,我不知道这个,否则,sql方法似乎是一个很好的解决方案,但是如果它不会导致太多的同时访问问题。 谢谢!
3 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问