まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

2024 年になってから yum(dnf) 関連のブログエントリばかり書いてる気がしますが、今回のテーマも yum(dnf) 関連です。

前回のブログでも書いたのですが、yum は指定したモジュールを「ダウンロードだけ実行する(インストールは行わない)」ことを指定するパラメータがあります:
"yum install xxxxx" でインストールされるモジュールをダウンロードだけする

yum はダウンロードした .rpm ファイルを一時フォルダに格納して、その .rpm ファイルを使ってローカルインストールを実行します。インストールは普通に rpm ツールを使って実行するだけなのですが、今回のブログテーマはその手前、「ダウンロード」する部分に着目します。

例えば以下のような場面に遭遇しているとします(あまり関係ないですが RHEL 8.8 で実行した内容です):
# yum install ansible
Updating Subscription Management repositories.
Last metadata expiration check: 2:22:50 ago on Tue 02 Jan 2024 05:03:04 AM UTC.
Dependencies resolved.
================================================================================
 Package  Arch    Version           Repository                             Size
================================================================================
Installing:
 ansible  noarch  2.9.27-1.el8ae    ansible-2-for-rhel-8-x86_64-rpms       17 M
Installing dependencies:
 sshpass  x86_64  1.09-4.el8        rhel-8-for-x86_64-appstream-eus-rpms   30 k

Transaction Summary
================================================================================
Install  2 Packages

Total download size: 17 M
Installed size: 96 M
Is this ok [y/N]:

コマンドラインからは "yum install ansible" と入力しました。"ansible" というモジュールをインストールしようとしています。 色々と調べた結果、"ansible" というツールに加えて、その実行条件となる "sshpass" というライブラリモジュールも(現在の環境には足りてないと判断されて)インストールしようとしている、という場面です。通常はここで "y" と入力してインストール開始、、という流れになると思っています。普通はこの画面にこれ以上着目する必要もないのですが、今回は(たまにはいい機会だと思うので)この画面をもう少し詳しく見てみます。

