CakePHP3のmigrationsシェルに一括オプション追加
CakePHP3のmigrationsシェルに一括オプションを追加
CakePHP3のCake Shell migrations
を拡張した話です。
それは、migrations
にbulk
オプションを追加して
複数のDatasourceに対するスキマを操作する内容です。
普通にDatasource
に一括操作の対象になるデータベースを全て設定し、
--connection
のオプションでmigrations
のSHELLコマンドをただいても
良いですが、私が管理しているアーキテクチャーは👇の通りでしたので
既にDatasource
の項目を設定して置くのは出来ませんでした。
分かりにくいかも知れないので、端的に説明させて頂きますと
実際のアプリのソースコードは一つで、ctrl_appというアプリ管理システムで
顧客向けのアプリケーションを発行・削除・管理をしたりしています。
もちろん以下の物も裏側で自動に生成されたりします。
- 各アプリケーションのDB
- 各アプリケーションのシンボリックリンク
- 各アプリケーションのcronファイル
- などなど
こんな構成にした理由は、もちろんすべてのアプリケーションのコード一貫性を守るためです。
Cacheなどを上手く管理するとCakePHP Frameworkのプロジェクトも普通に実装できました。
※ 少し記事のテマの話とずれてしまいますので、詳しい環境説明は省略します。
また、上端の画嬢で紹介している通り、このプロジェクトには
デプロイツール、Capistrano
を利用しています。
で、やりたかったのが、Capistrano
で共通のアプリソースコードをデプロイして
それぞれのデータベースのスキマも一括で操作したかったことです。
もちろんMgrationsShell
を拡張する選択肢以外にも色々ありますが、
とにかく!やっちゃいました。
まず、普通のMigrationsShell
の動きは以下のようになりますね。
Datasource
のdefault
設定に対するDBスキマを操作しています。
※ --connection
オプションを利用するとdefault
以外のキーむ可能です。
そして、改修してからはー
その後、オプションではなく、別途のSHELLコマンドとしてあった方が良さそうだったので−
これで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)とはウェブコンテンツを配信することに最新化されたネットワークという意味です。
基本的には、ウェブサイトにある画像や動画などの静的なコンテンツをウェブサーバとは別のサーバにキャッシュして静的データを提供する仕組です。例えば、Googleのサーバはドコにあるのでしょうか。具体的な場所は公開されていませんが、Google目く「世界中にある」そうです。そのユーザーの一番近いエッシサーバからデータを提供する仕組になっています。その仕組をCDNといいます。
CloudFrontとは
そうすると、AWSのCloudFront
サービスは何でしょう。
以下の通り🔗ドキュメントによく説明されています。
CloudFront は、静的および動的なウェブコンテンツ(.html、.css、.php、イメージファイルなど)をエンドユーザーに高速に配信するウェブサービスです。CloudFront は、エッジロケーションというデータセンターの世界的ネットワークを経由してコンテンツを配信します。CloudFront を使用して提供されているコンテンツをユーザーがリクエストすると、そのユーザーはエッジロケーションにルーティングされます。エッジロケーションでは最も低いレイテンシー(遅延時間)が提供されるので、コンテンツは可能な最高のパフォーマンスで配信されます。コンテンツがエッジロケーション内に最も低いレイテンシーですでに存在している場合、CloudFront はそのコンテンツを即時に配信します。コンテンツがこのエッジロケーションに現在存在しない場合、CloudFront は、コンテンツの最終バージョンのソースとして識別されている Amazon S3 バケットまたは HTTP サーバー(ウェブサーバーなど)からコンテンツを取り込みます。
CDNはオリジンサーバー
が重要です。
オリジンサーバーはそれぞれのクライアントに静的データを配布するサービスです。
オリジンサーバーはS3やEC2を主に利用しています。
実習
さて、一番基本的なS3をオリジンサーバーとして利用するCloudFront配布を生成して見ましょう。
① S3にBucketを生成して配布するhtmlファイルをアップロードします。
すみませんが、こちらの詳しい説明は他の記事をご覧ください。
<html> <head> <title>Example CloudFront Distribution</title> </head> <body> <MARQUEE behavior="alternate" scrollDelay="50">Hello CloudFront - S3</MARQUEE> </body> </html>
② CloudFrontサービス開始
AmazonのコンソールCloudFrontに移動して、新しい配布を作ります。
③コンテンツ配布方法選択
コンテンツを配布する方法を選択します。
今回は静的なコンテンツ、WEBを選択します。
動画のリアルタイミングプロトコル、RTMPも適用しています。
④生成する配布の設定
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 : 動的なコンテンツを送信するとき選択します。
続いてこ細かい設定でございます。
・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個まで設定するのができます。
今回は使いません。
続いてこ細かい設定でございます。
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 : 配布生成のみ非活性化します。
CloudFront配布が生成しました。
気になる部分及びもっと詳しい設定内容は🔗ドキュメントを参考してください。
Status
を見るとInProgress
に表示されインジケーターがぐるぐるしています。
配布が全てのエッジロケーションに電波されるまでは約15~20分かかるためです。
⑤結果確認
全てのエッジロケーション電波が完了されたら、Status
がDeployed
に変わります。
また、Domain Name
にCloudFront配布のドメインが表示されます。
では、ウェブでCloudFrontに接続してみましょう。
sample.html
内容がちゃんと出ています。
CloudFront配布ドメイン形はd39embebg71el9.cloudfront.net
で、前の d39embebg71el9
は生成した配布を区分しています。
これで、Webサーバの地域に関わらず全世界どこでも早くデータを配布するのができます。👏👏👏
⑥ChromeからHTTPヘッダーを確認
Web Browser、Chromeの開発ツールにはHTTPヘッダーを確認するのができます。
NetworkタブのResponse HeadersのX-Cache項目を見るとHit from cloudfront
だと表示されます。
これは、CloudFrontにキャッシュされたファイルを取り込んだという意味です。
キャッシュの維持時間が過ぎてCloudFrontがオリジンにアクセスしてファイルを取り込んだときは、
Miss from cloudfront
だと表示されます。
⑦CloudFront配布削除する
CloudFront配布を削除するためには、配布リストから配布を選択してDisable
設定をします。
非活性状態になったらまた全てのエッジに電波されるまで約15~20分かかります。
その後、Status
がDeployed
になったら削除可能になります。
jQuery.tooltipの「出力エリアをずれてしまう」の原因と解決
概要
皆さんは、tooltip
をよく利用していますか?
tooltip
とは、マウスを当該イメージ画面や特定の対象に持っておけば、当該対象に関する詳細説明が表示される機能でございます。
const IMG_MESSAGE = 'はじめまして!イと申します。'; $('.ldh-img').tooltip({ position: { my: "left+15 center", at: "right center" }, content: IMG_MESSAGE, track: false });
通常、🔗jQuery.tooltip、もしくは🔗Bootstrapで、機能を導入しています。
しかし、その後、テストや運用から以下のような「出力エリアをずれてしまう」の結果のため、困るかもしれません。
const TEST_CASE = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $('.ldh-img').tooltip({ position: { my: "left+15 center", at: "right center" }, content: TEST_CASE, track: false });
ということで、こいう結果の原因と解決方法を話しさせて頂きます。
原因
まず、いくつかのケースの結果をご覧して、どのケースで出力エリアをずれてしまうのか、確認しましょう。
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 });
ケース①、連続英字
ケース②、連続数字
ケース③、連続ひらがな・カタカナ
ケース④、連続漢字
ケース⑤、連続ハングル
ケース⑥、連続特殊文字
ケース⑦、連続ビックリ文字
ケース⑧、スペース含め連続数字
ケース⑨、ハングル含め連続数字
テストケースが多かった感じがありますが、テストの結果をご覧すると、原因をすぐ理解しましたと思っております。
原因は、🌟スペース以外の1バイト文字がスペースなしで連続に並んでいると、それを一つの単語と判断してエリアを過ぎてしまう
という原因でした。
解決
解決できる方法としては、いろいろあると思いますが、自分が解決した方法を説明させていただきたいと思っています。
それは、CSSのword-break
で改行処理する方法でございます。
word-break
とは、単語意味の通り、単語を切るというものです。
基本的に、次の行に変わるときは、単語単位で変わることになっています。
word-break
は、エリアの範囲を過ぎたら改行するCSS設定でございます。
.ui-tooltip { word-break:break-all; }
まとめ
jqueryから提供されている便利なオブジェクトがいろいろありますが、利用ケースによって予想以外の結果を出している場合があります。
その原因が起こる可能性が少ないだと無視するとまずいと思っております。
しっかり、利用する機能は色々なケースを確認しましょう!
以上です。
AWS SFTPサーバ構築手順
AWS SFTPサーバ構築手順
順番 |
テーマ |
内容 |
① |
VPCウィザードの開始 |
|
|
|
・"1 個のパブリックサブネットを持つ VPC"を選択して選択ボタンをクリック |
|
|
・VPCの設定情報を入力して"VPCの作成"ボタンをクリック ※セキュリティーグループはインスタンスを作成するタイミングで新規登録 |
② |
インスタンスの作成 |
・インスタンスを作成 |
|
|
・マシンイメージを選択 |
|
|
・インスタンスタイプの選択 ※AMIを立ち上げるためにt2.microを利用 (CPU速度が比較的に早いので) ※本番サーバを立ち上げるインスタンスタイプはt2.nanoを利用 |
|
|
・インスタンスの詳細の設定 ※本番サーバのインスタンスは”CloudWatch 詳細モニタリングを有効化”をチェック |
|
|
・ストレージの設定 |
|
|
・インスタンスのタグ付け ※値の内容に”for-ami”が付いていると、ami用だと判断して処理するルール |
|
|
・セキュリティグループの設定 |
|
|
・インスタンス作成の確認及びキーペアをダウンロード |
③ |
ボリュームの作成 |
・ボリュームを作成 アベイラビリティゾーンカラム内容を確認して統一する |
|
|
・区分しやすくなるため、ボリュームの名前を設定する ・ボリュームIDを別にメモしておく(awscliでボリュームをアタッチするとき必要) |
④ |
IAMの追加 |
🔻 🔻 ・グループ追加 |
|
|
🔻 🔻 ・ユーザー追加 |
|
|
🔻 🔻 🔻 ・グループにユーザーを追加 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の無効化 ➜ 再起動(실질 코멘트 넣기) |
⑥ |
マシンイメージ設定 (Packages設置及び awscliサービス) |
sudo yum install epel-release 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 の通報がバンバン来ていました。
先輩とすぐアクションを取ったのは以下の通りでした。
①❗Cakeのエラーログにセッションが書き込めないエラーが出ている
② セッションが書き込めないってことは、HDDの容量かな?
③ コマンド df
すると 容量が0であることの確認
④ 容量を食うシステムではない! 👉ということはメールログかな
⑤ /var/spool
確認する 👉 ログがたまってる
⑥ 👍 メッセージのキュー削除
🔗 Postfixのメールキュー操作
ひとまず対応したけど、一体原因は何だったかな−!
🌺原因
そのサーバには、多数のShellScriptがcloneで実行されています。
また、MTAのPostfixが設置されていました。
で、各種cronで叩かれたコマンドの出力結果が
ログではなく、自動にPostfixでメール送信を試みたことですね−
特にcronの各週出力をメールに転送出来るように設定したことでは無いので、
その全てが、Postfix Queueとして溜まったことが原因でした。
※ Postfixとは?
IBM Public Licenseを従って、Wietse Venemaが開発した
オープンソース MTA(Mail Transfer Agent)です。
sendmailとの交換性も高いし、安全で簡単な構造を持っています。
もちろん相対的に早い速度の特徴を持っているメールサーバのサービスです。
PostfixはSMTPサーバとしての機能しか持ってないので、
メールサーバとして動作させるためには、
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(); }
👇👇👇👇👇👇👇
・拡張
<?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; } }
👍👍👍👍👍
もし、知らなかった方がいらっしゃったらサーバが死ぬ前に対応しましょう!
以上です~👋