XcodeをGitHub連携する

最近Udemyでこちらの講座を受講し始めました。

www.udemy.com

アウトプット用に自分でも何か作らないとなぁと思い、ひとまずXcodeGitHubの連携を行いました。

動作環境

macOS Monterey 12.4
Git 2.32.1
Xcode 13.4.1

1. ローカルリポジトリ作成

①新規プロジェクトを作成

「Create a new Xcode project」をクリック

どのようなアプリケーションを作成するのかを選びます。
今回は特に何もいじらずに「Next」

「Product Name」を入力して「Next」
今回は「GitSample」としました。

次にプロジェクトの保管場所を聞かれるので、好きな場所を指定して「Create」を選択してください。 この時「Create Git repository on my Mac」にチェックを入れるとXcodeが自動でローカルリポジトリを作成してくれます。

XcodeにGitの設定をする

初期状態だとローカルリポジトリの作成に失敗してしまうので、「Fix...」を選んでGitの設定をしましょう。

Author NameとAuthor EmailにそれぞれGitHubのユーザー名、GitHubに登録したメールアドレスを入力します。 他はお好みで設定してください。

こちらの設定は「Xcode > Preferences > Source Control > Git」から行うこともできます。

③ローカルリポジトリ作成

ここまで行うとローカルリポジトリの作成ができるようになるので、作成していきましょう。 「Source Control」から「New Git Repositories...」を選択します。

「Create」を選択するとローカルリポジトリが作成されます。

④ローカルリポジトリが作成されているか確認

「Show the Source Control navigator」を選択して、「Repositories」のところに画像のように表示されていればローカルリポジトリが作成できています。

2. .gitignoreを追加

①.gitignoreファイルを追加

まず「Show the Project navigator」をクリックします。そして画像のようにプロジェクトネームを右クリックし、「New File...」を選択してください。

下の方からEmptyを選んで「Next」

「Save As」のところに「.gitignore」と入力して「Create」

画像のような警告が表示されると思うので、「Use "."」を選択しましょう。

これで.gitignoreファイルが作成されるので、開いて中身を編集しましょう。 私はこちらに記載されているものを使わせていただきました。

qiita.com

.gitignoreを編集できたら一度コミットしておきましょう。 「Source Control > Commit...」を選択してください。

下の画像のような画面が表示されるので、コミットメッセージを入力してコミットしてください。

②既にコミットされてしまっているファイルをgitignoreの対象に含める

おそらくローカルリポジトリを作成した段階でこんな感じでInitial Commitが作成されていると思います。

そのため.gitignoreに設定を追加しただけではignoreされないので、ターミナルから下記コマンドを実行しましょう。

$ cd [プロジェクトが保存されているディレクトリ]
$ git rm -r --cached .
$ git add .

git rm -r --cached .で一時的に全てのファイルをgitの対象から外すことができます。
その後にgit add .とすることで、.gitignoreで指定したファイルのみを除外することができます。

この状態で下記コマンドを実行することで、先ほど.gitignoreを追加した際のコミットに変更を追加できます。

$ git commit --amend --no-edit

これで.gitignoreの追加は完了です。

3. リモートリポジトリ作成

GitHubアカウントと連携

リモートリポジトリを作成するにはGitHubのアカウントと連携する必要があります。
その際にアカウント名とトークンを要求されるので、まずはGitHubトークンを取得しましょう。

右上から「Settings」を選択

下の方の「Developer Settings」をクリック

「Personal access tokens」から「Generate new token」をクリック

「Note」にはわかりやすい名前などを入力し、「Expiration」は「No expiration」を選択します。
「Select scopes」は「repo」にチェックを入れてください。「repo」を選択しないとリモートリポジトリへのpushなどができなくなります。

「Generate token」をクリックするとトークンが表示されるのでテキストエディターなどにコピーしておきましょう。

次にXcodeの方でアカウントを追加していきます。 「Xcode > Preferences > Accounts」からアカウントを追加しましょう。「+」をクリックしてください。

GitHub」を選択して「Continue」をクリックします。

GitHubのアカウント名と先ほど取得したトークンを入力して「Sign in」をクリックします。

