mgmmyBlog

Webエンジニア👩‍💻 Railsの話がメインです。

【LPIC101】システムアーキテクチャ:システムの起動②

f:id:mgmmy:20200506132934p:plain

LPICの勉強を兼ねて、Ping−tで学習したことをまとめています✍️

システムアーキテクチャ

システムの起動

UEFIUnified Extensible Firmware Interface

  • IntelBIOSを置き換えるために考案したEFIの統一仕様。
  • GUIでの操作をサポートしている。
  • ファームウェアが使用可能なメモリ量の上限が緩和されている。
  • GPT形式のHDDからの起動をサポート。

ESP(EFIシステムパーティション

  • 物理的なマシンを起動し、ファームウェアが読み込まれた後、その後の起動シーケンスで最初にアクセスされる領域。
  • /boot/efi にマウントされる。

GPT(GUID Partition Table)

  • 9.4ZB(8ZiB:ゼビバイト) までのHDDを管理することができるパーティションテーブルの形式。
    • BIOSで起動ディスクとしてサポートしているMBR形式のパーティションテーブルの上限は 2.2TB(2TiB:テビバイト)
  • 3TBを超える大容量HDDを起動ディスクとして使用する場合はUEFIとGPTを使用する必要がある。
    • Linuxの場合は GRUB2 ブートローダがGPTをサポートしているため、BIOSからGRUBローダーをロードできればGPT形式のハードディスクからの起動は可能。

dmesg コマンド

  • カーネルが出力するメッセージが格納されるリングバッファの内容を出力する。
    • リングバッファはマシンの再起動やシャットダウンによってリセットされる。
    • 運用中にいっぱいになると古い情報から上書きされる。
  • rootユーザで dmesg --clear を実行することでリングバッファの内容をクリアできる。

/proc/cmdline ファイル

使用例

# 実行
cat /proc/cmdline

# 結果
ro root=/dev/sda2

大容量の記憶装置を正常に起動できない場合の対処

  • BIOSが古い場合、大容量の記憶装置を正常に起動できない(実際より少ない容量を認識するなど)場合がある。
  • BIOSをアップデートすることで解消できることがある。

ハードディスクから正常に起動できなくなったときの対処

  • CD-ROM/DVDやUSBなどのインストールブートメディアからレスキューモードでシステムを起動することができる。
  • レスキューモードで起動できた場合はCPU/メモリといったハードディスク以外の装置には問題がないと考えられる。
  • レスキューモードで起動したシステムから起動に失敗するハードディスクのファイルシステムをマウントできるかを確認する。
  • 正常にマウントできた場合は var/log 配下のログでエラーを確認したり、重要なファイルを取り出せる可能性がある。

【LPIC101】システムアーキテクチャ:システムの起動①

f:id:mgmmy:20200503130258p:plain

LPICの勉強を兼ねて、Ping−tで学習したことをまとめています✍️

システムアーキテクチャ

システムの起動

ブートプロセス

一般的なLinuxシステムでは、

BIOSブートローダカーネルinit の順にブートプロセスが進行する。

BIOS

  • コンピュータの電源を入れると最初に起動する。
  • 記憶装置等に対して最低限の認識をし、起動デバイスの優先順位を決定する。
  • 優先順位に従い、各デバイスの先頭セクタにあるMBRを読み込み、得られたブートローダに制御を移す。
  • 起動デバイスの優先順位はBIOSセットアップ画面で任意の順序に変更可能。

ブートローダ

  • 起動されると、記憶装置(HDD)内のカーネルをロードし、制御を移す。
  • BIOSの次に起動される。
  • Linuxシステムでは GRUB が該当する。
  • MBR に格納されている 第一段階部分 と、 記憶装置内 の別の場所に格納されている 第二段階部分 がある。
    • 厳しいサイズ制限があるためこのように分かれている。
  • 記憶装置内のカーネルをロードし、カーネルに制御を移す役割を果たす。

カーネル

  • 起動されると、高度にハードウェアを認識・制御し、ルートファイルシステムのマウントなど様々な初期化処理を行う。

初期RAMディスク(initramfs)

  • /boot ディレクトリに格納される。
  • 展開してイメージ内のディレクトリ・ファイルを参照できる。
  • lsinitrd コマンドで格納されているディレクトリ・ファイルを参照できる。
  • カーネルの各バージョンに対応する初期RAMディスクが存在する。

init

  • 最初に起動されるプロセス。PID(プロセスID)は必ず 1
SysVinit
  • 従来のinitプログラム。 /sbin/init が起動される。
  • initプロセスは設定ファイル /etc/inittab の記述に基づいて、自動起動すべきプロセスを立ち上げるなど、アプリケーションレベルの初期化を行う。
  • 以降、initプロセスは全てのプロセスの先祖(直接・間接的な呼び出し元)として存在し続ける。
  • 最近のシステムでは初期化処理を高速化した Upstartsystemd を採用している場合がある。
    • その場合は基本的に etc/inittab ファイルは使用されない。
Upstart
  • SysVinitを改善した新しい仕組み。現在はsystemdへの置き換えが進められている。
  • サービスやタスクを ジョブ という単位で扱う。
  • 各ジョブの実行に必要な前提条件を イベント で管理し、前提条件が全て成立した時点でジョブを実行する イベント駆動型
    • イベントはシステム上の変化を検知するだけではなく、initctl コマンドで発行することもできる。
    • サービスの起動に必要な条件が成立した時点で起動処理が行われるため不要な待機時間がなくなる。
  • 各ジョブの実行がパラレルに行われるため、関連のない独立したサービスは同時に起動できる。
systemd
  • 各サービスを並列起動することができる。
    • 順次起動していくSysVinitに比べて高速なシステム起動や停止が行える。
  • cgroups というLinuxカーネルの機能によってプロセスのリソースを管理できる。
    • SysVinitではPIDで管理していた。
  • Unitという単位で管理される。
    • systemctl list-unit-files コマンドで利用可能なUnit一覧を表示する。
    • 各機能ごとに拡張子が割り当てられている。
    • 拡張子を見ることでどういった機能のためのUnitか判別できる。
拡張子 機能
device 各種デバイスを管理するUnit
mount ファイルシステムのマウントを管理するUnit
service サービスを制御するUnit
swap スワップ領域を管理するUnit
target 複数のサービスを一つのグループにするためのUnit
systemctl コマンド
  • 各サービスの稼働状況や起動設定を管理する。
  • コマンドの書式: systemctl サブコマンド [Unit名]
    • Unit名に拡張子がない場合は.service の拡張子を持つUnitが選択されたとみなす。
主なサブコマンドの一覧
サブコマンド 用途
disable サービスの自動起動を無効にする
enable サービスの自動起動を有効にする
get-default 次回起動時のターゲットを表示する
halt システムを停止しhalt状態にする
is-active サービスが稼働しているかを表示する
list-unit-files すべてのUnit定義ファイルを一覧表示する
reboot システムを再起動する
reload サービスの設定ファイルを再読み込みする
restart サービスを再起動する
set-default 次回起動時のターゲットを設定する
start サービスを起動する
status サービスの状態を表示する
stop サービスを停止する
poweroff システムを停止し電源を切断する
journalctl コマンド
  • systemd-journald のログを表示する。
    • systemd-journald が書き込むログファイルはバイナリ形式のため catless では正常に表示できない。
  • コマンドの書式: journalctl [オプション] [検索文字列]
  • -k または、 --dmesg オプションで dmesg コマンドと同じ情報(起動時にカーネルが出力したメッセージ)が出力できる。

【LPIC101】システムアーキテクチャ:ハードウェア設定の決定と構成②

f:id:mgmmy:20200503114902p:plain

LPICの勉強を兼ねて、Ping−tで学習したことをまとめています✍️

システムアーキテクチャ

ハードウェア設定の決定と構成

大容量記憶装置(Mass Storage Devise)

  • OSをインストールして、起動ディスクとして使用できる。

主に以下のものがある

  • HDD(Hard Disk Drive)
    • 容量が大きく、コストパフォーマンスが高い。
    • データの記録には磁気を使用する。
    • コンピュータ内蔵のもの、外付けのものがある。
    • 装置内部の プラッタ という部分に対してデータの読み書きを行う。
      • 衝撃によりプラッタが傷ついてデータが破損する場合がある。
  • USBフラッシュドライブ
    • USBメモリと呼ばれる記憶装置。
    • 内部の フラッシュメモリ にデータの読み書きを行う。
    • 書き換え回数やデータ保持期間に制限があるため長期保存には向かない。
  • SSD(Solid State Drive)
    • 記憶装置として半導体メモリを用いており、フラッシュメモリに属する機器である。
    • USBメモリと同様に書き換え回数とデータ保持期間に制限あり。
    • ランダムアクセス性能の優れ、省電力で静音。
    • 接触メディアであるため耐振動・衝撃性に強い。
    • フラッシュメモリの高速性を引き出すため、 SATA より高速な NVMe インターフェースで接続するタイプもある。

IRQ(Interrupt ReQuest)

  • マウスやキーボードなどのデバイスからCPUへの割り込み要求のこと。
  • 0 から 1 2 3 のように順に番号がつき、そのうちいくつかは特定のデバイスに割り当てられる。
    • 0 はシステムタイマー、 1 はキーボードに割り当てられる。

【LPIC101】システムアーキテクチャ:ハードウェア設定の決定と構成①

f:id:mgmmy:20200502155013p:plain

今日からLPICの勉強をしたいと思います!

とりあえず、Ping−tで学習したことをまとめます✍️

システムアーキテクチャ

ハードウェア設定の決定と構成

/proc ディレクト

  • 起動中のプロセスやカーネルが認識しているハードウェアおよびシステムリソースなどの情報が格納されている。
  • 仮想的なファイルシステム。ハードディスク上には存在しない。
    • システムが起動される際にメモリ上に作成される。

lsmod コマンド

  • ロードされているカーネルモジュールの情報を表示する。
  • /proc/modules ファイルはロードされているモジュールの情報が格納されているので cat /proc/modules でも情報を確認することができる 。

lspciコマンド

  • PCI(Peripheral Components Interconnect)デバイスの情報を表示する。
  • /proc/bus/pci/devices ファイルにPCIバイスの情報が格納されている。
  • オプションの -v で詳細表示、 -vv でさらに詳細を表示できる。

lspci -v を実行すると確認できること

  • PCI識別番号
  • PCIバイスの種類
  • ベンダー名(ベンダーID)
  • バイス
  • バスの速度
  • IRQ番号
  • I/Oポートアドレス

D-Bus(Desktop Bus)

  • プログラム同士が情報を伝達するプロセス間通信機構のひとつ。
  • Linuxでは dbus-daemon などがプロセス間通信の中継を行う。

BIOS/UEFI

BIOS/UEFIセットアップ画面でできること

  • 日付と時刻
  • 電源管理
  • 起動デバイスの優先順位
  • 組み込みデバイスの有効化/無効化

modprobe

  • 依存関係を考慮してカーネルモジュールをロードまたはアンロードするコマンド
  • 設定ファイルは /etc/modprobe.d/ 配下の .conf の拡張子を持つファイル。(カーネル2.4までは /etc/modules.conf

設定ファイルの記述

  • options
    • カーネルモジュールのデフォルトパラメータを指定する。
  • alias
  • install
    • 特定のカーネルモジュールのロード時に実行されるコマンドを指定する
  • remove
    • 特定のカーネルモジュールのアンロード時に実行されるコマンドを指定する
  • blacklist
    • ロードしたくないカーネルモジュールを指定する。

udev(Userspace DEVise management)

  • ホットプラグデバイスを接続した際にデバイスファイルを動的に作成する。
  • バイスの接続を検知(カーネルから通知される)した際、デバイスファイルを動的に作成する。
  • バイスファイル作成時の動作は etc/udev/rules.d ディレクトリ配下の .rules の拡張子を持つファイルに記述された情報に基づいて行われる。

I/Oポートアドレス

  • 周辺機器とCPUがデータをやりとりする際に使用する16ビットのアドレス。
  • proc/ioports ファイルに、どのデバイスにどのI/Oポートアドレスが割り当てられているか確認できる。
    • I/Oポートアドレスが重複しているとハードウェアが正常に動作しない場合がある。

DMA、DMAチャネル

  • CPUを介することなくデバイスとメインメモリとの間で直接的にデータ転送を行う方式。
  • DMAチャネルは周辺機器がDMAのコントローラに対して情報転送を要求するために使用する通信経路のこと。
  • proc/dma ファイルにはデバイスが使用中のDMAチャネルに関する情報が確認できる。

USBデバイス

  • USBデバイスはいくつかのデバイスクラスに分かれている
  • それぞれのデバイスにはクラスドライバという汎用ドライバが用意されている
バイスクラス バイス
HID(Human Interface Devise) キーボード、マウス
Mass Storage Class ハードディスク、USBメモリ
ACM Communication Devise Class モデム、TA
Audio Class スピーカー、マイク

TokyoGirls.rb Meetup vol.2 に参加しました!

先日、TokyoGirls.rb Meetup vol.2に参加してきました🙋‍♀️

f:id:mgmmy:20191224005225j:plain

👉イベントページはこちら

今回はイベントについてのレポートを書きます🌷

登壇者と各LTについてのまとめ

Ruby on Rails最初の一歩

スピーカー:ただあきさん(Classi)

Rails初心者やチームに新人がいる方の参考になるようなポイントをわかりやすく発表しておられました。

  • ドキュメントの読み方について
    • 公式のドキュメントを読むだけで参考になることがたくさんあるよ
    • エイリアスがわかったりするよ
    • サンプルコードがシンプルで参考になるものが多いよ
  • PRの出し方やポイント
    • 自分の気になる点については補足を書いたり、ピンポイントでコメントするといいよ
    • 機能単位でPR出すといいよ(細かくコミットする)
      • それでも差分が多いときは対応した箇所ごとに出す

事業知識を深掘りし、より人の役に立つサービスに改善する

スピーカー:Kubota Naoさん(エイチームフィナジー

事業知識の深堀りをすることによって、理解する前と後とではサービスの品質向上や改善につながったというお話でした。

  • 事業内容を理解していない場合のデータベースの設計
    • 専門用語の変数名の命名がうまくできず、何を指しているのか不明
    • 表示修正を行うたびに毎回多くの工数がかかる
    • 属人化
  • 事業知識を掘り下げた結果
    • 現実で発生するような要望に沿ったデータの提供できるように
    • サービスの改善提案ができるように
    • チーム内のコミュニケーションコストが少なくなった
    • 結果サービス品質の向上につながる
  • 一つひとつの言葉の意味に疑問を持ち意味を調べる
    • 普段使っている言葉も業界によっては違う解釈をすることもある

Rackミドルウェア入門のためのRackミドルウェア

スピーカー:塩井美咲さん(キャタル)

正直、まだ自分が未熟すぎて内容が理解できなかったです😢
もう少し知識をつけて、改めてスライドを理解したいと思います💪

エンジニアとチームを組んで見えないものをデザインする

スピーカー:羽野めぐみさん(デザイナー/キッチハイク)

今回唯一のデザイナーの方でした。
チームでプロダクトを作り上げていく中での大切なことについてのお話。
たしかにデザイナー目線とエンジニア目線では考えていることが全く違うなと思いました。 表面的な言葉にとらわれず、文脈を共有してお互いを知ることが大切なのだなと感じました😌

プロジェクトマネジメント沼にようこそ

スピーカー:浪川舞さん(PeerQuest)

プロジェクトマネジメントについてのお話。 自分にはまだまだ先の話と思っていましたが、チームで開発するということについてとても参考になる内容だと感じました。

  • プロジェクトマネジメントをやってみて
    • 朝会の定期開催
      • 温度感の共有
      • 課題を顕在化させる
      • 全員でとりくむ空気をつくる
    • 進捗管理数値の分析
      • 担当の明確化
      • 進捗率ではなく作業効率を重視
      • バーンダウンチャートを全員で共有(タスクの可視化)
    • メンバーの顔を見る
      • 何か抱えてそうな人には声をかける
      • 辛そうな人は休ませる
  • 結果
    • タスクの調整がしやすい
    • 属人化がなくなった
    • 問い合わせ対応スムーズに
  • 大事にしていること
    • セオリーの活用
    • 数値の分析
    • 人とのコミュニケーション
      • 上下関係のない1on1 情報の共有
        • 上司の場合はいいところを見せたかったり、本音が言えない。
      • 自分とメンバーの特性を知る
      • ファシリテーション研修導入
  • メンバーのモチベーション保つためには
    • ビジネスのOKRを共有する

いつもの開発のようにOSS活動をしよう

スピーカー:makicamelさん(ITMONO)

私には程遠い話なんだろうなー🤔と思いながら聞いていましたが、
一連の流れは確かにいつもの開発と近いのかもしれないと感じました。

  • 新しいプロジェクトに関わるときと同じ。わからないことは調べればいい。
  • コンテキストがわからない場合は大変かも
  • rails/railsのIssueとかPRを毎日見てみる
  • 好きなリポジトリ見てみるのおすすめ

絶対に手戻りしない!時短勤務ママエンジニアの、要件ヒアリング力

スピーカー:ちょうかおりさん(Div)

エンジニアの仕事の本質は、問題の発見と解決であり、そのために背景を知ることの大切さについてのお話でした。

  • 納期は期待値のひとつとして考える
    • 背景を知ることが大切
  • 理想を正しく把握すること
    • なぜをきく(現状どうしてるとか)
    • 納期も一応きく
  • 依頼にある要望は氷山の一角かも
  • 時間で解決する以外の方法がある
  • ヒアリングしすぎて要望が増えた場合
    • 最初のリリースで様子みてもらう
    • マストじゃなければ様子みて改めて依頼してもらう

強いエンジニアという灯

スピーカー:大場寧子さん(万葉)

強いエンジニアとして居続けるためには、現場でエンジニアリングをし続ける必要がある。でも、色々な選択肢の中で強いエンジニアとは違うところにいる可能性もある。自分の大切にしたいものを信じていくことが大切と思ったお話でした。

  • 強いエンジニアとは
    • 技術を使った問題解決がうまい
    • 折れない心
    • 柔軟
    • 骨太
  • スキルを伸ばすための要素
    • 自分の頭で考える
      • クラッチでコードが書ける
      • 自分のアプリを開発する
    • 覚える
      • 覚えることは速さの根源
      • 調べる時間を短く、考える時間を増やす
      • メソッド名などの命名法則を考える
        • 名前づけの法則がわかれば暗記しなくても推測できるようになる
    • 信念を積み上げる
      • 性質や挙動をふわっと理解ではだめ
      • こう動くはずと信念を持つ
        • 確信があれば的を絞って調べられる
    • 自分のやったことを評価する
      • 振り返りを行う
        • うまくいったか
        • 失敗したところを考える
        • 成功した形を覚える
    • 失敗の芽を蓄える
      • 失敗したことがあると回避策が浮かぶ
      • 回避できるようになるからうまくいく
      • たくさん失敗できる環境に身を置こう
    • うまくいっている状態をパターン認識
      • うまくいっている状態と今の現実を比較する
      • レビューのときなどに応用すると
        • 書かれたコードに反応する
          • 行、メソッド、クラスといった部分を失敗の芽を潰すようにみる
          • 自分がうまくいくパターンと比較して違和感に気づく
        • 書かれるべきコードに気づく
          • 仕様や挙動の失敗の芽をさがす
          • うまくいくパターンと比較して必要なコードが欠けていないかを見る

最後に

今回始めての参加で、こんなに大きなイベントに参加するのも初めてで
緊張しつつ会場に向かいましたが、とても勉強になったし楽しめました!

最後に参加者全員で「はい、each✌️」で記念撮影して終了〜🎉
学習意欲が高まった勉強会でした😌🚀

【Ruby on Rails】Rspecを使ったテストの種類

f:id:mgmmy:20191202001931p:plain

Rspecを使ったテストの種類

全体的なテスト

システムテスト

E2E(End to End)テストに相当し、システム全体を通してテストを行うこと。
Webサービスの場合は、ユーザと同じようにブラウザを操作し、挙動が期待通りになっているかを確認する。

Rspecでの名称

  • System Spec

  • Feature Spec

結合テスト

色々な機能の連続が想定どおりに動くかを確認するテスト。
システムテストよりも内部的な確認ができる。

Rspecでの名称

  • Request Spec

機能テスト

結合したプログラムを1つの機能として行うテスト。
利用する頻度はそこまで多くない。

Rspecでの名称

  • Controller Spec

部品のテスト

モデルのテスト

検証やデータの制御、複雑なロジックの挙動などを個別のテストケースとして記述する。
小さい粒度のテストがかけるため、システムテストなどでは行いづらい、様々な条件下でのわずかな挙動の違いを確認するのに向いている。

Rspecでの名称

  • Model Spec

その他のテスト

他にも以下のようなSpecがある。
モデルほど頻度は高くないが、複雑なルーティングや、ほかのテストで置き換えづらいメーラーやジョブのテストは利用する場面がある。

  • Routing Spec

  • View Spec

  • Helper Spec

  • Mailer Spec

  • Job Spec

コメント

テストを書く機会が増えたので、テストの種類について調べてまとめてみた!
書く機会が多いのはFeature Specなので、他のテストについてはあまり書く機会がない…
学習も兼ねてSpecごとに掘り下げた記事も書きたいと思います 🤓

参考

書籍:現場で使える Ruby on Rails 5速習実践ガイド

【Ruby】『raise』意図的に例外を発生させる

f:id:mgmmy:20191130152416p:plain

意図的に例外を発生させる

概要

  • raiseメソッドを使用する
  • メソッドを実行するとRuntimeErrorが発生する
  • メソッドの引数に文字列を渡すと、その文字列がエラーメッセージになる。
    • 文字列は省略もできるが、原因が特定しづらくなるためあまり良くない。
  • 第1引数例外クラス第2引数文字列を渡すとRuntimeError以外の例外を発生させることができる。

使い方

引数に文字列のみを渡すと、RuntimeErrorが発生する。

def capital_of(country)
  case country
  when :japan
    'tokyo'
  when :china
    'beijing'
  when :france
    'paris'
  else
    raise "無効な国名です。#{country}"
  end
end

capital_of(:japan) # => "tokyo"
capital_of(:india) # => RuntimeError: 無効な国名です。india

例外クラスを指定することもできる

def capital_of(country)
  case country
  when :japan
    'tokyo'
  when :china
    'beijing'
  when :france
    'paris'
  else
    raise ArgumentError, "無効な国名です。#{country}"
  end
end

capital_of(:china) # => "beijing"
capital_of(:italy) # => ArgumentError: 無効な国名です。italy

文字列を省略することも可能だが、原因がわかりにくいため避ける。

def capital_of(country)
  case country
  when :japan
    'tokyo'
  when :china
    'beijing'
  when :france
    'paris'
  else
    raise
  end
end

capital_of(:japan) # => "tokyo"
capital_of(:germany) # => RuntimeError ※原因がわかりにくい!

コメント

実際に使用した場面は、特定の権限のユーザーがログインしたときの条件分岐で
何も当てはまらない場合に例外を起こすように実装を行った。

エラー原因がわかりにくいエラーメッセージが出ていたので、
エンジニアサイドで原因がすぐに理解できるようエラーメッセージを表示させた。

意図的に例外を発生させるってなんのためにやるのかイマイチわからなかったけど、
エラーが起きたときに、原因がわかるようにすることが目的だったのか〜😉