2017年2月20日月曜日

LumenでPHPのerror_reporting(エラーレベル)を設定する

どうも、俺です。

Lumenはデフォルトで全てのエラーが出力されます。
本番環境では出力されるエラー内容を設定したいのですが、その場合は、

$ vim /PATH/TO/vendor/laravel/lumen-framework/src/Concerns/RegistersExceptionHandlers.php
を開き、


    protected function registerErrorHandling()
    {   
        error_reporting(-1);

        set_error_handler(function ($level, $message, $file = '', $line = 0) {
            if (error_reporting() & $level) {
                throw new ErrorException($message, 0, $level, $file, $line);
            }   
        }); 

        set_exception_handler(function ($e) {
            $this->handleUncaughtException($e);
        }); 

        register_shutdown_function(function () {
            $this->handleShutdown();
        }); 
    }   
にある、error_reporting(-1)を変更します。

本番の場合は「何も出力しない or 重大なエラーだけ出力」、で良いと思うので、

  // 何も表示しない
  error_reporting(0);

  // 重大な実行時エラーを出力
  error_reporting(E_ERROR);

になります。


以上でぇぇぇぇぇぇす!

2017年2月9日木曜日

Lumenでcron処理

どうも、俺です。

Lumen(多分5.3.1)でcronプログラムを作って登録する方法について。
おそらくLaravelはもうちょっと楽に出来そうですが、基本は同じはず。


Laravelの公式HP参照

【手順1】app/Console/Commands/以下にphpファイルを作成


$ vim app/Console/Commands/MyScript.php

内容は以下のような感じ。

<?php
namespace App\Console\Commands;

use Illuminate\Console\Command;

class MyScript extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'my_script_signature';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description.';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        // ここに処理を書く
        echo "HELLO!\n";
    }
}


【手順2】app/Console/Kernel.phpに登録


$ vim app/console/Kernel.php

内容は以下。

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        // ここに作成したコマンドクラスを追記していく。
        \App\Console\Commands\MyScript::class,
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        // ここに実行させたいコマンドクラスのシグネチャを記す。
        $schedule->command('my_script_signature')->cron('* * * * * *');
    }
}

【手順3】動作を試してみる


$ php artisan my_script_signature
HELLO!

問題なし!

【手順4】cronに登録する


* * * * * php /path/to/artisan schedule:run 1>> /path/to/cron.log 2>&1

これで定期的に処理をさせることが出来ます。



以上でぇぇぇぇす!

2017年2月8日水曜日

pgpool-2のオンラインリカバリを試す

どうも、俺です。

pgpool-2でオンラインリカバリを試したのでその方法をメモ。
若干ややこしかった...。

【環境】
・postgresql v9.5.3
・pgpool-2 v3.5.4
・ノード1のあるサーバー 192.168.0.1
・ノード2のあるサーバー 192.168.0.2
・pgpool-2のあるサーバー 192.168.0.1
※PostgreSQLとpgpool-2はすでに稼働中とします。
※pgpool-2の公式HP参照


手順1) C言語関数インストール

各ノードのPostgreSQLデータベースに関数をインストールします。
すべてのノードのあるサーバーで以下を行います。

# su - postgres
% cd /path/to/pgpool-II-3.5.4/src/sql/pgpool-recovery
% make install
% psql -p ポート番号 -f pgpool-recovery.sql template1 


手順2) pgpool.confの設定

オンラインリカバリを行うための設定を追加します。

# vim /path/to/pgpool/etc/pgpool.conf

--- 以下pgpool.conf内容 ---

# PCPの設定
pcp_listen_addresses = '*'
pcp_port = 9898
pcp_socket_dir = '/tmp'

# リカバリを行うPostgreSQLのユーザとパスワード。
recovery_user = 'postgres'
recovery_password = 'postgres'
# オンラインリカバリを実行するスクリプト名。
recovery_1st_stage_command = 'recovery_1st_stage.sh'
recovery_2nd_stage_command = 'recovery_2nd_stage.sh'
# オンラインリカバリのタイムアウト秒数。
recovery_timeout = 120 
# リカバリ中にアイドル状態のクライアントを何秒で切断するか。0は無効。-1は即時切断。
client_idle_limit_in_recovery = 1 


手順3) postgresql.confの設定

archive_logを取るように設定します。
既に設定済みであれば不要です。

# vim /path/to/pgsql/data/postgresql.conf

--- 以下postgresql.confの内容 ---

archive_mode = on

# /usr/local/pgsql/data/archive というディレクトリ以下にarchive_logがコピーされる
archive_command = 'cp %p /usr/local/pgsql/data/archive/%f'


手順4) リカバリスクリプトの作成

・recovery_1st_stage.sh
・recovery_2st_stage.sh
・pgpool_remove_start
の3ファイルを作成します。

