ディレクトリの操作

ディレクトリの操作

今回はターミナルにおけるディレクトリの操作についてまとめます。

pwd(Print Working Directory)コマンド

pwdコマンドはカレントディレクトリまでのパスを出力するコマンドです。

cd(Change Directory)コマンド

カレントディレクトリから移動する際に使うコマンドです。

mkdir(Make Directory)コマンド

ディレクトリを新たに作成する際に用いるコマンドです。

rmdir(Remove Directory)コマンド

ディレクトリを削除する際に用いるコマンドです。だたし、中身が空のディレクトリしか削除することができないため、中身があるディレクトリを削除したい場合は、rm -r ディレクトリ名とすると削除することができる。

特別なディレクト

.

.はカレントディレクトリを指す。

..

..は親ディレクトリ(一階層上のディレクトリ)を指す。

~

ホームディレクトリのことを指し、ユーザーの作業開始位置となるディレクトリです。ターミナルを立ち上げた直後はホームディレクトリにいる。

/

ルートディレクトリを指し、最上位階層を指す。

コマンドによるファイル操作

今回はコマンドを用いたファイルの操作についてまとめます。

ls(List)コマンド

lsコマンドはファイルやディレクトリを一覧で表示したいときに使うコマンドです。

オプション

-a:.で始まる隠しファイル等もすべて表示する。 -l:長(Long)形式で表示する。 -t:最終更新時間(Time)によってソートして表示する。 -r:逆順(Reverse)にソートして表示する。

cp(Copy)コマンド

cpコマンドはファイルを複製し、新しくできた複製ファイルのファイル名を指定することができるコマンドです。

書式

cp [オプション] コピー元 コピー先
オプション

-i:ファイルの内容を上書きする際に確認をしてくれるオプション。誤って上書きすることを防ぐことができる。 -r:ディレクトリのコピーをする。 -p:元のファイル情報を保持する。ファイルには所有者、属性、更新日時などの情報があるが、cpコマンドを実行すると全ての情報が新しくなる。新しい情報ではなく、古い情報を保持したままコピーしたいときに使う。

mv(Move)コマンド

mvコマンドはファイルを移動するときに使うコマンドです。

書式

mv 移動元ファイル 移動先ファイル

オプション

-i:ファイルの内容を上書きする際に確認をしてくれるオプション。誤って上書きすることを防ぐことができる。 -f:強制的に処理を実行するためのオプション。

rm(Remove)コマンド

rmコマンドはファイルを削除するときに使うコマンドです。

書式

rm ファイル名
オプション

-i:ファイルの内容を上書きする際に確認をしてくれるオプション。誤って上書きすることを防ぐことができる。 -f:強制的に処理を実行するためのオプション。 -r:ディレクトリを対象とする。このオプションを追加するとディレクトリを削除することができる。

ワイルドカード

*:任意の文字列を示し、この間に何文字が入っても検索対象として出力される。 ?:一個に付き、何らかの一文字を示す。

Linuxについて

Linuxについて

この記事ではLinuxの誕生や特徴について記述しています。

基本ソフトウェアと応用ソフトウェアについて

コンピュータはハードウェアとソフトウェアに分けることができます。また、ソフトウェアは基本ソフトウェアと応用ソフトウェアに分けることができます。基本ソフトウェアとは、OS(Operating System)のことでWindowsLinuxまたはMacOSなどが当てはまります。応用ソフトウェアとは、基本ソフトウェア上で動くアプリケーションのことをいい、ExcellやWordなどが当てはまります。

UNIX

Linuxの基になったのが、UNIXです。UNIXは米国の通信会社AT&Tのベル研究室で誕生しました。この会社はUNIXの設計に関する基本部分をそのまま配布していたため、手に入れたユーザーは自由に研究・開発をすることができました。その中で派生UNIXというものも誕生しました。

Linuxの誕生

1991年にフィンランドの大学生が自身で作っているOSを公開したことで開発が進みました。このOSに機能拡張やソフトウェア、ツールを組み合わせてLinuxが誕生しました。Linuxでは実質無料でかつ自由に利用、改変できるライセンス体系であるGPLというライセンス形式が採用されたため、より多くのユーザーに使われるようになり、発展していきました。

Linuxの特徴

ソフトウェアは基本ソフトウェアと応用ソフトウェアに分けることができるが、さらに基本ソフトウェアはカーネルユーザランドに分けることができます。カーネルとは、OSの中核となる部分でハードウェアと直接やり取りをします。対してユーザランドは、OSが動作するのに必要なカーネル以外の部分のことを指します。
Linuxは基本的にコマンドで操作します。その際、シェルという対話型のコマンド入力環境が用意されています。シェルには大きく2つの機能があります。1つは、コマンド入力を受け付けることです。もう1つは、シェルスクリプトを実行することです。シェルスクリプトとは、コマンドの入力を自動化するためのもので、1つのファイルに1行ずつコマンドを記述することで作成することができます。