このピンク色の部分をよく見ると、以下のような挙動を行おうとしていることが分かります:
ansible-2-for-rhel-8-x86_64-rpms リポジトリから ansible-2.9.27-1.el8ae.noarch.rpm をダウンロード(約 17MB
rhel-8-for-x86_64-appstream-eus-rpms リポジトリから sshpass-1.09-4.el8.x86_64.rpm をダウンロード(約 30kB


ではこれらの2つのファイルは具体的にはどこからダウンロードされるのでしょう? その答を調べるにはリポジトリに登録されている情報を調べる必要があります。CentOS や RHEL の場合、"/etc/yum.repos.d/" 以下に ".repo" という拡張子を持つファイルが1つ以上あり、その中にリポジトリの情報が記述されています。

私の環境では "/etc/yum.repos.d/redhat.repo" というファイルが1つだけ存在していて、このファイルの中に全てのリポジトリの情報が含まれていました。その一部だけを紹介しますが、以下のような内容になっていました(一部伏字にしています):
  :
  :
[rhel-8-for-x86_64-baseos-rpms]
name = Red Hat Enterprise Linux 8 for x86_64 - BaseOS (RPMs)
baseurl = https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/rhel8/8.8/x86_64/baseos/os
enabled = 1
gpgcheck = 1
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
sslverify = 1
sslcacert = /etc/rhsm/ca/katello-server-ca.pem
sslclientkey = /etc/pki/entitlement/xxxxxxxxxxxx-key.pem
sslclientcert = /etc/pki/entitlement/xxxxxxxxxxxx.pem
metadata_expire = 86400 enabled_metadata = 1 : : [rhel-8-for-x86_64-appstream-eus-rpms] name = Red Hat Enterprise Linux 8 for x86_64 - AppStream - Extended Update Support (RPMs) baseurl = https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/eus/rhel8/8.8/x86_64/appstream/os
enabled = 1 gpgcheck = 1 gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release sslverify = 1 sslcacert = /etc/rhsm/ca/katello-server-ca.pem sslclientkey = /etc/pki/entitlement/xxxxxxxxxxxx-key.pem
sslclientcert = /etc/pki/entitlement/xxxxxxxxxxxx.pem
metadata_expire = 86400 enabled_metadata = 1 : : [ansible-2-for-rhel-8-x86_64-rpms] name = Red Hat Ansible Engine 2 for RHEL 8 x86_64 (RPMs) baseurl = https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os
enabled = 1 gpgcheck = 1 gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release sslverify = 1 sslcacert = /etc/rhsm/ca/katello-server-ca.pem sslclientkey = /etc/pki/entitlement/xxxxxxxxxxxx-key.pem
sslclientcert = /etc/pki/entitlement/xxxxxxxxxxxx.pem
metadata_expire = 86400 enabled_metadata = 1 : :

ピンク色で記載しているのがリポジトリ名です。今回の処理でダウンロード元に指定されている2つのリポジトリがともに含まれていることがわかります(今回はリポジトリファイルが1つだけなので、1つのファイルを確認するだけで分かったのですが、複数のリポジトリファイルが存在している場合は全て調べないと分からない可能性があります)。

ではリポジトリファイルに記載されている情報を使って、目的の2つのファイルをダウンロードしてみます(単にダウンロードするだけなら前回のブログの応用で可能なのですが、今回は yum の仕組みを理解することを目的として wget を使ってダウンロードすることにします)。

では wget を使って2つのファイルをダウンロードしてみます。まずは ansible のファイルをダウンロードしてみます。

yum の実行結果やリポジトリファイルに書かれている情報から、ansible のファイルは ansible-2.9.27-1.el8ae.noarch.rpm というファイル名であることや、このファイルは(リポジトリの baseurl である)以下の文字列を含む URL からダウンロードされることがこの時点で推測できます:
https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/eus/rhel8/8.8/x86_64/appstream/os

では単純に https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/eus/rhel8/8.8/x86_64/appstream/os/ansible-2.9.27-1.el8ae.noarch.rpm という URL からダウンロードできるのでは? という予想もあると思いますが(現にそういう単純なパターンのケースもありますが)、ここはちゃんと調べてみましょう。ここからは wget を併用して調べてみます(手元の PC から直接接続できる URL であれば wget ではなくブラウザを使ってもいいのですが、以下の手順ではネットワークが繋がっていない可能性があることと、鍵ファイルも必要になることから wget を使うことにします。wget の方法で覚えておけば色んなケースに対応できてある意味安心です)。

まずはシンプルに baseurl の値から wget を実行してみます。一般的には baseurl の値に HTTP クライアントでアクセスするとファイルやフォルダの一覧(の HTML)が表示されるので、その画面から次にどの URL にアクセスすればよいか、を推測することができます。

というわけで wget で baseurl の値をヒントにアクセスしてみます:
# wget https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os
--2024-01-02 09:59:30--  https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os
Resolving rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)... 161.xx.xx.xx
Connecting to rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)|161.xx.xx.xx|:443... connected.
HTTP request sent, awaiting response... 403 [('PEM routines', 'PEM_read_bio', 'no start line')]
2024-01-02 09:59:30 ERROR 403: [('PEM routines', 'PEM_read_bio', 'no start line')].

おっと、接続はできているのですが 403 エラーが出てしまいました。「権限がない」という意味ですが、これは??

この 403 エラーの原因はリポジトリに記述されていました。改めて ansible-2-for-rhel-8-x86_64-rpms リポジトリの内容を確認してみます:
  :
  :
[ansible-2-for-rhel-8-x86_64-rpms]
name = Red Hat Ansible Engine 2 for RHEL 8 x86_64 (RPMs)
baseurl = https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os
enabled = 1 gpgcheck = 1 gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release sslverify = 1 sslcacert = /etc/rhsm/ca/katello-server-ca.pem sslclientkey = /etc/pki/entitlement/xxxxxxxxxxxx-key.pem
sslclientcert = /etc/pki/entitlement/xxxxxxxxxxxx.pem

