ポンコツ.log

ひよっこエンジニアのちょっとしたメモ。主に備忘録。たまに雑記。

Rails Girls Naganoにコーチとして参加してきましたメモ

RailsGirlsNaganoにコーチとして参加してきました。
RailsGirlsもコーチも長野も全て初だったので、長々と書いています。

まとめるとこんな感じです。
- プログラミングの地域格差ありそうだけど実際のところどうなのかなー
- 北海道でのRailsGirlsどうなのかなー
- コーチになって見えた課題めちゃくちゃ多いなー
- 長野良いとこだなー

初RailsGirls

性別関連の話題に対しては、超個人的な捻くれた感情があるのであまり触れずにいたいのですが、「"プログラミング好きな人"がみんな楽しめてハッピーだと良いよね」ということは思っています。
頭ハッピーマンみたいな言葉ですが。
そのためにこうなっていると良いよね、という考え方の一つが、RailsGirlsでもある「過去の方針によりできてしまった男女格差のバランスを整えよう」という動きなのかなと思います。

プログラミングに関して言えば、地域の差も結構あるような気がしています。
自分は北海道の田舎出身ですが、
たまたま家にネットが使える環境があって、
たまたま情報系に興味を持って、
たまたま情報系の大学に入学して、
それで初めてプログラミングに触れたわけですが、この「たまたま」が1つでも無ければ、今プログラミングをしていることもなかったのかなと思います。
興味が向いているから目につきやすいというのもありますが、東京に来て、プログラミングに触れる機会の多さに驚きました。

余談ですが、プログラミング授業にちょっとだけ期待していたりもします。
小さい頃に何か少しでも触れる機会があれば、何も知らないより良いよね、ぐらいの感覚。
と言っても自分が地方にいた頃はすでに6年近く前になるので、だいぶ環境も変わっていると思いますが…。(GWに帰省した時、高校生が大学生にプログラミング授業の質問をしていて少し感動しました)

地域格差が気になっていて、北海道でも(特に田舎でも)プログラミングを「知る・触れる」といった機会を増やせないかなー、活発になればなーという思いがあって、各地で毎回楽しそうに開催されているRailsGirlsを気にかけていました。
北海道では6年ほど前に1度開催されて以降、続きは無く、なんかちょっと勿体無いなぁという気持ちがあったのもあります。
とは言えRailsGirlsに参加したことがなかったので、まずは参加してみなければということで、タイミングもよく、地方開催の長野に参加してみようと考えていたのですが、ふと気づけばRails経験もすでに5年。
今更Girlsとして参加できないし、残るはコーチ…やってみるか…という思いで参加しました。

気が小さいチキンなもので、
「自分みたいのがコーチして良いのか…」
「そもそも長野に関わっていたことも行ったこともないのに、長野の回に参加して良いのか…」
「ていうかRailsGirlsにすら参加したことないけどいきなりコーチって…良いのか…」
「説明ダメダメすぎて、相手を泣かしてしまったらどうしよう…(学生時代のトラウマの1つ)」
みたいなことを、コーチ募集前から1ヶ月近く悩んだりしていました。

重すぎですね。

初コーチ

もう、緊張しまくりでした。

自分の感覚として、人に何かを教えるというのは、同時に教わることだと思っています。
前日まで「この質問来るかな」「ここ自分もわからなかったよな〜」ということを考えながら、色々と準備をするわけです。
その過程で「ああ、ここちゃんと理解してなかったかも」なところを見つけて、人に説明できるレベルまで自分の中に落とし込んだり、進めていく中での相手からの質問で「たしかに、なんでだろう!調べる!」みたいな、自分とは違う視点での発見があったり。

この時点で自分も色々といただいているのですが、RailsGirlsに参加する方って、プログラミング自体初めてだったりするので、動いた時に一緒に「やったー!動いたー!」が出来るんですよね。
自分が過去のどこかに置いて来てしまった「初めて意図した通りに動いた時の感動」をもう1度体験できて、やっぱプログラミング楽しいなー、良いなーと、という初心の頃の感動をおすそ分けしてもらいます。

教えるというところでは、課題がはっきりした部分もありました。
アレコレと何個も出てきて埋まるぐらいですが、気をつけようとして中々直せなかった強敵を挙げると、
- 雑談下手(普段から…)
- 日本語の便利なニュアンス、言葉に頼ってしまう
- 情報量の操作(人のレベルに合わせた情報の取捨選択)ができていない
- 動作にも気を配る

