経緯
yumを使用できないサーバにrpmでパッケージをインストールする作業が最近増えてきた。
OSのインストールディスク(/Packagesディレクトリ)にある大量のrpmファイルから必要なファイルを抽出し、rpmコマンドでインストールするという作業が多い。
rpmを使用したインストールは、毎回依存関係に苦しめられる。これのせいでヘタすると1日がかりになってしまうこともある。
yumだと5分もかからない作業なので、アホらしくなってくる。
今後も何回か発生しそうな作業なので、bashスクリプトを作成して作業時間の短縮を試みる。
[2015/12/27 追記]
iwaim@github様より、yumコマンドでもOSのインストールディスクからインストールできることを教えていただきました。
※下記コメント参照。
こちらの方もご覧ください。
内容
作成するスクリプトの動作は以下の通り。
検索用辞書作成
事前に検索用の辞書ファイルを作成する。
大量のrpmファイルから「パッケージ名」「含まれているファイル名」を抽出し、ファイルに出力する。インストールされていない依存関係にあるrpmファイル名抽出
インストールするrpmファイル名と検索用辞書を元に、インストールされていない依存関係にあるrpmファイル名を抽出する。-
rpmインストールコマンド文字列生成
インストールされていない依存関係にあるrpmファイルを含めたインストールコマンド文字列を生成する。インストールコマンド文字列のフォーマットrpm -ivh <rpmファイル名> [<rpmファイル名2>...]
例)
rpm -ivh xorg-x11-utils-7.5-6.el6.x86_64.rpm libX11-1.5.0-4.el6.x86_64.rpm ...
スクリプト
OSのバージョンは以下の通り。
Red Hat Enterprise Linux Server release 6.4 (Santiago)
検索用辞書作成
# ----------------------------------------------------------------------------------------------
# Name : create_rpmlist
# Purpose : rpm依存ファイル検索で使用する辞書を作成する。
# Usage : create_rpmlist
# Return :
# _DEPENDENCY_INFO_FILE変数で指定したファイルに辞書を出力する。
# 辞書のフォーマットは以下の通り。(空白区切り)
# "パッケージ名" "rpmファイル名" "rpmファイルに含まれるファイル名"
# 例)
# …(省略)…
# gcalctool gcalctool-5.28.2-3.el6.x86_64.rpm /usr/share/omf/gcalctool/gcalctool-zh_HK.omf
# gcalctool gcalctool-5.28.2-3.el6.x86_64.rpm /usr/share/omf/gcalctool/gcalctool-zh_TW.omf
# gcc gcc-4.4.7-3.el6.x86_64.rpm /usr/bin/c89
# gcc gcc-4.4.7-3.el6.x86_64.rpm /usr/bin/cc
# …(省略)…
# Example : create_rpmlist /tmp/_rpmlist.txt
# Remarks1 :
# _DEPENDENCY_INFO_FILE変数を必ず設定すること。
# 例) _DEPENDENCY_INFO_FILE=/tmp/_rpmlist.txt
# Remarks2 : i686の情報は格納しない。
# Remarks3 :
# rpmファイル名からパッケージ名を取得する処理について。
# "rpm -qip"を使用し詳細情報を取得後、"Name : "で始まる行の3フィールド目を取得する。
# 実行例)
# # rpm -qip gcc-4.4.7-3.el6.x86_64.rpm
# …(省略)…
# Name : gcc Relocations: (not relocatable)
# Version : 4.4.7 Vendor: Red Hat, Inc.
# Release : 3.el6 Build Date: 2012年10月19日 02時33分21秒
# …(省略)…
# ----------------------------------------------------------------------------------------------
function create_rpmlist(){
for fname in *.rpm ; do
pname=$(rpm -qip "${fname}" 2>&1 | grep 'Name :' | sed -e 's/ */ /g' | cut -d ' ' -f3)
for line in $(rpm -qpl "${fname}"); do
echo "$pname $fname $line"
done
done 2> /dev/null | grep -v '.i686.' > "${_DEPENDENCY_INFO_FILE}" # 今回のマシンはi686ではないので除外する。
echo "ListFile creation completion!"
}
インストールされていない依存関係にあるrpmファイル名抽出
# ----------------------------------------------------------------------------------------------
# Name : search_dependent
# Purpose : インストールされていない依存しているrpmファイルを検索する。
# Usage : search_dependent <rpmfile> [<rpmfile2> ...]
# Return : インストールされていない依存しているrpmファイル名のリスト(空白区切り)
# Example :
# search_dependent gcc-4.4.7-3.el6.x86_64.rpm libstdc++-devel-4.4.7-3.el6.x86_64.rpm
# ↓結果例
# cloog-ppl-0.15.7-1.2.el6.x86_64.rpm cpp-4.4.7-3.el6.x86_64.rpm glibc-devel-2.12-1.107.el6.x86_64.rpm
# Remarks1 :
# _DEPENDENCY_INFO_FILE変数を必ず設定すること。
# 例) _DEPENDENCY_INFO_FILE=/tmp/_rpmlist.txt
# Remarks2 : 事前に辞書を作成すること。(create_rpmlistを使用)
# Remarks3 :
# 依存性確認の処理について
# "rpm -ivh --test 〜"を使用して依存を確認する。依存する「パッケージ名」または
# 「rpmに含まれるファイル名」が出力されるが、結果だけではどちらか判断できない。
# 結果例)
# gcc = 4.4.7-3.el6 is needed by gcc-c++-4.4.7-3.el6.x86_64 ★パッケージ名
# libmpfr.so.1()(64bit) is needed by gcc-c++-4.4.7-3.el6.x86_64 ★rpmに含まれるファイル名
# libstdc++-devel = 4.4.7-3.el6 is needed by gcc-c++-4.4.7-3.el6.x86_64 ★パッケージ名
# rpm実行時にエラーが出るだけで大事にはいたらないので、複雑な処理は避けたい。
# 以下を仕様とする。
# - 調査対象の文字列を、まず「パッケージ名」として検索する。存在しない場合は
# 「rpmに含まれるファイル名」として検索する。
# - 「rpmに含まれるファイル名」にも関わらずパッケージ名でヒットしてしまう可能性が
# あるが、仕様とする。
# ----------------------------------------------------------------------------------------------
function search_dependent(){
local rpmfiles="$@"
local keywords=$(LANG=C rpm -ivh --test ${rpmfiles} 2>&1 | grep ' is needed by ' | sed -e 's/^\s*//g' -e 's/(.*)//g' | cut -d ' ' -f1)
local pnames=$(for keyword in ${keywords}; do
# 「パッケージ名」よりrpmファイル名を抽出
pnames=($(cat "${_DEPENDENCY_INFO_FILE}" | awk '{ if($1 == "'"${keyword}"'") print $2; }' ))
if [ "${#pnames[@]}" -eq 0 ]; then
# 「rpmに含まれるファイル名」よりrpmファイル名を抽出
pnames=($(cat "${_DEPENDENCY_INFO_FILE}" | awk '{ if($3 ~ /'"${keyword}"'/) print $2; }'))
fi
echo "${pnames}"
done | sort | uniq )
echo ${pnames} # 改行を消す
}
rpmインストールコマンド文字列生成
# ----------------------------------------------------------------------------------------------
# Name : create_rpminstallcmd
# Purpose : rpmインストールコマンド文字列作成
# Usage : create_rpminstallcmd <rpmfile> [<rpmfile2> ...]
# Return : rpmインストールコマンド文字列
# Example :
# create_rpminstallcmd gcc-c++-4.4.7-3.el6.x86_64.rpm
# ↓結果例
# rpm -ivh gcc-4.4.7-3.el6.x86_64.rpm libstdc++-devel-4.4.7-3.el6.x86_64.rpm …(省略)… glibc-devel-2.12-1.107.el6.x86_64.rpm
# Remarks1 :
# _DEPENDENCY_INFO_FILE変数を必ず設定すること。
# 例) _DEPENDENCY_INFO_FILE=/tmp/_rpmlist.txt
# Remarks2 : 事前に辞書を作成すること。(create_rpmlistを使用)
# ----------------------------------------------------------------------------------------------
function create_rpminstallcmd(){
local rpmfiles="$@"
local depfiles=''
# "30"は依存ファイルの依存を調査する回数。
# "while :"を使用した場合無限ループになる可能性があるため、forで制限を設定した。
# 依存が30層を上回ることはまずないだろう。
for (( i=0; i<30; ++i ))
do
depfiles=$(search_dependent "${rpmfiles}")
[ "${#depfiles}" -eq 0 ] && break
rpmfiles="${rpmfiles} ${depfiles}"
done
echo "rpm -ivh ${rpmfiles}"
}
実行
# OSインストールディスクマウント
su -
mount -r -t iso9660 /dev/cdrom /media
# rpmファイルが置いてあるディレクトリに移動
cd /media/Packages
# 一時ファイルの設定
_DEPENDENCY_INFO_FILE=/tmp/_rpmlist.txt
# 検索用辞書ファイルを作成
create_rpmlist
# rpmインストールコマンド作成スクリプト実行1
create_rpminstallcmd unzip-6.0-1.el6.x86_64.rpm
# rpm -ivh unzip-6.0-1.el6.x86_64.rpm
# rpmインストールコマンド作成スクリプト実行2
create_rpminstallcmd xorg-x11-utils-7.5-6.el6.x86_64.rpm
# rpm -ivh xorg-x11-utils-7.5-6.el6.x86_64.rpm libX11-1.5.0-4.el6.x86_64.rpm libXext-1.3.1-2.el6.x86_64.rpm libXi-1.6.1-3.el6.x86_64.rpm libXinerama-1.1.2-2.el6.x86_64.rpm libXrender-0.9.7-2.el6.x86_64.rpm libXtst-1.2.1-2.el6.x86_64.rpm libXv-1.0.7-2.el6.x86_64.rpm libXxf86dga-1.1.3-2.el6.x86_64.rpm libXxf86misc-1.0.3-4.el6.x86_64.rpm libXxf86vm-1.1.2-2.el6.x86_64.rpm libdmx-1.1.2-2.el6.x86_64.rpm libxcb-1.8.1-1.el6.x86_64.rpm libX11-common-1.5.0-4.el6.noarch.rpm libXau-1.0.6-4.el6.x86_64.rpm
# 複数のrpmインストールコマンドを生成し、まとめて実行。
(
create_rpminstallcmd unzip-6.0-1.el6.x86_64.rpm
create_rpminstallcmd gcc-4.4.7-3.el6.x86_64.rpm
create_rpminstallcmd gcc-c++-4.4.7-3.el6.x86_64.rpm
create_rpminstallcmd binutils-2.20.51.0.2-5.36.el6.x86_64.rpm
) > /tmp/temp.sh
sh /tmp/temp.sh
メモ
rpmファイル名から詳細情報を取得する。
"rpm -qip 〜"を使用する。
▼コマンド
rpm -qip gcc-4.4.7-3.el6.x86_64.rpm
▼ 結果例
警告: gcc-4.4.7-3.el6.x86_64.rpm: ヘッダ V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY
Name : gcc Relocations: (not relocatable)
Version : 4.4.7 Vendor: Red Hat, Inc.
Release : 3.el6 Build Date: 2012年10月19日 02時33分21秒
Install Date: (not installed) Build Host: x86-001.build.bos.redhat.com
Group : Development/Languages Source RPM: gcc-4.4.7-3.el6.src.rpm
Size : 19404986 License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ with exceptions
Signature : RSA/8, 2012年12月05日 18時55分12秒, Key ID 199e2f91fd431d51
Packager : Red Hat, Inc. <http://bugzilla.redhat.com/bugzilla>
URL : http://gcc.gnu.org
Summary : Various compilers (C, C++, Objective-C, Java, ...)
Description :
The gcc package contains the GNU Compiler Collection version 4.4.
You'll need this package in order to compile C code.
rpmコマンドでインストールせずに依存性を確認する。
"rpm -ivh --test 〜"を使用する。
▼コマンド
rpm -ivh --test gcc-4.4.7-3.el6.x86_64.rpm
▼ 結果例
※「依存性の欠如」には、「パッケージ名」と「rpmに含まれるファイル名」が表示されている。その他に種類があるのかどうかは不明。
警告: gcc-4.4.7-3.el6.x86_64.rpm: ヘッダ V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY
エラー: 依存性の欠如:
cloog-ppl >= 0.15 は gcc-4.4.7-3.el6.x86_64 に必要とされています
cpp = 4.4.7-3.el6 は gcc-4.4.7-3.el6.x86_64 に必要とされています
glibc-devel >= 2.2.90-12 は gcc-4.4.7-3.el6.x86_64 に必要とされています
libgomp = 4.4.7-3.el6 は gcc-4.4.7-3.el6.x86_64 に必要とされています
libgomp.so.1()(64bit) は gcc-4.4.7-3.el6.x86_64 に必要とされています