ディストリビューション

Linuxはインストール作業が非常に困難だったため、様々な団体が簡単な手順で簡単にインストールできるようにしました。さらに、パッケージというものが登場しました。これは、応用ソフトウェアの実行をLinux上で行うにはソースをダウンロードして自らビルドしていたためにかかっていた手間と時間を省くためのものです。 また、1つの応用ソフトウェアの導入に複数の応用ソフトウェアやライブラリが必要になることもありました。その際、プログラムの依存関係を考慮し、それらを正しい場所に正しい順序でインストールする必要がありました。そこで、パッケージを簡単にインストールしたりアップデートするパッケージマネージャというものが標準で用意されるようになりました。今日のLinuxディストリビューションには何らかのパッケージマネージャが必ず用意されています。

Herokuへデプロイ

アプリケーションをHerokuへデプロイ

アプリケーションをHerokuへデプロイするための手順についてまとめていきます。

Herokuとは

Paasの一つでアプリケーションの公開、運用を行うためのサーバーを提供しているサービスのこと。基本機能だけの場合、無料で使うことができ、デプロイの手間が少なく容易であるというメリットがある。

Herokuへデプロイするための手順

Heroku CLIをインストールする

Herokuへデプロイするアプリケーションのディレクトリで以下を実行する。

brew tap heroku/brew && brew install heroku
heroku --version  # インストールが完了したか確認

Herokuへログインする

heroku login --interactive

EmailとPasswordを要求されるため入力する。

rails_12factoryの導入

rails_12factoryは静的アセットファイルやログの保存先をHeroku用に微調整してくれるGem。 Gemfileのgroup :production内にgem 'rails_12factory'を記述する。

Heroku上にアプリケーションを作成する

Herokuへデプロイするアプリケーションのディレクトリで以下を実行する。

heroku create アプリケーション名
git config --list | grep heroku  # 正しく設定されているか確認(fatal: not in a git directory以外が表示されれば良い。)

heroku createコマンドはHeroku上に公開するためのアプリケーションを作成することができるコマンド。続けてアプリケーション名を記述することで、Heroku上でのアプリケーション名を決めることができる。

Heroku上でMySQLを使えるようにする

アプリケーションをデプロイする前にDBの設定をしておく。HerokuではデフォルトでPostgreSQLというDBが設定されている。そのため、MySQLを使用できるようにするために以下のコマンドを実行する。

heroku addons:add cleardb
# このように出力されていると成功(WARNという警告が出てもそのまま進む)
Creating cleardb on ⬢ ajax-app-123456... free
Created cleardb-vertical-00000 as CLEARDB_DATABASE_URL
Use heroku addons:docs cleardb to view documentation

clearDBアドオンとは、MySQLを使うためのツール。これを追加することでHerokuでMySQLを使うことができるようになる。

設定を変更する

Railsを使う場合、MySQLに対するGemについて考慮する必要があるため、以下のコードを実行して設定を変更する。

heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`  # ClearDBのURLを変数heroku_cleardbに格納
heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}  # DBのURLの再設定

# 出力結果
Setting DATABASE_URL and restarting ⬢ ajax-app-123456... done, v◯◯
DATABASE_URL: mysql2://000000000000:0aa0000@us-cdbr-east-02.cleardb.com/heroku_aaa00000000?reconnect=true

Heroku上で環境変数を設定する

Heroku上で環境変数を設定するために以下のコードを実行する。

heroku config:set RAILS_MASTER_KEY=`cat config/master.key`
heroku config  # Heroku上の環境変数一覧を表示

アプリケーションをHerokuへpushする

以下のコマンドを実行し、Herokuへアプリケーションをpushする。

git push heroku master

Heroku上でマイグレーションファイルを実行する。

Heroku上のDBにはマイグレーションの情報が反映されていないため、以下のコマンドを実行する。

heroku run rails db:migrate

heroku runコマンドはHeroku上で実行したいコマンドに用いる。

公開を確認する

以下のコマンドを実行する。

heroku apps:info

heroku apps:infoコマンドはHerokuへデプロイされたアプリケーションの情報を見ることができる。ここに記述されているURLへアクセスすれば、公開したアプリケーションにアクセスすることができる。

デプロイ後のエラー対応方法

まず、エラーログを確認する。エラーログとは、アプリケーションなどのシステム実行時に発生したエラーを記録したもの。以下のコマンドを実行すると確認することができる。

heroku logs --tail --app <<アプリケーション名>>  # --tailはログの最後の10行だけを表示するためのオプション

Herokuへのデプロイを行ってみて

Heroku以外でもよくあるが、環境変数を設定し忘れて接続できないことがある。本番環境をAWSに置き換えたりするときにエラーが出たらまず環境変数を疑ってみる。
手順はたくさんあるが、焦らず一つずつやっていくことが大事。

CircleCIの導入!

ポートフォリオにCircleCIを導入した話

Dockerに続いてCircleCIを導入しました。具体的なコードと詰まったところについて記述するので、最後まで読んでください。

具体的なコード

version: 2.1

jobs:
  rubocop:
    docker:
      - image: circleci/ruby:2.6.5-node-browsers-legacy
        environment:
          RAILS_ENV: test
          MYSQL_HOST: 127.0.0.1
      - image: circleci/mysql:5.6.47
        environment:
          BUNDLER_VERSION: 2.1.4
          MYSQL_ARROW_EMPTY_PASSWORD: 'true'
          MYSQL_ROOT_HOST: '%'
    working_directory: ~/projects/reading_memo

    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock"}}
            - v1-dependencies-
      - run: gem install bundler -v 2.1.4
      - run: bundle install --jobs=4 --retry=3 --path vendor/bundle
      - run: yarn install
      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock"}}
      - run:
          name: Rubocop
          command: bundle exec rubocop 

  rspec:
    docker:
      - image: circleci/ruby:2.6.5-node-browsers-legacy
        environment:
            RAILS_ENV: test
            MYSQL_HOST: 127.0.0.1
      - image: circleci/mysql:5.6.47
        environment:
          BUNDLER_VERSION: 2.1.4
          MYSQL_ROOT_PASSWORD: password
          MYSQL_USER: root
          MYSQL_DB: reading_memo_test
    working_directory: ~/projects/reading_memo
    steps:
      - checkout
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "Gemfile.lock"}}
            - v1-dependencies-
      - run: gem install bundler -v 2.1.4
      - run: bundle install --jobs=4 --retry=3 --path vendor/bundle
      - run: yarn install
      - save_cache:
          paths:
            - ./vendor/bundle
          key: v1-dependencies-{{ checksum "Gemfile.lock"}}
      - run: bundle exec rake db:create
      - run: bundle exec rake db:schema:load
      - run:
          name: Rspec
          command: bundle exec rspec

workflows:
  version: 2
  rubocop_rspec:
    jobs:
      - rubocop
      - rspec:
          requires:
            - rubocop

発生したエラーと解決策

Could not find 'bundler' (2.1.4) required by your /home/circleci/projects/reading_memo/Gemfile.lock. (Gem::GemNotFoundException)

解決策

BUNDLER_VERSION: 2.1.4   # image: circleci/mysql:5.6.47のenvironmentのところに追加する(bundle2.0.1以上の場合bundle installに失敗するため、明示的に指定する必要がある)
- run: gem install bundler -v 2.1.4 # - run: bundle install --jobs=4 --retry=3 --path vendor/bundleの上に追加する

The following cops were added to RuboCop, but are not configured.

解決策

.rubocop.ymlにNewCops: enableを追加

AccessorMethodName(Rubocop)

解決策

メソッド名の先頭のsetやgetを消去する

l Can't connect to local MySQL server through socket

解決策

test:
  <<: *default
  database: reading_memo_test
  host: <%= ENV['MYSQL_HOST'] %>  # 追加

Can't connect to MySQL server on '127.0.0.1' (115)

解決策

environment:
  BUNDLER_VERSION: 2.1.4
  MYSQL_ROOT_PASSWORD: password  # 追加
  MYSQL_USER: root
  MYSQL_DB: reading_memo_test

CircleCIを導入してみて

2日ぐらいかかった。基本的なことを勉強してすぐにやったことが良かった。Dockerのときは参考書とか読みすぎた。
自動化はやっぱり気持ち良い。コードとかはまだ完全には理解していないからこれからその辺りを詰めていく必要がある。
とりあえず導入できてよかった。

Dockerの導入!

ポートフォリオにDockerを導入した話

今回、紙の本で読書をしたときのメモを整理するオリジナルアプリを作成しました。本番環境にAWSを導入したあとに開発環境にDockerを導入しました。この記事ではDockerを導入するために記述したコードとどこで詰まったのかについて述べていきます。

具体的なコード

#ベースイメージを取得
FROM ruby:2.6.5

#コンテナ内で必要なコマンドをインストール
RUN apt-get update && \
    apt-get install -y mariadb-client nodejs vim --no-install-recommends && \
    rm -rf /var/lib/apt/lists/*

#reaading_memoというディレクトリを作成して基点にする
RUN mkdir /reading_memo

WORKDIR /reading_memo

#Gemfileをコンテナにコピーし、bundle installを実行
ADD Gemfile /reading_memo/Gemfile
ADD Gemfile.lock /reading_memo/Gemfile.lock

RUN gem install bundler
RUN bundle install

#ローカルのディレクトリをコンテナにコピー
ADD . /reading_memo

ADDよりCOPYを使ったほうが良い。これはImageサイズとセキュリティの観点から言えることらしい。そのためADDをCOPYに変えて記述し直すつもりです。

version: '3.7'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    volumes:
      #データの永続化のために必要
      - mysql-data:/var/lib/mysql                                                               
    ports:
      - "4306:3306"

  app:
    #コンテナ上でbinding.pryするために必要
    tty: true                                                         
    #コンテナ上でbinding.pryするために必要                                         
    stdin_open: true                                                                                   
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      #ローカルのディレクトリをコンテナ上にマウント
      - .:/reading_memo          
      #bundle installした後buildし直す必要がなくなる                                                                  
      - bundle:/usr/local/bundle                                                                  
    ports:
      - "3000:3000"
    links:
      - db
    environment: 
      - AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
      - AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY

volumes:
  mysql-data:
  #bundle installした後buildし直す必要がなくなる
  bundle:                                                                                                    
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password
  socket: /tmp/mysql.sock

development:
  <<: *default
  database: reading_memo_development
  #作成したdbコンテナと接続するため(この記述がないとsocket通信でDBと接続してしまい、作成したdbコンテナの意味がなくなる)
  host: db

以下省略

passwordとusernameは任意

実行コマンド

docker-compose build 
docker-compose up -d
docker-compose exec app bundle exec rails db:create
docker-compose exec app bundle exec rails db:migrate

詰まったところ

コンテンを起動してからhttp://localhost:3000/に接続してもつながらない。

確証はないが、docker-compose exec web bundle exec rails db:createをターミナルで実行したら解決できたと思う。その他にもDockerfile、docker-compose.ymlまたはdatabase.ymlなどの記述を見直した。

データを保存できない

ターミナルでdocker-compose exec web bundle exec rails db:migrateを実行した。このコマンドを実行していなかったため、テーブルが作成されておらずエラーが出たと考えている。

環境変数を設定していない

画像を保存するときにAWSのS3に保存しているが、そこに保存するための環境変数をコンテナ内に持ち込んでいなかったことが原因。.envファイルに環境変数を記述し、解決した。

.envファイルをGitHubへのpush対象から外す

GitHubに変更を反映するためにpushしようとしたが、.envファイルはpushできないと表示された。そのため、.gitignoreに/.envを記述し対象外にしようとしたが、反映されなかった。そこで下記のコードを実行し、.gitignoreの内容が反映されるようにした。

git rm -r --cached .
git add .
git commit -m "コミット名"

開発環境にDockerを導入してみて

初めてのことだったので、結構時間がかかった。ほぼ一週間かかったかもしれない。ただ、今回やったおかげでDockerがどういうものか多少はわかった。得体の知れないものではなくなったことが何よりの収穫。これからも時間はかかるだろうが粘り強くやっていきたい。
今回まとめていて思ったが、エラーの内容とかはきっちりとメモとかにまとめておいたほうが良い。何をしてどんなエラーが出てどうやって解決したのかがあやふやになってしまいやすい。あと、何を書いたら良いのかわからず、集中力が低下しやすい。メモを習慣にするための仕組みを作っていきたい。

Dockerを使用して既存のRailsプロジェクト開発環境構築してみた(Rails+Mysql) - Qiita

既存のRailsアプリをDockerコンテナで動かす方法+sequel proによるDBコンテナ可視化 - Qiita

DockerfileにてなぜADDよりCOPYが望ましいのか - Qiita

Gitで.gitignoreを反映させる方法 | Awesome Blog

attr_accessorメソッドについて

attr_accessorメソッドとは

クラスにインスタンス変数を読み書きするためのアクセサメソッドを定義するメソッドのこと

使い方

class Car
  attr_accessor :name
end
class Car
  def name
    @name
  end
  def name(val)
    @name = val
  end
end

上記の2つのコードは同じことを意味している.

アクセスメソッドを定義するとインスタンス変数に外部からアクセスすることができる.

今日の気付き

インスタンス変数は同じクラス内に定義されたインスタンスメソッド内でも使えることは知っていたが, インスタンスメソッドも同じことができることは知らなかった.知らなかったため,理解するのに時間がかかった.

class Car
  attr_accessor :name

  def print_upcase
    puts name.upcase
  end

  def coppy
    print_upcase
  end
end

car = Car.new
car.name = "a"
car.print_upcase
car.coppy

=>
A
A

このように記述して実行しても,得たい結果を得ることができる.

自分で簡単なコードを書いて確かめてやっとわかった. 自分でやってみることが大事!