特に3つ目のは、自分が上手い説明ができず、「良い言葉・例えないかな〜」というときに首を掻くクセがあるようで、なんとなくその行動が相手にとっては「なんでわからないのかな〜」に見えているような気配を感じて、あっこれすぐにでも直さなきゃあかんヤツと思ったりしました。
全然そんなことないし、自分の説明下手が原因なのですが、言葉では無い分余計違って捉えられそう…。
途中から意識してみたものの、クセはそう簡単には無くならないですね…。精進します…。

とまあ反省は多かったものの、それも含めてものすごく良い経験でした。
思い切って良かった〜。
楽しんでもらえていると良いのですが。

(お弁当も美味しかったです。デザート付き。)
f:id:mr_96:20190528231041j:plain

初長野

いや〜良かったですね、長野。
北海道に似た雰囲気があって、落ち着きました。

意図せずリフレッシュ期間になった感じで、色々なことが「長野の力!すごい!」になっています。単純設計ですね。
出発前ひどかったアトピーが、長野にいる期間ほとんど痒くならなかったことは個人的に大きいです。すごい。今はかゆい。
バス待ちの間に寄った足湯の湯治効果もあるかもしれない。
宿泊先だった白馬村、道路の隅に足湯あったりしてビビります。駅にもあった。
ガサガサゴワゴワだった足が今普通の肌になっていて、温泉の力…長野すごい…とか思ったりしています。

金曜日は善光寺近くの1166バックパッカーズさん、土曜日は白馬村Nori's Sharehouse Hakubaさんに泊まったのですが、どちらもすごく良かったです。
1166さんはよくある二段ベッドが複数あるタイプのゲストハウスですが、落ち着いた雰囲気がめちゃくちゃ良い。内装おしゃれ。
近くのパン屋さんが毎朝配達に来てくれるようで、美味しいパンを買うこともできます。

Nori'sさんは民泊の形式ですが、なんと一人部屋。めっちゃ寛げる一人部屋。
快適すぎて寝落ちしましたごめんなさい。
外は暑くても窓を開けているだけで涼しい風が入ってくるので、寝覚めも快適でした。
それと、星が本当に綺麗に見えます。
『そうだ、星を売ろう』の舞台も長野でしたよね。
星が売れる、ちょっとわかる気がします。

日中は30℃超えの日でしたが、白馬駅の奥にある大出公園は快適なレベルで涼しく、しかも絶景。
良いところですねぇ。
f:id:mr_96:20190528232320p:plain

白馬村は以前から冬に行きたいなーと思っていたので、また今度冬に行きたいなと思っています。
(ちゃんと善光寺も行きました!!豆暦さんという和菓子屋さんも素敵でした!!!)

ぼやき

本当に北海道開催を考えているのであれば、もっと動いていかないといかんなーと思いました。
これまではどちらかと言うと「立ち上げる人をサポートする人」のポジションだったので、そのポジションも考えないといけないですね。うーむ。
道内のエンジニアともちょっとお話ししてみたいと言うのもあって、こっそり道内のイベント参加のタイミングを伺っていたりします。

しばらくはモゴモゴしそうだなぁ。
f:id:mr_96:20190529000504j:plain

【AWS】ALBのリスナールールでリダイレクトを設定する

平成最後の仕事ではBCryptのコードを読んでいました。(ここに来て初めて「平成最後」を使いました)


URL正規化の1対策として、http->httpsへのリダイレクトによく対応したりしますが、nginxで処理させるとき、ALB通すとプロトコル考慮しないといけないので、若干面倒なんですよね。
wwwの統一もしようとすると、あのフラグ立てて…このフラグ立てて…になったり。
すでにリリースから1年経とうとしていますが、ようやくまともにALBのリダイレクト機能を使ったので、ちょっとしたメモを置きます。

http -> httpsのリダイレクト

