Amazon Linuxでのnginx rebuild とエラーデバッグ時の思考回路

AWS

2022.5.24

Topics

謎のプレッシャーがすごい。(挨拶)

こんにちは。tshibaと申します。そろそろ隠居を考えている今日この頃ですが頑張っていきたいと思います。

新しい技術のやってみた系は次の歴史をつくる若者たちに任せて、私は泥臭いトラブルシューティングについて書きたいと思います。

答えをざっと書いてしまうと数行で終わってしまってつまらないので、エラーを見たときにどう思ったかや、問題解決までの私の思考も書きたいと思います。

検証環境

本記事の検証環境は以下の通りです

  • Amazon Linux 2
  • nginx-1.20.0-2.amzn2.0.4

Amazon Linuxでのnginx rebuild

ある日、私はとあるシステムをオンプレミス環境からAWSへ移行するために検証をしていました。
そのシステムは単純な nginxphp で構成されており、楽勝やん!引退間近でもこれくらいできるぞ!と調子に乗っていました。

検証用の EC2 を 1台起動し、慣れた手付きでコマンド叩きました

$ sudo amazon-linux-extras install nginx
$ #(旧サーバーからconfigを移す)
$ sudo nginx -t

結果

$ sudo nginx -t
nginx: [emerg] unknown directive set_from_accept_language in /etc/nginx/nginx.conf:xx
nginx: configuration file /etc/nginx/nginx.conf test failed
$

えぇ… set_from_accept_language ってなんだよ…

  • とりあえず nginx set_from_accept_language でぐぐる
  • 一番上に公式のページがひっかかる。ラッキー
  • localeを取得するモジュールか。はいはい。
  • インストールの仕方を調べる

Installation
1. Download the module source from Github
2. Unpack, and then compile NGINX with:

$ ./configure –add-module=path/to/nginx_accept_language_module
出典: Accetp Language モジュール

ふむ…ソースから入れ直さないといけないのか…
ソースファイル から入れるのは管理上良くないので、rebuildしてパッケージを作り直す戦略でいきます。
でもその前に…一旦心を落ち着かせるためにお菓子を食べる!

nginx を rebuld するための準備

お菓子を食べたら rebuild のための準備します。

$ sudo yum -y install git.x86_64
$ sudo yum -y install rpmdevtools // rpmbuild をインストール
$
$ # 以下は必須ではないけど、このユーザーつくると rpmbuild実行時の warning がでなくなる
$ sudo useradd -s /sbin/nologin mockbuild
$ sudo useradd -s /sbin/nologin mock

必要なパッケージをインストールして

$ rpmdev-setuptree

を実行します。 よく rpmbuild を紹介しているブログ等をみると

$ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

として、rpmbuild のためのディレクトリを作成する方法を紹介していますが、 rpmdev-setuptree を打つと上記のコマンドと同じことをしてくれます。まぁ別に大したことはしてません。どっちでもいいです。

続いて追加する nginx のモジュールと nginx の src.rpm をダウンロードします。

$ git clone https://github.com/giom/nginx_accept_language_module.git /tmp/nginx_accept_language_module
$ yumdownloader --source nginx

ダウンロードした src.rpm をインストールします。

$ rpm -ivh nginx-1.20.0-2.amzn2.0.4.src.rpm

問題なくインストールできていれば ~/rpmbuild/SPECS 配下に nginx.spec ファイルが生成されています。
nginx_accept_language_module を組み込むために spec ファイルを編集します

$ vi rpmbuild/SPECS/nginx.spec

nginx.specbuild セクションで ./configure を定義しているところがあるので

--add-module=/tmp/nginx_accept_language_module \

の一行を追記します。これで rebuild の準備が整いました。

エラーその1 (雑魚戦)

rpmbuild コマンドを実行して rpm を作成します。

