2019年8月26日月曜日

iOS証明書を更新する

どうも、俺です。

1年ほど前にiOS PUSH通知証明書の更新方法をメモしましたが、今日はiOS証明書の更新方法をメモ。

全体の流れは、


  1. 証明書署名要求を作成
  2. Apple Developer Programで新しい証明書を作成
  3. .p12ファイルを作成
  4. プロビジョニングプロファイルを更新
です。


手順1: 証明書署名要求を作成

キーチェーンアクセス.appを起動し、メニューにある
「キーチェーン」→「証明書アシスタント」→「認証局に証明書を要求...」をクリック
・ユーザーのメールアドレス ... Apple Developer Programのメールアドレス
・通称 ... なんでもOK
・CAのメールアドレス ... 空白
・ディスクに保存 ... チェック
・鍵ペア情報を指定 ... チェック
で「続ける」をクリックし、適切なディレクトリに保存します。


鍵ペア情報は「2048ビット」「RSA」でOK。
保存するファイル名を変更していなければ、対象のディレクトリにCertificateSigningRequest.certSigningRequestというファイルが生成されます。

手順2: Apple Developer Programで証明書を作成

Apple Developer Programにログインし、
メニュー→「Certificates」をクリックし選択。


↑の画像にある「+」ボタンをクリックし新しい証明書作成画面に移ります。

続いて「iOS App Development」を選択。
これは開発用の証明書です。
AdHoc用や本番用の証明書を作る場合は「iOS Distribution (App Store and Ad Hoc)」を選択。


次に、手順1で作成した証明書要求の CertificateSigningRequest.certSigningRequest を選択します。


すると、次の画面で作成された証明書情報が見れますので、右上の「Download」をクリックし保存します。



これで新しい証明書が作成され、PCにも保存されました。
DLした証明書をダブルクリックし、キーチェーンアクセスに登録しておきます。



古い証明書は有効期限まで使えますが、もう新しい証明書を使ってしまってOKです。

手順3: .p12ファイルの作成

個人で開発されてる方はここの手順は不要です。
チーム開発されてる場合などは、.p12ファイルを作成 & 共有して使うと良いです。

まず、キーチェーンアクセスを起動し、登録したての新しい証明書を選択します。


左側にある「▶」をクリックし、「秘密鍵」と書かれた鍵マークのある列を選択します。
そこで右クリックし「" ****** を書き出す..."」をクリックし、適切な名前をつけて.p12ファイルを保存します。
これで.p12ファイルが出来上がります。


手順4: プロビジョニングプロファイルを更新

証明書が新しくなると、プロビジョニングプロファイルを更新する必要があります。
※有効期限が切れると使えなくなるため



既存のプロビジョニングプロファイルを「Edit」から編集し、新しい証明書を選択して作り直します。





以上でぇぇぇえす。

2019年3月22日金曜日

DKIM設定してさらにメール到達率を上げる

どうも、俺です。

男もすなるDKIMといふものを女もししてみむとてするなり。

環境はCentOS7.2 + Postfix 2.10.1 です。

OpenDKIMのインストール

yumで入れます。
# yum install opendkim

鍵やら何やらを作るので、専用のディレクトリを作成します。
# mkdir /etc/opendkim/keys/MYDOMAIN.com(ドメイン名)

で、鍵やら何やらを作ります。
# opendkim-genkey -D /etc/opendkim/keys/MYDOMAIN.com/ -b 1024 -d MYDOMAIN.com -s koexuka

-Dは生成ディレクトリ
-bは1024や2048など鍵のビット長
-dはドメイン名
-sはセクレタ名。鍵を識別できる分かりやすい名前が良いです。サイト名や作成日付など。

これでファイルが2つできてるはずです。
# ls -l /etc/opendkim/keys/MYDOMAIN.com

-rw------- 1 opendkim opendkim 887  3月 22 15:11 koexuka.private
-rw------- 1 opendkim opendkim 317  3月 22 15:11 koexuka.txt


