AWS EC2 不具合インスタンスの不具合調査備忘録

Auto Scalingが設定してあるインスタンスで深刻な不具合が発生すると、設定によっては、調査中に勝手にインスタンスがTerminateされてしまうことがあります。

これを回避する方法のメモ。乱文。

正しいやり方かはわからないけれど、現状のインスタンス規模なら適当。

前提

インスタンス数: 2台
Auto Scaling設定あり(=重篤な不具合を検知すると自動で代替インスタンスが立ち上がる)

インスタンスのスタンバイ状態を活用する

  1. インスタンスの内部をいじる場合は、まずインスタンスを「スタンバイ状態」にしておきます。
    スタンバイ状態にすれば、ロードバランサーがアクセス異常を検知しなくなるので、好きなだけゆっくりと調査ができます。
    1. Auto Scaling > [インスタンス]タブ
    2. 対象のインスタンスを選択し、 [操作] > [スタンバイに設定]
      • ※スタンバイ状態にすると、ロードバランサーはそのインスタンスにリクエストを投げなくなります(=インスタンスとしては稼働しているが、いないものとして扱われる)。
    3. このとき、代替インスタンスを自動で立ち上げるかを選択できます。
      • 立ててもいいですが、調査対応後の動作確認をする際に、当該インスタンス以外をすべてスタンバイに切り替えるので、可能な限り立ち上げない方が良いかもしれません。
      • ※スタンバイ状態に切り変えると、Auto Scalingの「希望インスタンス数」の値は自動で変動し、意図しないインスタンスの増減を防止します。
  2. 調査後、問題なさそうになったら、スタンバイ状態のインスタンスを「実行中」に設定します。
  3. 当該インスタンスの「ライフサイクル」が「実行中」に切り替わるのを待ちます。
  4. その後、調査対象のインスタンス以外のインスタンスを「スタンバイ」に設定し、動作検証を行いたいインスタンスのみがアクセスの対象となるようにします。
  5. 動作確認します。
  6. 問題なく稼働するようであれば、インスタンスのイメージを取得して保存します。
  7. 適当なインスタンス数になるよう調整したりなんだりします。
    • インスタンスの希望台数を適性に設定し直し、不要なインスタンスを終了させていく。
    • ※スタンバイ状態にしたままインスタンスがTerminateされると、Auto Scalingの[インスタンス]タブにゾンビ項目みたいに残ったりする?かもしれない。多分インスタンスが終了しても即座に紐付けが消失しないせい。
      (インスタンス一覧から消えればさすがに反映されると思われる)

CloudWatchのログを見る

CloudWatchにログを吐き出す設定をしていれば、ログが利用できるはずです。

  1. CloudWatch > 左側メニュー[ロググループ]
  2. ドメイン名などで検索をかけ、表示するログを絞ります。
  3. ログを開くと、インスタンスごとにファイルがわかれているので、問題が生じているインスタンスのIDで検索をかけてログファイルを特定します。
  4. ログを見ます。
    • ログの最下部にあるpauseを押せば、ログの自動更新を一時停止できます。
    • 時間を絞って表示することもできてまあまあ便利。

インスタンスのログを見る

Apache : /var/log/httpd/error_log とか。
nginx : /var/log/nginx/error_log とか。

参考

PHP コード内で PHPUnit を呼び出す(実行する)

PHPUnitを実行するPHPスクリプトを書きたい日がありました。
まあまあ時間が溶けたので備忘録です。

結論

このように書けばOK。

exec('/path/to/phpunit /path/to/tests');

参考: php – How to trigger unit testing from Laravel Artisan – Stack Overflow

特定のテスト単体を実行したい場合はこのように書けばOK。

exec('/path/to/phpunit /path/to/target /path/to/tests');

関数ごとの出力例をざっくり

記述法は結論の通り。

PHPには外部プログラムの実行ができる関数が色々あるので、出力結果を見比べてみました。

下記のようなコードで出力を確認しました。

$result = exec('/path/to/phpunit/ /path/to/tests');
var_dump(gettype($result));
var_dump($result);

exec()

成功時
var_dump(gettype($result));
string(6) "string"
var_dump($result);
string(24) "OK (1 test, 1 assertion)"
エラー発生時
var_dump(gettype($result));
 string(6) "string" 
var_dump($result);
 string(52) "Tests: 75, Assertions: 3650, Errors: 4, Failures: 8." 

エラー発生時に ERROR! の文言が出ないが、成功時はシンプルかつ OK と出るので良さそう。


shell_exec()