うまくサインインができればGitHubアカウントとの連携は完了です。

②リモートリポジトリを作成

まずはローカルリポジトリが作成されているか確認した時と同じように「Show the Source Control navigator」をクリックして「Repositories」を選択してください。
その中のプロジェクトネームを右クリックして、「New "[Project Name]" Remote」を選択します。

「Create」をクリックするとリモートリポジトリが作成されます。

画像のように「origin」と表示されていればリモートリポジトリ作成成功です。

うまくいけばこれでリモートリポジトリへのpushまで行われるかと思います。

以上でXcodeGitHubの連携は完了です。お疲れさまでした。

【Java】例外が発生しないメソッド = 万能とは限らない

Javaでオブジェクトを文字列に変換する方法ってたくさんありますよね。toString()とかString.valueOf()とか。中でもObjects.toString()は例外も発生しないし、nullだった場合の値を自分で決められるし最強じゃんと思っていたのですが、何でもかんでもObjects.toString()を使えばいいと言うわけではないことに気がつきました。

オブジェクト → 文字列変換メソッドの違いについておさらい

それぞれのメソッドの主な違いはnullだった場合の動作です。

  • 例外が発生するtoString()
Object obj = null;
obj.toString();  // NullPointerExceptionが発生
  • 例外が発生しないString.valueOf
Object obj = null;
String.valueOf(obj);  // "null"と言う文字列が返る
  • 例外が発生しないかつnullの時の値を自分で決められるObjects.toString()
Object obj = null;
Objects.toString(obj); // "null"と言う文字列が返る
Objects.toString(obj, "存在しません");  // 第二引数に指定した"存在しません"が返る

Objects.toString()使っとけばOKなの?

一見便利そうなObjects.toString()。実際Javaを使い慣れていない私は、とりあえず文字列に変換するときはObjects.toString()を使っておけば安心なんだなと感じました。

ですが! だからと言って何でもかんでもObjects.toString()を使えばいいと言うわけではありません。

そもそもnullを許容できない場合がある

DB保存するときにその値にNOT NULL制約が指定されている場合とか、APIにリクエスト送信するのに必須値になっている場合はnullを許容できないですよね。そう言う場合って、外部からリクエストを受ける際に何らかの方法でnullチェックを行うと思います。 Spring Bootだったら@NotNullアノテーションを付けたり。 その状態でいざ文字列に変換しようと言う時にnullが入っている場合、考えられる状況は変換する前の処理で実装ミスがあるか予期せぬ不具合ぐらいしかないと思います。この場合ぬるぽが発生してくれた方がありがたくないでしょうか?

nullを許容できない場合はtoString()で問題ない

nullを許容できない場合はそもそもそこでnullになっていること自体がおかしいので、Objects.toString()を使う必要はありません。むしろ、nullをスルーしてしまう上に、変な値を入れてしまうことになるので使わない方がいいです。ぬるぽが発生すれば実装ミスにいち早く気づけますし、catchしてログを出力することもできます。 なので、こう言う場合はぬるぽを恐れずにどんどんtoString()を使っていきましょう。

まとめ

今までぬるぽを発生させるような実装をしてはいけない、と言う言葉を鵜呑みにして、とりあえずぬるぽが発生しないメソッドを選びがちでしたが、本質に気付くことができたような気がします。何事も馬鹿の一つ覚えにならないように気をつけていきたいですね。

MySQLを8.0にアップデートするのに紆余曲折あった

先日MySQLを5.6から8.0にアップデートしたら、2つほど苦労がありました。

1つめは、MySQLがアップデートされない!  ← ただの凡ミス
2つめは、Sequel Proがクラッシュするようになった!

です。
1つめはまぁ置いといて、Sequel Pro使いにとって2つめは結構困りますよねぇ・・・。

でも、なんとかSequel ProでDB見れる方法があったので、そのお話です。

まずはMySQLをアップデート

前提として、MySQLはHomebrewを使ってインストールしてあります。
HomebrewでインストールしたMySQLのアップデートは以下の手順でできるようです。

$ brew update
$ brew upgrade mysql

