技術ネタはQiitaに移りました。壁もどこぞに。

AWS EC2 セットアップメモ ディスクマウント

社内向けの m3.xlarge のセットアップをすることがあったのでメモ。

まずはマウントディスクの状態から確認。

$ df
ファイルシス   1K-ブロック   使用   使用可 使用% マウント位置
/dev/xvda1         8377344 876560  7500784   11% /
devtmpfs           7602628      0  7602628    0% /dev
tmpfs              7487128      0  7487128    0% /dev/shm
tmpfs              7487128  16668  7470460    1% /run
tmpfs              7487128      0  7487128    0% /sys/fs/cgroup
/dev/xvdb         38565344  49164 36534128    1% /mnt

デフォルトこんな感じだったので、まずはアンマウントから。

$ sudo umount /dev/xvdb
$ df
ファイルシス   1K-ブロック   使用   使用可 使用% マウント位置
/dev/xvda1         8377344 876560  7500784   11% /
devtmpfs           7602628      0  7602628    0% /dev
tmpfs              7487128      0  7487128    0% /dev/shm
tmpfs              7487128  16668  7470460    1% /run
tmpfs              7487128      0  7487128    0% /sys/fs/cgroup

マウントはずれたので、マウント先のディレクトリ作成。
次いで、ディスクマウント。

$ sudo mkdir /mnt/flush1
$ sudo mkdir /mnt/flush2
$ sudo mount /dev/xvdb /mnt/flush1 -t auto
$ sudo mount /dev/xvdb /mnt/flush2 -t auto
$ df
ファイルシス   1K-ブロック   使用   使用可 使用% マウント位置
/dev/xvda1         8377344 876560  7500784   11% /
devtmpfs           7602628      0  7602628    0% /dev
tmpfs              7487128      0  7487128    0% /dev/shm
tmpfs              7487128  16668  7470460    1% /run
tmpfs              7487128      0  7487128    0% /sys/fs/cgroup
/dev/xvdb         38565344  49164 36534128    1% /mnt/flush1
/dev/xvdc         38565344  49164 36534128    1% /mnt/flush2

マシンの再起動後にもマウントが維持されるように fstab も編集。

$ sudo vi /etc/fstab

#
# /etc/fstab
# Created by anaconda on Mon Sep 29 21:48:54 2014
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=0f790447-ebef-4ca0-b229-d0aa1985d57f /                       xfs     defaults        1 1
/dev/xvdb       /mnt/flush1       auto    defaults,nofail,comment=cloudconfig     0       2
/dev/xvdc       /mnt/flush2       auto    defaults,nofail,comment=cloudconfig     0       2

リブートして確認。

$ sudo reboot

$ df -B G
ファイルシス   1G-ブロック  使用 使用可 使用% マウント位置
/dev/xvda1              8G    1G     8G   11% /
devtmpfs                8G    0G     8G    0% /dev
tmpfs                   8G    0G     8G    0% /dev/shm
tmpfs                   8G    1G     8G    1% /run
tmpfs                   8G    0G     8G    0% /sys/fs/cgroup
/dev/xvdb              37G    1G    35G    1% /mnt/flush1
/dev/xvdc              37G    1G    35G    1% /mnt/flush2

よさげ。

iPhoto ライブラリから写真をコピーする

そんなに手順は多くないのだが、忘れてしまいそうなのでメモ。

きっかけはストレージ不足に陥り、サイズの大きなファイルやディレクトリを探していたところ、1500枚程度しか写真を管理していないのに異常なまでに肥大化していた iPhoto ライブラリを見つけたことから。

なお、参考までにどれくらい容量を食っていたかというと、iPhone 程度の解像度1500枚で15GB くらい。異常。

早速手順を紹介。iPhoto のバージョンは、9.6 (910.29)。

写真の選択

iPhoto を開いて写真を全て選択。

f:id:Yoichi-KIKUCHI:20150208010746p:plain

写真の書き出し

メニューから、[ファイル]>[書き出す]を選択。

f:id:Yoichi-KIKUCHI:20150208010824p:plain