まずはサクッとできるところとして、全てのhttpアクセスをhttpsにリダイレクトさせます。

  1. ロードバランサーの「リスナー」タブから、HTTPプロトコルの「ルールの表示/編集」を選択

    f:id:mr_96:20190427003321p:plain
    ALB

  2. 最初はデフォルトのルールが表示されているだけすが、「+」を選択するとキャプチャのような「ルールの挿入」リンクが表示されるので、「ルールの挿入」からルールを追加

    f:id:mr_96:20190427005438p:plain
    ルール編集画面
    http->httpsぐらいであれば、デフォルトのルールを触っても問題ないと思いますが…。まあ、まあ…。

  3. リダイレクト条件とリダイレクト先を設定
    今回は単純なhttp->httpsなので、全てのパス(パスが*)をhttpsの同じホスト、パス、クエリにリダイレクトするよう設定します。

    f:id:mr_96:20190427004923p:plain
    リダイレクトルール
    考え方的にはIFTTTっぽい。
    IFの条件ではパスの他に送信元IPやクエリ、ホスト等を設定できるので、結構いろんなパターンに対応できそうなイメージがあります。すてき。

  4. 保存してアクセス確認し、ちゃんとリダイレクトされていればOKとなります。簡単。

ドメインからのリダイレクト

やっぱりもうちょっと対応したいリダイレクトとかあると思うんです。
リニューアルでドメイン変わってしまった時とか。

「このドメインのアクセスはすべてここに!」ぐらいに単純な場合は、Route53で向き先を同じALBにしてしまって、ALBでリダイレクトするのもありかなーと思います。
(細かいリダイレクトに対応しようとすると面倒なので裏でごにょった方が楽そうな気がしますが…)

  1. http->httpsの時と同じく、リスナーのルール編集からルール編集へ遷移
  2. ルールを設定
    ドメインなので、リダイレクト条件をホストで指定します。
    リダイレクト先も、元のままではなくカスタムでホストを指定します。
    f:id:mr_96:20190427010436p:plain
    ドメインリダイレクト
  3. HTTPの別ドメインリダイレクト対応はできたので、HTTPSの方も同じように設定
  4. Route53で、リダイレクト元で指定したホストと、リダイレクト先で指定したホストを、同じALBに向かせる

これだけで別ドメインからのリダイレクトも対応できます。すてき。
リダイレクトだけでなく、転送先ターゲットの指定もできるので、ホストでターゲットを振り分けることも可能です。
\\便利//

※ ホストに指定できる文字に制限あります。
参照:Application Load Balancer のリスナー - Elastic Load Balancing

ぼやき

AWS、どんどんできることが多くなりますね。
追いかけるのも大変ですが、なんでしょうね、この、発表がある度に「おおおおおーー!!!!!!」ってテンション爆上がりしてしまう感じ。
ドメインのリダイレクトに関しては、少し前までは「このためにインスタンス立てておくのもな〜S3のホスティングしかないのかな〜😩」なんて思っていましたが、ALBで完結するようになるとは。
設定も簡単な上、コストも抑えられて嬉しいですね。

S3使った方法はAWSのナレッジセンターにあります。
Route 53 を使用してドメインを別のドメインにリダイレクトする

参考

【AWS】CloudFrontで特定ファイルをキャッシュしないようにする

S3にアップしたファイルをCloudFrontを通して配信するケースはよくあると思うのですが、ものによってはCloudFrontのキャッシュを効かせたくないファイルが出てきたりします。

「都度個別対応とか必要なのかなーどうなのかなー」と思ったら、ばっちりAWSのサポートにありました。
CloudFront がファイルをキャッシュするのを防ぐ

Amazon CloudFront が特定のファイルをキャッシュしないようにするには、オリジンかディストリビューションのどちらかで、次に挙げるいずれかの設定を行います。

オリジンでの設定

カスタムオリジンウェブサーバーのアプリケーションで、CloudFront にキャッシュさせたくないオブジェクトに、Cache-Control no-cache、no-store、または private ディレクティブを追加します。Amazon Simple Storage Service (S3) をオリジンとして使用してる場合は、オブジェクトメタデータを使用して、特定の Cache-Control ヘッダーを追加することができます。

ディストリビューションでの設定

Amazon CloudFront コンソールで、ディストリビューションを開いてから、CloudFront にキャッシュさせたくないファイルを配信するキャッシュ動作を開きます。確実にキャッシュ動作の [Minimum TTL] が 0 秒間に設定されていることを確認してください。

