检测在后台运行的命令

时间:2013-05-23 01:05:14

标签: exec php

我正在使用php及其命令行界面来执行脚本。在脚本执行期间,我使用php.net中的以下代码在后台调用一些命令(其中一些非常耗时):

function execInBackground($cmd) { 
    if (substr(php_uname(), 0, 7) == "Windows"){ 
        pclose(popen("start /B ". $cmd, "r"));  
    } 
    else { 
        exec($cmd . " > /dev/null &");   
    } 
} 

在所有命令完全执行之前,主脚本可能会被调用几次。

如果在执行命令之前有没有办法检查它是否已经在之前执行脚本的后台运行了?

1 个答案:

答案 0 :(得分:1)

您可以跟踪后台命令的一种方法是将信息存储在某个文件中。该命令的名称在整个系统中可能不唯一,因此您无法检查该命令。您可以将进程ID存储在配置文件中,并按字符串检查命令:

function execInBackground($cmd)
{
    $running = false;

    // get the state of our commands
    $state = json_decode(file_get_contents("state.json"));

    // check if the command we want to run is already running and remove commands that have ended
    for ($i = 0; $i < count($state->processes); $i++)
    {
        // check if the process is running by the PID
        if (!file_exists("/proc/" . $state->processes[$i]->pid))
        {
            // this command is running already, so remove it from the list
            unset($state->processes[$i]);
        }

        else if ($cmd === $state->processes[$i]->command)
        {
            $running = true;
        }
    }

    // reorder our array since it's probably out of order
    $state->processes = array_values($state->processes);

    // run the command silently if not already running
    if (!$running)
    {
        $process = proc_open($cmd . " > /dev/null &", array(), $pipes);
        $procStatus = proc_get_status($process);

        $state->processes[] = array("command" => $cmd, "pid" => $procStatus["pid"]);
    }

    // save the new state of our commands
    file_put_contents("state.json", json_encode($state));
}

配置文件看起来像这样:

{
    "processes": [
        {
            "command": "missilecomm launch -v",
            "pid": 42792
        }
    ]
}

(我是JSON的“说服”,但你可以使用你想要的任何格式;))

如果有时想要多次运行相同的命令字符串,这将不起作用。

由于execInBackground()如何清除已完成的命令,它只能在Linux上运行。您必须找到另一种方法来检查Windows上是否存在进程ID。此代码未经过测试,我也不确定我的proc_*调用是否正确。