設定ファイルの更新

KeyTableファイルを編集します。
# vim /etc/opendkim/KeyTable

koexuka._domainkey.MYDOMAIN.com MYDOMAIN.com:koexuka:/etc/opendkim/keys/MYDOMAIN.com/koexuka.private

SigningTableファイルを編集します。
# vim /etc/opendkim/SigningTable

*@MYDOMAIN.com koexuka._domainkey.MYDOMAIN.com

TrustedHostファイルを編集します。
# vim /etc/opendkim/TrustedHosts

127.0.0.1
::1
#host.example.com
#192.168.1.0/24

CIDR形式で記述できます。
上記IPにマッチした場合だけ署名されます。

opendkim.confを編集します。
# vim /etc/opendkim.conf

Mode sv
#KeyFile        /etc/opendkim/keys/default.private #コメントアウトする
KeyTable       /etc/opendkim/KeyTable
SigningTable   refile:/etc/opendkim/SigningTable
ExternalIgnoreList     refile:/etc/opendkim/TrustedHosts
InternalHosts  refile:/etc/opendkim/TrustedHosts

/etc/sysconfig/opendkimファイルを編集します。
# vim /etc/sysconfig/opendkim

# これを追加
AUTOCREATE_DKIM_KEYS=NO

main.cfを編集します。
#vim /etc/postfix/main.cf

# これを追加
smtpd_milters = inet:127.0.0.1:8891
non_smtpd_milters = $smtpd_milters
milter_default_action = accept

Postfixを再起動します。
# systemctl restart postfix


ドメイン情報を更新

利用しているDNSサーバーでTXTゾーンにDKIMの内容を反映させます。
まず、公開鍵の内容を確認します。

# cat /etc/opendkim/keys/MYDOMAIN.com/koexuka.txt

koexuka._domainkey     IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNAD(〜略〜)//ciSVp9o(〜略〜)ZBCwIDAQAB" )  ; ----- DKIM key koexuka for MYDOMAIN.com

DNS管理画面で以下を追加します。
Aレコード koexuka._domainkey.MYDOMAIN.com 123.45.67.89(IPアドレス)
TXTレコード koexuka._domainkey p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNAD....ZBCwIDAQAB; v=DKIM1; k=rsa;


あとは実際にメールを送信してみて、受信側でメールヘッダに
dkim=pass
とあればOKです!

以上でぇぇぇぇえぇ〜す。

2019年3月15日金曜日

PostgreSQL10のでパーティショニング

どうも、俺です。

PostgreSQLがv10になってからパーティショニングの設定が超ラクになりました。
これまでは、CREATE TABLE するときにトリガーや関数を逐一設定する必要がありましたが、
PostgreSQL 10からはCREATE TABLE文の中だけでパーティショニングの設定が可能です。

簡単なサンプルで見てみます。

-- 元となる親テーブルの作成
CREATE TABLE test_table (
  id SERIAL,
  user_id INTEGER NOT NULL,
  name VARCHAR(512) NOT NULL,
  created_at TIMESTAMP NOT NULL
)
-- user_idをキーにパーティションする
PARTITION BY LIST (user_id);

-- user_idが1の場合はtest_table_1へ
CREATE TABLE test_table_1 PARTITION OF test_table FOR VALUES IN (1);
-- user_idが2の場合はtest_table_2へ
CREATE TABLE test_table_2 PARTITION OF test_table FOR VALUES IN (2);
-- user_idが3と4の場合はtest_table_3へ
CREATE TABLE test_table_3 PARTITION OF test_table FOR VALUES IN (3,4);
-- user_idが5と6と7の場合はtest_table_4へ
CREATE TABLE test_table_4 PARTITION OF test_table FOR VALUES IN (5,6,7);
.
.
.

これだけでOKです。


ただ、このパーティショニングの方法だと、user_idが増えれば増えるほどパーティショニング子テーブルをいちいち CREATE TABLE する必要があるので、
子テーブルを予め10個作成しておき、user_idを10で割った余りを元にパーティショニングするように変更してみます。

CREATE TABLE test_table (
  id SERIAL,
  user_id INTEGER NOT NULL,
  name VARCHAR(512) NOT NULL,
  created_at TIMESTAMP NOT NULL
)
-- user_idを10で割った余りをキーにパーティションする
PARTITION BY LIST ((user_id%10));

CREATE TABLE test_table_1 PARTITION OF test_table FOR VALUES IN (1);
CREATE TABLE test_table_2 PARTITION OF test_table FOR VALUES IN (2);
CREATE TABLE test_table_3 PARTITION OF test_table FOR VALUES IN (3);
CREATE TABLE test_table_4 PARTITION OF test_table FOR VALUES IN (4);
CREATE TABLE test_table_5 PARTITION OF test_table FOR VALUES IN (5);
CREATE TABLE test_table_6 PARTITION OF test_table FOR VALUES IN (6);
CREATE TABLE test_table_7 PARTITION OF test_table FOR VALUES IN (7);
CREATE TABLE test_table_8 PARTITION OF test_table FOR VALUES IN (8);
CREATE TABLE test_table_9 PARTITION OF test_table FOR VALUES IN (9);
CREATE TABLE test_table_0 PARTITION OF test_table FOR VALUES IN (0);



以上でぇぇぇえ〜す。

2018年7月25日水曜日

iOS PUSH通知証明書を更新する

どうも、俺です。

 1年毎にやってくるPUSH通知証明書の更新ですが、毎回手順を調べるのも面倒なのでメモ。
 全体の流れは、

  1. 証明書署名要求を作成
  2. Apple Developer Programで証明書を作成
  3. .p12ファイルを作成
  4. .pemファイルを作成
です。

【手順1: 証明書署名要求を作成】

キーチェーンアクセス.appを起動し、メニューの
「キーチェーン」→「証明書アシスタント」→「認証局に証明書を要求...」をクリック。

・ユーザーのメールアドレスを入力...適当なメアド
・通称 ... 何でもOK
・CAのメールアドレス ... 空白
・ディスクに保存 ... チェック
・鍵ペア情報を指定 ... チェックしない
で、「続ける」をクリックし、保存先を決めてファイルを保存。

CertificateSigningRequest.certSigningRequest というファイルが生成されます。


【手順2: Apple Developer Programで証明書を作成】

Apple Developer Programにログイン。
メニューにある「Certificates」→「All」をクリック。


画面右上にある「+」ボタンをクリックし証明書作成を開始する。

次の画面で、「Production」内にある「Apple Push Notification service SSL (Sandbox & Production)」にチェックを入れ「Continue」をクリック。
※開発版の場合は「Develop」内にある「Apple Push Notification service SSL (Sandbox)」にチェックを入れる。



次の画面で、PUSH通知証明書を更新するアプリのApp IDを選択し「Continue」。



次の画面はそのまま「Continue」をクリック。



次の画面で、先ほど生成した CertificateSigningRequest.certSigningRequest を選択し「Continue」。



すると、証明書が作成されるので「Download」をクリックし保存する。


【手順3: .p12ファイルを作成】

手順2で作成した証明書ファイルをダブルクリックし、キーチェーンアクセスに登録します。

次にキーチェーンアクセス上で、登録した証明書を「右クリック」→「"Apple Push Services: XXX.XXX.XXX"を書き出す...」をクリックして適当なディレクトリに保存します。
パスワードが必要な場合は設定して下さい。次の手順4で利用します。

すると、証明書.p12のようなファイル名でファイルが書き出されます。
ファイル名は半角英数で aps_prod.p12 のように変えておいたほうが良いです。



【手順4: .pemファイルを作成】

多くのPUSH通知証明書更新について書かれたサイトは、
手順3で作成した「.p12ファイルをサーバーにあげて使って下さい」、とあるのですが、
一応、.pemファイルを作ってそれをサーバーにUPする手順も書いておきます。
(...というか、その方法でしかやった事がない)

ターミナルを開き、手順3で作成した.p12ファイルがあるディレクトリまで移動し、
以下のコマンドを叩きます。

$ openssl pkcs -in aps_prod.p12 -out aps_prod.pem -nodes

これで、.pemファイルが生成されます。
※手順3でパスワードを指定していた場合は、パスワードを問われます。



手順は以上。
作られたaps_prod.pemをサーバーにアップしてPUSH通知が届くかテストして作業完了です!


以上でぇぇぇぇぇぇぇす。

2018年7月11日水曜日

SQLiteのコマンドラインを見やすくしちゃう

どうも、俺です。

SQLiteのコマンドラインって見にくいですよね。
そこで見やすくする方法についてメモ。


$ vim ~/.sqliterc

.header on
.mode column

これでOKです。


または、SQLiteのコマンドライン内で直接、
$ sqlite3 hoge.sqlite

sqlite> .header on
sqlite> .mode column

これでもOKです。


以上でぇぇぇす。

2018年4月23日月曜日

PostgreSQL TIMESTAMP型のDEFAULTS値に小数点以下を表示させない

どうも、俺です。

PostgreSQLのテーブル定義で
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP

という定義をすると、
created_atカラムに値を指定せずINSERTすると
2018-04-23 16:12:23.13289

秒の後に小数点が入ります。


小数点を入れずに、年月日 時分秒 というフォーマットにするには
created_at TIMESTAMP NOT NULL DEFAULT DATE_TRUNC('second', now() :: timestamp)

という定義にしておけばOKです。


以上でぇぇえぇす。

2018年4月20日金曜日

動画をパラパラアニメに変換するサービスを5日で作りました

どうも、俺です。

 やれライブ配信だ、やれ動画広告だ、と騒がれがちな昨今ですが、
 動画ファイル(.mp4 .mov)をパラパラアニメに変換するサービスを作りました。







パラパラ動画です。


変換したい動画ファイルを選択し、
フレームレート(fps)と再生速度、出力フォーマット(gif または webp)を選んでアップロードすれば、
見事なパラパラアニメが完成します。

aPNGにも変換できるようにしてるんですが、
如何せん変換後のファイルサイズがバカでかいので、取りやめました。
仕事の合間に作ったので結構日数かかりました。

素のPHP + TwitterBootstrap3 + SQLiteです。
ページデザインはこれ以上オシャレにできませんToT

「ブログにパラパラ画像を載せたい!」というような場面で是非活用してもらえればうれしいです。



以上でぇぇぇす。

2018年4月19日木曜日

今さらながら、Let's EncryptでSSL対応 + 自動更新

どうも、俺です。

今日は、随分前からWeb界隈でもてはやされているLet's Encryptの導入と自動更新設定についてメモ。

環境はCentOS6.9。たぶんCentOS7系でも一緒だと思う..。
Apache 2.4。

(1) certbotをダウンロード

$ wget "https://dl.eff.org/certbot-auto"

// certbot-autoを適当なPATHへ持っていく
# mv certbot-auto /usr/local/bin

// certbot-autoに実行権限を付与
# chmod +x /usr/local/bin/certbot-auto

(2) SSL証明書を作成

※注意 :この時点で対象サーバーにドメインが当たっていないと以下のコマンドは失敗します。

# certbot-auto certonly --webroot -w /www/path/to/public -d example.com --email info@example.com

うまくいくと
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/example.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/example.com/privkey.pem
   Your cert will expire on 2018-07-18. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot-auto
   again. To non-interactively renew *all* of your certificates, run
   "certbot-auto renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
が表示されます。

(3) 証明書の確認

$ ls /etc/letsencrypt/live/example.com

README  cert.pem  chain.pem  fullchain.pem  privkey.pem


  • cert.pem ... 証明書
  • chain.pem ... 中間証明書
  • fullchain.pem ... 証明書と中間証明書とを一緒にした証明書
  • privkey.pem ... 秘密鍵