成功時
var_dump(gettype($result));
string(6) "string"
var_dump($result);
string(194) "PHPUnit 5.7.27 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 231 ms, Memory: 14.00MB OK (1 test, 1 assertion) "
エラー発生時
var_dump(gettype($result));
string(6) "string"
var_dump($result);
string(108797) "PHPUnit 5.7.27 by Sebastian Bergmann and contributors. (中略) ERRORS! Tests: 75, Assertions: 3650, Errors: 4, Failures: 8. "

OKERROR! の文言は出るものの、出力が長大で微妙……


system()

成功時
system()の出力(勝手に出る)
PHPUnit 5.7.27 by Sebastian Bergmann and contributors. . 1 / 1 (100%) Time: 229 ms, Memory: 14.00MB OK (1 test, 1 assertion)
var_dump(gettype($result));
string(6) "string"
var_dump($result); 
string(24) "OK (1 test, 1 assertion)"
エラー発生時
system()の出力(勝手に出る)
PHPUnit 5.7.27 by Sebastian Bergmann and contributors. (中略) ERRORS! Tests: 75, Assertions: 3650, Errors: 4, Failures: 8.
var_dump(gettype($result));
string(6) "string"
var_dump($result);
string(52) "Tests: 75, Assertions: 3650, Errors: 4, Failures: 8."

system()は実行結果をすべて出力するため、 var_dump(gettype($result)); の出力内容の前にPHPUnitの実行結果がドカドカ出てきてしまい、見にくかった。

var_dump($result);の出力結果は exec() と同じ。見やすくて良い。

ということで

PHPUnitを外部から実行し、出力内容を利用して成否判定するようなことができるようになりました。

system() は実行結果を出力するところまで行うため、PHPUnitの実行結果(最後の行)だけ見たい場合には、 exec()を使うのが良さそう。

参考

Vagrant CentOS6 PHP5.6 → 7.2 バージョンアップ

ローカル開発環境のPHPが5.6だったので、バージョンを上げてみようと思いました。

CentOSにPHP7.2入れたい
 →Remiというプロジェクトのリポジトリを使うとyumで入れられるらしい
  →Remiを利用するためにはEPELリポジトリのインストールも必須要件

手順

root権限を持つユーザで作業します。

EPELリポジトリのインストール

# yum -y install epel-release

えーなんか出た……

[root@localhost ~]# yum -y install epel-release
Geladene Plugins: fastestmirror
Einrichten des Installationsprozess
Loading mirror speeds from cached hostfile
Could not get metalink https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=x86_64 error was
14: problem making ssl connection
 * base: ftp-srv2.kddilabs.jp
 * epel: ftp.riken.jp
 * extras: ftp-srv2.kddilabs.jp
 * remi-safe: ftp.riken.jp
 * updates: ftp-srv2.kddilabs.jp
Paket epel-release-6-8.noarch ist bereits in der neusten Version installiert.
Nichts zu tun

yumの設定を書き換えて対処。
baseurl のコメントアウトを外して、 mirrorlist をコメントアウト。
参考: yumがepelのmirrorにつながんねーよと怒ってる時の対処法 – Qiita

# vim /etc/yum.repos.d/epel.repo
[epel]
name=Extra Packages for Enterprise Linux 6 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

[epel]
name=Extra Packages for Enterprise Linux 6 - $basearch
baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
#mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6

再実行

# yum -y install epel-release
[root@localhost ~]# yum -y install epel-release
Geladene Plugins: fastestmirror
Einrichten des Installationsprozess
Loading mirror speeds from cached hostfile
 * base: ftp-srv2.kddilabs.jp
 * extras: ftp-srv2.kddilabs.jp
 * remi-safe: ftp.riken.jp
 * updates: ftp-srv2.kddilabs.jp
epel                                                         | 4.7 kB     00:00
epel/primary_db                                              | 6.1 MB     00:02
Paket epel-release-6-8.noarch ist bereits in der neusten Version installiert.
Nichts zu tun

ヨシ!

Remiリポジトリのインストール

# yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
[root@localhost ~]# yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
Geladene Plugins: fastestmirror
Einrichten des Installationsprozess
remi-release-7.rpm                                                                                               |  20 kB     00:00
Untersuche /var/tmp/yum-root-KfXqbk/remi-release-7.rpm: remi-release-7.7-2.el7.remi.noarch
Markiere /var/tmp/yum-root-KfXqbk/remi-release-7.rpm als eine Aktualisierung für remi-release-6.9-2.el6.remi.noarch
Loading mirror speeds from cached hostfile
 * base: ftp-srv2.kddilabs.jp
 * extras: ftp-srv2.kddilabs.jp
 * remi-safe: ftp.riken.jp
 * updates: ftp-srv2.kddilabs.jp