注意: [Object Caching (オブジェクトキャッシング)] について、[Use Origin Cache Headers (オリジンキャッシュヘッダーの使用)] が選択されている場合、[Minimum TTL] はデフォルトで 0 です。[カスタマイズ] が選択されている場合、[Minimum TTL] を 0 に変更する必要があります。

CarrierWaveでの場合

RailsでCarrierWaveを使っている場合は下記のような感じでfog_attributesで設定できるので、ささっと「これだけ…!」な対応がしたい場合は、オリジンでno-cache設定で良いかもしれないです。

CarrierWave.configure do |config|
  config.fog_provider = 'fog/aws'
  ...(略)...
  config.fog_attributes = { 'Cache-Control' => 'no-cache' }
end

uploaderごとの対応

uploaderが複数あるとき、uploaderごとにcacheの設定を分けたい場合は、uploaderでfog_attributesを追加することで、個別の対応ができます。

# config/initializers/carrierwave.rb
CarrierWave.configure do |config|
  config.fog_provider = 'fog/aws'
  ...(略)...
  config.fog_attributes = { 'Cache-Control' => 'public, max-age=604800' }
end

HogeUploaderではデフォルト(CarrierWave.configureの設定)まま

# app/uploaders/hoge_uploader.rb
class HogeUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick
end

PiyoUploaderではno-cacheを設定

# app/uploaders/piyo_uploader.rb
class PiyoUploader < CarrierWave::Uploader::Base
  include CarrierWave::MiniMagick

  # PiyoUploaderではno-cacheの設定を追加
  def fog_attributes
    { 'Cache-Control' => 'no-cache' }
  end
end

consoleで確認すると↓の感じに。

$ rails c
> HogeUploader.new.fog_attributes
#=> { 'Cache-Control' => 'public, max-age=604800' }

> PiyoUploader.new.fog_attributes
#=> { 'Cache-Control' => 'no-cache' }

【Ionic】『初心者でも大丈夫!!IonicとFirebaseでゼロからはじめるアプリ開発』をなぞってみた

技術書典5へ行った時に下記の書籍を見かけ、興味半分で購入していました。 sinack.booth.pm

週末の隙間時間で少しずつ進めるという亀スピードでしたが、それでも1週間ぐらいで終わったので、ちゃんと時間とってやれば1、2日で一通りなぞれるのではないかなという分量です。
リポジトリはこちら
GitHub - s-mori/ionic-board-sample

感想

簡単に開発できる

Ionic自体はTitaniumに近い感じがしました。
TypeScriptとHTMLでサクサク作れます。
TypeScript自体も初だったので、TypeScriptをもっとちゃんとやっておけば良かったかなぁという気持ちになりました。
まあでもコードが読めないレベルではないので、一旦後回し。あとでちゃんとTypeScriptもやろう思います。

タイトルにもある通り、インフラ周りは全てFirebase。
FirebaseはAPIとして簡単に触ったことがあったのでお久しぶりでしたが、相変わらず「こんな簡単に認証できて良いのか…まじか…DBも…まじか…」と、徐々に語彙力も失われていくぐらいの衝撃があります。
DBにあたるFirestoreはNoSQLなので、Mongoに触れたことがある場合はスッと入れるかなと言う感じがしています。

内容がわかりやすい

「わかりやすい」ってすごく個人視点なので、「どういった人にとって何がどうなっていてわかりやすいのか」の説明が難しく思いますが…。
自分としては、コードの提示と、「このコードはどういう動きをする」、「どういうアウトプットになる」といった情報があれば、気になった箇所は都度ググれるので、「んー、良さそう」みたいにざっくり判断をしたりします。

それは置いておくとして。
初めにベースとなっているAngularの説明や、TypeScriptの説明がざっくりとされており、Ionicの導入、チュートリアル形式での開発と進みます。
「超!入門書です」とあるように、コードの解説も丁寧で初心者にもわかりやすく、機能単位で順に作っていくので、テンポもよくて進めやすかったです。

この後

本書の冒頭でプッシュ通知など実装できていない機能がぽろっと挙げられていたので、そこの実装を自力で進めてみようかなと思います。
ログインはできるものの、セッション管理ができていない気がするので、その辺りも調べつつ…。

せっかくなので個人用アプリも作ってみたいところです。

builderscon2018参加して来たメモ

公開したと思っていたらずっと下書きでした。

