Linuxが注目されるようになった背景

 Linuxの歴史に関する情報を軽く整理しておきます。

 

 LinuxとはOSの一種です。コンピュータ本体のことをハードウェアといい、コンピュータが処理するプログラムやデータのことをソフトウェアと言います。その中でもOS(オペレーティングソフト)は基本ソフトウェアのことを指します。またアプリのことを応用ソフトウェアと言います。

 

 このLinuxが注目されるようになった根底には、「大型コンピュータを複数の人間で同時に共有したい」という願いがあります。

 

バッチ処理

 IBMがもともと作っていたコンピュータはバッチ処理」(一括処理)で動いていました。バッチ処理は、1日に何度でもではなく、1日の終わりに一気に全てのデータを処理するといったことです。コンピュータ的にはそれが効率良かったのですが、ユーザー的には問題でした。なぜなら1つの処理が終わるまで順番を待たなければいけないからです。

 

タイムシェアリング

 そこで考えられるようになったのが「タイムシェアリング」という複数の作業を同時に行う方法でした。飲食店で1組目の注文メニューを全て出し終えるまで、2組目に対応できなかったのが「バッチ処理」でしたが、「タイムシェアリング」は、4組のお客さんにもバランスよく注文を届けられるようになるといったイメージです。

 

MULTICS

 このタイムシェアリングの思想に基づいて最初に作られたOSがMULTICSでした。しかしこのMULTICSは、複数のユーザーが同時に使えるようにするといったことで生じる情報漏洩の問題に対処するために、厳重なセキュリティの仕組みを組み込んでいました。このことによって実用に耐えない処理速度となり、あまり使われなかったのです。

 

UNIX

 そこで、セキュリティ機構を取り外して仲間内だけで使われ始めたのがUNIXでした。これがやがて全米に広がっていったのです。このUNIXは、パソコンではなく、ワーク・ステーションと呼ばれる高性能・高価格のコンピュータで主に使われていました。

 

Linux

 しかしパソコンの性能が向上し、ワーク・ステーションとの境界線が消えつつありました。そうした中で、パソコン用UNIXとして開発されたのがLinuxでした。このLinuxはただのパソコン用UNIXではなく、2つの特徴を持っていたことによってインターネットの中で成長するOSとなりました。その2つの特徴とは「フリー」「オープン」です。フリーとは無料で使用できることであり、オープンとはプログラムの中身が公開されていることです。このことによってプログラムに自信のある人たちが、タダで手に入れたLinuxに手を加えて、より安定して使いやすいものに改良することが増えたのです。

 

 これらの情報を整理するにあたって以下の書籍を参考にしました。

坂村健『痛快! コンピュータ学』(集英社文庫、2016年)

 

 

 

JavaScriptのdocumentオブジェクトとは?

 JavaScriptのdocumentオブジェクトに関わる知識をまとめていきます。

 

documentオブジェクトとは

 ブラウザで表示された情報(HTML)を操作することができる「オブジェクト」です。HTMLに対して何かしらの処理をする際に頻繁に利用します。

 

JavaScriptのオブジェクトとは

 JavaScriptのオブジェクトとは「データ」「処理」をひとまとめにした「集合体」です。例えば「採取される」、「食べられる」といった処理が行われる「りんご」は、「果物」として1括りにまとめることができます。この果物がオブジェクトになります。

 

オブジェクト内のデータとは

 「果物」の中でも、「りんご」や「バナナ」といったものは「データ」です。またデータは「キー」と「バリュー」がセットになったものを指し、これを「プロパティ」と言います。りんごというデータで例えるなら、「色が赤い」、「形が丸い」といった特徴の部分が「プロパティ」です。そして「色」や「形」が「キー」であり、「赤い」や「丸い」といった部分が「バリュー」になります。

 

オブジェクト内の処理とは

 「果物」の中でも「採取される」、「食べられる」といったことは「処理」です。オブジェクトが「車」の場合は、「走行する」、「止まる」といったことも処理です。こういったプロパティに紐付けられた処理のことを「メソッド」と言います。このメソッドの操作は、functionといった関数を用いることで実現できます。

 

JavaScriptとは

 ブラウザで動くプログラミング言語です。

 

JavaScriptで定義済みのオブジェクト

 JavaScriptにはあらかじめ「windowオブジェクト」をはじめとしたオブジェクトが定義されています。このwindowオブジェクトの「プロパティ」の中に「consoleオブジェクト」や「documentオブジェクト」があります。

 

DOM(Document Object Model)とは

 単なる文字情報である、HTMLをユーザーが閲覧できる状態にするまでの「仕組み」です。この作業はGoogle ChromeSafariといったブラウザが行います。ブラウザ内でHTMLが解析されてDOMに変換されたのち、JavaScriptCSSが読み込まれて、ユーザーが閲覧できる状態になります。

 

DOMツリー(ドキュメントツリー)とは

 「階層構造になったデータ」です。これはDOMによって解析されたHTMLのことです。<body>の中に<header>があるといった入れ子構造が、わかりやすく整理された状態になることです。

 document.getElementById("id名")のようなJavaScriptのメソッドは、このDOMツリー状態になったHTMLを操作するメソッドです。

 

 

 

 

 

 

 

AWSで使う用語の説明①

 AWSの理解を深める目的でAWSに関連する知識を整理してみました。あくまでも自己満足ですし、まだ勉強不足であるため解釈に間違いがある可能性もあります。今回整理する知識は以下のものです。

 

  1. EC2インスタンス
  2. AMI
  3. キーペア
  4. パブリックIP
  5. Elastic IP
  6. ssh
  7. プロトコルのレイヤー
  8. ポート
  9. セキュリティグループ
  10. インスタンスのログイン方法
  11. yumコマンド
  12. Node.js
  13. Yarn
  14. EC2でRubyを使えるようにする

 

 

1. EC2インスタンス

 EC2インスタンスとは仮想マシンです。AWSがこのソフトウェアを利用して、仮想的に1つのLinuxサーバーを利用できる仕組みを使えるようにします。

 

2. AMI(Amazon Machine Image)

 AMIとはサーバーのデータを丸ごと保存した「データ」のことです。この中には事前にインストールされた「OS」があるため、自分で1からインストールしなくても済みます。インスタンス起動時に「Amazon Linux 2 AMI」といったAMIを選択できます。

 

3. キーペア

 インスタンスへログインする際に必要となる秘密鍵のことです。

 

4. パブリックIP

 「EC2インスタンス」作成時に自動で割り振られるIPアドレスです。このパブリックIPはサーバーを再起動させるたびに変わってしまいます。

 

5. Elastic IP

 サーバーを再起動させるたびにパブリックIPが変わってしまうという問題を解決する、AWSから割り振られる「固定のパブリックIPアドレスのことです。このElastic IPをEC2インスタンスに紐づけることで、インスタンスの起動や停止に関係なく同じIPアドレスで通信ができます。

 

6. ssh(Secure Shell)

 EC2インスタンスにアクセスするための「通信手段」です。暗号や認証の技術を利用して、離れた場所にあるリモートサーバーと安全に通信できます。しかしアプリケーション層のHTTPのように他の接続は一切つながりません。

 

7. プロトコルのレイヤー

 アプリケーション層のHTTPと言いましたが、このHTTPとは、通信の「ルール」であるプロトコルの一種であり、このプロトコルの種類は階層ごとに分類されています。過去の記事でも言及しました。

kim-shun.hatenablog.com

 ではこのプロトコルの階層構造をもう少し詳しく説明します。最も上層部にアプリケーション層(レイヤー4)があり、その下にトランスポート層(レイヤー3)、さらにその下にインターネット層(レイヤー2)、そして最下部にネットワークインターフェース層(レイヤー1)があります。

 そしてアプリケーション層にHTTPSMTPFTPなどのプロトコルがあり、トランスポート層TCPUDPインターネット層にIP、ICMP、ネットワークインターフェース層にWi-Fiイーサネットなどがあります。

 アプリケーション層はアプリごとの役割を規定し、トランスポート層はデータの分割や品質保証を規定します。そしてインターネット層はネットワーク間の通信を規定し、ネットワークインターフェース層は、コネクタ形状や周波数といったハードウェアに関する規定をします。

 

8. ポート

 「ssh」で「EC2インスタンス」にアクセスする際に、EC2インスタンスがHTTPと繋がるように開放する必要がある「仕組み」です。IPアドレスを住所の番地に例えた際に、部屋番号に該当するのがポート番号であり、このポート番号は「0~65535」まで使用できます。リクエスト時にこのポート番号を指定することで1つのサーバーとクライアントが繋がります。

 

9. セキュリティグループ

 EC2インスタンスが属する「まとまり」です。このセキュリティグループで複数のEC2インスタンスのネットワーク設定を一括で行うことができます。またこのセキュリティグループでポートの設定を行います。

 設定時に出てくる「0.0.0.0」や「::/0」は「全てのアクセスを許可する」という意味です。

 

