4907
下のスクリプトでexecを用いてシェルスクリプトを実行しようとしています。  
定期的にページへアクセスがあった場合に、シェルスクリプトが同時に動かないようにするため  
排他制御を加えないといけないのですが、ご教示いただけないでしょうか。

<http://localhost/index.php?hoge=30>  
で引数を渡しています。

```

    <?php
    if(isset($_GET['hoge'])) {
        $hoge = $_GET['hoge'];
        //取得した値を表示
        print("$hoge<br>\n");
    }
    
    // hogeが規定値より大きい場合  
    if ($hoge > 50 ){
        echo '動作1';
    }        
    //hogeが規定値と等しい場合 
    elseif ($hoge == 50) {
        echo '動作2';
    //hogeが規定値より小さい場合
    } else {
        echo '動作3';
        exec(' /Users/hoge/Desktop/test.sh');
    }
    ?>
    
```
CC BY-SA 3.0
2015-01-20T08:13:14.480
4900
2015-01-20T12:51:19.760
2015-01-20T12:51:19.760
7590
question
php
PHPで外部コマンドを実行する際の排他制御はどうすればいいか
セマフォを使うこと排他処理は実現可能だと考えられます。

<http://php.net/manual/ja/function.sem-acquire.php>

```

    echo '動作3';
    sem_acquire($a); //<--ここでセマフォを取得
    exec(' /Users/hoge/Desktop/test.sh');
    
```
CC BY-SA 3.0
2015-01-20T08:34:40.453
4904
2015-01-20T08:40:33.890
2015-01-20T08:40:33.890
7593
7593
4900
answer
いろんなやり方があると思いますが、以下にいくつか紹介します。

# セマフォを使った排他制御

Windows以外では[セマフォ](http://php.net/manual/ja/book.sem.php)を利用して排他制御を行うことができます。

セマフォID を取得する際 `sem_get()` の 2つめの引数で同時にセマフォを得ることが可能なプロセス数を指定出来るので、そこが 1
であれば同時に1プロセスしか起動できません（プロセスが解放されるまで待たされる）。

具体的には以下のようなコードになります。

```

    <?php
    
    // セマフォIDの取得
    $res = sem_get(ftok(__FILE__, 'g'), 1);
    
    // セマフォを得る
    if (!sem_acquire($res)) {
        throw new Exception('sem_acquire failed');
    }
    
    // 同時実行させたくない処理
    // ....
    
    // セマフォを解放
    if (!sem_release($res)) {
        throw new Exception('sem_release failed');
    }
    
    echo "finish!\n";
    
```

# ロックファイルを使った簡易排他制御

精度が求められない、簡易的に排他制御が出来ればいい場合は、ファイルの有無などで排他制御を行う事も可能でしょう。（あくまでも簡易的に、ですが）

```

    <?php
    
    $lockFile = __FILE__ . '.lock';
    
    // ファイルがなくなるまで待つ
    while (file_exists($lockFile)) {
        usleep(500000); // 0.5病魔ッ
    }
    
    // ロックファイルを作成
    touch($lockFile);
    
    // 同時実行させたくない処理
    // ....
    
    // ロックファイルを削除
    unlink($lockFile);
    echo "finish!\n";
    
```
CC BY-SA 3.0
2015-01-20T09:11:43.490
4907
2015-01-20T09:11:43.490
2944
4900
answer