builderscon.io 去年は行けなかったbuilderscon、今年はなんとか参加することができました。

ガチャ負荷やば…こわ…と怯えてみたり、
IEぐぬぬ、Edgeぐぬぬ、という気持ちになったり、
セッションに触発されてパフォーマンス計測したくなったり、
ビジネスサイドの巻き込みと決断すご…と思ってみたり、
テーマが「知らなかった、を聞く」だったので、もっと冒険したセッション選びをすれば良かったなとちょっとだけ後悔しています。
あとで動画で追おう。

改めてこういうイベント好きだなー、と思いました。
最後のLTまでずっと楽しかったです。
行って良かったー。

ぼやき

結構、満員御礼で入れないセッションが多くて、しょんぼりしてたりしました。
聞きたいセッションの被りも多く、これまたしょんぼりしてました。
戦略でも立てておけば良かったんですかね…。

以下、自分のメモがてらセッションの関連リンクをズラーっと並べているだけなので折ります。

続きを読む

【Docker】Rails環境の構成をテンプレート化してみた

DockerでRailsの環境を作ろうとした時に、毎度構成に悩みます。

Railsプロジェクトの中に入れるのも、
- 本番をDockerで動かしていない時は不要なファイルになる
- Docker環境を捨てる時が来たらパッと捨てられるように分離したい

という気持ちがあるので、「どうしたもんかなぁ🤔」と構成を変えたりしていたのですが、毎度作り直したりも面倒なので、今のところしっくり来ている構成をテンプレートにしてみました。

docker-dir
├ .git  
├ mysql  
│ ├ configs
│ │ └ docker-entrypoint-initdb.d  
│ │   └ 01_init.sh
│ └ data
│   └ .gitkeep
├ rails  
│ ├ data
│ │ └ .gitkeep
│ ├ project
│ │ └ .gitkeep
│ └ Dockerfile
├ .env  
├ .gitignore
├ docker-compose.yml 
└ README.md

GitHub - s-mori/rails_docker_template

サービス毎にディレクトリを作って(テンプレートの場合だと、mysqlrails)、Dockerfileやプロジェクトディレクトリなどのそのサービスに関わるものは、それぞれサービスのディレクトリに中に格納するようにしています。
プロジェクトは docker-dir > rails > project の中で git clone git@github.com:hoge/piyo.git .

DBのユーザ、パスは .env ファイルの中で定義して、開発環境だけで使う想定なので、そのままgit管理。
doc: Environment variables in Compose > The “.env” file

今のところ特に問題も起きていないし、不都合も特にないものの、これがベストかと言われると🤔なところ。
いろんな「これが良さげ!」を見てみたいこの頃です。

【gulp】heroku環境のgulp-webserverでbasic認証を設定する

gulp入門2日目です。

デザイナーさんからいただいたgulpプロジェクトのページを誰でも確認できるように、herokuへアップしました。
basic認証を設定したかったのですが、思った以上に(gulp触りたてというのもあるかもしれない…)はまったので、備忘録として。

gulp-webserver

gulp-webserverをインストールします。

$ npm -i --save 

gulp/tasks/webserver.jsを作成し、サーバ起動時のhost、portの設定を記述します。
herokuの場合、ポートが異なるためにアクセスできない状況になりやすいので、process.env.PORTでherokuのポートを取得します。

'use strict';

const gulp = require('gulp');
const webserver = require('gulp-webserver');

gulp.task('webserver', () => {
  gulp.src('dev')
    .pipe(webserver({
      // livereload: true, livereloadを使うときは有効にする
      host: process.env.HOST || 'localhost',
      port: process.env.PORT || 8000
    }))
});

$ npm run start
でサーバを起動できるように、"start": "gulp webserver"package.jsonscriptsに追加します。

{
  "scripts": {
    "start": "gulp webserver",
    "build": "gulp build"
  }
}

basic-auth

basic-authを利用して、gulp-webservermiddlewarebasic認証を実装します。
まずはインストール。

$ npm -i --save basic-auth

middlewareの認証部分を追加した、webserver.jsの全体像はこちら。

heroku

basic認証のユーザ、パスはherokuの環境変数に設定します。

$ heroku config:set USER=user_name PASS=pass

また、devに保存したモジュールをインストールするための変数、web-serverのHOSTをherokuに追加します。

