EC2インスタンスの再起動と停止/起動のちがい

先に結論

ここに書いてあるとおり

docs.aws.amazon.com

  • 再起動: インスタンスは、同じホストコンピュータで保持される
  • 停止/開始: インスタンスは新しいホストコンピュータに移動されます

メンテナンスでEC2のハードウェア退役や再起動する場合は、停止/起動 の方がいいの?

イベントの告知でも、stopping and starting your instance と書かれているので、停止/起動のほうが良いと思う

そんなおぼえがき

複数バージョンのbundlerがインストールされている時の挙動おぼえがき

概要

複数バージョンのbundlerがインストールされているとき、どれが選択されるのか曖昧だったので実験

注意

公式ドキュメントの記述がみあたらなかったので、バージョンが変わると挙動が変わるかもしれないです

環境

ruby:3.0.1-alpine を使用。defaultで入っているbundlerは、2.2.15です

docker run --rm --name ruby -it ruby:3.0.1-alpine /bin/sh
/ # gem list --local | grep bundler
bundler (default: 2.2.15)
/ # bundler -v
Bundler version 2.2.15

先に結論

以下の優先順でバージョンが選ばれるようです。default は関係ない様子

  1. $BUNDLER_VERSION
  2. Gemfile.lock の BUNDLED WITH
  3. 一番新しいバージョン

複数バージョンを入れた場合、default や、インストール順は左右されず、最新のバージョンが参照される

/ # gem install bundler:2.2.20
Fetching bundler-2.2.20.gem
Successfully installed bundler-2.2.20
1 gem installed

/ # gem install bundler:2.2.19
Fetching bundler-2.2.19.gem
Successfully installed bundler-2.2.19
1 gem installed

/ # gem list --local | grep bundle
bundler (2.2.20, 2.2.19, default: 2.2.15)

/ # bundle -v
Bundler version 2.2.20

ディレクトリに Gemfile.lock がある場合、そこの BUNDLED WITH にかかれているバージョンが参照される

/ # cat <<EOS > Gemfile.lock
> GEM
>   remote: https://rubygems.org/
>   specs:
>     rack (2.0.6)
> 
> PLATFORMS
>   ruby
> 
> DEPENDENCIES
>   rack
> 
> BUNDLED WITH
>   2.2.19
> EOS
/ # bundle -v
Bundler version 2.2.20

環境変数 BUNDLER_VERSION があると、それが最優先される

/ # export BUNDLER_VERSION=2.2.15

/ # bundle -v
Bundler version 2.2.15

環境変数 BUNDLER_VERSION や、Gemfile.lock に書かれたバージョンがインストールされていな場合、最新のバージョンが参照される

bundle install しない限り、特に警告は出ませんでした

/ # export BUNDLER_VERSION=2.2.13

/ # cat <<EOS > Gemfile.lock
> GEM
>   remote: https://rubygems.org/
>   specs:
>     rack (2.0.6)
>
> PLATFORMS
>   ruby
>
> DEPENDENCIES
>   rack
>
> BUNDLED WITH
>   2.2.16
> EOS

/ # bundle -v
Bundler version 2.2.20

おまけ: bundle _version_ でバージョンを明示的に指定すると、そのバージョンが参照される

/ # bundle _2.2.15_ -v
Bundler version 2.2.15

存在しないバージョンを指定すると怒られます

/ # bundle _2.2.00_ -v
/usr/local/lib/ruby/3.0.0/rubygems.rb:281:in `find_spec_for_exe': can't find gem bundler (= 2.2.00) with executable bundle (Gem::GemNotFoundException)
        from /usr/local/lib/ruby/3.0.0/rubygems.rb:300:in `activate_bin_path'
        from /usr/local/bundle/bin/bundle:23:in `<main>'

古い ruby image だと、挙動が変わります

docker run --rm --name ruby -it ruby:2.5.1-alpine /bin/sh
/ # gem list --local | grep bundler
bundler (1.16.6, default: 1.16.2)
/ # bundler -v
Bundler version 1.16.6

2.2.20 をインストールしても、1.16.6 が参照されたまま

/ # gem install bundler:2.2.20
/ # gem list --local | grep bundler
bundler (2.2.20, 1.16.6, default: 1.16.2)
/ # bundler -v
Bundler version 1.16.6

これは、古い ruby の Dockerfile の中で BUNDLER_VERSION が設定されているため そのため、BUNDLER_VERSION を unset しないと想定通りの挙動してくれない

こちらのissueで議題になって、新しいバージョンでは BUNDLER_VERSION がセットされないようになっています

github.com

elasticbeanstalkのプラットフォーム(ruby puma)のバージョンを上げると、nio4r の依存関係でエラーが発生する件

elasticbeanstalkのプラットフォーム(ruby puma)のバージョンを上げると、こんなエラーが出るようになる

/opt/rubies/ruby-2.7.3/lib/ruby/site_ruby/2.7.0/bundler/runtime.rb:302:in `check_for_activated_spec!': You have already activated nio4r 2.5.7, but your Gemfile requires nio4r 2.5.5. Prepending `bundle exec` to your command may solve this. (Gem::LoadError)

原因

プラットフォームに入っている puma に依存している Gem と、自分が入れた Gem がコンフリクトしているために発生している模様

解決方法

アプリの puma のバージョンをプラットフォームの puma のバージョンと合わせれば解決

参考

おんなじ問題にハマった人

各環境ごとのpumaのバージョン

Nginxのデバッグログを取る方法

Nginxの内部転送の設定がうまく行かない時とかにデバッグログは便利なのですが、その設定方法をよく忘れるのでメモ

エラーログのログレベルを debug にする

error_log /dev/stdout debug;

内部転送を出力するように設定

rewrite_log on;

Nginxをデバッグモードで起動

nginx-debug -g "daemon off;"

いじょうです

CORSの理解が不足していたのでメモ

CORSって何?

CORS: Cross-Origin Resource Sharing

オリジン間リソース共有

オリジンって何?

同じところからのリクエストであるかを判別するための方法

URIの、scheme、host、portが一致していると、それは「同一オリジン」である

scheme、host、portとか、URIの呼称については、こちらを参照

kasei-san.hatenadiary.org

どういう時に使うの?

異なるオリジンにAjaxリクエストやWebフォントの読み込みを行う際に使われる

なんで必要なの?

悪意あるサイトがAjaxで勝手にどこかAPIを叩けないよう、同一オリジン以外へのリクエストはブロックされるようになっている

  • これを、Same Origin Policy(同一オリジンポリシー) と呼ぶ

ただし、異なるオリジンにリクエストを投げる必要もあるため、CORS という仕組みが生まれた

どういう風にやるの?

単純リクエストという方式の場合、以下のような流れ

  1. ブラウザ側からリクエスト。リクエストヘッダの中に Origin が含まれる
    • Origin は、リクエストの発生元がどこであるかを示す
  2. サーバ側からレスポンス。レスポンスヘッダの中に Access-Control-Allow-Origin が含まれる
    • Access-Control-Allow-Origin はサーバが許可するオリジンを入れる
    • * の場合は「すべて許可」となるが、非常に脆弱なのでやめるべき
    • 複数の値を含めることはできない。許可すべきオリジンが複数ある場合は、サーバ側で制御する
  3. ブラウザ側で OriginAccess-Control-Allow-Origin が一致していれば、処理が行われる

プリフライトリクエスト

クロスオリジンのリクエストが いろいろな条件を満たさなかった場合、上記の単純リクエストではなく、プリフライトリクエストが行われる

ユーザーデータに影響を与える可能性があるようなリクエストの場合、プリフライトが行われる(らしい)

プリフライトリクエストの流れ

OPTIONS メソッドをつかって、事前に安全にクロスオリジンの通信が行えるかチェックする

以下のような流れ

  1. ブラウザ側で、 OPTIONS メソッドで以下のリクエストを投げる
    • Origin : 単純リクエストと同じ
    • Access-Control-Request-Method : 送るメソッド
    • Access-Control-Request-Headers : 送るリクエストヘッダ
  2. サーバ側からレスポンスを投げる。その時、以下のレスポンスヘッダを含む
    • Access-Control-Allow-Origin : 単純リクエストと同じ
    • Access-Control-Allow-Methods : 許可するメソッド
    • Access-Control-Allow-Headers : 許可するリクエストヘッダ
    • Access-Control-Max-Age: プリフライトリクエストの結果をキャッシュして良い時間(秒)
  3. ブラウザ側でレスポンスヘッダを読み込んで、問題なさそうならば実際のリクエストを開始する

資格情報を含むリクエスト

標準では cookie や basic 認証を含むリクエストに関わる情報は送信されない

そのためには、JavaScript 側で withCredentials というオプションを true にする必要がある

さらに、cookie の情報をやり取りしたい場合は、レスポンスヘッダに Access-Control-Allow-Credentials: true をつけて、許可する必要がある

また、Set-Cookie については、サードパーティCookieと同じく、ドメインが異なるとブラウザの設定によっては読み込めない

あと、 資格情報を含むリクエストの場合 Access-Control-Allow-Origin* は使えない

参考

yamory.io

developer.mozilla.org

Amazon Linux2 に MySQL5.7のクライアントを入れる方法

踏み台サーバに手動で入れる必要が出たので個人的なメモ

参考

dev.mysql.com

dev.classmethod.jp

だいたいここの通りにやればOK

前提1

Amazon Linuxでは、いくつかのパッケージを Extras Library として提供しているが、MySQLは提供していない(mariadbはある)

  • コマンド amazon-linux-extras で提供しているパッケージを確認可能

前提2

80番ポートを開ける必要がある

  • 443だけでやろうとしてめっちゃ苦労して、あきらめた

MySQLのリポジトリのrpmをインストール

sudo yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
  • localinstall は、rpm を yum でインストールするコマンド。 rpm -i と異なり、依存関係がある場合、その rpm もインストールしてくれる
  • Amazon Linux 2 は、RHEL7ベースという噂なので、RHEL7のMySQLのリポジトリをインストール
  • ダウンロード先のURLは、こちら で、「Download」を選択した後に「 No thanks, just start my download.」のリンクを見れば確認可能

リポジトリがインストールされたことを確認

yum repolist enabled | grep "mysql.*-community.*"

デフォルトでは、MySQL8がインストールされてしまうので設定を変更

$ yum repolist enabled | grep "mysql.*-community.*"
mysql-connectors-community/x86_64     MySQL Connectors Community          194
mysql-tools-community/x86_64          MySQL Tools Community               126
mysql80-community/x86_64              MySQL 8.0 Community Server          247
sudo yum-config-manager --disable mysql80-community
sudo yum-config-manager --enable mysql57-community

確認

$ yum repolist enabled | grep mysql
mysql-connectors-community/x86_64     MySQL Connectors Community          194
mysql-tools-community/x86_64          MySQL Tools Community               126
mysql57-community/x86_64              MySQL 5.7 Community Server          504

インストール

sudo yum install -y mysql-community-client

無事インストールされました

$ mysql --version
mysql  Ver 14.14 Distrib 5.7.34, for Linux (x86_64) using  EditLine wrapper

logrotateおぼえがき

RHEL系のお話です

全体設定ファイル

/etc/logrotate.conf

ローテーションごとの設定ファイルが置かれるディレクトリ

/etc/logrotate.d/

dryrun

/usr/sbin/logrotate -dv /etc/logrotate.conf

手動実行(root権限で実行すること)

/usr/sbin/logrotate -f /etc/logrotate.conf

最終ローテーション日時が格納されているファイル

/var/lib/logrotate.status

手動実行の流れ

1日1回ローテーションしていて、すでに本日実行済の場合

  • すでにあるローテーション済のファイルをrenameする
  • /var/lib/logrotate.status にある最終実行日を昨日の日付に変更する
  • /usr/sbin/logrotate -dv /etc/logrotate.conf して実行されるか確認
  • 問題なければ、 /usr/sbin/logrotate -f /etc/logrotate.conf で手動実行

手動実行でエラーがでたとき

ローテーション実行時のスクリプトの戻り値が0以外だとエラーになる

なので例えば、最後に実行したコマンドが test コマンドで、testの結果が「偽」の場合、exit 1 になるのでエラーとなってしまう

  • lastaction の実行結果ならば、ローテーション自体は完了している

参考

kotaroito.hatenablog.com