1

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

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

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

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

4

1 回答 1

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_*调用是否正确。

于 2013-05-23T02:49:08.960 回答