10. インスタンスのログイン方法

 EC2インスタンスを作成すると「ec2ユーザー」というユーザーと対応する「ssh秘密鍵」が生成されます。このec2ユーザーを使ってログインする方法は下記のコマンドを実行することです。

 

ターミナル

% cd ~
% mkdir ~/.ssh
% mv Downloads/鍵の名前.pem .ssh/
% cd .ssh/
% chmod 600 鍵の名前.pem
% ssh -i 鍵の名前.pem ec2-user@Elastic IP
% ssh -i aws_key.pem ec2-user@52.68.~~~~~~

 「.ssh」というディレクトリを作成し、ダウンロードしたpemファイルを.sshディレクトリに移動させます。そして最後の行のssh接続を実行した場合は「yes」と入力してログインが完了します。

 

11. yumコマンド

 yumコマンドとは、サーバに元々あるプログラムをアップデートできる、Linuxにおけるソフトウェア管理の「仕組み」です。MacOSにとってのHomebrewと同じ役割を果たす、「パッケージ」と言えます。パッケージとは、LinuxOS下における、ある機能を持った「プログラムの集合」のことです。

 以下のようなコマンドを実行してパッケージをアップデートできます。

 

ターミナル

[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y update
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install git make gcc-c++ patch
libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel
libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel libcurl
libcurl-devel curl

 このyumコマンドの中で使われている「-y」はyumコマンドのオプションです。このオプションをつけることで、全ての問いに「Yes」と自動的に答える設定ができます。

 

12. Node.js

 Node.jsとは、本来ブラウザで動くはずのJavaScriptをサーバーサイドで動かす「パッケージ」のことです。

 

ターミナル

[ec2-user@ip-172-31-25-189 ~]$ sudo curl -sL https://rpm.nodesource.com/setup_10.x |
sudo bash -
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install nodejs

 このようなコマンドでEC2にNode.jsをインストールできます。

 

13. Yarn

 Railsに搭載されているJavaScriptのパッケージを管理するための「パッケージマネージャー」です。

 

ターミナル

[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install wget
[ec2-user@ip-172-31-25-189 ~]$ sudo wget https://dl.yarnpkg.com/rpm/yarn.repo -O
/etc/yum.repos.d/yarn.repo
[ec2-user@ip-172-31-25-189 ~]$ sudo yum -y install yarn

 このようなコマンドでEC2にYarnをインストールできます。

 

14. EC2でRubyを使えるようにする

 以下のようなコマンドでRubyのバージョンを管理するツールとRubyをEC2にインストールできます。

ターミナル

[ec2-user@ip-172-31-25-189 ~]$ git clone https://github.com/sstephenson/rbenv.git ~/
.rbenv
[ec2-user@ip-172-31-25-189 ~]$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >>
~/.bash_profile
[ec2-user@ip-172-31-25-189 ~]$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
[ec2-user@ip-172-31-25-189 ~]$ source .bash_profile
[ec2-user@ip-172-31-25-189 ~]$ git clone https://github.com/sstephenson/ruby-build.git
~/.rbenv/plugins/ruby-build
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash
[ec2-user@ip-172-31-25-189 ~]$ rbenv install 2.6.5
[ec2-user@ip-172-31-25-189 ~]$ rbenv global 2.6.5
[ec2-user@ip-172-31-25-189 ~]$ rbenv rehash
[ec2-user@ip-172-31-25-189 ~]$ ruby -v

 これらのコマンドで、gitからクローンした「rbenv」や「ruby-build」といったRubyのバージョン管理ツールをインストールしています。また「パスを通す」作業もしています。PATHとは、複数の絶対パスの情報が保存されている環境変数のことです。パスを通すとは、どのディレクトリからでもアプリを呼び出せる状態にすることです。

 「source .bash_profile」は設定したパスを読み込むことであり、「rbenv rehash」は、使用しているRubyのコマンドで、gemのコマンドを使えるようにするためのコマンドです。

 またこのコマンドではRubyの「2.6.5」をインストールしています。

 

 

以上です。

 

 

 

 

 

 

 

 

Qiitaに移行します

 はてなブログで記事を書いていくときにコードのインデントが整わずに読みづらいという問題が発生していました。マークダウン記法にすれば良かった話なのですが、コードを用いる記事に関してはQiitaに移行していくことにしました。

 

qiita.com

 今日からQiitaでも随時記事を投稿していきます。

 

 

コマンドの仕組みと管理ツール

 環境構築の時に実行するコマンドの仕組みや、インストールできるソフトウェアの仕組みについてまとめておきます。

 

ターミナルでコマンドを実行できる理由

 ターミナルでコマンドを実行できる理由は、「シェル」が、ターミナルから入力されたコマンドを読み取ってOSに指示を出しているからです。シェルはターミナルとOSを繋ぐ役割を果たす存在であり、2019年にmacOSの標準シェルが「zsh」(ズィーシェル)となりました。

 またシェルはコマンドが入力された時に「PATH」に記述されたパスのディレクトリ内のファイルを検索します。PATHとは、OS用の変数である「環境変数」のことを指します。このPATHに複数の絶対パスの情報が保存されています。

 

コマンドを追加したいときは?

 OSは指示を受けてコマンドに合ったアプリケーションを動作させますが、全てのアプリが動くわけではありません。OSに初めから入っていないアプリを動かしたい場合はコマンドラインツール」を使います。

 コマンドラインツールとは、コマンドで操作するアプリケーションのまとまりのことです。これを導入すれば、コマンドで操作できるアプリを増やせます。gitコマンドでGitを操作できるのもコマンドラインツールのインストールのおかげです。

 

依存関係を解消させる方法

 あるファイルを正常に動作させるためにはそのファイルに紐づいた別のファイルの処理が必要になる場合があります。これを依存関係と言います。そして、1つのファイルだけバージョンが更新されることによって、期待した動作が得られないという問題が発生する場合があります。このような問題を解決する方法が「パッケージ管理ツール」にあります。

 macOSのパッケージ管理ツールとして「Homebrew」があります。macOSで動作するアプリの多くがHomebrewからインストールできます。これによって複数のパッケージのバージョンをコントロールできます。

 環境構築時にHomebrewを用いてインストールできるものに「Node.js」があります。Node.jsは本来ブラウザで動作するJavaScriptをサーバーサイドで動作させる「実行環境」のことです。Node.jsのインストールによってサーバーサイドで利用できるJavaScriptのパッケージを活用できます。さらにこのNode.jsの環境上でのパッケージを管理するツールのことを「Yarn」と言います。環境構築時にHomebrewを使ってYarnをインストールできます。

 またプロジェクトや言語のバージョンを管理する「バージョン管理ツール」として「rbenv」があります。これはRubyのバージョンを切り替えられるものであり、Homebrewでインストールできます。

 

 

 

 

 

 

 

 

 

 

 

 

クラスとインスタンスのメソッド

 クラスとインスタンスに関するメソッドについて説明したいと思います。

kim-shun.hatenablog.com

 過去に記事にした通り、クラスとは「設計図」のことであり、インスタンスとは「設計図」の中で使う「データ」のことです。今回説明するのはその中で登場する具体的なメソッドです。

 

  1. クラスメソッド「self」
  2. インスタンス変数とローカル変数
  3. initializeメソッド

 

 以上の流れで説明していきます。

 

1. クラスメソッド「self」

 クラスが使用できるメソッドには「new」の他に「self」があります。下記のような記述で「こちらの車を販売しています」という文字列を出力させることができます。クラスメソッドはクラスで共通の情報を使った処理に使用します。

class Car
def self.sell
puts "こちらの車を販売しています"
end
end

Car.sell

 実行結果は以下の通りです。

こちらの車を販売しています

 

 

2. インスタンス変数とローカル変数

 下記のコードを実行するとエラーが起きます。なぜなら、car_name、car_priceという変数を複数のインスタンスメソッド内で使用しているからです。このcar_nameやcar_priceのように頭文字に何もついていない変数のことを「ローカル変数」と言います。ローカル変数は、記述しているインスタンスメソッド内でしか使えません。

class Car

def self.sell
puts "こちらの車を販売しています"
end

def initialize(name, price)
car_name = name
car_price = price
end
 
def introduce
puts "#{car_name}#{car_price}円です"
end
end

Car.sell

tanto = Car.new("タント", 5000000)
n_box = Car.new("N-BOX", 6000000)
hustler = Car.new("ハスラー", 7000000)

tanto.introduce
n_box.introduce
hustler.introduce

 このエラーを解消する方法が、インスタンス変数の使用です。インスタンス変数であれば、別のインスタンスメソッド内でも使用できます。

class Car

def self.sell
puts "こちらの車を販売しています"
end

def initialize(name, price)
@car_name = name
@car_price = price
end
 
def introduce
puts "#{@car_name}#{@car_price}円です"
end
end

Car.sell

tanto = Car.new("タント", 5000000)
n_box = Car.new("N-BOX", 6000000)
hustler = Car.new("ハスラー", 7000000)

tanto.introduce
n_box.introduce
hustler.introduce

 インスタンス変数とは頭文字に「@」がついた変数です。car_name、car_priceに「@」をつけることでエラーは解消されます。実行結果は以下の通りです。

こちらの車を販売しています
タントは5000000円です
N-BOXは6000000円です
ハスラーは7000000円です

 

 

 

3. initializeメソッド

 initializeメソッドとは、インスタンスが生成されるタイミングで呼び出されるメソッドです。Rubyのクラスから生成されるインスタンスでは、initializeメソッドは自動的に実行されています。インスタンス生成時に新たに処理を追加したい場合にこのinitializeメソッドを定義します。

 

class Car
def initialize
puts "こちらの車を販売しています"
end
end

Car.new

 「Car.new」の記述だけで下記の文字列が出力されます。

こちらの車を販売しています

 

 

 では今度は著者、記事タイトル、本文の情報を扱うArticleクラスでinitializeメソッドを使ってみます。

class Article
def author(author)
author
end

def title(title)
title
end

def content(content)
content
end
end

article = Article.new
puts article.author("田中")
puts article.title("今日の天気")
puts article.content("晴れ")

 この上記のコードでinitializeメソッドを用いると下記のようになります。

class Article

def initialize(author, title, content)
@author = author
@title = title
@content = content
end

def author
@author
end

def title
@title
end

def content
@content
end

end

article = Article.new("高橋", "今日の天気", "晴れ")
puts article.author
puts article.title
puts article.content

 このようにすることで、著者、記事タイトル、本文の処理の定義がインスタンス生成と同時に実行されるようになります。さらにそれらをそれぞれインスタンス変数に代入することで複数のインスタンスメソッド内で使用可能となります。

def author
@author
end

def title
@title
end

def content
@content
end

 この記述はただインスタンス変数の値を返すためだけのメソッドです。

 

 

 以上です。クラスとインスタンスに関しては自分の中でもう少し理解が深まった時に再度記事にしていきたいと思います。

 

 

 

 

 

 

 

 

配列の入子構造を紐解く

 配列の入れ子構造を紐解いていきたいと思います。これからこちらのデータを使っていきたいと思います。

vegetables_price = [["cabbage", [200, 100, 320]], ["onion", [100, 210, 80]],
["carrots", [120, 150]]]

 ここからそれぞれの野菜の合計金額を算出してみたいと思います。

 

  1. each文を使ってみる
  2. 添字を利用してみる
  3. vegetable[1]で繰り返し処理をする

 以上の流れで説明していきます。

 

 

1. each文を使ってみる

 まずeach文を使って全ての情報を表示できるようにしてみました。

vegetables_price.each do |vegetable|
puts vegetable
end

 上記のコードを実行すると実行結果は以下のようになりました。

cabbage
200
100
320
onion
100
210
80
carrots
120
150

 

2. 添字を利用してみる

 ここからさらに取り出す値を絞るために配列の中の配列の添字を指定してみました。

vegetables_price.each do |vegetable|
puts vegetable[0]
end

 vegetable[0]とすると全ての野菜だけが出力されます。

cabbage
onion
carrots

 今度はvegetable[1]にしてみました。

vegetables_price.each do |vegetable|
puts vegetable[1]
end

 すると価格が全て表示されました。このvegetable[1]が使えそうです。

200
100
320
100
210
80
120
150

 

3. vegetable[1]で繰り返し処理をする

 今度はさらにこのvegetable[1]の中身を区別できるようにしたいと思います。vegetable[1]の中身は上記で示しています。野菜ごとに分けて合計金額を算出するためにeach文を使ってみることにしました。

vegetables_price.each do |vegetable|
sum = 0
vegetable[1].each do |price|
sum += price
end
puts sum
end

 これで各野菜の合計金額が算出されました。

620
390
270

 またどの野菜の合計金額がどれかが分かるように野菜の名前も出力されるようにしました。

vegetables_price = [["cabbage", [200, 100, 320]], ["onion", [100, 210, 80]],
["carrots", [120, 150]]]

vegetables_price.each do |vegetable|
sum = 0
vegetable[1].each do |price|
sum += price
end
puts "#{vegetable[0]}の合計金額は#{sum}です"
end

 これで出力結果は以下のようになりました。

cabbageの合計金額は620です
onionの合計金額は390です
carrotsの合計金額は270です

 

 

 

 

以上です。