ダイアログから、[種類]に "オリジナル" を選択して、[書き出す]ボタンをクリック。

f:id:Yoichi-KIKUCHI:20150208010906p:plain

このあと、書き出し先のディレクトリを選択するダイアログが表示されるので、コピーを保存したいフォルダを選択する。これで iPhoto ライブラリを削除してしまってもだいじょうぶ。ストレージ容量を確保できるようになった。

なお、書き出し後のファイルサイズは合計でたったの2GB。

f:id:Yoichi-KIKUCHI:20150208011312p:plain

iPhoto ライブラリ、なんであんなにでかいんだろう…。

TeamCity で実際にビルドしてみる

前回は TeamCity で Build を作成した。

TeamCity で Build を作成 - 作業ノート

今回はそれに引き続いて、実際にプロジェクトのビルドを試してみる。TeamCity ならではのビルド結果の見やすさや、他ツールとの便利な連携などもいっしょに見ていく。

コミットグラフの表示

TeamCity では、ビルド結果の中の[Changes]というタブで、前回のビルドから今回のビルドまでに発生した差分をコミットグラフで表示してくれる。表示されているコミットにどのファイルが含まれているかもこのタブでいっしょに確認することができる。

この機能は、ビルドが成功したときよりも、失敗したときにこそ、その効果を強力に発揮する。開発者は失敗したビルドに、どのような変更が含まれているかを一目で把握することができる。

f:id:Yoichi-KIKUCHI:20150121013311p:plain

ビルドの失敗

ビルドが失敗した場合には、前述で触れたようにコミットグラフから変更差分を把握できる他、どのテストが失敗したかも簡単に確認できるようになっている。 なお、失敗したテストについては、[Overview]タブから確認することができる。

f:id:Yoichi-KIKUCHI:20150121013547p:plain

diff の表示

前回のビルドからの変更差分については、コミットグラフだけではなく、ソースコードの diff からも内容を確認できる。ビルド失敗時などは IDE を開くことなく、詳細な変更差分も TeamCity のみで確認することができるようになっている。

今回の例では、プロダクトコードに加えた変更自体には問題なかったが、テストコードに加えた変更に対応するプロダクトコードの実装が漏れていた、という例。

f:id:Yoichi-KIKUCHI:20150121013953p:plain

f:id:Yoichi-KIKUCHI:20150121014124p:plain

IDE 連携

ここまでで TeamCity のみで、ひとつのビルドからはじまり、変更の追跡、差分の確認などが非常に簡単、かつ明瞭におこなえるというのは十分にわかった。

TeamCity のみでいろいろな状態や、原因の確認、把握ができたとしても、実際にコードを修正するには、なにかしらのエディターなり、IDE なりを使うことになる。そんな IDE とも TeamCity は連携する。

いたるところに配置されている IDE アイコン。

f:id:Yoichi-KIKUCHI:20150121015229p:plain

これをクリックすることで、アクティブな IDE にさまざまな操作指示を与えることができるようになっている。該当ファイルのオープンであったり、パッチの作成だったりができる。

なお、IDE を連携させるには、事前に IDE 側に TeamCity 用のプラグインをインストールしておく必要がある。この IDE アイコンをクリックした際に、プラグインのインストールされた IDE が検出できなかった場合には、プラグインのダウンロードダイアログが表示されるため、ここからプラグインを入手する。 プラグインは、IntelliJ IDEA、Visual StudioEclipse 向けに用意されている。

f:id:Yoichi-KIKUCHI:20150121015629p:plain

プラグインを入手したら、これを IDE にインストールする。

f:id:Yoichi-KIKUCHI:20150121015659p:plain

プラグインがインストールされると、IDE の再起動後、メニューに TeamCity という項目が増える。 このメニューから、連携させる TeamCity へのログイン情報を設定すれば、事前設定は完了となる。

f:id:Yoichi-KIKUCHI:20150121015813p:plain

f:id:Yoichi-KIKUCHI:20150121020654p:plain

これで、さきほどの IDE アイコンから、アクティブな IDE に対して各種操作をおこなうことができるようになる。