ただ私の場合ここでbrew updateし忘れてしまったので、うまくいきませんでした。
通常なら、この後はテーブルのアップグレードを行って終了のようです。

$ sudo mysql_upgrade -u root -p

 これでパスワードの入力を求められたら入力して、Upgrade process completed successfully.と表示されたらOKなようです。

私の場合はbrew updateし忘れたことに気づかずに、MySQLを再インストールしてしまいました・・・。

Sequel Proがクラッシュするようになった!

MySQLを8.0にバージョンアップしてしまうと、Sequel Proが使えなくなります。
というか、Sequel ProがMySQL8.0に対応していないようです。

ですが、調べてみると、Sequel Pro NightlyというSequel Proのテスト版を入れるとMySQL8.0にも対応しているとのこと。
なので、Sequel Proを一度アンインストールして、Sequel Pro Nightlyをインストールしてみました。

公式サイトからダウンロードする場合はこちら↓
https://sequelpro.com/test-builds

Homebrewでインストールする場合はこちら↓

$ brew cask install homebrew/cask-versions/sequel-pro-nightly

これで無事にSequel ProでDBを見れるようになりました。

ちなみにSequel Pro Nightlyはあくまでテスト版なので、どうしてもSequel Proがいい!という方以外は別のツールに乗り換えてしまった方が今後楽かもしれませんね・・・。

git rebase -i でコミットをまとめる

実務でgit rebase -i を使う必要がありそうだったので、予習のために使ってみました。

シチュエーション

  • リモートにpush済み
  • コードレビューをしてもらった後に修正コミットがたくさんできている

この状況でコミットをまとめていきます。
ただ、リモートにpush済みのコミットをgit rebase -iでまとめるのは本来NGです。しかし、自分が作業をしているブランチが「絶対に自分しかいじらない」のであればコミットをまとめても大丈夫な場合があります。例えば私の職場では、コードレビュー後にコミットを1つにまとめるという文化がありますが、コミットをまとめないで欲しいというところもあるようです。コミットをまとめたいと思った時は、チームに確認してからにしましょう。

それでは、実際にやっていきたいと思います。

コミットlogを確認

まずはコミットlogを確認します。

$ git log --oneline

2fd949a (HEAD -> create_list, origin/create_list) リスト1を修正
968362c リスト2を修正
d196455 リスト1、リスト2を作成
f6bd217 (origin/title) titleを記載

「リスト2を修正」と「リスト1を修正」が修正コミットです。この2つの修正コミットと「リスト1、リスト2を作成」を1つにまとめます。

git rebase -i でまとめたいコミットを指定

git rebase -i でまとめたいコミットを指定します。その際二つの指定方法があるので紹介します。

git rebase -i HEAD~<数字>

数字の部分にはまとめたいコミットの数を指定します。今回であれば3つのコミットをまとめたいので、3を指定します。

$ git rebase -i HEAD~3
git rebase -i <コミットのハッシュ値>

こちらはコミットのハッシュ値を指定します。しかし、この指定方法には少し癖があります。HEADを使って指定する場合は「まとめたいコミットの数」とわかりやすいですが、コミットのハッシュ値を指定する場合は「まとめたいコミットの一つ前のハッシュ値」を指定します。例えば今回の場合だと、「リスト1を修正」〜「リスト1、リスト2を作成」までをまとめたいので、その前のコミットである「titleを記載」のハッシュ値を指定します。

$ git rebase -i f6bd217

git rebase -i を実行してコミットをまとめる

git rebase -i を実行します。

$ git rebase -i HEAD~3  もしくは  git rabase -i f6bd217

すると、以下のようにエディタが起動します。

pick d196455 リスト1、リスト2を作成
pick 968362c リスト2を修正
pick d196455 リスト1を修正 # Rebase 3c1cd16..d196455 onto 3c1cd16 (3 commands) # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue') # d, drop <commit> = remove commit # l, label <label> = label current HEAD with a name # t, reset <label> = reset HEAD to a label # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] # . create a merge commit using the original merge commit's # . message (or the oneline, if no original merge commit was # . specified). Use -c <commit> to reword the commit message. # # These lines can be re-ordered; they are executed from top to botto

