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

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

タグ:download

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)の手順)
 ・再度インストール(環境を元に戻す)
を順に実施することで目的のファイルのダウンロードができます。


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


日本時間の 2016 年 4 月 1 日に、レッドハット社から驚きの発表がありました:
No-Cost RHEL Developer Subscription now available

2016040101



開発(者)向け、という条件は付きますが、RHEL(RedHat Enterprise Linux) を含む Devloper Suite が無料でダウンロード可能になった、というものです。マジか!?これはタチの悪いエイプリルフールだろ?と思ったのですが、このニュースは米国時間の 3 月 31 日にリリースされており、エイプリルフールではなさそうです。。

自分はこれまで RHEL のコミュニティ版ともいえる CentOS ばかり使っていましたが、ついにこの領域にレッドハット社が脚を踏み入れることになるとは。。 色々な事情や背景も考えられますが、なにはともあれ使えるものなら使ってみたいわけです(笑)。試してみました。


まずは RHEL のダウンロードサイトへ行ってみると、既にこの発表を反映した内容になっています:
http://developers.redhat.com/products/rhel/download/

2016040102


このサイトから RHEL 7 がダウンロードできるようになっている模様です。リンクをクリックすると、アカウントログインが求められます。RedHat Developer アカウントを持っている場合は入力、持っていない場合は新規に作成してログインします。各種SNSの情報に紐付けたサインインもできるようです:
2016040103


そしてアカウントプロファイル作成後にログインすると、その場から RHEL サーバーの ISO イメージのダウンロードが開始されました(バージョン 7.2 の 64bit 版でした。そういや 7.x って 32bit 版ないんだっけ)。インストールなど、ダウンロード後の作業手順についてもここから参照できるようです:
2016040104


といっても特別な手順が必要なわけではなく、普通に ISO(DVD) からブートできます:
2016040105


インストーラーも普通でした。最初に日本語選んでおけばインストール作業から日本語GUIで行えます:
2016040106


インストールが完了してリブートした直後の画面がこちらです。"LICENSE INFORMATION" に警告マークがついているので、ここをクリックします:
2016040107


ライセンス条項を読み、確認して、同意にチェックを入れ、左上の「完了」ボタンで戻ります:
2016040108


画面が戻ると先程の警告マークが消えているはずです。右下のボタンで設定を完了します:
2016040109


「ようこそ」画面が出るので更に進めていきます。すると・・・:
2016040110


じゃーん!
2016040101


個人的には見る機会の少ない RedHat Enterprise Linux のデスクトップ画面が表示されました。7.x になってからは本当に初めてかもしれない。。 ともあれ、無料のアカウント登録だけで本当に使えてしまいました。

動いてしまえば、後は慣れた CentOS の感覚(?)で使えるようになります:
2014040101






MVC 型の PHP アプリケーション開発フレームワークである cakePHP を使ってます。単なるテンプレートエンジンである以上に、日本に利用者が多い(つまり日本語の情報を見つけやすい)こともあって、とても便利です。
cake-logo


そんな cakePHP を使って作っているアプリケーションで、「TSV(CSV) ファイルをダウンロードさせたい」という機能を実装する方法を紹介します。なまじ View/Controller の組み合わせに慣れてしまうと、TSV(CSV) のような View を無視する機能を cakePHP でどう実装するか、という点に迷いますよね。TSV ファイルを作成する前提で調査結果をまとめました。

結論として View(***.ctp) は用意しません。そして Controller 側に以下のような記述を行います:
function download(){
  $this->autoRender = false; //. Viewを使わない
  Configure::write('debug', 0); //. debugコードを出さない

  //. HTTP ヘッダを TSV 用に変更
  header ("Content-disposition: attachment; filename=test.tsv");
  header ("Content-type: application/octet-stream; name=test.tsv");

  //. TSV 本体を生成する部分
  $tsv = "";
  $items = $this->Item->find('all');
  foreach( $items as $item ){
    //. 日本語部分をシフトJISに変換しながら TSV の一行を作成
    $line = $item['Item']['id'] 
      . "\t" . mb_convert_encoding( $item['Item']['name'], "SJIS" )
      . "\t" . mb_convert_encoding( $item['Item']['body'], "SJIS" )
      . "\n";
    $tsv .= $line;
  }

  print($tsv); //. 生成した TSV を出力
  return;
}

肝として、まず View を使わずに処理を終えたいので、autoRender プロパティを false に変更します。また出力結果に debug コードを出したくないこともあるので、debug レベルを 0 に設定しておきます。 更に TSV ファイルをそのまま(選択肢なしで)ダウンロードさせたいので、HTTP ヘッダをダウンロード用のものに変更しています。

TSV 本体部分のコーディングは出力したい内容によって異なりますが、普通に出力したい内容をタブ("\t")区切りにして1行ずつ生成します。これだけでもいいのですが、もし出力した TSV をそのままエクセルで読み込みたい場合などは、文字コードをシフト JIS にしておく必要がある点に注意が必要です。

生成した TSV を最後に出力して処理終了、です。


cakePHP はとても便利なフレームワークですが、今回のような(ビューを使わない)特殊な処理を行う場合は少し特殊な手順が必要になる、というサンプルです。


 

このページのトップヘ