非常に強力で、たくさんの魅力的な機能を有する TeamCity。 Jenkins しか使ったことがない、Jenkins しか知らないならば、ぜひ一度触れてみることをおすすめする。

TeamCity で Build を作成

TeamCity 自体のセットアップはここまでで概ね終えたので、ここからは使いかたや、どんなところが便利なのかについて触れていこうと思う。

TeamCity では、Build という単位でビルドジョブを管理する。これは Jenkins でいうところの Job にあたる。また、Build の中には Build Step というものがあり、これを定義していくことで、どのような流れでビルドが進むのかを設定できる。これは Jenkins でいうところの Task にあたる。

では、さっそく Build を作成してみる。Github(または、GithubEnterprise)などでバージョン管理をおこなっている場合、非常に簡単に Build の作成ができるので流れを追って紹介していく。

Build の作成

まずダッシュボード。画面右上の[Administration]から、Build の作成、他、さまざまな TeamCity の管理ができる。さっそく[Administration]をクリックして管理画面へ移動する。

f:id:Yoichi-KIKUCHI:20150118002434p:plain

管理画面の初期表示には、プロジェクトの一覧が並ぶ。今回は Github に既に存在しているプロジェクトから、新たに Build を作成してみる。[+ Create project from URL]をクリック。

f:id:Yoichi-KIKUCHI:20150118002453p:plain

プロジェクトの作成ウィザードが始まるので、画面内の案内に従って必要な項目を埋めていく。[Repository URL:]には Github から clone する場合に指定する URL を、[Username:]および[Password:]には TeamCity のログインに使用している認証情報などを入力する。プロジェクトに親子関係を持たせたい場合は[Parent Project:]に親プロジェクトを指定する。今回はそのまま "<Root project>" に作成する。入力を終えたら、[Proceed]をクリック。

f:id:Yoichi-KIKUCHI:20150118002922p:plain

次にプロジェクト名と、ビルド名の確認。今回はそのままで進める。内容を確認して、[Proceed]をクリック。

f:id:Yoichi-KIKUCHI:20150118003419p:plain

プロジェクト内に、POM ファイルなどを検出すると、Maven ビルドのための Build Step を自動で追加するかどうかを聞かれる。今回はこれをこのまま使うので、チェックを付けて[Use selected]をクリック。

f:id:Yoichi-KIKUCHI:20150118003759p:plain

Build Step が定義され、Build が作成された。以降はこの画面の右上にある[Run]ボタンや、ダッシュボードのプロジェクト一覧から、いつでもビルド指示を出すことができる。

f:id:Yoichi-KIKUCHI:20150118003845p:plain

以上のように、非常にわかりやすく、簡単に始められるのも TeamCity のすばらしいところ。実際にビルドを進めたりする中で、もっとすばらしいと感じられる箇所は、このあとまだまだ出てくるので、これらはまたべつに追って紹介していこうと思う。

TeamCity の BuildAgent をデーモン化

以前の記事で、TeamCity、および BuildAgent のインストールをおこなった。 ところが、この状態だとサーバー再起動時などに再び手動で BuildAgent を起動しなければならないため、 今回は BuildAgent のデーモン化をおこなってみようと思う。 また、TeamCity、BuildAgent のインストールについてまだの場合は以下を確認しつつ進める。

TeamCity JavaEE:war 版のインストール - 作業ノート
TeamCity JavaEE:war 版に BuildAgent インストール - 作業ノート

CentOS7 以降ではシステム管理の方法が、systemctl にまとめられ 初見でこそ少々面食らってしまうが、いろいろと見通しが良くなり、 わかりやすくなった部分も多い。

今回は CentOS7 で環境を立てているため、 このあたらしい方法でデーモン化を行ってみたいと思う。 なお、デーモン化についてのより詳細な情報については、別途以下を確認してほしい。

systemd (日本語) - ArchWiki

BuildAgent の起動確認

TeamCity の BuildAgent をインストールしたあとは、 エージェントディレクトリ内の bin ディレクトリに配置されている、 agent.sh を使用してプロセスを起動することになる。