インサートモードに切り替えて、修正コミットの「pick」を「s」に変更・保存します。エディタにも書いてありますが、この「s」はsquashのsです。

pick d196455 リスト1、リスト2を作成
s 968362c リスト2を修正    ⬅︎ 変更
s d196455 リスト1を修正    ⬅︎ 変更

# Rebase 3c1cd16..d196455 onto 3c1cd16 (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to botto

するとコミットメッセージを編集するためのエディタが開きます。

# This is a combination of 3 commits.
# This is the 1st commit message:

リスト1、リスト2を作成 # This is the commit message #2:

リスト2を修正 # This is the commit message #3:

リスト1を修正 # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Wed Dec 11 23:52:55 2019 +0900 # # interactive rebase in progress; onto f53176d # Last commands done (3 commands done): # squash 968362c リスト2を修正 # squash d196455 リスト1を修正 # No commands remaining.

コミットメッセージは「リスト1、リスト2を作成」だけあればいいので、他の2つは削除します。

# This is a combination of 3 commits.
# This is the 1st commit message:

リスト1、リスト2を作成 # This is the commit message #2:

             ⬅︎ 削除 # This is the commit message #3:

             ⬅︎ 削除 # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Wed Dec 11 23:52:55 2019 +0900 # # interactive rebase in progress; onto f53176d # Last commands done (3 commands done): # squash 968362c リスト2を修正 # squash d196455 リスト1を修正 # No commands remaining.

この変更を保存するとrebaseが完了です。以下のように表示されれば問題なくrebaseできています。

Successfully rebased and updated refs/heads/create_list.

git log --oneline でlogを見てみると、コミットが1つにまとまっているのがわかると思います。

最後に、リモートにpushをします。ここで要注意なのが、rebaseをしたことでコミットのハッシュ値が変わっているので、pushができなくなっています。この場合、git push に-f オプションを付けて、強制的にpushすることができます。

$ git push -f origin create_list:create_list

これでGitHubを確認すると、コミットが1つにまとまっていると思います。

補足

git push -fなのですが、リモートの内容を破壊的に書き換えてしまうため、実はあまり多用することはおすすめできません。冒頭で、リモートのコミットをまとめるのが本来NGと書いたのは、実はこのgit push -f をする必要があるからでした。なので、git push -f を実行する時は、「絶対に自分以外いじらないブランチ」で作業をしているという確証のもと、実行するようにしてください。

リモートにpushする前に git pull --rebase を使ってみた

10月中旬頃から業務で本格的にプログラミングをし始めたのですが、gitが怖すぎるのでお試しでgit pull --rebaseを使ってみました。ただ使ってみただけだとすぐ忘れるので、せっかくなので書き残しておこうと思います。

やりたいこと

今回実現したいことは、git pull --rebaseを使って

リモートにpushする前に今作業しているブランチを最新の状態にする

 です。

masterからブランチを切ってしばらく作業している内に、masterがどんどん更新されていって自分のブランチが古くなってきたなー、なんて時はありませんか?
そんな時にgit pull --rebaseを使うと便利です。

例えば、masterからhogeブランチを切って作業していたとしましょう。そのhogeブランチをリモートにpushする前にgit pull --rebaseを使います。そうすると、hogeブランチを最新のmasterに合わせてそこにhogeブランチのcommitを付け足すことができます。

つまり、最新のmasterからhogeブランチを切ったことにできます。

今回はこれを実際にやって行きたいと思います。

前提

  1. try-gitというディレクトリの中にsample.htmlがあります
  2. 同じmasterからbranchAとbranchBが作られています
  3. 先にbranchAの変更をmasterにマージします

この段階でbranchBの状態を、branchAがマージされた後のmasterに合わせていきます。

sample.htmlを編集

branchAとbranchBでsample.htmlを編集していきます。
まだ何もマージされていない状態のmasterブランチでは以下のようになっています。

master

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>try-git</title>
</head>

<body>
  <h2>リスト1</h2>
  <ul>
    <li>コンテンツ1</li>
    <li>コンテンツ2</li>
    <li>コンテンツ3</li>
  </ul>