Löse Abhängigkeiten auf
--> Führe Transaktionsprüfung aus
---> Package remi-release.noarch 0:6.9-2.el6.remi will be aktualisiert
---> Package remi-release.noarch 0:7.7-2.el7.remi will be an update
--> Verarbeite Abhängigkeiten: epel-release = 7 für Paket: remi-release-7.7-2.el7.remi.noarch
--> Abhängigkeitsauflösung beendet
Fehler: Package: remi-release-7.7-2.el7.remi.noarch (/remi-release-7)
            Requires: epel-release = 7
            Installiert: epel-release-6-8.noarch (installed)
                epel-release = 6-8
 Sie können versuchen --skip-broken zu benutzen, um das Problem zu umgehen.
 You could try running: rpm -Va --nofiles --nodigest

ヨシ!

Remiのインストール状況を確認

# ls -l /etc/yum.repos.d/
[root@localhost ~]# ls -l /etc/yum.repos.d/
insgesamt 64
-rw-r--r--. 1 root root 1991 23. Okt 2014  CentOS-Base.repo
-rw-r--r--. 1 root root  647 23. Okt 2014  CentOS-Debuginfo.repo
-rw-r--r--. 1 root root  289 23. Okt 2014  CentOS-fasttrack.repo
-rw-r--r--. 1 root root  630 23. Okt 2014  CentOS-Media.repo
-rw-r--r--. 1 root root 5394 23. Okt 2014  CentOS-Vault.repo
-rw-r--r--  1 root root  957 22. Jun 18:47 epel.repo
-rw-r--r--. 1 root root 1056  5. Nov 2012  epel-testing.repo
-rw-r--r--  1 root root 1209  2. Dez 2013  mysql-community.repo
-rw-r--r--  1 root root 1060  2. Dez 2013  mysql-community-source.repo
-rw-r--r--. 1 root root  456 16. Jan 2018  remi-php54.repo
-rw-r--r--. 1 root root 1314 16. Jan 2018  remi-php70.repo
-rw-r--r--. 1 root root 1314 16. Jan 2018  remi-php71.repo
-rw-r--r--. 1 root root 1314 16. Jan 2018  remi-php72.repo
-rw-r--r--. 1 root root 2605 16. Jan 2018  remi.repo
-rw-r--r--. 1 root root  750 16. Jan 2018  remi-safe.repo

epel、remiともにインストールできていることがわかる。
特に、remi-php72.repoが取得できていることが確認できる。

ここまでが下準備。

古いPHPのアンインストール

インストール済のPHP関連のパッケージ一覧を表示

# yum info installed php*

ずらずらっと色々出てくる。

アンインストール

# yum remove php*
~~(php関連パッケージたち)~~

========================================================
Remove       93 Package(s)

Installed size: 95 M
Ist dies in Ordnung? [j/N] :j

~~(削除中)~~

Komplett!
[root@localhost ~]#

消えていることを確認

[root@localhost ~]# php -v
-bash: /usr/bin/php: Datei oder Verzeichnis nicht gefunden

新しいPHPのインストール

# yum install --disablerepo=* --enablerepo=epel,remi,remi-safe,remi-php72 php

インストール完了後、バージョン確認。

[root@localhost ~]# php -v
PHP 7.2.31 (cli) (built: Jun  9 2020 08:25:54) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies

<関係ないですが、ここで言語設定をドイツ語から英語に変更しました>

phpMyAdminのインストール

# yum install -y --enablerepo=remi-php72 phpMyAdmin

なんか言われた。

Error: Package: phpMyAdmin-4.0.10.20-1.el6.noarch (epel)
           Requires: php(language) < 7
           Installed: php-common-7.2.31-2.el6.remi.x86_64 (@remi-php72)
               php(language) = 7.2.31
           Available: php-common-5.3.3-49.el6.x86_64 (base)
               php(language) = 5.3.3
           Available: php-common-5.3.3-50.el6_10.x86_64 (updates)
               php(language) = 5.3.3
           Available: php-common-7.2.31-1.el6.remi.x86_64 (remi-php72)
               php(language) = 7.2.31
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest

phpMyAdminが入らないのはアカン。

対処します。
参考: centos – centOS6.8にphpMyAdminをyumでインストールしたさいのエラー – スタック・オーバーフロー

remiリポジトリのアップデート

# yum --disablerepo=* --enablerepo=remi,remi-php72 update

remiのみを指定して再インストール

# yum --disablerepo=* --enablerepo=remi,remi-php72 install phpMyAdmin

ずらずらっと処理が走って Complete! したのでOK。

Apacheの再起動

# service httpd restart

phpMyAdminが無事開けたのでOK

と思いきや、いざlocalを開いてみたらまたエラー

やれやれ

Notice: Undefined variable: u_id in (ファイルのパス) on line 78

Notice: Undefined index: action in (ファイルのパス) on line 11

Warning: require_once(hogefuga.php): failed to open stream: No such file or directory in (ファイルのパス) on line 4

