haayaaa’s diary

書きたい事があったら気軽に書いて行きます。普段は渋谷でRailsを使ったお仕事してます。

ssh公開鍵の置き方

本日ssh公開鍵の置き方を教えていただきました!!

いつも他の人に鍵を置いてもらう事ばかりでしたが、これからは自分で誰かの鍵を置いてあげることができるようになりました!!

忘れないように書いておきます!!

 

手順

sshでログイン
$ ssh hoge-hayashi@hoge-app1  -p 50022

Last login: Wed May 29 14:39:18 2019 from nttkyo898237.tkyo.nt.ngn.ppp.infoweb.ne.jp



       __|  __|_  )

       _|  (     /   Amazon Linux AMI

      ___|___|___|



https://aws.amazon.com/amazon-linux-ami/2015.09-release-notes/

117 package(s) needed for security, out of 243 available

Run "sudo yum update" to apply all updates.

Amazon Linux version 2018.03 is available.

 

 

rootユーザーになる
[hoge-hayashi@app1 ~]$ sudo -i



We trust you have received the usual lecture from the local System

Administrator. It usually boils down to these three things:



    #1) Respect the privacy of others.

    #2) Think before you type.

    #3) With great power comes great responsibility.



[sudo] password for hoge-hayashi: パスワードうつ

 

rootユーザーになると最初にいるディレクトリは/root です。

[root@app1 ~]# pwd

/root

 

 

/home/deployへ移動
[root@app1 ~]# cd /home/deploy

 

ls -l -aすると色々みれます。

[root@app1 deploy]# ls -l -a

合計 84

drwx------  7 deploy  10007  4096  6月  7 12:05 .
drwxr-xr-x 13 root   root    4096  528 15:34 ..
drwxr-xr-x  3 deploy  10007  4096  7月  6  2016 .ansible
-rw-------  1 deploy  10007 22517  617 21:17 .bash_history
-rw-r--r--  1 deploy  10007    18  9月  3  2015 .bash_logout
-rw-r--r--  1 deploy  10007   193  9月  3  2015 .bash_profile
-rw-r--r--  1 deploy  10007   124  9月  3  2015 .bashrc
drwxrwxr-x  3 deploy deploy  4096  3月  2  2017 .bundle
drwxrwxr-x  4 deploy  10007  4096 1221  2015 .gem
-rw-------  1 deploy  10007  2256  6月  7 11:27 .lesshst
-rw-------  1 deploy deploy   356  3月  2  2017 .mysql_history
drwxrw----  3 deploy  10007  4096  113  2016 .pki
drwx------  2 deploy  10007  4096  528 16:33 .ssh
-rw-------  1 deploy deploy 10763  6月  7 12:05 .viminfo

 

 

 

.ssh/authorized_keysファイルを開く

.ssh/authorized_keysの中にssh公開鍵が置いてあるのでviewコマンドやvim等で開くとみれます。

[root@app1 deploy]# view .ssh/authorized_keys

 

ずらりと公開鍵が置いてあるのがみれます。

gyazo.com

 

 

Linuxの知識薄すぎるので勉強がんばってゆきます!

 

 

 

「Linuxの仕組み」の輪読会へ行った

今日は「Linuxの仕組み」の輪読会へ行ってまいりました!!

この本を買ったのが昨日のことなので全く予習はできていなかったのですが、予習なしでOKの輪読会だったので有難かったっです!

 

今日は以下の内容を進めていきました!

・はじめに

・第1章 コンピューターシステムの概要

・第2章 ユーザーモードで実現する機能

 

 

この本は実際に手を動かしながら学んでいく形式です。

そこで、企画して下さった方々が作業するための環境をdockerで作ってくださりました!!

以下はそのリポジトリです!!

github.com

 

また、この本のサンプルコードはC言語で書かれているものがたくさんあったのですが、

C言語の解説をしてくださる方もいらっしゃり、とても理解が進みました!!

 

さらに、Dockerの何が良いのかについてVirtualBoxとの違いについての説明を交えながら教えていただいたり等、今まで理解せずに使ってきてしまった技術について学ぶこともできました!!

 

本にも書いてありましたが、

「ハードウェアの特性を考慮した、良いソフトウェアを開発できるようになる」、

「どのような指標に基づいてシステムを設計すれば良いか分かるようになる」、

「OSやハードウェアに関するトラブルが起きたときに、冷静に対処できるようになる」、といったことが出来るようになりたいのでしっかり輪読していこうと思います!!

 

 

SQL発行されまくるスクリプト

あるデータを取得する必要があり、コンソールでスクリプトを実行しておりました。

すると、AWS RDSのProcessor load が90%を超えているというアラートが何度も鳴ってしまいましたw

OPさんにも心配をさせてしまいたした。

 

その時のスクリプトが以下です。

idsに調べたいhogeidを代入し、Hogeモデルのレコードと関連するmessageのレコード情報を引っ張っておりました。

messages = []

ids.each do |id|
message =
Hoge.find_by(hogeid: id)&.message
messages << "#{message.id}........略"
end

puts messages

 

これだとレコード1つずつに対してSQLが発行されてしまっており、RDBへの負荷がとても大きくなってしまっていたようです。

さらに期間指定もしていない為、レコード全件見にいってしまっていたようです。。。

 

 

 

修正後のスクリプトが以下です。

いっぺんに100件ずつ処理を行うようにしてあげ、

includesで関連先レコード取得する際SQL発行されないようにし、

期間指定をして全件見にいかないようにしてあげました。

messages = []

ids.each_slice(100) do |new_ids|
pre_messages = Hoge.includes(:message).where(created_at: (DateTime.new(2019,6,6,7,00))..(DateTime.new(2019,6,6,21,00))).where(hogeid: new_ids)

pre_messages.each do |pre_message|
message = pre_message&.message
messages << "#{message.id}........略"
end
end

puts messages

 

これが正しいやり方なのかは分かりませんが、発行されるSQLがめちゃくちゃ減りました。

データの取得できるスピードも格段にアップしました。

最初のスクリプトだと一度に数百件ずつidsを代入していてもアラートが鳴っていたのが、1万件以上のidを代入してもアラートもならなくなりました。

 

アクティブレコードのメソッドがどんなSQLに変換されるのか、ログを見て意識していこうと思います!

 

 

 

 

 

find_eachで順番を指定したい

pdfの作成される順番を変えたいと思いコードをいじっておりました。

以下はpdfの作成される部分のコードの一部です。

 

class BatchPrintJob < ApplicationJob
 略
def perform(batch_print)

invoices.find_each do |invoice|
 略
pdf << CombinePDF.load(pdf_object.path)
end   
   略

end
end

 

invoicesのレコードを引っ張る際にorderで順番を指定すればうまくいくかと思ったのですが、

find_eachは順番を指定することができないらしく、pdfの作成される順番を指定するにはどうすればいいんだろう、、、と困っておりました。 

 

 

色々ググっていると以下の記事を発見しました!!

qiita.com

 

この記事を参考にしてみたら動いてくれました!!

以下のコードは変更後のものです。

class BatchPrintJob < ApplicationJob
 略
def perform(batch_print)

invoices.order("clients.yayoi_code").find_each_with_order do |invoice|
 略
pdf << CombinePDF.load(pdf_object.path)
end   
   略

end
end

 

class Invoice < ApplicationRecord

def self.find_each_with_order(options={})
page = 1
limit = options[:limit] || 1000

while
offset = (page-1) * limit
batch = limit(limit).offset(offset)
page += 1

batch.each{|x| yield x }

break if batch.size < limit
end
end

end

 

find_each_with_order メソッドの中身が難しくてよくわからなかったのでbinding.pryを挟みながら、変数の値を確認してみました。

 

limitはいっぺんにブロックの処理を実行するオブジェクトの数、

batchはいっぺんに処理を行うオブジェクトの塊、

offsetは、、、何だろう、、、batchの何番目の塊を引っ張るか判断するためのオブジェクトでしょうか。。。

 

batch.each{|x| yield x} の部分は do ~ endまでのブロックを実行しているようです。

 

ネットの情報を参考にするとしても、

理解した上で、きちんと理由を持って、コードを書いていきたいです。。。!!

 

 

 

 

 

FactoryBot難しい...

ジョブを実行すると、ある条件の時にレコードが更新されることをテストしたかったのですが、なかなかテストが通らないため、binding.pryを駆使してデバックしておりました。

 

しかし、binding.pryだときちんと値が更新されているのに、なぜかテストは落ちておりました。

 

そこで p メソッドでFactoryBotでつくったオブジェクトと、後からfind_byで検索したオブジェクトを出力してみたところ、同じものだと思っていたオブジェクトが別物であることがわかりました!

(テストじゃない場合は同じレコードになる)

 

以下はそのテストコードです。

require "rails_helper"

RSpec.describe InvoiceCloseJob, :type => :job do
include ActiveJob::TestHelper

  略

let!(:contract_auto_before_closing_day) { FactoryBot.create(:contract, :auto_before_closing_day) }


describe "契約期間延長処理" do

context "自動延長有効の契約書" do
context "契約期間終了日 < 締め期間の最終日" do
it "契約期間が更新されること" do
InvoiceCloseJob.perform_now(invoice_close)
p contract_auto_before_closing_day
p Contract.find_by(display_name: 'auto_before_closing_day')
expect(contract_auto_before_closing_day.to).to_not eq("2019-04-29".to_date)
end
end

   略

 

こちらはターミナルに出力されたオブジェクトです。

idが別物でした。

そして、find_byで検索してきた方のオブジェクトはきちんと値が更新されておりました。

#<Contract id: 511, client_id: 2, from: "2019-04-01", to: "2019-04-29", billing_closing_date_id: 1, contract_type: "従量課金制", status: "actived", display_name: "auto_before_closing_day", created_at: "2019-06-12 05:09:46", updated_at: "2019-06-12 05:09:46", service_id: 2, display_name_service: "", auto_extension: true, extension_months: 6, ceil_digit: nil, had_spot_item: false>

#<Contract id: 467, client_id: 2, from: "2019-04-30", to: "2019-10-29", billing_closing_date_id: 1, contract_type: "従量課金制", status: "actived", display_name: "auto_before_closing_day", created_at: "2019-06-12 04:32:07", updated_at: "2019-06-12 05:09:49", service_id: 2, display_name_service: "", auto_extension: true, extension_months: 6, ceil_digit: nil, had_spot_item: false>

 

 

無事、expect( ) の引数をfind_byで引っ張ってきた方のオブジェクトに変更したところ、テストが通ってくれました。

 

FactoryBot難しい。。。

 

 

 

 

 

@sinamon129さんの「システム障害との向き合い方」をもう一度読んだ

@sinamon129さんの「システム障害との向き合い方」をもう一度読んでみました。

このご発表を聞いた当時はシステム障害を経験したことがありませんでしたが、先日まさにシステム障害を経験することがあったからです。

そのスライドが以下です!!

 

speakerdeck.com

 

 

 

自分の状況と照らし合わせてみる

自分の前提は以下のような感じです

・受託

ウェブアプリケーション

・プロジェクトに関わる人はインフラエンジニア1名、アプリ側エンジニア3名、PO1名

  

このスライドの中でシステム障害の種類として、以下の5つを挙げてくださっておりました。

①開発時の実装ミス(バグ)

②手動操作のミス

③ アクセスの急増

④使用しているサービスの不具合

⑤これらの複合

今回自分が経験したのは③のアクセスの急増が原因の障害でした。

 

そして現在自分の関わっているプロジェクトは、

発生 → 発覚 → 調査 → 一時対応 → 収束 → 振り返りと恒久対応

という順番の「収束」の段階で、これから恒久対応していくという段階です。

 

  

心に残った部分と感想その他

ご講演を聞いてもシステム障害を経験したことのなかった自分には理解しきれない所が多かったのですが、今読み返してみると「なるほど!!これは大事だ!!これは気をつけていきたい!!」と思えるようになった部分がありました。

 

スライドにも書かれておりましたが、戦力にならなくても率先して参加し、発生した障害を学びに変えていきたいと思います!!

そして連絡すべきことは担当の人にしっかり連絡し、一人でできない部分はきちんと周りの人にきく、ということも気をつけていこうと思います。

 

さらに、障害を起こさないために普段コードを書いたりレビューする段階で、

「条件分岐を意識し、細かい書き方より条件があっているかを確実にする」

「変更が意図しない部分に影響を与える実装になっていないか確認する」

「変更はロールバックできる状態にする」

というのも実行していきたいです!!

 

 

 

ActiveDecoratorを(ごく一部)読んだ

 

先ほどActiveDecoratorを使って定義したメソッド(を呼んでるモデルに定義したメソッド)をコントローラーで呼んだところ、エラーとなりました。

ActiveDecoratorをView以外で使う時は、ActiveDecorator のデコレーターメソッドをかましてあげる必要があるとのことでした。

 以下のように、ActiveDecorator::Decorator.instance.decorate( ) とメソッドを呼ぶインスタンスに処理を加えてあげると無事動いてくれました。

class AmountChecksController < ApplicationController

   略

private
def total_amount_sum(invoices)
invoices.map{|invoice| ActiveDecorator::Decorator.instance.decorate(invoice).total_amount_for_read}.sum
end
end

 

 

この処理が何をしているのか気になったため、定義元をみてみました。

 

github.com

 

 

active_decorator/lib/active_decorator/decorator.rb の中にdecorate( ) メソッドがあり、定義は以下のようになっておりました。


def
decorate(obj)
return if defined?(Jbuilder) && (Jbuilder === obj)
return if obj.nil?

if obj.is_a?(Array)
obj.each do |r|
decorate r
end
elsif obj.is_a?(Hash)
obj.each_value do |v|
decorate v
end
elsif defined?(ActiveRecord) && obj.is_a?(ActiveRecord::Relation)
# don't call each nor to_a immediately
if obj.respond_to?(:records)
# Rails 5.0
obj.extend ActiveDecorator::RelationDecorator unless obj.is_a? ActiveDecorator::RelationDecorator
else
# Rails 3.x and 4.x
obj.extend ActiveDecorator::RelationDecoratorLegacy unless obj.is_a? ActiveDecorator::RelationDecoratorLegacy
end
else
if defined?(ActiveRecord) && obj.is_a?(ActiveRecord::Base) && !obj.is_a?(ActiveDecorator::Decorated)
obj.extend ActiveDecorator::Decorated
end

d = decorator_for obj.class
return obj unless d
obj.extend d unless obj.is_a? d
end

obj
end

 

引数のオブジェクトがArrayならeachで取り出して再度1つずつdecorateメソッドを呼び、

Hashならeach_valueでバリューを取り出して1つずつdecorateメソッドを呼んでおります。

 

そして必ずオブジェクトを返すように、様々な条件分岐させてモジュールを生やしておりました。

 

 

Viewだとdecorate( ) メソッドを呼ばなくてもActiveDecoratorを使えるようになってるのはどうやっているのだろうと思い、そのほかのファイルものぞいてみたのですが、難しかったのでまた後日チャレンジしてみようと思います。。。!!