LoginSignup
5
4

More than 5 years have passed since last update.

大量のrpmファイルからインストールされていない依存関係にあるrpmファイルを抽出するbashスクリプト

Last updated at Posted at 2015-12-26

経緯

yumを使用できないサーバにrpmでパッケージをインストールする作業が最近増えてきた。
OSのインストールディスク(/Packagesディレクトリ)にある大量のrpmファイルから必要なファイルを抽出し、rpmコマンドでインストールするという作業が多い。

rpmを使用したインストールは、毎回依存関係に苦しめられる。これのせいでヘタすると1日がかりになってしまうこともある。
yumだと5分もかからない作業なので、アホらしくなってくる。

今後も何回か発生しそうな作業なので、bashスクリプトを作成して作業時間の短縮を試みる。

[2015/12/27 追記]
iwaim@github様より、yumコマンドでもOSのインストールディスクからインストールできることを教えていただきました。
※下記コメント参照。
こちらの方もご覧ください。

内容

作成するスクリプトの動作は以下の通り。

  1. 検索用辞書作成
    事前に検索用の辞書ファイルを作成する。
    大量のrpmファイルから「パッケージ名」「含まれているファイル名」を抽出し、ファイルに出力する。

  2. インストールされていない依存関係にあるrpmファイル名抽出
    インストールするrpmファイル名と検索用辞書を元に、インストールされていない依存関係にあるrpmファイル名を抽出する。

  3. 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 に必要とされています
5
4
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4