Fatal error: require_once(): Failed opening required 'hogefuga.php' (include_path='.:/usr/share/pear:/usr/share/php') in (ファイルのパス) on line 4

.htaccessを確認

<IfModule mod_php5.c>
 php_value include_path "hogehogehogehogehohgeohgoehogehogheogehoge"
 php_value error_reporting 6135
 php_value mysql.connect_timeout 1
</IfModule>

あーーーーーーー!

対処

php_value include_path "hogehogehogehogehohgeohgoehogehogheogehoge"
php_value error_reporting 6135
php_value mysql.connect_timeout 1

一般的に、<IfModule>使うのはよろしくないという言説も見かけるので削除。

再びのApache再起動

# service httpd restart

きちんとページが表示されたのでヨシ!

参考

AWS S3アップロード用のIAMユーザーを作成する

プログラムからファイルをアップロードする用のユーザー登録を駆け足で。

1. IAMダッシュボードを開く

AWSマネジメントコンソールへログイン後、Identity and Access Managementへアクセスします。

2. ユーザーの登録

1. 画面左の[ユーザー]をクリックします。

2. 画面上部の[ユーザーを追加]をクリックします。

青い[ユーザーを追加]をクリックする。

3. 作成の流れ

1. 名称とか適当に入れます。
今回はプログラムからのアクセス用IAMを作ります。
2. S3FullAccessの権限を与えます。
3. タグはお好きに。
4. 設定内容を確認。
5. 作成すると、アクセスキー等が表示されます。
シークレットアクセスキーの[表示]をクリック。
6. シークレットアクセスキーが表示されるのでコピーしてコードに貼っ付けるなりします。
後から確認はできないっぽいので、csvダウンロードしておくのも良いかも。
7. hogeが作成されてる。
8. シークレットアクセスキーがわからなくなった等あれば、
アクセスキーを再生成してしまうのも手。

以上。

あとはプログラムでS3にアクセスするときの値に入れるだけです。
s3にファイルをアップロードする処理内で、例えば下記のように設定します。

AWS_ACCESS_KEY = 'XXXXXXXXXXXXXXXXXXXX';
AWS_SECRET_ACCESS_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
AWS_S3_BUCKET_NAME = 'test_bucket';


function upload_to_s3($upload_file) {
    // S3clientのインスタンス生成
    $s3client = new Aws\S3\S3Client([
        'credentials' => [
            'key' => AWS_ACCESS_KEY,
            'secret' => AWS_SECRET_ACCESS_KEY
        ],
        'region' => 'ap-northeast-1',
        'version' => 'latest'
    ]);
    
    // 画像のアップロード
    $s3client_image_upload = $s3client->putObject([
        'ACL' => 'public-read',
        'Bucket' => AWS_S3_BUCKET_NAME,
        'Key' => $upload_file['file_name'],
        'SourceFile' => $upload_file['file_path'],
        'ContentType' => mime_content_type($upload_file['file_path'])
    ]);
        
    // アップロードファイルのURL取得
    return $s3client_image_upload['ObjectURL'];;
}

Scala sbtでビルドするとFAILED DOWNLOAD

Scalaまったく初心者の私です。

今回、Windows10+IntelliJ で前からあるプロジェクトのメンテナンスをします。

まずは、やっぱり一応動作させたいじゃないですか。

前回、チュートリアルとかやってみて、

「ふむふむ。Scalaってsbtというビルドツールがあるのね。」

とかわかってきたぐらいです。

まずは、sbtをインストールします。

涙が出るほど簡単です!下記から、Windows用のmsiをダウンロードしてインスコします。

https://www.scala-sbt.org/1.x/docs/ja/Installing-sbt-on-Windows.html

ありがたやー。( ˊᵕˋ )

コマンドプロンプトで、

sbt

って打ってみます。

なんやかんや出てきたら、sbtインストール成功です。

じゃあ、ついに、プロジェクトをビルドしてみますYO!

今回は、既存プロジェクトのメンテなので、もうsbtファイルが存在しています。sbtファイルは、ビルドに必要な情報が入ったファイルです。

build.sbt

コマンドプロンプトで、上記のファイルのあるフォルダへ移動します。

sbt

と打ちます。

ドン!

いろいろとメッセージが流れていきます。

FAILED DOWNLOAD

ってなってしまいました…。(>_<)

調べたところ、下記にあるように

https://stackoverflow.com/questions/25306976/failed-download-error-while-trying-to-create-scala-jar

build.sbtに下記を付け加えます。

libraryDependencies ++= Seq(
"org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" artifacts (
Artifact("javax.servlet", "jar", "jar")
)
)

そうしたら、無事にビルドできました!( ˊᵕˋ )