$ rpmbuild -ba ~/rpmbuild/SPECS/nginx.spec
$ rpmbuild -ba ~/rpmbuild/SPECS/nginx.spec
エラー: ビルド依存性の失敗:
gcc は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
gperftools-devel は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
openssl11-devel は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
pcre-devel は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
zlib-devel は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
GeoIP-devel は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
gd-devel は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
perl-devel は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
perl-generators は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
perl(ExtUtils::Embed) は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
libxslt-devel は nginx-1:1.20.0-2.amzn2.0.4.x86_64 に必要とされています
$
  • うん…いいね(謎
  • 依存するパッケージが足りないだけだね
  • 基本 yum search [pkg] -> yum install [pkg] を繰り返すだけでok
$ sudo yum -y install gcc.x86_64
$ sudo yum -y install gperftools-devel pcre-devel zlib-devel gd-devel GeoIP-devel perl-ExtUtils-Embed libxslt-devel
$ sudo yum -y install openssl11-devel.x86_64

順調… あとは perl-generators だけ…

$ yum search perl-generators
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
警告: 一致するものが見つかりません: perl-generators
No matches found
$
  • ない!
  • え…なぜない…
  • “amazon linux perl-generators” でぐぐる
  • 一番上は CentOS用のパッケージ だね
    • 却下
  • ぐぐった結果の2つ目あたりは Amazon Linux2022用のパッケージ のリリースノート…
    • バージョンは2022じゃないけど… All packages って書いてある…
    • perl-generators でページ内検索すると……ある!あるね
    • え、あるの…
  • ある……あるけど yum にはでてこない…ないけどある………そっか、epel だ(探偵が閃くエフェクト
$ sudo amazon-linux-extras install epel -y
$ yum search perl-generators
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
218 packages excluded due to repository priority protections
===== N/S matched: perl-generators =======================
perl-generators.noarch : RPM Perl dependencies generators

Name and summary matches only, use "search all" for everything.
$
  • あぁあったあった
    • 余裕やん
$ sudo yum install -y perl-generators

perl-generators をインストールして もう一回 rpmbuild

$ rpmbuild -ba ~/rpmbuild/SPECS/nginx.spec
実行中(%prep): /bin/sh -e /var/tmp/rpm-tmp.v7hoki
+ umask 022
+ cd /home/ec2-user/rpmbuild/BUILD
+ cat /home/ec2-user/rpmbuild/SOURCES/maxim.key /home/ec2-user/rpmbuild/SOURCES/mdounin.key /home/ec2-user/rpmbuild/SOURCES/sb.key
+ /usr/lib/rpm/redhat/gpgverify --keyring=/home/ec2-user/rpmbuild/BUILD/nginx.gpg --signature=/home/ec2-user/rpmbuild/SOURCES/nginx-1.20.0.tar.gz.asc --data=/home/ec2-user/rpmbuild/SOURCES/nginx-1.20.0.tar.gz
/var/tmp/rpm-tmp.v7hoki: line 30: /usr/lib/rpm/redhat/gpgverify: No such file or directory
エラー: /var/tmp/rpm-tmp.v7hoki の不正な終了ステータス (%prep)

RPM ビルドのエラー:
/var/tmp/rpm-tmp.v7hoki の不正な終了ステータス (%prep)
$
  • メゲるわ……
  • コーヒー入れよ…

エラーその2 (ボス戦)

コーヒーを飲んで心を落ち着かせた後にエラーを見直してみる。

  • この手のエラーの原因は ファイルが読み込めていないパーミッションエラー が9割(偏見)
  • なのでキーワードとして No such file or directoryPermission denied を探す

今回のエラーは

/usr/lib/rpm/redhat/gpgverify: No such file or directory

ここだね

  • やばい…嫌な予感しかしない
    • /usr/lib/rpm/redhat なんて特殊なディレクトリは普段使わない
  • “rpmbuild gpgverify” でぐぐってみる
    • パッとみ有効な情報がない!
    • なんかハマりそうな気がしてきた
  • 社内の slack で全文検索してみる
    • ない!
  • 社内のドキュメントシステムを全文検索してみる
    • ない!
  • どこにもノウハウがない情報なら ブログのネタになるな とか呑気なことを考える
  • 心を落ち着かせるためにベットでゴロゴロする
    • リモートワークの醍醐味

原因の特定

(10年後)

エラーになってる spec ファイルを改めて見てみる

# Combine all keys from upstream into one file
cat %{S:2} %{S:3} %{S:4} > %{_builddir}/%{name}.gpg
%{gpgverify} --keyring=%{_builddir}/%{name}.gpg --signature=%{SOURCE1} --data=%{SOURCE0}
  • ふむ…ここの gpgverify がない
  • verify だから鍵の検証をしてるだけだと思うけど…パッとみ何やってるかわからないなぁ
  • ………わからないものをいくら考えても仕方ない。ここを調べるのは後だ

もう一度 今度は “gpgverify” だけでぐぐってみる

  • fedora の pull-req が引っかかる
    • あ…
    • fedoraなのが若干気になるけど…issueになってるエラー内容は似てる
    • Files Changed をみると gpgverify を追加してる!
    • あ!これただのシェルスクリプトだ
       - ここでやっと中身がわかった
       - 最悪これコピーしたら良さそう
       - ちょっと気持ちが楽になる
    • そのまま main ブランチ見てみると…gpgverifyがあるね
       - History みてみると last commit が2年前(2022年現在)
       - (これだけ更新されてないなら)ますますもうこれでいいんじゃないかって思いはじめる

Amazon Linuxにはこの redhat-rpm-config ってのがあるのか調べる

$ yum search redhat-rpm-config
読み込んだプラグイン:extras_suggestions, langpacks, priorities, update-motd
218 packages excluded due to repository priority protections
========== 一致: redhat-rpm-config ===============================
system-rpm-config.noarch : Amazon Linux specific rpm configuration files
$

あっt…いや、ちがう! system-rpm-config.noarchだねこれ。

$ rpm -qa | grep system-rpm-config
system-rpm-config-9.1.0-76.amzn2.0.13.noarch
$

すでにインストール済だった。 gpgverifyが含まれているか調べる

$ rpm -ql system-rpm-config-9.1.0-76.amzn2.0.13.noarch | grep gpgverify
$

いや、gpgverify はないよね。ないんだよね。

てことは

OS rpm configuration files gpgverify
fedora redhat-rpm-config 含まれる
Amazon Linux2 system-rpm-config 含まれない

ていう構図になってるということですね。とりあえず エラーになる原因がわかった

gpgverifyを入れてエラーを解消する

あとはなんとかして gpgverify をインストールできないか…だけを気にする。
でも この感じだと gpgverify は 他のrpmで提供してそうだな…

  • “gpgverify rpm” でぐぐる
  • epel-rpm-macros なるもを見つける
    • Files/usr/lib/rpm/gpgverify を見つける
    • これやん
    • でもなんかパスが違う
    • …………でもこれが fedora のと同じものならこれでいいか。どうせこれシェルスクリプトだし

epel-rpm-macros をインストールする

$ sudo yum -y install epel-rpm-macros.noarch
  • ふむ…gpgverify が /usr/lib/rpm/gpgverify に入った
    • fedoraのものと見比べると…
    • なんか微妙に違うなw
    • あ、でも差分はコメントアウトの部分だけだ
    • よしこれでいこう!
  • cp してもいいけど…後でわからなくなりそうだからシンボリックリンクしとこ(好み
$ sudo ln -s /usr/lib/rpm/gpgverify /usr/lib/rpm/redhat/gpgverify

うん、いいね…これで rpmbuild をもう一回打つ

$ rpmbuild -ba ~/rpmbuild/SPECS/nginx.spec
実行中(%prep): /bin/sh -e /var/tmp/rpm-tmp.SaUNUJ
+ umask 022
+ cd /home/ec2-user/rpmbuild/BUILD
+ cat /home/ec2-user/rpmbuild/SOURCES/maxim.key /home/ec2-user/rpmbuild/SOURCES/mdounin.key /home/ec2-user/rpmbuild/SOURCES/sb.key
+ /usr/lib/rpm/redhat/gpgverify --keyring=/home/ec2-user/rpmbuild/BUILD/nginx.gpg --signature=/home/ec2-user/rpmbuild/SOURCES/nginx-1.20.0.tar.gz.asc --data=/home/ec2-user/rpmbuild/SOURCES/nginx-1.20.0.tar.gz
gpgv: Signature made Tue Apr 20 14:39:52 2021 UTC using RSA key ID A1C052F8
gpgv: Good signature from "Maxim Dounin <mdounin@mdounin.ru>"
...(省略)...
+ cd /home/ec2-user/rpmbuild/BUILD
+ cd nginx-1.20.0
+ /usr/bin/rm -rf /home/ec2-user/rpmbuild/BUILDROOT/nginx-1.20.0-2.amzn2.0.4.x86_64
+ exit 0

できたあああああああああああああああああ

$ ls -1 rpmbuild/RPMS/x86_64/
nginx-1.20.0-2.amzn2.0.4.x86_64.rpm
nginx-debuginfo-1.20.0-2.amzn2.0.4.x86_64.rpm
nginx-mod-http-geoip-1.20.0-2.amzn2.0.4.x86_64.rpm
nginx-mod-http-image-filter-1.20.0-2.amzn2.0.4.x86_64.rpm
nginx-mod-http-perl-1.20.0-2.amzn2.0.4.x86_64.rpm
nginx-mod-http-xslt-filter-1.20.0-2.amzn2.0.4.x86_64.rpm
nginx-mod-mail-1.20.0-2.amzn2.0.4.x86_64.rpm
nginx-mod-stream-1.20.0-2.amzn2.0.4.x86_64.rpm
$

これだ…これがほしかったんや…

最後に今入ってるやつと入れ替えて終わり

$ sudo yum remove nginx
$ sudo yum install -y ~/rpmbuild/RPMS/x86_64/nginx-1.20.0-2.amzn2.0.4.x86_64.rpm
$ sudo cp -ip /etc/nginx/nginx.conf.rpmsave /etc/nginx/nginx.conf // removeしたときにbkが取られる
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$

できた!

事の顛末

落ち着いた後に少しだけ調査してみました。

gpgverify について

gpgverify は一体何なのかなんですが、度々参照しているスクリプトの中身をみると

gpgverify is a wrapper around gpgv designed for easy and safe scripting.

と書かれており、 gpqv のラッパーであることがわかります。

gpqvOpenPGP署名のチェックツールです。

gpgverify 内で実行されているコマンドは以下の通りですが、

# Decode any ASCII armor on the keyring. This is harmless if the keyring isn't
# ASCII-armored.
gpg2 --homedir="${workdir}" --yes --output="${workring}" --dearmor "${keyring}"
check_status 'Decoding the keyring' $?

# Verify the signature using the decoded keyring.
gpgv2 --homedir="${workdir}" --keyring="${workring}" "${signature}" "${data}"
check_status 'Signature verification' $?

gpg2gpgv2 も初めからインストールされているコマンドですので、gpgverify はただの便利スクリプトであることがわかります。
ですので、シンボリックリンク貼っただけの今回の対応で問題ないでしょう。
(詳細はコメントアウトを参照)

おわりに

ぐぐっても答えがでてこないニッチな問題についてまとめてみました。
gpgverifyにお困りなニッチな人々の助けになれば幸いです。

tshiba

希望に満ちていた若者もアラフォーになりました。もうちょっとだけがんばります。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら