CakePHP3のmigrationsシェルに一括オプション追加

CakePHP3のmigrationsシェルに一括オプションを追加

CakePHP3のCake Shell migrations を拡張した話です。
それは、migrationsbulkオプションを追加して
複数のDatasourceに対するスキマを操作する内容です。

普通にDatasourceに一括操作の対象になるデータベースを全て設定し、
--connectionのオプションでmigrationsのSHELLコマンドをただいても
良いですが、私が管理しているアーキテクチャーは👇の通りでしたので
既にDatasourceの項目を設定して置くのは出来ませんでした。
f:id:ldhdba:20171012171047p:plain

分かりにくいかも知れないので、端的に説明させて頂きますと
実際のアプリのソースコードは一つで、ctrl_appというアプリ管理システムで
顧客向けのアプリケーションを発行・削除・管理をしたりしています。
もちろん以下の物も裏側で自動に生成されたりします。
- 各アプリケーションのDB
- 各アプリケーションのシンボリックリンク
- 各アプリケーションのcronファイル
- などなど

こんな構成にした理由は、もちろんすべてのアプリケーションのコード一貫性を守るためです。 Cacheなどを上手く管理するとCakePHP Frameworkのプロジェクトも普通に実装できました。
※ 少し記事のテマの話とずれてしまいますので、詳しい環境説明は省略します。

また、上端の画嬢で紹介している通り、このプロジェクトには
デプロイツール、Capistrano を利用しています。
で、やりたかったのが、Capistranoで共通のアプリソースコードをデプロイして
それぞれのデータベースのスキマも一括で操作したかったことです。

もちろんMgrationsShellを拡張する選択肢以外にも色々ありますが、
とにかく!やっちゃいました。

まず、普通のMigrationsShellの動きは以下のようになりますね。
Datasourcedefault設定に対するDBスキマを操作しています。
--connection オプションを利用するとdefault以外のキーむ可能です。
f:id:ldhdba:20171012171345p:plain

そして、改修してからはー
f:id:ldhdba:20171012171401p:plain

その後、オプションではなく、別途のSHELLコマンドとしてあった方が良さそうだったので−
f:id:ldhdba:20171012171430p:plain

これでCapistranoで共通のコードをデプロイした後、 各DBスキマ更新も楽になりました。

以下はMigrationsShellを拡張したクラスでございます。

<?php

namespace App\Shell;

use Migrations\Shell\MigrationsShell as CakeMigrationsShell;
use Migrations\MigrationsDispatcher;
use Symfony\Component\Console\Input\ArgvInput;
use Cake\Datasource\ConnectionManager;

class AppDeployMigrationsShell extends CakeMigrationsShell
{
    /**
     * main
     * \Migrations\Shell\MigrationsShell override method
     * デフォルトでctrl_appに登録されている全てのアカウント(db)を一括操作する.
     *
     * @author lee
     *
     * @return bool Success of the call
     */
    public function main()
    {
        if ($this->argv[1] == 'dump') {
            $exitCode = parent::main();
        } else {
            // ⭐最初こちらに来て、migrations SHELLコマンドに dump -cオプションを付ける⭐
            $connectedDbs = $this->connectAccountsDatasource();
            foreach ($connectedDbs as $name) {
                $argv = ['migrations', $this->argv[1], '-c', $name];
                $app = new MigrationsDispatcher(PHINX_VERSION);
                $input = new ArgvInput($argv);
                $app->setAutoExit(false);
                $exitCode = $app->run($input);
                $dispatchCommand = 'migrations dump';
                $dispatchCommand .= ' -c '.$name;
                $dumpExitCode = $this->dispatchShell($dispatchCommand);
            }
        }
        if (isset($dumpExitCode) && $exitCode === 0 && $dumpExitCode !== 0) {
            $exitCode = 1;
        }

        return $exitCode === 0;
    }

    /**
     * connectAccountsDatasource
     * ctrl_appのapiで登録アカウント(db)を受け取り、全てconfigする.
     *
     * @author lee
     *
     * @return array
     */
    private function connectAccountsDatasource()
    {
        $defaultConnectInfo = ConnectionManager::get('default');
        $defaultResourceInfo = $defaultConnectInfo->config();
        $accounts = \App\Statics\Api::getAttachCode();
        $connectedDbs = [];
        foreach ($accounts as $name) {
            $migrateResourceInfo = $defaultResourceInfo;
            $migrateResourceInfo['database'] = $name;
            // config infoをgetしたやつをsetする場合、以下の情報が抜けているので追加する
            $migrateResourceInfo['className'] = 'Cake\Database\Connection';
            $connectedDbs[] = $name;
            if (!empty(ConnectionManager::config($name))) {
                continue;
            }
            ConnectionManager::config($name, $migrateResourceInfo);
        }

        return $connectedDbs;
    }
}

以上、CakePHP3のCake Shell migrations を拡張した話でした。

AWSのCDNサービスCloudFrontを始める (実習オリジンサーバー👉s3)

概要

最近、色んなプロジェクトで面白い仕組みのback-end、front-endを触れるようになりました。
面白かった仕組みの中で一つがCDNでした。
また、AWSのCloudFrontサービスでCDN仕組みを簡単に構築できました。
ということで、自分のリマインダーと初心者の方に伝えるために記事を書いておきます。

CDNとは

CDN(Contents Delivery Network)とはウェブコンテンツを配信することに最新化されたネットワークという意味です。

image

基本的には、ウェブサイトにある画像や動画などの静的なコンテンツをウェブサーバとは別のサーバにキャッシュして静的データを提供する仕組です。例えば、Googleのサーバはドコにあるのでしょうか。具体的な場所は公開されていませんが、Google目く「世界中にある」そうです。そのユーザーの一番近いエッシサーバからデータを提供する仕組になっています。その仕組をCDNといいます。

image

CloudFrontとは

そうすると、AWSCloudFrontサービスは何でしょう。

以下の通り🔗ドキュメントによく説明されています。

image

CloudFront は、静的および動的なウェブコンテンツ(.html、.css、.php、イメージファイルなど)をエンドユーザーに高速に配信するウェブサービスです。CloudFront は、エッジロケーションというデータセンターの世界的ネットワークを経由してコンテンツを配信します。CloudFront を使用して提供されているコンテンツをユーザーがリクエストすると、そのユーザーはエッジロケーションにルーティングされます。エッジロケーションでは最も低いレイテンシー(遅延時間)が提供されるので、コンテンツは可能な最高のパフォーマンスで配信されます。コンテンツがエッジロケーション内に最も低いレイテンシーですでに存在している場合、CloudFront はそのコンテンツを即時に配信します。コンテンツがこのエッジロケーションに現在存在しない場合、CloudFront は、コンテンツの最終バージョンのソースとして識別されている Amazon S3 バケットまたは HTTP サーバー(ウェブサーバーなど)からコンテンツを取り込みます。

CDNオリジンサーバーが重要です。
オリジンサーバーはそれぞれのクライアントに静的データを配布するサービスです。 オリジンサーバーはS3EC2を主に利用しています。

実習

さて、一番基本的なS3をオリジンサーバーとして利用するCloudFront配布を生成して見ましょう。

image

① S3にBucketを生成して配布するhtmlファイルをアップロードします。

すみませんが、こちらの詳しい説明は他の記事をご覧ください。

<html>
<head>
    <title>Example CloudFront Distribution</title>
</head>
<body>
    <MARQUEE behavior="alternate" scrollDelay="50">Hello CloudFront - S3</MARQUEE>
</body>
</html>

image

image

② CloudFrontサービス開始

AmazonのコンソールCloudFrontに移動して、新しい配布を作ります。

③コンテンツ配布方法選択

コンテンツを配布する方法を選択します。
今回は静的なコンテンツ、WEBを選択します。
動画のリアルタイミングプロトコルRTMPも適用しています。

image

④生成する配布の設定

image

Origin Domain Name

オリジンのドメイン名を設定します。
入力エリアをクリックすると、現在利用できるS3バケットとELBのリストが表示されます。
上で生成したS3バケットを選択します。

Origin ID

オリジン区分するIDです。
特に気にする部分ではありませんし、Origin Domain NameでS3バケットを選択すると自動に設定されます。

Restrict Buket Access

S3バケットにCloudFrontしかアクセス出来ないように設定する項目です。
Yesを選択してください。

Origin Access Identity

オリジンにアクセスする識別子でございます。
新たに生成することもできますし、もうあるものも利用できます。
今回はCreate a New Identityを選択しましょう。

Comment

新たに生成する識別子です。
デフォールトそのまま使いましょう。

Grant Read Permissions on Bucket

CloudFrontがS3でファイルを読める権限をバケットのBucket Policyに設定します。
Yesに設定すると、他のアクセスは制限され、CloudFrontしかアクセス出来るようにバケットにBucket Policyが設定されます。
Yes, Update Bucket Policyを選択しましょう。

Path Pattern

CloudFrontでファイルを取り込む規則です。
デフォルトは「*」に設定されているので、全てのファイルを取り込むことになります。
この部分は生成した後、追加するのができます。

Viewer Protocol Policy

CloudFrontのプロトコル政策です。
デフォルトのそのまま利用しましょう。
- HTTP and HTTPS : HTTPとHTTPS全部利用します。
- Redirect HTTP to HTTPS : 全てのHTTPアクセスをHTTPSにリダイレクトします。
- HTTPS Only : HTTPSのみ利用します。

Allowed HTTP Methods

許可するHTTPメソッドの種類です。
デフォルトのそのまま利用します。
- GET, HEAD : ファイルを読むときだけ選択します。
- GET, HEAD, PUT, POST, PATCH, DELETE, OPTIONS : 動的なコンテンツを送信するとき選択します。

続いてこ細かい設定でございます。

image

・Object Caching

ファイルのキャッシュの維持時間を設定します。
維持時間が過ぎたらCloudFrontにあるファイルが削除されます。
デフォルトそのまま利用します。
- Use Origin Cache Headers : オリジンHTTPヘッダーのキャッシュ設定を従います。
それぞれのファイルあたりに設定するのが出来るメリットがあります。
キャッシュ設定が無かったらデフォルトキャッシュ維持時間は24時間です。 - Customize : デフォルトキャッシュ維持時間を設定します。 - Minimum TTL : 最初のキャッシュの維持時間です。
秒単位で設定して、このMinimum TTL設定時間とオリジンHTTPヘッダーのキャッシュ設定(Cache-Control)時間中、長い時間が適用されます。

Forward Cookies

オリジンのクッキーをCloudFrontを経てクライアントに伝えるかを設定します。
デフォルトそのまま利用しましょう。
- None : クッキーを伝えません。キャッシュの性能がもっと向上されます。
- Whitelist : クッキーを選別して伝えます。
- Whitelist Cookies : 伝えるクッキーの名前を設定します。
それぞれのクッキーは行別に区分されます。

Query String Forwarding and Caching

CloudFrontにオリジンでクエリー文字列を伝えます。
オリジンでクエリー文字列を区分して見せるためには設定します。
設定しないとキャッシュの性能が向上されます。
デフォルトそのまま利用しましょう。

・Smooth Streaming

リアルタイムストリーミングプロトコルMicrosoft Smooth Streamingを利用する時設定します。
デフォルトそのまま利用しましょう。

Restrict Viewer Access

Signed URLでCloudFrontの利用を制限したい場合設定します。
デフォルトそのまま利用しましょう。

Price Class

料金のレベルです。 エッジロケーション利用範囲を設定するとき、実際サービスにはそんなに必要じゃない地域を除外する場合設定します。
デフォルトそのまま利用しましょう。

Alternate Domain Names

Route 53でドメインを連携する場合、こちらを設定するべきです。
色んなドメインでしたら、行別に区分して最大10個まで設定するのができます。
今回は使いません。

続いてこ細かい設定でございます。

image

SSL Certificate

HTTPSプロトコルを利用するための認証書の設定です。
デフォルトそのまま利用しましょう。
− Default CloudFront Certificate : CloudFrontの認証書を利用します。
− Custom SSL Certificate : 利用者が購入したドメインと認証書を利用する場合設定します。認証書の保存はIAMで可能です。
− Custom SSL Client Support :カスタムSSLクライアント設定です。先にCustom SSL Certificateを設定するべきです。
− All Clients : 専用IP利用者指定SSL設定です。詳しい内容は🔗ドキュメントを参考してください。

Amazon CloudFront には、ウェブサイト全体を高速化しつつ、CloudFront のどのエッジロケーションからでも HTTPS 経由でコンテンツを安全に配信する 3 つのオプションがあります。エッジロケーションからの安全な配信に加えて、オリジンフェッチ用に HTTPS 接続を使用するよう、CloudFront を設定することもできます。これにより、お客様のオリジンサーバーとエンドユーザーのエンドツーエンド間でデータが暗号化されます。
Supported HTTP Versions

サポートするHTTPバージョンを設定します。
デフォルトそのまま利用しましょう。

Default Root Object

CloudFront配布のドメインの最上位にアクセスしたとき見せるファイルの名前です。
今回はsample.htmlにしました。

Logging

CloudFrontアクセスログ設定です。
デフォルトそのまま利用しましょう。
− Bucket for Logs : CloudFrontログを保存するS3バケットを設定します。
− Log Prefix : S3バケットにログを保存する場合、ディレクトリー名を設定します。

Enable IPv6

IPv6からのアクセスも反映するかを設定します。 今回はチェックしなかったです。

Comment

メモです。追加で説明とか記録する場合、利用します。

Distribution State

配布を生成した後、配布状態を設定します。
− Enabled : すぐ利用出来る状態になります。
− Disabled : 配布生成のみ非活性化します。

image

CloudFront配布が生成しました。
気になる部分及びもっと詳しい設定内容は🔗ドキュメントを参考してください。
Statusを見るとInProgressに表示されインジケーターがぐるぐるしています。
配布が全てのエッジロケーションに電波されるまでは約15~20分かかるためです。

⑤結果確認

image

全てのエッジロケーション電波が完了されたら、StatusDeployedに変わります。
また、Domain NameにCloudFront配布のドメインが表示されます。

では、ウェブでCloudFrontに接続してみましょう。 sample.html内容がちゃんと出ています。
CloudFront配布ドメイン形はd39embebg71el9.cloudfront.netで、前の d39embebg71el9は生成した配布を区分しています。

image

これで、Webサーバの地域に関わらず全世界どこでも早くデータを配布するのができます。👏👏👏

ChromeからHTTPヘッダーを確認

Web Browser、Chromeの開発ツールにはHTTPヘッダーを確認するのができます。
NetworkタブのResponse HeadersのX-Cache項目を見るとHit from cloudfrontだと表示されます。
これは、CloudFrontにキャッシュされたファイルを取り込んだという意味です。

image

キャッシュの維持時間が過ぎてCloudFrontがオリジンにアクセスしてファイルを取り込んだときは、 Miss from cloudfrontだと表示されます。

⑦CloudFront配布削除する

CloudFront配布を削除するためには、配布リストから配布を選択してDisable設定をします。
非活性状態になったらまた全てのエッジに電波されるまで約15~20分かかります。
その後、StatusDeployedになったら削除可能になります。

jQuery.tooltipの「出力エリアをずれてしまう」の原因と解決

概要

皆さんは、tooltipをよく利用していますか?
tooltipとは、マウスを当該イメージ画面や特定の対象に持っておけば、当該対象に関する詳細説明が表示される機能でございます。

const IMG_MESSAGE = 'はじめまして!イと申します。';
$('.ldh-img').tooltip({
    position: { my: "left+15 center", at: "right center" },
    content: IMG_MESSAGE,
    track: false
});

f:id:ldhdba:20160923083402p:plain

通常、🔗jQuery.tooltip、もしくは🔗Bootstrapで、機能を導入しています。
しかし、その後、テストや運用から以下のような「出力エリアをずれてしまう」の結果のため、困るかもしれません。

const TEST_CASE = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$('.ldh-img').tooltip({
    position: { my: "left+15 center", at: "right center" },
    content: TEST_CASE,
    track: false
});

f:id:ldhdba:20160923080948p:plain

ということで、こいう結果の原因と解決方法を話しさせて頂きます。

原因

まず、いくつかのケースの結果をご覧して、どのケースで出力エリアをずれてしまうのか、確認しましょう。

const TEST_CASE_1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
const TEST_CASE_2 = '12345678901234567890123456789012345678901234567890';
const TEST_CASE_3 = 'ひらがなカタカナひらがなカタカナひらがなカタカナひらがなカタカナ';
const TEST_CASE_4 = '漢字漢字漢字漢字漢字漢字漢字漢字漢字漢字漢字漢字漢字漢字漢字漢字';
const TEST_CASE_5 = '한글한글한글한글한글한글한글한글한글한글한글한글한글한글한글한글한글한글';
const TEST_CASE_6 = '@#()*$(*%()!#&%)(&!#*()&*)(!#&*(&!#(*&*()!$&*(!#&%*(!#&*!#$';
const TEST_CASE_7 = '!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!';
const TEST_CASE_8 = '12345678901234567890123456789012345678 9012345 67890';
const TEST_CASE_9 = '12345678901234567890123456789012345678한901234567890';

$('.ldh-img').tooltip({
    position: { my: "left+15 center", at: "right center" },
    content: TEST_CASE_9,
    track: false
});

ケース①、連続英字
f:id:ldhdba:20160923083948p:plain

ケース②、連続数字
f:id:ldhdba:20160923084033p:plain

ケース③、連続ひらがな・カタカナ
f:id:ldhdba:20160923084059p:plain

ケース④、連続漢字
f:id:ldhdba:20160923084140p:plain

ケース⑤、連続ハングル
f:id:ldhdba:20160923084154p:plain

ケース⑥、連続特殊文字
f:id:ldhdba:20160923084242p:plain

ケース⑦、連続ビックリ文字
f:id:ldhdba:20160923084334p:plain

ケース⑧、スペース含め連続数字
f:id:ldhdba:20160923084507p:plain

ケース⑨、ハングル含め連続数字
f:id:ldhdba:20160928134400p:plain

テストケースが多かった感じがありますが、テストの結果をご覧すると、原因をすぐ理解しましたと思っております。
原因は、🌟スペース以外の1バイト文字がスペースなしで連続に並んでいると、それを一つの単語と判断してエリアを過ぎてしまう
という原因でした。

解決

解決できる方法としては、いろいろあると思いますが、自分が解決した方法を説明させていただきたいと思っています。

それは、CSSword-breakで改行処理する方法でございます。
word-breakとは、単語意味の通り、単語を切るというものです。
基本的に、次の行に変わるときは、単語単位で変わることになっています。
word-breakは、エリアの範囲を過ぎたら改行するCSS設定でございます。

.ui-tooltip {
    word-break:break-all;
}

f:id:ldhdba:20160923095835p:plain

まとめ

jqueryから提供されている便利なオブジェクトがいろいろありますが、利用ケースによって予想以外の結果を出している場合があります。
その原因が起こる可能性が少ないだと無視するとまずいと思っております。
しっかり、利用する機能は色々なケースを確認しましょう!
以上です。

AWS SFTPサーバ構築手順

AWS SFTPサーバ構築手順

順番

テーマ

内容

VPCウィザードの開始

 

f:id:ldhdba:20170929101236p:plain

VPCコンソール画面で”VPCウィザードの開始”ボタンをクリック

 

 

f:id:ldhdba:20170929101248p:plain

・"1 個のパブリックサブネットを持つ VPC"を選択して選択ボタンをクリック

 

 

f:id:ldhdba:20170929101259p:plain

VPCの設定情報を入力して"VPCの作成"ボタンをクリック

※セキュリティーグループはインスタンスを作成するタイミングで新規登録

インスタンスの作成

f:id:ldhdba:20170929101306p:plain

インスタンスを作成

 

 

f:id:ldhdba:20170929101318p:plain

・マシンイメージを選択

 

 

f:id:ldhdba:20170929101327p:plain

インスタンスタイプの選択

※AMIを立ち上げるためにt2.microを利用 (CPU速度が比較的に早いので)

※本番サーバを立ち上げるインスタンスタイプはt2.nanoを利用

 

 

f:id:ldhdba:20170929101338p:plain

インスタンスの詳細の設定

※本番サーバのインスタンスは”CloudWatch 詳細モニタリングを有効化”をチェック

 

 

f:id:ldhdba:20170929101353p:plain

・ストレージの設定

 

 

f:id:ldhdba:20170929101403p:plain

インスタンスのタグ付け

※値の内容に”for-ami”が付いていると、ami用だと判断して処理するルール

 

 

f:id:ldhdba:20170929101413p:plain

・セキュリティグループの設定

 

 

f:id:ldhdba:20170929101429p:plain

インスタンス作成の確認及びキーペアをダウンロード

ボリュームの作成

f:id:ldhdba:20170929101456p:plain

・ボリュームを作成

アベイラビリティゾーンはインスタンスリストの

    アベイラビリティゾーンカラム内容を確認して統一する

 

 

f:id:ldhdba:20170929101508p:plain

・区分しやすくなるため、ボリュームの名前を設定する

・ボリュームIDを別にメモしておく(awscliでボリュームをアタッチするとき必要)

IAMの追加

    🔻

    🔻

・グループ追加

 

 

   🔻

   🔻

・ユーザー追加

 

 

    🔻

    🔻

    🔻

・グループにユーザーを追加

ssh -i -/taka.pem centos@???

ssh -i ~/repos/linkmate/file/aws/linkmate-email-test-in-japan-resion.pem centos@52.199.38.125

 

ansible-playbook playbook.yml -i host -u centos --private-key=~/repos/linkmate/file/aws/linkmate-email-test-in-japan-resion.pem

 

 

 

マシンイメージ設定

(再起動必要な作業)

・`sudo yum update -y`でyumアップデートする ➜ 再起動

・timezone変更 ➜ 再起動 (실질 코멘트 넣기)

 (参考リンク:http://qiita.com/pugiemonn/items/bfcbfaa3caae614bb076

SELinuxの無効化 ➜ 再起動(실질 코멘트 넣기)

 (参考リンク:http://qiita.com/mattsun/items/470581ff34f87c7eb21d

マシンイメージ設定

Packages設置及び

   awscliサービス)

sudo yum install epel-release

sudo yum install python-pip

sudo pip install awscli

マシンイメージ設定

(aws configure)

 

マシンイメージ設定

jp設置)

sudo yum install jq

マシンイメージ設定

(ボリュームアタッチ)

aws ec2 attach-volume --volume-id vol-06fae433e3c6a067e --device /dev/sdf --instance `curl --retry 10 --retry-delay 1 --silent --fail http://169.254.169.254/latest/meta-data/instance-id` --region ap-northeast-1

 

 

自動マシンイメージ設定

(ボリュームアタッチ)

#crondをまず止める

systemctl disable crond

 

#アタッチ内容

vi /etc/fs-init.sh

 

chmod a+x /etc/fs-init.sh

 

vi /etc/rc.local

※ 一番下に`/etc/fs-init.sh`を追加

 

#権限変更

chmod u+x /etc/rc.d/rc.local

 

#Package自動アップデート止める

vi /etc/cloud/cloud.cfg.d/99_mysettings.cfg

※ 内容は`repo_upgrade: none`を入れる

イメージの作成

・イメージを作成する

AMIの作成

      🔻

      🔻

      🔻

      🔻

      🔻

      🔻

AMIの作成の結果確認

 

EIPの登録及び反映

 

cronの標準出力がPostfix Queueに溜まりすぎてサーバが危なくなった!

🌺概要

ShellScriptをcronから動かしているなら、標準出力を管理しなければいけないです。

🌺背景

或るサービスのAWSクラウドサーバを管理してます。
或る日、そのサーバのHDD容量がゼロになってしまう事項が起きました。

システムに異常な動作をしていることを見つたら、
Nagios、k1LoW/faultline の通報がバンバン来ていました。
f:id:ldhdba:20170928102408p:plain

先輩とすぐアクションを取ったのは以下の通りでした。
①❗Cakeのエラーログにセッションが書き込めないエラーが出ている
② セッションが書き込めないってことは、HDDの容量かな?
③ コマンド df すると 容量が0であることの確認
f:id:ldhdba:20170928102442p:plain

④ 容量を食うシステムではない! 👉ということはメールログかな
/var/spool 確認する 👉 ログがたまってる
⑥ 👍 メッセージのキュー削除
🔗 Postfixのメールキュー操作

f:id:ldhdba:20170928102648p:plain

ひとまず対応したけど、一体原因は何だったかな−!

🌺原因

そのサーバには、多数のShellScriptがcloneで実行されています。
また、MTAのPostfixが設置されていました。

で、各種cronで叩かれたコマンドの出力結果が
ログではなく、自動にPostfixでメール送信を試みたことですね−
特にcronの各週出力をメールに転送出来るように設定したことでは無いので、
その全てが、Postfix Queueとして溜まったことが原因でした。
f:id:ldhdba:20170928102800p:plain

Postfixとは?

f:id:ldhdba:20170928102836p:plain
IBM Public Licenseを従って、Wietse Venemaが開発した
オープンソース MTA(Mail Transfer Agent)です。
sendmailとの交換性も高いし、安全で簡単な構造を持っています。
もちろん相対的に早い速度の特徴を持っているメールサーバのサービスです。
PostfixSMTPサーバとしての機能しか持ってないので、
メールサーバとして動作させるためには、
POPサーバやIMAPサーバが別途に必要になるかもしれません。

🌺解決

各ShellScriptの必要なログとエラーのログは別のログファイルで管理しています。
なので、そもそもその標準出力は要らなかったです。
で、私はcronから実行される各種ShellScriptの標準出力を切る方式を選びました。
方法は、大きく2つありました。

① cronにコマンドを追加する

方法は簡単です。 crontabで >/dev/null 2>&1 ってコマンドを追加することだけです。

* * * * * /usr/bin/sh /.../*.sh > /dev/null 2>&1

※コマンド>/dev/null 2>&1 とは?

エラー出力(1)を含めた標準出力(2)をゴミ箱(/dev/null) に入れますという意味でございます。

② ShellScriptの標準出力を切る (CakePHP3 Shell)

CakePHP3の Cake\Console\Shell を拡張します。

・まず、CakePHP3 の CakeShellの基本標準出力
// Cake\Console\Shell

   /**
     * Displays a header for the shell
     *
     * @return void
     */
    protected function _welcome()
    {
        $this->out();
        $this->out(sprintf('<info>Welcome to CakePHP %s Console</info>', 'v' . Configure::version()));
        $this->hr();
        $this->out(sprintf('App : %s', APP_DIR));
        $this->out(sprintf('Path: %s', APP));
        $this->out(sprintf('PHP : %s', phpversion()));
        $this->hr();
    }

f:id:ldhdba:20170928103944p:plain
👇👇👇👇👇👇👇

・拡張

<?php

namespace App\Shell;

use Cake\Console\Shell;

class AppShell extends Shell
{
    /**
     * overriding the parent method
     * stop to the welcome stdoutput for postfix.
     *
     * @author lee
     */
    protected function _welcome()
    {
        return;
    }
}

f:id:ldhdba:20170928104046p:plain
👍👍👍👍👍

もし、知らなかった方がいらっしゃったらサーバが死ぬ前に対応しましょう!
以上です~👋