</body>

</html>

この状態からまずはbranchAを以下のように編集します。

branchA

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>try-git</title>
</head>

<body>
  <h2>リスト1</h2>
  <ul>
    <li>コンテンツ1</li>
    <li>コンテンツ2</li>
    <li>コンテンツ3</li>
  </ul>
  <h2>リスト2</h2>        ⬅︎ ここから
  <ul>
    <li>コンテンツ1</li>
    <li>コンテンツ2</li>
    <li>コンテンツ3</li>
  </ul>           ⬅︎ ここまで追加
</body>

</html>

この変更をmasterにpushし、マージします。

次に、ブランチをbranchBに切り替え、sample.htmlを編集します。

branchB

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>try-git</title>
</head>

<body>
  <h1>Welcome!!</h1>      ⬅︎ ここを追加
  <h2>リスト1</h2>
  <ul>
    <li>コンテンツ1</li>
    <li>コンテンツ2</li>
    <li>コンテンツ3</li>
  </ul>
</body>

</html>

branchBではまだpushはせず、commitだけしておきます。

git pull --rebaseでbranchAを最新のmasterに合わせる

今、masterではbranchAがマージされたのでsample.htmlは以下のようになっています。

master

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>try-git</title>
</head>

<body>
  <h2>リスト1</h2>
  <ul>
    <li>コンテンツ1</li>
    <li>コンテンツ2</li>
    <li>コンテンツ3</li>
  </ul>
  <h2>リスト2</h2>
  <ul>
    <li>コンテンツ1</li>
    <li>コンテンツ2</li>
    <li>コンテンツ3</li>
  </ul>
</body>

</html>

リスト2が追加されていますね。branchBでもこの変更を反映したいです。
そこで活躍するのが、git pull --rebaseです。

まずはブランチをmasterに切り替え、ローカルのmasterを最新の状態にします。

$ git pull --rebase origin master

これでローカルのmasterにもリスト2が追加されました。
次にbranchBに移動します。ここでgit pull --rebaseを実行します。

$ git pull --rebase origin master

コンフリクトが起きていなければ問題なく成功するはずです。
エディタでsample.htmlを確認すると、以下のようになっているかと思います。

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>try-git</title>
</head>

<body>
  <h1>Welcome!!</h1>
  <h2>リスト1</h2>
  <ul>
    <li>コンテンツ1</li>
    <li>コンテンツ2</li>
    <li>コンテンツ3</li>
  </ul>
  <h2>リスト2</h2>
  <ul>
    <li>コンテンツ1</li>
    <li>コンテンツ2</li>
    <li>コンテンツ3</li>
  </ul>
</body>

</html>

branchBにもリスト2が追加されました。
branchBをリモートにpushすると、branchAをマージ後のmasterからbranchBを切ったことになっているのがGitHub上でわかると思います。

せっかくなのでコンフリクトさせてみる

今回コンフリクトさせた状態でgit pull --rebaseを試してみたので、そちらについてもまとめておこうと思います。

コンフリクトした状態でgit pull --rebaseを実行すると以下のようになると思います。

$ git pull --rebase origin master

From https://github.com/ユーザー名/try-git
 * branch            master     -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: コミットメッセージ
Using index info to reconstruct a base tree...
M   sample.html
Falling back to patching base and 3-way merge...
Auto-merging sample.html
CONFLICT (content): Merge conflict in sample.html
error: Failed to merge in the changes.
Patch failed at 0001 コミットメッセージ
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

これはgit pull --rebaseが失敗しています。
エラーメッセージをよく見てみると、

Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue".

となっています。
これを簡単に訳すと

コンフリクトを解消してgit add、もしくはgit rmを実行してgit rebase --continueを実行してね

ということです。

なので、言われた通りにやってみましょう。
Visual Studio Codeを使っている場合、この段階でエディタを開くとコンフリクト解消画面になっていると思うので、コンフリクトを解消してgit addします。
そして、git rebase --continueを実行しましょう。

$ git add sample.html
$ git rebase --continue Applying: コミットメッセージ

