ソフトウェアエンジニアリング - 機能 #14
GitBucket 2.1のRPMを作成する
2014/07/20 21:31 - 高橋 徹 ステータス: 終了 開始日: 2014/07/20 優先度: 通常 期日: 担当者: 高橋 徹 進捗率: 100% カテゴリ: 予定工数: 0.00時間 対象バージョン: 作業時間: 0.00時間 説明 GitBucket 2.1のRPMを作成します。 GitBucketの入手先(GitHub)は次のURLです。 https://github.com/takezoe/gitbucketこのリポジトリのcontribには、Red Hat Enterprise
Linux用のRPM作成に使うSPECファイル、サービス起動のinitファイル、設定ファイルが登録されていますが、rootユーザーで動く 仕様となっています。
そこで、Jenkinsのようにrootではなく特定のユーザー権限で動くようにRPMを作成します。 関連するチケット:
関連している 機能 #54: GitBucket 3.11のRPMを、H2 database migrationツ... 却下 2016/02/28
履歴 #1 - 2014/07/20 21:43 - 高橋 徹 - ステータス を 新規 から 進行中 に変更 - 進捗率 を 0 から 50 に変更 まずは、GitHubリポジトリより次のファイルを入手します。 gitbucket.war (Javaバイトコード) gitbucket-2.1.tar.gz (ソースファイル) gitbucket.spec (RPMビルド用定義ファイル) gitbucket.conf (GitBucket実行時の設定ファイル) gitbucket.init (GitBucketをservice起動するためのスクリプトファイル) それぞれRPMビルド用に配置します。 $HOME/rpm +-- SPECS | +-- gitbucket.spec +-- SOURCES +-- gitbucket.war +-- gitbucket-2.1.tar.gz +-- gitbucket.conf +-- gitbucket.ini GitBucketのcontribをほぼそのままでRPM作成(rootユーザー実行) --- gitbucket.spec 2014-07-20 21:23:47.303501900 +0900 +++ rpm/SPECS/gitbucket.spec 2014-07-20 21:27:18.326450470 +0900 @@ -1,6 +1,6@@ Name: gitbucket
Summary: GitHub clone written with Scala. -Version: 1.7 +Version: 2.1 Release: 1%{?dist} License: Apache URL: https://github.com/takezoe/gitbucket @@ -40,6 +40,9@@
%changelog
+* Sun Jul 20 2014 Toru Takahashi <torutk at gmail.com> +- Version bump to v2.1.
+
* Mon Oct 28 2013 Jiri Tyr <jiri_DOT_tyr at gmail.com> - Version bump to v1.7.
RPMビルドを実行します。
~$ rpmbuild -ba rpm/SPECS/gitbucket.spec : RPMおよびSRPMが生成されます。 $HOME/rpm +-- RPMS | +-- noarch | +-- gitbucket-2.1-1.el6.noarch.rpm +-- SRPMS +-- gitbucket-2.1-1.el6.src.rpm 生成されたRPMをインストールします。
~$ sudo rpm -Uvh rpm/RPMS/noarch/gitbucket-2.1-1.el6.noarch.rpm
準備中... ########################################### [100%] 1:gitbucket ########################################### [100%] ~$ 次のファイルがインストールされました。 ~$ rpm -ql gitbucket /etc/init.d/gitbucket /etc/sysconfig/gitbucket /usr/share/gitbucket/lib/gitbucket.war /var/log/gitbucket/run.log ~$ 手動でgitbucketを実行します。
~$ sudo service gitbucket start
gitbucketのログは、/var/log/gitbucket/run.log に生成されます。 gitbucketのプロセスIDは、/var/run/gitbucket.pid に生成されます。
#2 - 2014/07/20 21:47 - 高橋 徹 gitbucketをrootユーザーではなくgitbucketユーザーで動かすために必要なことを調べる rootで動くgitbucketをインストールした後、これをgitbucketユーザーで動かすために必要な修正をしていきます。 修正が完了した時点でgitbucket.specファイルほかを修正していきます。 #3 - 2014/07/21 03:11 - 高橋 徹 gitbucketをrootユーザーではなくgitbucketユーザーで動かすために必要なことを調べる Jenkinsが同じくwarファイルをjavaで実行するタイプですが、rootユーザーではなくjenkinsユーザーで実現しているので、Jenkinsの起動スクリプト を参考にします。 https://github.com/jenkinsci/jenkins/blob/master/rpm/SOURCES/jenkins.init.in rootで動くgitbucketをインストールした後、これをgitbucketユーザーで動かすために必要な修正をしていきます。 修正が完了した時点でgitbucket.specファイルほかを修正していきます。 gitbucketユーザー/グループの作成
~$ sudo groupadd -r gitbucket
~$ sudo useradd -g gitbucket -s /bin/false -r -c "GitBucket SCM Server" -d /var/lib/gitbucket gitbucket
jenkinsの設定に倣ってユーザーのシェルを/bin/falseにしたけど、su gitbucket -c "コマンド"がスカって起動しません。調べると、 /bin/false はシェルを通じて一切の操作ができない偽シェル(su <ユーザー> -c
"コマンド"も操作できない模様)。daemonで起動する場合はシェルを通じないかも(jenkinsのinitスクリプトではdaemon関数でコマン ドを実行していた)。
gitbucketのログディレクトリ/ファイルの所有者変更
~$ sudo chown -R gitbucket.gitbucket /var/log/gitbucket
gitbucket起動スクリプト(/etc/init.d/gitbucket)でコマンドをgitbucketユーザーで実行する変更
@@ -41,7 +41,7@@ fi
# Run the Java process
-daemon --user gitbucket --pidfile ${PID_FILE} "GITBUCKET_HOME=${GITBUCKET_HOME} java $GITBUCKET_JVM_OPTS -jar $GITBUCKET_WAR_ FILE $START_OPTS >>$LOG_FILE 2>&1 &"
+
GITBUCKET_HOME="${GITBUCKET_HOME}" java $GITBUCKET_JVM_OPTS -jar $GITBUCKET_WAR_FILE $START_OPTS >>$LOG_FILE 2>&1 & RETVAL=$?
# Store PID of the Java process into a file
最初 su gitbucket -c "..."
で実行しようとしましたが、gitbucketユーザーのシェルが偽シェル(/sbin/false)だと駄目だったのでdaemon関数で実行してみました。
起動しましたが、serviceからstopができません。PIDファイルが空です。
gitbucket起動スクリプト(/etc/init.d/gitbucket)でdaemon関数で起動したjavaプロセスのPIDを取得する変更
@@ -46,6 +46,13@@
# Store PID of the Java process into a file echo $! > $PID_FILE
+ /bin/ps hww -u gitbucket -o sess,ppid,pid,cmd | \ + while read sess ppid pid cmd; do
+ [ "$ppid" = 1 ] || continue
+ echo "$cmd" | grep $GITBUCKET_WAR_FILE > /dev/null
+ [ $? = 0 ] || continue
+ echo $pid > "$PID_FILE"
if [ $RETVAL -eq 0 ] ; then
success "GitBucket startup"
gitbucketのデータは、/var/lib/gitbucketの下に作成されます。ここの所有権をgitbucketユーザーに変更します。
~$ sudo chown -R gitbucket.gitbucket /var/lib/gitbucket
#4 - 2014/07/21 05:28 - 高橋 徹
実効ユーザーを変更したRPMを作成するための修正
SPECファイルにgitbucketユーザー・グループ作成とファイルのパーミッション指定を追加
@@ -1,7 +1,7@@
Name: gitbucket
Summary: GitHub clone written with Scala.
Version: 2.1 -Release: 1%{?dist} +Release: 2%{?dist} License: Apache URL: https://github.com/takezoe/gitbucket Group: System/Servers @@ -26,6 +26,25@@
%{__install} -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/%{name} touch %{buildroot}%{_localstatedir}/log/%{name}/run.log
+%pre
+/usr/sbin/groupadd -r gitbucket &> /dev/null || :
+/usr/sbin/useradd -g gitbucket -s /bin/false -r -c "GitBucket GitHub clone" -d %{_sharedstatedir}/%{name} gitbucket &> /dev/null || : +
+%post
+/sbin/chkconfig --add gitbucket +
+%preun
+if [ "$1" = 0 ]; then
+ /sbin/service gitbucket stop > /dev/null 2>&1 + /sbin/chkconfig --del gitbucket
+fi +exit 0 + +%postun
+if [ "$1" -ge 1 ]; then
+ /sbin/service gitbucket restart > /dev/null 2>&1 +fi
+exit 0
%clean
[ "%{buildroot}" != / ] && %{__rm} -rf "%{buildroot}" @@ -34,12 +53,16@@ %files %defattr(-,root,root,-) %{_datarootdir}/%{name}/lib/%{name}.war -%{_sysconfdir}/init.d/%{name} -%config %{_sysconfdir}/sysconfig/%{name} -%{_localstatedir}/log/%{name}/run.log +%config %{_sysconfdir}/init.d/%{name} +%config(noreplace) %{_sysconfdir}/sysconfig/%{name}
+%attr(0755,gitbucket,gitbucket) %{_sharedstatedir}/%{name} +%attr(0750,gitbucket,gitbucket) %{_localstatedir}/log/%{name}
%changelog
+* Mon Jul 21 2014 Toru Takahashi <torutk at gmail.com> +- execute as gitbucket user
+
* Sun Jul 20 2014 Toru Takahashi <torutk at gmail.com> - Version bump to v2.1. #5 - 2014/07/21 19:07 - 高橋 徹 - ステータス を 進行中 から 解決 に変更 - 進捗率 を 50 から 80 に変更 本作業の成果物は、GitBucketページに上げています。 #6 - 2014/10/26 11:38 - 高橋 徹 Gitbucket 2.4.1がリリースされたので、RPMパッケージを作成しました。 https://github.com/takezoe/gitbucket/releases からソースコードとwarをダウンロードし、~/rpm/SOURCESにコピー 2.1のSPECファイルをバージョンを2.4.1に修正 ソースコードを作業ディレクトリに展開し、contrib/gitbucket.{conf,init}を取り出し~/rpm/SOURCESにkピー rpmbuild実行 出来たRPMをインストール サービス実行
~$ sudo service gitbucket start ~$
あれ、なにもメッセージが出ません。おかしい。/etc/init.d/gitbucketを直接実行
~$ cd /etc/init.d
inti.d$ sudo ./gitbucket start init.d$
同じく。gitbucketに片っ端からecho文を埋めてみると、
13 set -e 14
15 [ -f /etc/rc.d/init.d/functions ] && source /etc/rc.d/init.d/functions # RedHat
15行目より後に入れたecho文が出ない。 → set -e について調べてみた set -e での動作を想定していないライブラリを . (ドット) コマンド や source コマンドで読み込んだときに使えない。 http://qa.atmarkit.co.jp/q/2813 とあった。set -eを削除するとメッセージが出るようになった。 現状はjavaプロセスがrootで実行される。gitbucketユーザーで実行するために、/etc/rc.d/init.d/functionsで定義されるdaemonファンクションを使 用してみました。
GITBUCKET_HOME="${GITBUCKET_HOME}" daemon --user=gitbucket java $GITBUCKET_JVM_OPTS -jar $GITBUCKET_WAR_FILE $START_OPTS >>$LOG_FILE 2>&1 &
/var/lib/gitbucketのパーミッションがrootだと動かないのでgitbucketに変更したら動きました。
#7 - 2014/11/23 22:19 - 高橋 徹 service gitbucket stopで停止しない /etc/init.d/gitbucket の起動部分を抜粋
60 GITBUCKET_HOME="${GITBUCKET_HOME}" daemon --user=gitbucket java $GITBUCKET _JVM_OPTS -jar $GITBUCKET_WAR_FILE $STA RT_OPTS >>$LOG_FILE 2>&1 &
61 RETVAL=$? 62
63 echo $! > $PID_FILE
起動するプロセスをps auxから抜粋
~$ ps aux|grep gitbucket
root 1194 /bin/bash /etc/rc3.d/S60gitbucket start
root 1203 runuser -s /bin/bash gitbucket -c ulimit -S -c 0 >/dev/null 2>&1 ; java -Dmail.smtp.starttls.enable=true -jar /usr/share/gitbucket /lib/gitbucket.war --port=8080 --host=0.0.0.0
496 1205 bash -c ulimit -S -c 0 >/dev/null 2>&1 ; java -Dmail.smtp.starttls.enable=true -jar /usr/share/gitbucket/lib/gitbucket.war --port= 8080 --host=0.0.0.0
496 1206 java -Dmail.smtp.starttls.enable=true -jar /usr/share/gitbucket/lib/gitbucket.war --port=8080 --host=0.0.0.0
このとき、/var/run/gitbucketの中は、1194
となっていた。これはgitbucketプロセスではなく、gitbucketプロセスを起動するシェルスクリプトのPIDとなっている。
daemon functionに渡す--pidfileオプションは参照用でそのファイルを生成してPIDを書き込んではくれない!
@@ -60,8 +60,6@@
GITBUCKET_HOME="${GITBUCKET_HOME}" daemon --user=gitbucket java $GITBUCKET_JVM_OPTS -jar $GITBUCKET_WAR_FILE $START _OPTS >>$LOG_FILE 2>&1 &
RETVAL=$?
- echo $! > $PID_FILE
-if [ $RETVAL -eq 0 ] ; then success "Success" else
@@ -77,11 +75,10@@
echo -n $"Stopping GitBucket server: "
# Run the Java process
- kill $(cat $PID_FILE 2>/dev/null)>>$LOG_FILE 2>&1 + pkill -f $GITBUCKET_WAR_FILE>>$LOG_FILE 2>&1
RETVAL=$?
if [ $RETVAL -eq 0 ] ; then
- rm -f $PID_FILE
success "GitBucket stopping" else
#8 - 2014/11/24 10:14 - 高橋 徹
GitBucketの起動制御スクリプトの再構築
CentOS 6でGitBucketの起動制御スクリプトを使えるようにするため、リポジトリの元ネタから再度修正を開始します。 https://github.com/takezoe/gitbucket/blob/master/contrib/gitbucket.init これをCentOS 6で動かすと次の行でエラーとなりました。 if [ `isMac` ]; then CentOS 6にはisMacというコマンドがないためです。gitbucket.initはこのスクリプトは、RedHat/Ubuntu/Mac OS X共用になっています。ファイル先頭のコメント部分を抜き出します。 # RedHat: /etc/rc.d/init.d/gitbucket # Ubuntu: /etc/init.d/gitbucket# Mac OS/X: /Library/StartupItems/GitBucket
しかし、スクリプト中にif文で切り分けを入れる作りでは、3つの環境を持っていてすべてで確認しながら修正作業をする必要があります。すべての 環境を持っていることは稀で、持っていたとしても甚だ手間がかかります。実際、上述のようにRedHat系のCentOSにはないコマンドを実行するコ ードが入ってしまっています。スクリプトは環境ごとに分けるべきでしょう。 ということで、まずRedHat系専用のスクリプトにします。gitbucketのリポジトリを見ると gitbuckt +-- contrib : +-- linux : | +-- redhat : | +-- gitbucket.spec : +-- macosx : | +-- makePlist : +-- README.md : +-- gitbucket.conf : +-- gitbucket.init : +-- install となっているので、RedHat専用にする起動制御スクリプトは、contrib/linux/redhat/に置くのが好ましいでしょう。そこで、contrib/gitbucket.init を、contrib/linux/redhat/gitbucket.init にコピーしこれを変更していきます。 Ubuntu/MacOS用コードの削除 -# Ubuntu: /etc/init.d/gitbucket
-# Mac OS/X: /Library/StartupItems/GitBucket :
-[ -f /etc/rc.common ] && source /etc/rc.common # Mac OS/X :
-## MacOS proxies for System V service hooks: -StartService() { - start -} -StopService() { - stop -} --RestartService() { - restart -}
--if [ `isMac` ]; then - RunService "$1" -else
: -fi
-set -e
-gitbucketユーザーで実行(前に述べた修正)
- GITBUCKET_HOME="${GITBUCKET_HOME}" java $GITBUCKET_JVM_OPTS -jar $GITBUCKET_WAR_FILE $START_OPTS >>$LOG_FILE 2>&1 &
+ GITBUCKET_HOME="${GITBUCKET_HOME}"daemon --user=gitbucket
java $GITBUCKET_JVM_OPTS -jar $GITBUCKET_WAR_FILE $START_OPTS >>$LOG_FILE 2>&1 &
pidファイルによるサービス(プロセス)終了の制御ができないため代替方法 -PID_FILE=/var/run/gitbucket.pid : - echo $! > $PID_FILE -:
- kill $(cat $PID_FILE 2>/dev/null)>>$LOG_FILE 2>&1 + pkill -f gitbucket.war>>$LOG_FILE 2>&1
:
- rm -f $PID_FILE
:
status)
- status -p $PID_FILE java
+ pgrep -f gitbucket.war >> $LOG_FILE 2>&1 RETVAL=$?
+ if [ $RETVAL -eq 0 ]; then
+ echo $"GitBucket is running...."
+ else
+ echo $"GitBucket is stopped"
;;
ここまでの修正でサービス起動制御スクリプトを実行すると次のようになります。
~$ sudo service gitbucket status
which: no success in (/sbin:/usr/sbin:/bin:/usr/bin) which: no failure in (/sbin:/usr/sbin:/bin:/usr/bin) GitBucket is stopped
これは、次のスクリプト記述が原因です。
if [ -z "$(which success)" ]; then function success {
printf "%b\n" "$GREEN $* $OFF" }
fi
if [ -z "$(which failure)" ]; then function failure {
printf "%b\n" "$RED $* $OFF" }
fi
successとfailureは、/etc/rc.d/init.d/functionsスクリプトで定義されるシェル関数です。whichコマンドでパスを取得することができません。しかし 、このスクリプト記述はsuccessとfailureがコマンドである想定で書かれています。RedHat系専用スクリプトでは、ばっさり削除してしまいます。
-if [ -z "$(which success)" ]; then - function success {
- printf "%b\n" "$GREEN $* $OFF"
- }
-fi
- function failure {
- printf "%b\n" "$RED $* $OFF"
- }
-fi
起動に失敗しても、スクリプト上は成功として表示されてしまいます。次のスクリプト部分が課題です。
GITBUCKET_HOME="${GITBUCKET_HOME}" daemon --user=gitbucket java $GITBUCKET \ _JVM_OPTS -jar $GITBUCKET_WAR_FILE $START_OPTS >>$LOG_FILE 2>&1 & RETVAL=$?
if [ $RETVAL -eq 0 ] ; then success "Success"
else
failure "Exit code $RETVAL" fi
バックグラウンド実行(末尾に'&'をつけて実行)した場合、コマンド実行結果('$?')は常に0(成功)となります。
そこで、daemonでバックグラウンド実行後、一定時間経過待ち1してからpgrepでプロセスを探して結果を判定することにします。
GITBUCKET_HOME="${GITBUCKET_HOME}" daemon --user=gitbucket java $GITBUCKET _JVM_OPTS -jar $GITBUCKET_WAR_FILE $START _OPTS >>$LOG_FILE 2>&1 &
+ sleep 3
+ pgrep -f $GITBUCKET_WAR_FILE >> $LOG_FILE 2>&1 RETVAL=$?
1 本当はプロセスが立ち上がったことを確認したかったのですが、うまいやり方が見つからずsleepにしてしまいました。
#9 - 2015/02/23 07:58 - 高橋 徹
- ステータス を 解決 から 終了 に変更 - 進捗率 を 80 から 100 に変更
【棚卸し】この修正を、gitbucketのgithubリポジトリからフォークを作成して、ブランチにコミット https://github.com/torutk/gitbucket/commit/676670e9e3a1666404bedb4cccf54de2773ad0b9 プルリクエストを発行して、その後取り込んでいただきました。
#10 - 2016/02/28 10:47 - 高橋 徹