metadata_expire = 86400 enabled_metadata = 1 : :

よく見ると、この URL にアクセスするには SSL の証明書が必要という情報が書かれていました。この情報が抜けていてアクセスに失敗していたようです。sslcacert は CA 証明書、sslclientkey は秘密鍵、sslclientcert はクライアント証明書で、それぞれのファイルの位置がフルパスで記述されています。

そして wget では以下のオプションを指定することができます:
 ・CA証明書: "--ca-certificate=(ファイルパス)"
 ・秘密鍵: "--private-key=(ファイルパス)"
 ・クライアント証明書: "--certificate=(ファイルパス)"

これらの情報を使い、CA 証明書、秘密鍵、クライアント証明書をそれぞれ指定するオプションを追加して再度先ほどのコマンドを実行してみます:
# wget --ca-certificate=/etc/rhsm/ca/katello-server-ca.pem --private-key=/etc/pki/entitlement/xxxxxxxxxxxx-key.pem --certificate=/etc/pki/entitlement/xxxxxxxxxxxx.pem https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os
--2024-01-02 10:19:58--  https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os/
Loaded CA certificate '/etc/rhsm/ca/katello-server-ca.pem'
Resolving rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)... 161.xx.xx.xx
Connecting to rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)|161.xx.xx.xx|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 407 [text/html]
Saving to: ‘index.html’

index.html          100%[===================>]     407  --.-KB/s    in 0s

2024-01-02 10:19:58 (29.8 MB/s) - ‘index.html’ saved [407/407]

今度は成功したようです。wget は text/html のウェブページに対して(ファイル名がないような URL で)実行すると、結果を "index.html" というファイルに保存してくれます。今回も成功して "index.html" というファイルができていたので、その内容を確認すると以下のように記載されていました:
        <!DOCTYPE html>
        <html>
            <body>
                <ul>

                    <li><a href="Packages/">Packages/</a></li>

                    <li><a href="config.repo">config.repo</a></li>

                    <li><a href="repodata/">repodata/</a></li>

                </ul>
            </body>
        </html>

3つのパスへのリンクが含まれる HTML になっていました。一般的にインストールファイルは "Packages/" フォルダ以下にあるので、今度はさっきの URL の後ろに "Packages/" を足して実行してみます:
# wget --ca-certificate=/etc/rhsm/ca/katello-server-ca.pem --private-key=/etc/pki/entitlement/xxxxxxxxxxxx-key.pem --certificate=/etc/pki/entitlement/xxxxxxxxxxxx.pem https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os/Packages/
--2024-01-02 10:19:58--  https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os/Packages/
Loaded CA certificate '/etc/rhsm/ca/katello-server-ca.pem'
Resolving rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)... 161.xx.xx.xx
Connecting to rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)|161.xx.xx.xx|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 295 [text/html]
Saving to: ‘index.html.1’

index.html.1        100%[===================>]     295  --.-KB/s    in 0s

2024-01-02 10:34:15 (8.24 MB/s) - ‘index.html.1’ saved [295/295]

今度は "index.html.1" というファイルに結果が保存されたようです。このファイルを確認します:
        <!DOCTYPE html>
        <html>
            <body>
                <ul>

                    <li><a href="a/">a/</a></li>

                    <li><a href="s/">s/</a></li>

                </ul>
            </body>
        </html>

ダウンロードされる .rpm ファイルは "Packages/" フォルダ直下に用意されているケースもありますが、多くの場合(ファイルが多いこともあってか)ファイル名の頭文字がついたサブフォルダの下に用意されているケースが多いです。今回のそのようでこの "Packages/" フォルダには "a/" と "s/" というサブフォルダが用意されていました。今回の目的のファイル名は "ansible-2.9.27-1.el8ae.noarch.rpm" だったので、おそらく "a/" サブフォルダの中に保存されている可能性が高いと推測できます。

というわけで再度、今度は URL の最後に更に "a/" を付けて wget を再実行してみます:
# wget --ca-certificate=/etc/rhsm/ca/katello-server-ca.pem --private-key=/etc/pki/entitlement/xxxxxxxxxxxx-key.pem --certificate=/etc/pki/entitlement/xxxxxxxxxxxx.pem https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os/Packages/a/
--2024-01-02 10:19:58--  https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os/Packages/a/
Loaded CA certificate '/etc/rhsm/ca/katello-server-ca.pem'
Resolving rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)... 161.xx.xx.xx
Connecting to rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)|161.xx.xx.xx|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7647 (7.5K) [text/html]
Saving to: ‘index.html.2’

index.html.2        100%[===================>]   7.47K  --.-KB/s    in 0s

2024-01-02 10:43:45 (293 MB/s) - ‘index.html.2’ saved [7647/7647]

今度は "index.html.2" というファイルに結果が保存されたようです。このファイルを確認します:
        <!DOCTYPE html>
        <html>
            <body>
                <ul>

                    <li><a href="ansible-2.8.0-1.el8ae.noarch.rpm">ansible-2.8.0-1.el8ae.noarch.rpm</a></li>

                    <li><a href="ansible-2.8.1-1.el8ae.noarch.rpm">ansible-2.8.1-1.el8ae.noarch.rpm</a></li>

                    <li><a href="ansible-2.8.2-1.el8ae.noarch.rpm">ansible-2.8.2-1.el8ae.noarch.rpm</a></li>

                    <li><a href="ansible-2.8.3-1.el8ae.noarch.rpm">ansible-2.8.3-1.el8ae.noarch.rpm</a></li>

                    <li><a href="ansible-2.8.4-1.el8ae.noarch.rpm">ansible-2.8.4-1.el8ae.noarch.rpm</a></li>

                        :
                        :

                    <li><a href="ansible-2.9.26-1.el8ae.noarch.rpm">ansible-2.9.26-1.el8ae.noarch.rpm</a></li>

                    <li><a href="ansible-2.9.27-1.el8ae.noarch.rpm">ansible-2.9.27-1.el8ae.noarch.rpm</a></li>

                    <li><a href="ansible-2.9.4-1.el8ae.noarch.rpm">ansible-2.9.4-1.el8ae.noarch.rpm</a></li>

                        :
                        :

                    <li><a href="ansible-test-2.9.5-1.el8ae.noarch.rpm">ansible-test-2.9.5-1.el8ae.noarch.rpm</a></li>

                    <li><a href="ansible-test-2.9.6-1.el8ae.noarch.rpm">ansible-test-2.9.6-1.el8ae.noarch.rpm</a></li>

                    <li><a href="ansible-test-2.9.7-1.el8ae.noarch.rpm">ansible-test-2.9.7-1.el8ae.noarch.rpm</a></li>

                    <li><a href="ansible-test-2.9.9-1.el8ae.noarch.rpm">ansible-test-2.9.9-1.el8ae.noarch.rpm</a></li>

                </ul>
            </body>
        </html>

"ansible-2.9.27-1.el8ae.noarch.rpm" 、やっと見つかりました!このフォルダの下にあったんですね。

というわけで最後に "ansible-2.9.27-1.el8ae.noarch.rpm" を URL の最後に追加して wget を実行します:
# wget --ca-certificate=/etc/rhsm/ca/katello-server-ca.pem --private-key=/etc/pki/entitlement/xxxxxxxxxxxx-key.pem --certificate=/etc/pki/entitlement/xxxxxxxxxxxx.pem https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os/Packages/a/ansible-2.9.27-1.el8ae.noarch.rpm
--2024-01-02 10:19:58--  https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/dist/layered/rhel8/x86_64/ansible/2/os/Packages/a/ansible-2.9.27-1.el8ae.noarch.rpm
Loaded CA certificate '/etc/rhsm/ca/katello-server-ca.pem'
Resolving rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)... 161.xx.xx.xx
Connecting to rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)|161.xx.xx.xx|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 17705052 (17M) [application/octet-stream]
Saving to: ‘ansible-2.9.27-1.el8ae.noarch.rpm’

ansible-2.9.27-1.el 100%[===================>]  16.88M  --.-KB/s    in 0.06s

2024-01-02 10:53:08 (270 MB/s) - ‘ansible-2.9.27-1.el8ae.noarch.rpm’ saved [17705052/17705052]

長い道のりを経て、やっと "ansible-2.9.27-1.el8ae.noarch.rpm" がダウンロードできました!

もう1つのファイル "sshpass-1.09-4.el8.x86_64.rpm" も同様にして "rhel-8-for-x86_64-appstream-eus-rpms" リポジトリからダウンロードできます:
# wget --ca-certificate=/etc/rhsm/ca/katello-server-ca.pem --private-key=/etc/pki/entitlement/xxxxxxxxxxxx-key.pem --certificate=/etc/pki/entitlement/xxxxxxxxxxxx.pem https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/eus/rhel8/8.8/x86_64/appstream/os/Packages/s/sshpass-1.09-4.el8.x86_64.rpm
--2024-01-02 10:19:58--  https://rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com/pulp/repos/customer/Library/content/eus/rhel8/8.8/x86_64/appstream/os/Packages/s/sshpass-1.09-4.el8.x86_64.rpm
Loaded CA certificate '/etc/rhsm/ca/katello-server-ca.pem'
Resolving rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)... 161.xx.xx.xx
Connecting to rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com (rhha02.updates.jp-tok.iaas.service.xxxxxxxxxx.com)|161.xx.xx.xx|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 30568 (30K) [application/octet-stream]
Saving to: ‘sshpass-1.09-4.el8.x86_64.rpm’

sshpass-1.09-4.el8. 100%[===================>]  29.85K  --.-KB/s    in 0s

2024-01-02 11:07:37 (185 MB/s) - ‘sshpass-1.09-4.el8.x86_64.rpm’ saved [30568/30568]

まとめると、、
・yum コマンドの実行結果にリポジトリの情報が含まれている
・/etc/yum.repos.d/ 以下にリポジトリの URL や鍵に関する情報が含まれている
・これらの情報を組み合わせつつ、wget でフォルダ階層を調べながら目的ファイルの URL を調べていくことでファイルのダウンロードも可能

となります。

前回に引き続き yum(dnf) 関連の小ネタです。


前回のおさらいも含めますが、yum を使って、例えば "wget" をインストールしようとする場合、以下のような "yum install" コマンドを実行することになります:
# yum install wget
Updating Subscription Management repositories.
Last metadata expiration check: 1:19:58 ago on Mon Jan  1 09:30:11 2024.
Dependencies resolved.
================================================================================
 Package Arch      Version            Repository                           Size
================================================================================
Installing:
 wget    x86_64    1.21.1-7.el9       rhel-9-for-x86_64-appstream-rpms    794 k

Transaction Summary
================================================================================
Install  1 Package

Total download size: 794 k
Installed size: 3.1 M
Is this ok [y/N]:

普通にインターネット環境が整っていれば、インターネット上のリポジトリを参照し、必要な依存ライブラリと現在の OS にインストール済みのライブラリとを比較し、足りない(追加でインストールが必要な)ライブラリとまとめてインストールしてくれます。一般的な利用であればこれだけ覚えておけば充分なケースも少なくありません。

ただ少し特殊なケース、例えば「インターネット接続環境がない」 CentOS/RHEL 環境の場合にどうやってインストールするか、というのは少し工夫が必要になります。今回のブログのテーマがこれです。

これはケース・バイ・ケースなんですが、おそらく以下(1)~(3)のいずれかの方法で解決できると思っています。実現が容易な順に(1)から(3)と記載しているので、数字が小さい方法で解決できるものかどうかを調べて、できない場合は次の数字へ、、という順に調べていただくのがおススめです。なおインストールするパッケージのライセンスに関わる問題は解決済みである(正式なライセンスを持っていて、インターネット接続できている場合はライセンス含めて問題なくインストールできるもの)と仮定します。

(1)DVD や ISO などのインストールメディアを持っている場合、

インターネット環境はないけれど、OS のインストール時に使った DVD メディアや、その ISO ファイルを持っているようなケースです(本来なら初期インストール時に一緒に入れておけばよかったのに入れ忘れたケースも含みます)。目的のファイルの rpm パッケージが含まれたメディアが手元にある場合は、そのメディアを使ってインストールすることが可能です。

具体的にはそのメディアをマウントした上で、ローカル環境に新しいリポジトリを1つ追加することで、インターネット上ではなく、ローカルファイルシステムに展開されたリポジトリが使えるようになり、そのローカルリポジトリを使ってインストールする、という方法です。少し古い環境で書かれていますが、以前に書いたこちらのブログエントリを参照するとより具体的な手順を説明しています:
ローカル環境内に yum リポジトリを作成する


(2)DVD や ISO などのインストールメディアを持っていない場合、

問題はこちらです。インターネット上に目的のパッケージファイルがあり、インストール用 DVD や他の DVD などでは提供されていないようなケースです(ansible などはこのパターンです)。インターネットに接続されている状況下であれば普通に "yum install" でインストールできるけど、接続がないとモジュールにアクセスできないのでインストールできない、ということになります。

これも考え方としては(1)と同様で「なんとかしてインストールに必要なファイルを入手して、ローカルファイルシステム上に用意」して、「ローカルリポジトリを作ってインストールする」ことになります。問題は「なんとかしてインストールに必要なファイルを入手」する部分です。

ここから先は実際にインターネットに接続されていない環境(目的のインストールを行う環境)とは別にインターネットに接続された環境を用意するか、その環境を一時的でいいのでインターネットに接続して実施する必要があります。インターネット接続のある環境で準備して、準備したファイルを目的の環境にコピー(転送)すれば、後は(1)と同様にできる、というやり方です。この前提が必要となる点に注意してください。

さて、インターネット接続のある環境で目的のファイルを(インストールではなく)ダウンロードだけ行うにはどのようにすればいいでしょうか? 例えば上述の "wget" の例で考えると、「"yum install wget" の結果としてダウンロードされてインストールされるファイルをダウンロードだけしたい」ことになります。

これは yum のオプション指定で可能でした。具体的には以下2つのオプションを指定します:
 ・"--downloadonly"
 ・"--destdir=(保存先ディレクトリ)"

"wget" の例だと以下のように実行します(この例だと保存先に /tmp を指定し、また確認プロンプトで止めないように "-y" オプションも指定しています):
# yum install --downloadonly --destdir=/tmp -y wget
Updating Subscription Management repositories.
Last metadata expiration check: 0:59:59 ago on Tue Jan  2 05:56:23 2024.
Dependencies resolved.
================================================================================
 Package       Architecture    Version                  Repository         Size
================================================================================
Installing:
 wget          x86_64          1.21.1-7.el9             myrhel92          794 k

Transaction Summary
================================================================================
Install  1 Package

Total size: 794 k
Installed size: 3.1 M
YUM will only download packages for the transaction.
Downloading Packages:
Complete!

成功すると(私の環境だと) "/tmp/wget-1.21.1-7.el9.x86_64.rpm" というファイルがダウンロードできていました。具体的なファイル名は実行環境やタイミングによって(バージョンなどが)少し変わる可能性もありますが、目的のファイルがダウンロードできたことになります。 ちなみにこうしてダウンロードできた rpm ファイルをスタンドアロン環境でインストールするには、上述のようなローカルリポジトリを作って行う場合以外にも、
# yum install /tmp/wget-1.21.1-7.el9.x86_64.rpm