pgpoolレプリケーションモード | PostgreSQL関連情報のスクリプトを使わせて頂きました。ありがとうございます。

recovery_1st_stage.sh

#!/bin/sh

PSQL="/usr/local/pgsql/bin/psql"
PORT=5432
MASTER_BASEDIR=$1
RECOVERY_HOST=$2
RECOVERY_BASEDIR=$3

$PSQL -p $PORT -c "SELECT pg_start_backup('pgpool-recovery')" postgres

echo "restore_command = 'cp /usr/local/pgsql/data/archive/%f %p'" > $MASTER_BASEDIR/recovery.conf

ssh -l postgres -T $RECOVERY_HOST rm -rf $RECOVERY_BASEDIR.bk
ssh -l postgres -T $RECOVERY_HOST mv -f $RECOVERY_BASEDIR{,.bk}

rsync -az -e ssh -l postgres $MASTER_BASEDIR/ $RECOVERY_HOST:$RECOVERY_BASEDIR/

ssh -l postgres  -T $RECOVERY_HOST cp -f $RECOVERY_BASEDIR.bk/postgresql.conf $RECOVERY_BASEDIR
ssh -l postgres  -T $RECOVERY_HOST rm -f $RECOVERY_BASEDIR/postmaster.pid

rm -f $MASTER_BASEDIR/recovery.conf

$PSQL -p $PORT -c "SELECT pg_stop_backup()" postgres

recovery_2nd_stage.sh

#!/bin/sh

PSQL="/usr/local/pgsql/bin/psql"
PORT=5432
ARCHIVEDIR=/usr/local/pgsql/data/archive/
MASTER_BASEDIR=$1
RECOVERY_HOST=$2
RECOVERY_BASEDIR=$3

$PSQL -p $PORT -c 'SELECT pg_switch_xlog()' postgres

rsync -az -e ssh  -l postgres $ARCHIVEDIR $RECOVERY_HOST:$ARCHIVEDIR 

pgpool_remove_start

#! /bin/sh

PGCTL=/usr/local/pgsql/bin/pg_ctl
RECOVERY_HOST=$1
RECOVERY_BASEDIR=$2

ssh -l postgres -T $RECOVERY_HOST $PGCTL -w -D $RECOVERY_BASEDIR start 2>/dev/null 1> /dev/null < /dev/null &

これら3ファイルに実行権限を付けて、各ノードサーバーのデータディレクトリ以下に配置します。

以上で、オンラインリカバリの準備は完了です。


では実際にオンラインリカバリを試してみます。
オンラインリカバリを行うには、いずれかのノードサーバーがpgpool側で異常検知されている必要があります。
今回は192.168.0.2のPostgreSQLを止めてからオンラインリカバリをしてみます。


% /usr/local/pgsql/bin/pg_ctl -D /path/to/pgsql/data stop

% /usr/local/pgsql/bin/psql -p 9999  // ←pgpoolへ接続
postgres=# show pool_nodes;
 node_id |   hostname   | port | status | lb_weight |  role  | select_cnt 
---------+--------------+------+--------+-----------+--------+------------
 0       | 192.168.0.1  | 5432 | 2      | 0.500000  | master | 1200
 1       | 192.168.0.2  | 5432 | 3      | 0.500000  | slave  | 884
(2 rows)

192.168.0.2が停止しています。

この状態で、pcp_recovery_nodeコマンドでオンラインリカバリを行います。

% /path/to/pgpool/bin/pcp_recovery_node -h 192.168.0.1 -p 9898 -U postgres -n 1

-h ... PCP(pgpool Communication Manager Connection)の稼働ホスト?
-p ... PCPの稼働ポート
-U ... pgpoo.confに記したrecovery_user名
-n ... 何番のノードを起動させるか。今回はnode_id=1の192.168.0.2

以上で、問題なければオンラインリカバリが成功するはずです。
ただ、オンラインリカバリを行うのは意外と時間かかる場合があるので気長に待つ必要も大切です。


【実際に試してみた】

サービス稼働中を模して、
無限ループでINSERTさせながらオンラインリカバリをやってみました。
...が、ターミナル上はSuccess!と出たのですが、
実際にデータを確認してみると2件レコードのズレがありました...。
やはり、データ誤差が出た場合は一旦サービス止めてdata/ディレクトリ丸ごとコピーの方が安全なのでしょうか。。?


以上でぇぇぇぇす!

2017年2月7日火曜日

tmuxですべてのペインに同じコマンドを同時入力!

どうも、俺です。

タイトルの通り、tmuxで複数のペイン分割した状態で
全てのペインに同じコマンドを送ってやりたいとき。



: set-window-option synchronize-panes on
これです!


ちなみにやめたい時は

: set-window-option synchronize-panes off
です。

複数のペイン上で複数の作業を同時進行したい時、
とかに使えます。

以上でぇぇぇぇす!