$ heroku config:set NPM_CONFIG_PRODUCTION=false
$ heroku config:set HOST=0.0.0.0

herokuでは、deploy -> npm install -> postinstall -> start の流れになるようなので、postinstallでbuildができるようにします。 package.json

{
  "scripts": {
    "postinstall": "gulp build",
    "start": "gulp webserver",
    "build": "gulp build"
  }
}

あとはherokuにプッシュして、見守ります。

余談

久々にherokuを見たのですが、以前はあった制限がなくなっていたりと、簡単なサービスなら十分herokuでも行けるのでは…?と思ったりしました。
実際に稼働しているサービスもありますし。

あとgulp。
最近webpackも触ったりしていたのですが、gulpも楽じゃーんと思ったりして、いまいちこのあたりの違いがまだ見えていなかったりします。
も少しフロントエンドの話題にもついていけるようにしたいなぁと思う今日この頃です。

今回のbasic認証、アクセスの度にURLが一瞬ちらついてしまうのがきになるところですね…もう少し調査が必要そうです…。

参考:

Herokuでgulpのwebserverをそのまま使う
Heroku上でもgulp-webserverを使う
Herokuでgulpのwebserverをそのまま使う
How to use middleware? · Issue #78 · schickling/gulp-webserver · GitHub

【CentOS】CentOS6.9にCloudWatchモニタリングスクリプトを入れて監視する

CloudWatchのメトリクスで取れそうで取れないものがディスク容量やメモリ使用量ですが、さすがAWSさん。
公式でプラグインスクリプトを用意してくれています。ありがたい。
Amazon EC2 Linux インスタンスのメモリとディスクのメトリクスのモニタリング - Amazon Elastic Compute Cloud

このプラグインの導入、CentOS7だとさっくりできたのに、CentOS6.9だと無駄にウロウロしたので、備忘録としておいておきます。

先に結論

フラフラしたので結論だけ書くと、CloudWatchClient.pmの26行目を書き換えました。

use LWP 6;
↓
use LWP;

なんか思わぬところでハマるんじゃ無いかという恐れもありますが、今の所動いています。

IAMの作成

モニタリングスクリプトを実行するIAMユーザが必要になるので、先に作っておきます。
IAM > ユーザー > ユーザーを追加 から、下記4つの権限を持ったユーザを作成します。
アクセスキー、シークレットアクセスキーが必要になるので、アクセスの種類では「プログラムによるアクセス」を有効にします。

  • cloudwatch:PutMetricData
  • cloudwatch:GetMetricStatistics
  • cloudwatch:ListMetrics
  • ec2:DescribeTags

完了したら、認証ファイルをダウンロードしてスクリプトのインストールに進みます。
余談ですけど、IAMの権限の設定すごく楽になりましたよね。

インストール

Amazon EC2 Linux インスタンスのメモリとディスクのメトリクスのモニタリング - Amazon Elastic Compute Cloudの内容に沿って、必要なライブラリをインストールします。

$ sudo yum install perl-Switch perl-DateTime perl-Sys-Syslog perl-LWP-Protocol-https zip unzip -y

Perlが入っていない場合、追加でPerlのインストールも必要です。

$ sudo yum -y install perl-CPAN gcc perl-libwww-perl libyaml-devel openssl-devel

CPANを実行して、必要なモジュールをインストールします。

$ sudo cpan
cpan[1]> install YAML 
cpan[1]> install LWP::Protocol::https 
cpan[1]> install Sys::Syslog 
cpan[1]> install Switch 

インストールが終わったら、プラグイン本体をダウンロード、展開します。

$ curl https://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.2.zip -O
$ unzip CloudWatchMonitoringScripts-1.2.2.zip

認証情報のテンプレートファイルをコピーして、中に作成しておいたIAMのアクセスキー等を設定します。

$ cd aws-scripts-mon
$ cp awscreds.template awscreds.conf
$ vi awscreds.conf
AWSAccessKeyId=ACCESS_KEY_ID
AWSSecretKey=SECRET_ACCESS_KEY

これでインストールは完了したので、mon-put-instance-data.plを実行して動作をみます。
--disk-space-utilオプションでディスク使用量の確認、--verifyオプションでテスト実行します。