のようにフルパス指定することでも可能になります。

ちなみに、上の wget のケースでは rpm ファイル1つだけが必要で、ダウンロードファイルも1つだけでした。これが、
# yum install --downloadonly --destdir=/tmp jq
Updating Subscription Management repositories.
Last metadata expiration check: 1:06:58 ago on Tue Jan  2 05:56:23 2024.
Dependencies resolved.
================================================================================
 Package           Architecture   Version                Repository        Size
================================================================================
Installing:
 jq                x86_64         1.6-14.el9             myrhel92         190 k
Installing dependencies:
 oniguruma         x86_64         6.9.6-1.el9.5          myrhel92         221 k

Transaction Summary
================================================================================
Install  2 Packages

Total size: 411 k
Installed size: 1.1 M
Is this ok [y/N]:

のように依存ライブラリが存在しているような場合はどうなるのでしょうか? 答はシンプルで「依存ファイルもまとめてダウンロード」されることになります。上の例だと、
 ・/tmp/jq-1.6-14.el9.x86_64.rpm
 ・/tmp/oniguruma-6.9.6-1.el9.5.x86_64.rpm

という2つのファイルがダウンロードされます。ダウンロード後のインストールは2つのファイルをそれぞれフルパス指定してローカルインストールしてもいいですし、2つのファイルを含むローカルリポジトリを作ってから "yum install jq" を実行する、でもセットアップできます。


(3)既にインストール済みの場合、

最後はちょっとややこしいケースです。例えば "wget" のモジュールをダウンロードしようとして、以下のようなメッセージがでることがあります:
# yum install --downloadonly --destdir=/tmp -y wget
Updating Subscription Management repositories.
Last metadata expiration check: 1:14:12 ago on Tue Jan  2 05:56:23 2024.
Package wget-1.21.1-7.el9.x86_64 is already installed.
Dependencies resolved.
Nothing to do.
Complete!

「(この環境には)既にインストール済みなので何もすることはない」というメッセージが表示されています。ある程度環境が整っているマシンで実行すると、このようなケースは珍しくないと思っています。が、元々このマシンでインストールしたくてダウンロードしているのではなく、別のインターネットにつながっていないマシンでローカルインストールできるようにするためのダウンロードをしているので、今のマシンにインストールされているかどうかは関係なくダウンロードしたい、という背景があります。

これは「1度アンインストールする」ことで話が単純になります。つまり、
 ・一度アンインストール
 ・ローカルにダウンロード(上の(2)の手順)
 ・再度インストール(環境を元に戻す)
を順に実施することで目的のファイルのダウンロードができます。


っていうか、インターネットのない環境でのセットアップ、って今はもうかなり面倒なことになってきているんですね。まあ確かに「内側からインターネットに出ていくだけ」すら許されない環境って、「そのせいでここまでセットアップにコストがかかる」デメリットを凌ぐだけの理由があるんだろうか?? という気がして・・・ あ、いえいえ、仕事の愚痴ではありませんよ。


2024 年最初のブログとなりました。「ブログの書初め」です、本年もよろしくお願いします。

CentOS / RHEL 系の Linux で rpm パッケージをインストールする際には "yum"("dnf" 派の人もいるかもしれませんが、ここでは "yum" で統一します。内容は同じなので単純に読み替えていただいて大丈夫です)を使う機会が多いと思っています。

この yum を使って、例えば "wget" をインストールしようとすると、
# yum install wget

というコマンドを実行します。すると、
# yum install wget
Updating Subscription Management repositories.
Last metadata expiration check: 3:32:04 ago on Mon Jan  1 05:44:30 2024.
Dependencies resolved.
================================================================================
 Package Arch      Version            Repository                           Size
================================================================================
Installing:
 wget    x86_64    1.21.1-7.el9       rhel-9-for-x86_64-appstream-rpms    794 k

Transaction Summary
================================================================================
Install  1 Package

Total download size: 794 k
Installed size: 3.1 M
Is this ok [y/N]:

↑のようなメッセージが表示されて、最後に "Is this ok [y/N]:" と確認メッセージが表示されて止まります。「このパッケージをインストールするよ、OK?」と聞かれていて、"y" と入力するとインストール開始、"n" だとインストールせずに終了します("[y/N]" と "N" が大文字になっているのでデフォルトは "n" ということになります。つまりそのままリターンキーを入力すると "n" とみなされます)。

で、この確認メッセージで止まるのが面倒な場合、つまり「正しいことはわかっているから、いいからインストールして」と思っている場合はコマンドのどこか(最後とか)に "-y" オプションを指定します。つまり、
# yum install wget -y

と入力することで、確認メッセージなしでインストールを始めることができます。シェルスクリプトなどで連続実行したい場合はよく使いますよね。


で、このブログのメインはここからです。需要は少ないかもしれないのですが、「この "-y" の逆のオプションって何だろう?」という疑問が生じて調べてみました。要は「 "yum install" のインストール直前までを実行して、インストールせずに終了する」ようなオプションです。

単純に「 "-n" かな?」と思ったのですが「そんなパラメータ知らん」と怒られてしまいました:
# yum install wget -n
Updating Subscription Management repositories.
usage: yum install [-c [config file]] [-q] [-v] [--version]
                   [--installroot [path]] [--nodocs] [--noplugins]
                   [--enableplugin [plugin]] [--disableplugin [plugin]]
                   [--releasever RELEASEVER] [--setopt SETOPTS]
                   [--skip-broken] [-h] [--allowerasing] [-b | --nobest] [-C]
                   [-R [minutes]] [-d [debug level]] [--debugsolver]
                   [--showduplicates] [-e ERRORLEVEL] [--obsoletes]
                   [--rpmverbosity [debug level name]] [-y] [--assumeno]
                   [--enablerepo [repo]] [--disablerepo [repo] | --repo
                   [repo]] [--enable | --disable] [-x [package]]
                   [--disableexcludes [repo]] [--repofrompath [repo,path]]
                   [--noautoremove] [--nogpgcheck] [--color COLOR] [--refresh]
                   [-4] [-6] [--destdir DESTDIR] [--downloadonly]
                   [--comment COMMENT] [--bugfix] [--enhancement]
                   [--newpackage] [--security] [--advisory ADVISORY]
                   [--bz BUGZILLA] [--cve CVES]
                   [--sec-severity {Critical,Important,Moderate,Low}]
                   [--forcearch ARCH]
                   PACKAGE [PACKAGE ...]
yum install: error: unrecognized arguments: -n

"-n" ではないとしたら、果たしてそんなオプショことがあるのか(そもそも「そんなオプション使うことがあるのか?」と言われそうですが、その件についてはいずれまた)、という疑問が生じ、一度ちゃんと調べてみました。結論としては存在していて、上のエラーメッセージ内にも表示されている "--assumeno" オプションでした。このオプションを付けて実行することで、インストールされる rpm ライブラリに関する(アーキテクチャやバージョン、サイズなどの)情報を表示されるだけでインストールは実行しない、という挙動が可能になります:
# yum install wget --assumeno
Updating Subscription Management repositories.
Last metadata expiration check: 0:09:21 ago on Mon Jan  1 09:30:11 2024.
Dependencies resolved.
================================================================================
 Package Arch      Version            Repository                           Size
================================================================================
Installing:
 wget    x86_64    1.21.1-7.el9       rhel-9-for-x86_64-appstream-rpms    794 k

Transaction Summary
================================================================================
Install  1 Package

Total download size: 794 k
Installed size: 3.1 M
Operation aborted.

# 

インストールは何もせずに "Operation aborted." と表示されてプロンプトに戻ってきました(この挙動は "n" を入力した時と全く同じです)。


インストールしようと思っているライブラリに関する情報だけを収集するようなシェルスクリプトを作るようなケースで役立つ、かもしれない、情報でした。



このページのトップヘ