なお、スクリプトの内容を見ると分かる通り、 agent.sh には引数を与えて動作指示を出すことができ、 以下4つのオプションが用意されている。

  • start
    • バックグラウンドでエージェントを起動する。
  • stop
    • 現在おこなっているビルドがあれば、それが完了した後に、エージェントを停止する。
  • run
    • フォアグラウンドでエージェントを起動する。
  • stop force
    • 現在おこなっているビルドがあってもそれを中止して、エージェントを停止する。

起動を確認する。今回は、/opt/teamcity/buildAgent-1 にエージェントがインストールされているものとする。

$ cd /opt/teamcity/buildAgent-1/bin
$ sudo ./agent.sh start
Starting TeamCity build agent...
Java executable is found in '/bin/..'.
Starting TeamCity Build Agent Launcher...
Agent home directory is /opt/teamcity/buildAgent-1
Current Java runtime version is 1.7
Lock file: /opt/teamcity/buildAgent-1/logs/buildAgent.properties.lock
Using no lock
$ ls ../logs/
buildAgent.pid  buildAgent.xmlRpcPort  error.log  launcher.log  output.log  teamcity-agent.log  teamcity-vcs.log  upgrade.log

エージェントが起動すると、log ディレクトリに pid ファイルが作成される。この pid ファイルはデーモン化で使用することになるので、生成パスを覚えておくと良い。

また、同様にスクリプト内のコメントから、いくつかの環境変数が使用されることも分かる。エージェントがうまく起動しなかった場合は、以下の設定も確認しておく。

  • JAVA_HOME、または JRE_HOME
    • エージェントの使用す bin/java の配置されているディレクトリを指定する。
  • TEAMCITY_AGENT_MEM_OPTS
    • (任意)エージェントの使用するメモリーを、JVM オプションで指定する。
  • TEAMCITY_AGENT_OPTS
    • (任意)追加の JVM オプションを指定する。
  • TEAMCITY_LAUNCHER_OPTS
    • (任意)エージェントランチャーの JVM オプション。
  • TEAMCITY_AGENT_PREPARE_SCRIPT
    • (任意)エージェントの、起動および停止前に実行するスクリプトの名前を指定する。

BuildAgent のデーモン化

エージェントの起動を確認できたら、一度 agent.sh stop でエージェントは停止しておく。つづいて、デーモン化できるように service ファイルの作成をしていく。

デーモン起動に必要なファイルは以下のいずれかのディレクトリに配置する。なお、同名のスクリプトが両方に存在する場合は、/usr/lib/systemd/system に存在するほうが優先され、ユーザー定義の起動ファイルもこちらに配置する。

  1. /etc/systemd/system
  2. /usr/lib/systemd/system

ここまでで動きを確認した agent.sh と、buildAgent.pid を使用して起動設定ファイルを作成する。

$ sudo vi /usr/lib/systemd/system/teamcity-agent-1.service
[Unit]
Description=TeamCity Build Agent 1
After=network.target

[Service]
Type=forking
PIDFile=/opt/teamcity/buildAgent-1/logs/buildAgent.pid
ExecStart=/opt/teamcity/buildAgent-1/bin/agent.sh start
ExecStop=/opt/teamcity/buildAgent-1/bin/agent.sh stop

[Install]
WantedBy=multi-user.target

保存をして、デーモンの再起動と起動設定ファイルの適用を確認する。

$ sudo systemctl daemon-reload

$ sudo systemctl start teamcity-agent-1

$ systemctl status teamcity-agent-1
teamcity-agent-1.service - TeamCity Build Agent 1
   Loaded: loaded (/usr/lib/systemd/system/teamcity-agent-1.service; disabled)
   Active: active (running) since 土 2015-01-17 03:22:39 JST; 20h ago
  Process: 7008 ExecStart=/opt/teamcity/buildAgent-1/bin/agent.sh start (code=exited, status=0/SUCCESS)
 Main PID: 7031 (java)
   CGroup: /system.slice/teamcity-agent-1.service
           ├─7031 java -ea -cp ../launcher/lib/launcher.jar jetbrains.buildServer.agent.Launcher -ea -Xmx384m -Dteam...
           └─7042 java -ea -Xmx384m -Dteamcity_logs=../logs/ -Dlog4j.configuration=file:../conf/teamcity-agent-log4j...