となっていればgit pull --rebaseの完了です。

ただ、コミットを複数している状態だと何度かコンフリクトを修正しなければいけないことがあるようです。これは、git pull --renbaseの仕様によるものなのですが、ここでは説明を割愛させていただきます。
こちらにかなり詳しく書いてあるので、ぜひ一度読んでみることをお勧めします!

https://www.clear-code.com/blog/2016/9/2.html

コンフリクトした場合の対処方法だけではなく、「--rebase」なしのgit pullとの違いなどもまとめられています。

suとsudoが使えなくなってOSを再インストール

とあるコマンドを実行したらsudoとsuが使えなくなり、詰んでしまったので二度とこのような悲劇を繰り返さないための覚え書きです。

 

sudo chown -R コマンド

私を絶望の淵に叩き落としたのがこちらのコマンドです。

$ sudo chown ユーザー名 ディレクトリ名 または ファイル名

上記のようにすることでディレクトリやファイルの所有者を変更することができます。これに-Rというオプションをつけると指定したディレクトリ以下のファイルやディレクトリの所有者を全て変更することができます。一括で変更できるので便利だなーと思っていたのですが、これを実行してはいけないディレクトリがあります。私はそれを知らずにやらかしてしまい、sudoとsuが機能しなくなってしまいました。

usrディレクトリにchownコマンドはNG

このディレクトリに対して上記のコマンドを実行するとどうなるか。

私のように詰みます。

つまり、suとsudoが使えなくなります。
では、なぜそうなってしまうのでしょうか?私はそこをちっともわかっていませんでした。

usrディレクト

usrディレクトリはルートディレクトリの直下にあります。そしてこのusrディレクトリ以下にはbinというディレクトリがあります。このbinディレクトリに移動してlsコマンドを実行すると、以下のように色々と出てきます。

f:id:Riri1904:20190612220436j:plain

 

赤く囲まれた部分に注目してください。suとsudoがあります。実はこれの所有者を変更してしまうと、suやsudoを使ってもルートユーザーに成り代わることができなくなります。ここで何もわからない私はまた所有者をrootに戻せばいいのでは?と思ってしまいましたが、当然そんなことはできません。そもそもそれができるのはルートユーザーだけだからです。これでルートユーザーしか操作できないコマンドなどを全く使うことができなくなってしまいました。

OSを再インストール

もう残された手段はこれしかないので実行しました。

そうしたら無事に解決できました。OSを再インストールしてもデータが残ると言うことを知らなかったため、今まで作ったものをGitHubに上げたりしてからやりましたが、結局全てもと通り。全部しっかり残ってました。ただ消えてしまう可能性もゼロではないみたいなので、バックアップを取ってから再インストールした方が安全ではあるみたいです。今回の場合は外付けのハードにバックアップ取らないといけませんが・・・。

まとめ

sudo chownコマンドを使うときは慎重に!

一時はどうなることかと思いましたが、無事に復活して一安心です。私の場合、これを直そうとしてターミナルが使えなくなるところまで行ってしまったので、私のMacBook終わったんじゃないかと思ってかなり落ち込みました。でも、TECH::EXPERTのメンターさんのお力添えのおかげでまた勉強できるようになりました。こんな失敗やらかす人、私以外にいないかもしれませんがご一読いただいた皆様はどうかお気をつけてください。

unicornでRailsのサーバーが2回目以降立ち上がらない!!

ブログ始めたはいいけど、全然記事書いてなかったのでたまにはと思い書いてみます。

 

私は今TECH::EXPERTというプログラミングスクールに通っていて、カリキュラムの中でunicornを使ってRailsのサーバーの立ち上げをしたのですが、1回目は上手くいったのに2回目はすぐにコマンドが終了してしまう・・・というエラーに悩まされたので、それについて書いていきます。

 

unicornRailsのサーバーが立ち上がらない・・・

原因は色々あるみたいですが、私の場合はこちらの記事に書いてある通りでした。

https://qiita.com/Coconew5/items/2f4ba976e58da9c1ec22

ただ、ここにたどり着くまでに苦労したことがあったのでそれを記事として残しておこうと思います。

 

lessコマンドでlog/unicorn.stderr.logの中身を確認する

カリキュラム通りにunicornの設定をするとlog/unicorn.stderr.logにエラーを記録する設定になっているそうなので、以下のコマンドを実行しました。

$ less log/unicorn.stderr.log

 そうすると以下のように色々と表示されます。

I, [2019-06-10T07:29:21.273529 #22256]  INFO -- : Refreshing Gem list
I, [2019-06-10T07:29:23.574423 #22256]  INFO -- : listening on addr=/var/www/アプリ名/tmp/sockets/unicorn.sock fd=10
I, [2019-06-10T07:29:23.574613 #22256]  INFO -- : listening on addr=0.0.0.0:3000 fd=11
E, [2019-06-10T07:29:23.575034 #22256] ERROR -- : Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) (Mysql2::Error::ConnectionError)
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/client.rb:90:in `connect'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/mysql2-0.5.2/lib/mysql2/client.rb:90:in `initialize'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.7.2/lib/active_record/connection_adapters/mysql2_adapter.rb:25:in `new'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.7.2/lib/active_record/connection_adapters/mysql2_adapter.rb:25:in `mysql2_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.7.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:729:in `new_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.7.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:773:in `checkout_new_connection'
/home/ec2-user/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.0.7:

〜〜〜

しかし、これの見方が私にはよくわかりませんでした。唯一分かっていたのが4行目のEで始まる部分。この行がエラーを表しています。これはまだ最初の数行なのですが、わかる部分がそこしかないので他の部分は特に見ずにここに書いてある「Can't connect to local MySQL server through socket」をひたすら調べました。
こちらのエラーはmySQLに関するエラーなのですが、既にカリキュラムの方で解決していたはずのものなので「何でまた・・・」と思いながら色々と試しました。
しかし、何をやってもサーバーが立ち上がることはありませんでした。

 

catコマンドで確認する

「これはもうメンターさんを頼るしか・・・」と諦めかけた時、カリキュラムの中に「lessコマンドかcatコマンドでunicorn.stderr.logを確認する」と書いてあるのを見つけ、catコマンドを試してみようと思い以下のコマンドを実行しました。

$ cat log/unicorn.stderr.log

そうしたらlessで表示した時には見つけられなかった[Argument error]となっている行を発見しました。残念ながらその時のエラー文を残していないのですが、「〇〇〇〇・・・ 長々と書かれている何かのパス 〇〇〇〇[Argument error]」となっていました。そこで「〇〇〇〇[Argument error]」を丸々コピペして検索してみたところ、上記の記事を見つけ見事解決・・・といきたいところなのですが、ここでも少し引っかかってしまいました。

 

ps aux | grep unicornコマンド

上記記事を参考にps aux | grep unicornコマンドでunicornのプロセスを確認してみました。そうしたら以下のように表示されました。

ec2-user xxxxx ...
ec2-user xxxxx ...

「xxxxx」の部分には数字が書いてあります。

そして、記事によるとこの中のどれかのxxxxxのプロセスが残ってしまっているということでした。しかしどれが残ってしまっているプロセスなのかよくわからずまたしばらく悩んでしまい、他の原因を探り始めてまた解決への道から遠ざかってしまいました。
当然解決策は見つからず、途方に暮れながら何となく[Argument error]の部分を眺めていると、偶然解決への糸口を見つけることができました。

 

答えは[Argument error]の先頭部分にあった

[Argument error]の部分を先頭からよくみてみると、どこかでみたような数字が書いてあり、それが「既に実行済みですよ」のようなニュアンスの英語が書いてありました。もしかしてと思ってps aux | grep unicornの結果をみてみると、同じ数字を見つけ、「これだ!」と思って以下のコマンドを実行しました。

$ kill -9 xxxx

xxxxの部分には先ほど見つけた数字が入ります。

そうしたら無事にサーバーを立ち上げることができました!

 

まとめ

結局のところ、[Argument error]の冒頭部分の〇〇〇〇のところに全て書いてあったということですね。

エラー文はしっかり読まないといけないなーと思いました。