(4) Apache(2.4系)の設定

対象の.confファイル内に以下を記述。
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem

※2.2系の場合は以下も記述。
SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem

(5) Apache再起動

# /usr/local/apache2/bin/apachectl restart

(6) Let's Encrypt 自動更新設定

Let's Encryptの証明書は3ヶ月で有効期限が切れます。
そのためcronで自動更新させましょう。
# vim /etc/crontab

30  5  *  *  1  root /usr/bin/certbot-auto renew -q --no-self-upgrade --post-hook "/usr/local/apache2/bin/apachectl restart"

↑毎週月曜AM5:30に更新コマンドを叩いています。
更新ができるようになる30日前になったら、証明書が更新されます。
-qオプション ... 出力なし。
--no-self-upgrade ... プログラムの新バージョンへの自動更新をしない。




以上でぇぇぇえぇぇす。

2018年4月3日火曜日

"〜〜" not found using pkg-configのエラーが出る

どうも俺です。

Linux上で何かのプログラムをインストールしようとして、
$ ./configure
ERROR: libwebp >= 0.2.0 not found using pkg-config

のようなエラーが出る場合、pkg-configとやらが悪さをしている可能性があります。

その場合は、
$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

で解消する場合があるのでお試しあれ。
以上でぇぇえぇぇぇす。

2017年9月26日火曜日

Xcode8のままiOS11ビルドをする

どうも俺です。


iOS11がリリースされ、それに合わせてXcode v9もリリースされました。
Xcodeをバージョンアップするためには、
先にMacOSをバージョンアップする必要があって...いつもながら超面倒です。

Xcode8のままだとiOS11用にビルドできない...とお思いのみなさん、
裏技を使ってそのままiOS11ビルドできます。

※動作保証はできませんので、自己責任で行って下さい。


(1) Xcode 9をダウンロードする
https://developer.apple.com/download/more/
からXcode 9をダウンロードし解凍します。
結構時間かかります。

(2) Xcode 9.appを適当なディレクトリへおく
/Application/Xcode-9.app などへ移動させましょう。

(3) Xcode 8を適当な名前にリネームしておく。
仮に、Xcode-8.app としておきましょう。

(4) Xcode 8.appにXcode 9.app内にあるiOS11ディスクイメージのシンボリックを貼る

$ sudo ln -s /Applications/Xcode-9.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/11.0\ \(15A5278f\) /Applications/Xcode-8.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/11.0

(5) Xcode 8.appを再起動
再起動したら準備OK。iOS11端末をつなげてビルドできます。




ここに答えが。
Use Xcode 8 with iOS 11 | stack overflow



以上でぇぇぇぇす。

2017年8月8日火曜日

linker command failed with exit code 1が出た時の解決方法案

どうも、俺です。

Xcodeで開発してて目にすると1時間はその解決に費やしてしまうこともある地獄のエラー文言。
そう、それが
linker command failed with exit code 1


※Xcode 8.3.3

今日はこのエラーが出た時「これやったら直った」というあらゆる手段をお伝えします。


■プロビジョニングプロファイルは正しく設定されているか

人により設定方法は様々ですが、僕の場合、
・General>SigningにあるAutomatically manage signingのチェックをはずす

・Build Settings内、
 ProvisioningProfile (Deprecated)とProvisioning Profileの2箇所に適切なプロビジョニングプロファイルを設定。
 Code Signing Identityに正しい証明書を設定。
 最後にDevelopment Teamにチーム名を設定。

としています。
このミスの際は、ちゃんと「プロビジョニングプロファイル間違えているよ」というエラーが出ることが多い...。


■Enable Bitcodeの設定を間違えていないか

Build Settings>Build Options内にあるEnable Bitcodeが「Yes」になっているとアカン場合がある。
組み込んだフレームワークがbitcodeとやらに対応していないかもしれないので、速攻「No」に設定し直す。




■存在しないリソース(画像etc)を取り入れようとしていないか

Build Phases>Copy Bundle Resources内に存在しないリソースがないか要チェック。
無いものが含まれている場合は削除します。



■Deployment Targetを間違えていないか

General>Deployment InfoにあるDeployment Targetに無茶な値を入れていないか。
古すぎるターゲットなどに設定している場合は、よく考えて適切な値にします。



■Info.plistの設定Target Membershipは大丈夫か

Info.plistを選択してTarget Membershipにチェックが入っているとアウト。
チェックを外します。



■Xcodeを再起動しよう

この方法を使うと90%の確率でビルドが成功します。
試してみる価値あり。



■Mac本体ごと再起動しよう

この方法を使うと50%の確率でビルドが成功します。
試してみる価値あり。




上記以外でこのエラーの対処方法があれば教えてください。


※※※2017.08.18追記
このエラーが出た時に詳細ログが見れないのでモヤモヤしてたのですが、ログを見る方法が分かりました!
command+8 !!
LogNavigatorというやつらしいです!
これで具体的にエラー内容確認できます!


以上でぇぇぇぇす。

2017年5月1日月曜日

Macでgem installしたら "Operation not permitted" エラー

どうも、俺です。

 Mac(Sierra)でターミナルから
$ sudo gem install XXXX

とコマンドを打つと
Password:
ERROR:  While executing gem ... (Errno::EPERM)
    Operation not permitted - /usr/bin/XXXX
というエラーが出る場合の対処法。

以下のようにすればOK。
$ sudo gem install -n /usr/local/bin XXXX
これは、インストールディレクトリを
/usr/bin
から
/usr/local/bin
へ変更してインストールを行います。


MacのrootlessというSystem Integrity Protection(rootless)という機能があり、
/System
/bin
/usr
/sbin
フォルダ以下にファイルを作成できないという仕様のためです。

他にもrootlessを無効にする方法もありますが、セキュリティ的に望ましくはないので割愛します。


以上でぇぇぇぇぇす。

2017年3月13日月曜日

php: error while loading shared libraries: libpq.so.5: cannot open shared object fileが出る

どうも俺です。

構築したばかりのサーバーで
$ php -v
と打ってphpのバージョンを確認しようとしたら、

php: error while loading shared libraries: libpq.so.5: cannot open shared object file: No such file or directory
というエラーが出ちゃいました。

エラー内容のとおり、
何かしらの共有ライブラリ(今回はlibpq.so.5)が読み込めないというエラーです。

ちなみにrootになって同じコマンドを打つと

# php -v
PHP 5.6.24 (cli) (built: Mar  2 2017 15:32:45) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
と問題なく実行されます。
つまり、今回のエラーは何かしらのPermissionが関係してるだろうと予想つきました。

こういう場合は共有ライブラリの依存関係を確認してみます。

$ ldd /usr/local/bin/php
        linux-vdso.so.1 =>  (0x00007ffda23d7000)
        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f2982411000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f29821fa000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f2981fe0000)
        libpq.so.5 => not found
        librt.so.1 => /lib64/librt.so.1 (0x00007f2981dd7000)
        libcurl.so.4 => /lib64/libcurl.so.4 (0x00007f2981b6e000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f298186c000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f2981667000)
        libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f298144e000)
        libxml2.so.2 => /lib64/libxml2.so.2 (0x00007f29810e4000)

注目すべきは、libpq.so.5 => not found となっているところです。


今度はrootになって確認してみます。

# ldd /usr/local/bin/php
        linux-vdso.so.1 =>  (0x00007ffce4d60000)
        libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f0d05ff1000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f0d05dda000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f0d05bc0000)
        libpq.so.5 => /usr/local/pgsql/lib/libpq.so.5 (0x00007f0d05997000)
        librt.so.1 => /lib64/librt.so.1 (0x00007f0d0578e000)
        libcurl.so.4 => /lib64/libcurl.so.4 (0x00007f0d05525000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f0d05223000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f0d0501e000)
        libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f0d04e05000)

今度は libpq.so.5 => /usr/local/pgsql/lib/libpq.so.5 と表示されました。

ということで/usr/local/pgsqlディレクトリを確認してみます。


$ ls -l /usr/local
drwxr-xr-x   7 root     root       62  3月  2 15:44 bin
drwxr-xr-x.  2 root     root       22  7月 29  2016 etc
drwxr-xr-x.  2 root     root        6  8月 12  2015 games
drwxr-xr-x.  3 root     root       16  7月 29  2016 include
drwxr-xr-x.  3 root     root       30 12月  6 15:26 lib
drwxr-xr-x.  2 root     root        6  8月 12  2015 lib64
drwxr-xr-x.  2 root     root        6  8月 12  2015 libexec
drwx------   6 postgres postgres   52  3月  2 14:41 pgsql
drwxr-xr-x   3 root     root       16  3月  2 15:33 sbin
予想通りpgsqlユーザーのみ読み書きできる状態になってしまっていました。

適切に権限を追加して完了。




以上でぇぇぇぇす。

2017年3月1日水曜日

公開鍵認証を使い、sshで2段階ログイン(多段ログインもできちゃう)

どうも、俺です。

今日は、
~/.ssh/config
を使って、2段階先のサーバーへsshログインする方法をメモ。

<クライアント> → <サーバーA(192.168.0.2)> → <サーバーB(192.168.0.3)>
のように接続する際に

$ ssh サーバーB
と打てばサーバーBへsshログインできます。

(1) .ssh/configを編集


$ vim ~/.ssh/config

Host <サーバーA>
  HostName 192.168.0.2
  User ユーザー名
  Port 22
  IdentifyFile ~/.ssh/serverA_id_rsa

Host <サーバーB>
  HostName 192.168.0.3
  User ユーザー名
  Port 22
  ProxyCommand ssh -W %h:%p <サーバーA>
  IdentifyFile ~/.ssh/serverB_id_rsa

※クライアント側のPCにはサーバーAとサーバーBの認証鍵
~/.ssh/serverA_id_rsa
~/.ssh/serverB_id_rsa
があることが前提です。

(2) ログインする

$ ssh サーバーB

複数先のサーバーへログインする場合は、
上記の.ssh/config内に踏み台にするサーバーをドンドン追記していけばOKです。


以上でぇぇぇえぇぇす。

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
です。

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

以上でぇぇぇぇす!

2017年1月31日火曜日

Lumen(Laravel)でview()に渡した値を参照する

どうも、俺です。

変数の値を
view()->share("myName", $myName);
のように渡したあとで、
「あ、やっぱまたview()から取って使いたい〜〜!」となった場合。

view()->shared("myName");
で取得できるさかいに。

以上でぇぇぇぇす!

2017年1月27日金曜日

LumenのEloquentでupdate()を呼ぶとMassAssignmentExceptionが出てまう

どうも、俺です。

最近は軽量PHPフレームワークのLumenを使っています。
(※バージョンはたぶん5.2。確認の仕方が分からない...)

最近もっぱらPHP界隈を賑わしているLaravelから派生したフレームワークで、
機能が少ない分、軽量で処理速度も速いそうです。

LaravelもLumenもデータベースモデルはEloquentという機能を使って開発することができ、僕もそれを使っています。

で、データを更新するために
$userObject->update(["name"=>"山田さん", "age"=>30]);
のように実装すると、

 MassAssignmentException
が発生し小一時間ハマりました。

この場合は、その該当のモデルクラスに

// 変更可能なカラム名
protected $fillable = ["name", "age", "その他カラム名"];

// または変更不可能なカラム名
protected $guarded = ["id", "create_at"];

のどちらか(または両方)を記述すればOKです。

ただ、上記の変数を指定しなくてもupdate()メソッドが使える場合もあり、
その理由は未だ不明です...。



ちなみに、insert()またはsave()メソッドでは上記の例外の発生は未確認です。




以上でぇぇぇぇす!