$ ./mon-put-instance-data.pl --disk-space-util --disk-path=/ --verify --verbose --aws-credential-file=/home/centos/cloudwatch_plugins/aws-scripts-mon/awscreds.conf
LWP version 6 required--this is only version 5.833 at CloudWatchClient.pm line 26.
BEGIN failed--compilation aborted at CloudWatchClient.pm line 26.
Compilation failed in require at ./mon-put-instance-data.pl line 86.
BEGIN failed--compilation aborted at ./mon-put-instance-data.pl line 86.

はい。

LWPのバージョンをあげようとしてみる

どうやらバージョンが関わっていそうなので、アップグレードで解決?と考え始めます。

# LWPのバージョン確認
$ perl -MLWP -le "print(LWP->VERSION)"
5.833
# アップグレードできるもの確認
$ perl -MCPAN -e "CPAN::Shell->r"
Package namespace         installed    latest  in CPAN file
LWP                           5.833      6.34  ETHER/libwww-perl-6.34.tar.gz

latestは6.34。
libwww-perl-6.34.tar.gzを手に入れる必要がある?と考え、インストールチャレンジします。

$ sudo perl -MCPAN -e "CPAN::Shell->install('ETHER/libwww-perl-6.34.tar.gz')"
Warning: No success on command[/usr/bin/perl Makefile.PL INSTALLDIRS=site]
  ETHER/libwww-perl-6.34.tar.gz
  /usr/bin/perl Makefile.PL INSTALLDIRS=site -- NOT OK
Running make test
  Make had some problems, won't test
Running make install
  Make had some problems, won't install

できません。

スクリプトを書き換える

ふと冷静になります。
「LWP version 6 required」ということは、スクリプト内でバージョンの指定されているところか何かしらがあるのでは?

ここで冒頭に戻るわけですが、そのままだとCloudWatchClient.pmへの書き込み権限が無いようなので、先に権限を変更します。

$ ls -la
-r--r--r-- 1 centos centos 22519 2018-03-26 12:47 CloudWatchClient.pm
$ chmod 644 CloudWatchClient.pm
$ ls -la
-rw-r--r-- 1 centos centos 22519 2018-03-26 12:47 CloudWatchClient.pm

これで変更できるようになるので、冒頭に書いた通り、26行目にあるuse LWP 6;use LWP;に変更します。

変更したら、先ほど実行したmon-put-instance-data.plを再び実行します。

$ ./mon-put-instance-data.pl --disk-space-util --disk-path=/ --verify --verbose --aws-credential-file=/home/centos/cloudwatch_plugins/aws-scripts-mon/awscreds.conf
DiskSpaceUtilization [/]: 52.6020399623083 (Percent)
Using AWS credentials file </home/centos/cloudwatch_plugins/aws-scripts-mon/awscreds.conf>
Endpoint: https://monitoring.ap-northeast-1.amazonaws.com
Payload: {"MetricData":[{"Timestamp":1529401137,"Dimensions":[{"Value":"/dev/xvda1","Name":"Filesystem"},{"Value":"i-021839685456c0737","Name":"InstanceId"},{"Value":"/","Name":"MountPath"}],"Value":52.6020399623083,"Unit":"Percent","MetricName":"DiskSpaceUtilization"}],"Namespace":"System/Linux","__type":"com.amazonaws.cloudwatch.v2010_08_01#PutMetricDataInput"}

Verification completed successfully. No actual metrics sent to CloudWatch.

通った!\\ ٩( 'ω' )و //

参考

【Rails】Rails5+Pumaでlogrotate

放っておくといつの間にか容量が膨れ上がっているログファイル。
ふと気づくとディスク容量があっぷあっぷしている、なんてこともあるので、静かな侵略者と勝手に思っています。
rotateの設定をしていないのが悪いんですけどね。

Linuxのlogrotateを使ってもできるのですが、Puma+logrotate+Capistranoだとログ周りがうまく動かないという記事を見たので、RailsのLoggerでrotateする方法にしてみました。

Loggerの設定

config/environments/production.rbconfig/environments/development.rbなどの各環境で設定します。