うまく動いた。TeamCity 側でのエージェント認識までには、1分〜3分程度要する場合があるので、こちらは慌てずに待とう。これでサーバー再起動時にも、自動起動させたりできるようになる。

TeamCity JavaEE:war 版に BuildAgent インストール

通常、TeamCity(Windows/Mac OS X/Linux 版)では、すべてのモジュールひとつのパッケージに同梱されているため、BuildAgent のインストール作業などはとくに考慮する必要はない。

ところが、JavaEE 版では、BuildAgent のみ別でインストール必要がある。Java EE 版インストール後の BuildAgent の状態は、TeamCity 内の Agents メニューから確認でき、以下のようになっている。

There are no agents available.
Install Build Agents

MS Windows Installer
Zip file distribution for manual installation (unzip the file, specify the build agent's properties and run the executable file).
See our documentation for details.

f:id:Yoichi-KIKUCHI:20150113080217p:plain

BuildAgent のない状態では、TeamCity は役に立たないので、インストールを行っていく。案内に従いつつ試行錯誤した上での Agent インストール手順を残しておく。

環境変数 JAVA_HOME の設定

インストーラ内で使用しているようなので、済んでいなければ設定する。今回の環境では OpenJDK を yum インストールしていたので以下のように。

echo $JAVA_HOME

export JAVA_HOME=/usr/lib/jvm/java
echo $JAVA_HOME
/usr/lib/jvm/java

マニュアルインストーラの入手

画面の指示に従い、まずは zip 形式のインストーラを入手する。画面内の "Zip file distribution" リンクをコピーしておき以下のように。

$ cd ~
$ wget http://{hostname}:8080/TeamCity/update/buildAgent.zip

インストーラの展開と配置

入手したインストーラを展開しつつ、配置する。今回は /opt に配置することにした。

$ mkdir buildAgent
$ mv buildAgent.zip buildAgent
$ cd buildAgent
$ unzip buildAgent.zip
$ mv buildAgent.zip ../
$ sudo mkdir /opt/teamcity
$ sudo mv -R buildAgent /opt/teamcity/

BuildAgent のインストール

コンフィグレーションファイルを用意しつつ、BuildAgetn をインストールする。インストール自体はそう難しくないので、さくさく進む。

$ cd /opt/teamcity/buildAgent/bin
$ sudo chmod +x install.sh
$ sudo ./install.sh "http://{hostname}:8080/TeamCity/"
Installing TeamCity Agent for http://{hostname}:8080/TeamCity/
Looking for Java Runtime Environment...
Java executable is found in '/bin/..'.
Configuring the Agent's properties...
/opt/teamcity/buildAgent/bin
Starting the Agent under 'root' account...
nohup: 入力を無視し、出力を `nohup.out' に追記します
WARNING: The TeamCity Agent installed as standalone application and will not start automatically on machine reboot.

これだけ。しばらく待っていると、buildAgent/conf 配下に "buildAgent.properties" というファイルが作成され、ここにインストールされた BuildAgent の情報が記載される。

ただし、インストーラの吐いた最後の WARNING メッセージを見ても分かる通り、自動起動スクリプトを書くなどしないとサーバーの再起動ごとに都度起動してやらなければいけない。

BuildAgent 起動後は TeamCity の Agents メニューから、インストールされたエージェントを確認できるようになる。

f:id:Yoichi-KIKUCHI:20150113080235p:plain

TeamCity JavaEE:war 版のインストール

仕事で CI ツールの選定をしていたところ、 TeamCity が非常によく出来ていて気に入ったので、 プライベートでも立ててみた。

仕事先で入れた時には Linux 版(tar.gz を展開して、sh で起動)を 使用していたため、 とくに引っかかるところもなく、 簡単に立てられたのだが、 あまりポート使いまくるのもなーとか、 あんまりいろんな環境が増えるのもなーと思い、 今回は既にセットアップ済みの Tomcat 上にデプロイできるように、 Java EE 版(war)で構築してみようと思った。

ところが、URL にアクセスしてみると、以下のようなエラーが…。

TeamCity has failed to start
Unable to initialize logs. The logs directories are not accessible for writing.
TeamCity server process does not have enough permissions to write into the log files under the directory:
/usr/share/logs
Please fix permissions and restart TeamCity. You can read more about TeamCity logs in documentation.
TeamCity 9.0.1 (build 32116)

f:id:Yoichi-KIKUCHI:20150111173955p:plain

対処方法が分かってしまえば簡単なのだが、 TeamCity は非常にわかりやすい反面、資料や情報の豊富さでいえば、 やはり Jenkins に負けるので調べるのに少々手間取った。

以下、Java EE 版(war)のセットアップ手順。 なお、デプロイ先の環境(Tomcat など)はすでに構築済みであるものとする。

TeamCity の入手と配置

JetBrains の公式から、URL を調べて wget などで。 500M ちょっとあるので、少し時間がかかる。 ダウンロードできたら、webapps にデプロイする。

$ wget http://download.jetbrains.com/teamcity/TeamCity-9.0.1.war

$ sudo mv TeamCity-9.0.1.war /var/lib/tomcat/webapps/TeamCity.war

ログ出力先の設定

ここで、JVM Option で TeamCity のログ出力先を設定してやる必要がある。 これをやっておかないと、先に紹介したようなエラー画面が表示されてしまう。 デフォルトだと、tomcat ユーザーでは書き込めないようなディレクトリが指定されてしっているようす。

JVM Option に与える設定値は、以下のとおり。
-Dteamcity_logs={tomcat ユーザーの書き込み可能なログディレクトリ}

今回は、yum でインストールした tomcat に設定するため、以下にあるように、/usr/share/tomcat/conf/tomcat.conf を編集する。
yum でインストールした Tomcat に JVM オプションを設定 - 作業ノート

sudo vi /usr/share/tomcat/conf/tomcat.conf

...

# System-wide configuration file for tomcat services
# This will be sourced by tomcat and any secondary service
# Values will be overridden by service-specific configuration
# files in /etc/sysconfig
#
# Use this one to change default values for all services
# Change the service specific ones to affect only one service
# (see, for instance, /etc/sysconfig/tomcat)
#

# Where your java installation lives
JAVA_HOME="/usr/lib/jvm/jre"

# Where your tomcat installation lives
CATALINA_BASE="/usr/share/tomcat"
CATALINA_HOME="/usr/share/tomcat"
JASPER_HOME="/usr/share/tomcat"
CATALINA_TMPDIR="/var/cache/tomcat/temp"

# You can pass some parameters to java here if you wish to
#JAVA_OPTS="-Xminf0.1 -Xmaxf0.3"

# Use JAVA_OPTS to set java.library.path for libtcnative.so
#JAVA_OPTS="-Djava.library.path=/usr/lib64"

# What user should run tomcat
TOMCAT_USER="tomcat"

# You can change your tomcat locale here
#LANG="en_US"

# Run tomcat under the Java Security Manager
SECURITY_MANAGER="false"

# Time to wait in seconds, before killing process
SHUTDOWN_WAIT="30"

# Whether to annoy the user with "attempting to shut down" messages or not
SHUTDOWN_VERBOSE="false"

# Set the TOMCAT_PID location

CATALINA_PID="/var/run/tomcat.pid"

# Connector port is 8080 for this tomcat instance
#CONNECTOR_PORT="8080"

# If you wish to further customize your tomcat environment,
# put your own definitions here
# (i.e. LD_LIBRARY_PATH for some jdbc drivers)

##
## JVM Options
##
CATALINA_OPTS="-Dteamcity_logs=/var/log/tomcat/"

tomcat の起動

最後に、tomcat を起動、または再起動して画面を確認する。

$ sudo systemctl start tomcat

f:id:Yoichi-KIKUCHI:20150111174114p:plain