Rails.application.configure do
  # 日別にrotateされるように設定
  logger = ActiveSupport::Logger.new('log/production.log', 'daily')
  logger.formatter = config.log_formatter

  if ENV["RAILS_LOG_TO_STDOUT"].present?
    # 'log/production.log'以外(ex. 標準出力)にログ出力先を追加する場合
    stdout_logger           = ActiveSupport::Logger.new(STDOUT)
    stdout_logger.formatter = config.log_formatter
    multiple_loggers = ActiveSupport::Logger.broadcast(stdout_logger)
    logger.extend(multiple_loggers)
  end
  config.logger = ActiveSupport::TaggedLogging.new(logger)
end

日別にしたかったので

ActiveSupport::Logger.new('log/production.log', 'daily')

としていますが、dailyの部分をmonthlyにすると月別、weeklyにすると週別でのrotateになります。
また、

ActiveSupport::Logger.new('log/production.log', 5, 10 * 1024 * 1024)

のようにすると、10Mbずつ、5ファイル分保持します。

ファイルサイズで分割した時は指定したファイル数(ex. 5)を越えると自動で削除してくれますが、期間で分割した時は削除されないので、延々と過去ログが溜まっていきます。
このまま放っておいても、またサーバを圧迫してしまうので、削除バッチを作ってcron実行するようにします。

古いログファイル削除バッチの作成

namespace :log_rotate do
  desc "rotateされたログファイルのうち、1週間前のファイルを削除する"

  task :destroy_old_file => :environment do
    # 対象のファイルを取得
    log_files = Dir.glob(Rails.root.join("log/#{Rails.env}.log*"))

    log_files.each do |file|
      # 1週間前の日付
      last_week_date = Time.zone.today.weeks_ago(1)
      # ファイルの更新日を取得
      file_modified_date = File.mtime(file).in_time_zone.to_date
      # 更新日が1週間前のファイルは削除
      if file_modified_date < last_week_date
        FileUtils.rm file
      end
    end
  end
end

コードの通りですね。
ログ出力対象(log/env.log)のファイルの File.mtimeを使って対象ログファイルの最終更新日時を取得します。

取得した最終更新日時と一週間前の日時を比較して、古いものはFileUtils.rmで削除します。

あとはwhenever等でCronに登録しておきます。

puma起動

設定が終わったら、pumaコマンド(or pumactl)で起動します。

$ bundle exec puma -C config/puma.rb -e production -d

rails s でもpumaは起動しますが、この場合はlogrotateの設定が上手く反映されず、1ファイルに出力され続けるようです。
この辺りはもっとちゃんと調査したいところ…。

【CSS】user-selectでテキスト選択を制御

ひょんな事から、user-selectなるプロパティを知りました。
選択動作を制御するもので、選択できる範囲を制限したり、選択できなくさせるものだそうです。

ブラウザによって挙動が異なるので、ベンダープレフィックスが必要。
指定できる値は

  • none
    テキストを選択できなくする
  • auto
    ブラウザのデフォルトに従う
  • text
    ユーザが選択できるようにする。選択範囲の制限は無し。
  • all
    クリックで全選択状態にする
  • contain
  • element
    ユーザが選択できるようにする。選択範囲の制限あり。IEでのみ有効。

user-select - CSS: カスケーディングスタイルシート | MDN
user-selectで要素のテキスト選択を「させる」

遭遇した現象

SemanticUIのメニューとポップアップを併用した際、ポップアップで表示した部分が選択できない状況に遭遇しました。
例えばこんなメニュー&ポップアップ

See the Pen SemanticUI - menu and popup by s-mori (@s-mori) on CodePen.

Ruby on Rails」をクリックでポップアップを表示するようにしています。

何もせずに表示させると、ポップアップ内のテキストを選択しようとしてもできません。
要素を無効にしながら調べると、どうやらデフォルトで.ui.menu .itemuser-select: none;がついているようでした。

ポップアップ内のテキストは選択可能にしたかったので、ポップアップに対して

user-select: text;
-moz-user-select: text; // for firefox
-webkit-user-select: text; // for safari
-ms-user-select: text; // for Edge,IE

をつけて対応。各ブラウザで効くようにします。

余談

MDNによると

これは実験段階の機能です。 この機能は複数のブラウザーで開発中の状態にあります。互換性テーブルをチェックしてください。また、実験段階の機能の構文と挙動は、仕様変更に伴い各ブラウザーの将来のバージョンで変更になる可能性があることに注意してください。 https://developer.mozilla.org/ja/docs/Web/CSS/user-select

とのこと。