Next Previous Contents

5. 混合更新

為了混合更新,你需要由一個從一台Linux機器上擁有對發行目錄的寫權限, 以及安裝一個 rpm 。這里需要進行三步工作。

  1. 更改文件保護模式
  2. 更換更新的RPM包
  3. 產生hdlist文件

If you maintain a mirror of the updates directory, you can at any time produce a CD including the current updates by repeating these steps.

如果你在 updates 目錄維護一個鏡象的話,那么你可以在任何時候通過重復這些步驟制作CD。

5.1 更改文件保護模式

在安裝過程中,有些文件直接從從CD運行。但是不幸的是,FTP程序并不是總是保留被復制的文件和目錄的保護模式。這樣,就有必要確定程序是否有程序、SHELL腳本和共享庫執行權限,這需要在目錄被燒制到CD之前完成。通過運行在發行版的本地拷貝的 updatePerm 腳本可以做到這一點:


#!/bin/bash

RHVERSION=6.0

LIST=/tmp/er3hd3w25
CDDIR=/jaz/redhat-${RHVERSION}

# Find all directories, and make sure they have +x permission
find $CDDIR -type d -exec chmod -c 755 {} \;

# Find all files that are executables, shell or perl scripts
find $CDDIR -type f | file -f - | grep -v RPM \
   | egrep -i 'executable|perl|bourne|shell' | cut -f1 -d: > $LIST

# Find shared libraries
find $CDDIR -name \*.so >> $LIST

# Make them executable
while read file
do
   if [ ! -x $file ] ; then
      chmod -c 755 $file
   fi
done < $LIST

/bin/rm $LIST

exit 0

5.2 更換更新的RPM包

下面的這個腳本叫做 updateCD ,其功能為從更新目錄中復制所有的文件到 RPMS 目錄。這個腳本用了一些巧妙的RPM技巧來確定在UPDATES目錄下的哪個包更新。就的包被移到 ${OLD} 目錄中。


#! /bin/bash
# This script updates rpms in a RedHat distribution found in $RPMDIR.
# The old rpms will be placed in $OLDDIR.
# The new rpms should be located in $UPDDIR.
# The new images are in $IMGDIR
# The images to be updated are in $OMGDIR 
# The architechture is $ARCH.

RHVERSION=6.0
ARCH=i386

CDDIR=/jaz/redhat-${RHVERSION}
RPMDIR=${CDDIR}/${ARCH}/RedHat/RPMS
UPDDIR=${CDDIR}/updates/${ARCH}
IMGDIR=${CDDIR}/updates/images/${ARCH}
OMGDIR=${CDDIR}/${ARCH}/images
OLDDIR=${CDDIR}/old

if [ ! -d $OLDDIR ] ; then
   echo making directory $OLDDIR
   mkdir $OLDDIR
fi

allow_null_glob_expansion=1

for rpm in ${UPDDIR}/*.rpm ; do
  NAME=`rpm --queryformat "%{NAME}" -qp $rpm`
  unset OLDNAME
  for oldrpm in ${RPMDIR}/${NAME}*.rpm ; do
    if [ `rpm --queryformat "%{NAME}" -qp $oldrpm` = "$NAME" ]; then
      OLDNAME=$oldrpm;
      break
    fi
  done
  if [ -z "$OLDNAME" ]; then 
    echo $NAME is new
    cp -pv $rpm $RPMDIR
  else
    if [ `basename $rpm` != `basename $OLDNAME` ]; then
      mv $OLDNAME $OLDDIR
      cp -pv $rpm $RPMDIR
    fi
  fi
done


# Copy new boot image files to the right place...
for newfile in ${IMGDIR}/* ; do
  file=${OMGDIR}/$(basename ${newfile})
  if [ $newfile -nt $file ] ; then 
     cp -pv $newfile $file
  fi
done

exit 0

RedHat 6.0的重要注意事項:

一些RPM包,特別是kernel和kernel-smp包,需要文件名但不是在包名中包括文件的平台名稱,例如,“kernel”包需要如下所示:

 
kernel-2.2.5-22.i386.rpm
kernel-2.2.5-22.i586.rpm
kernel-2.2.5-22.i686.rpm

但是對于所有這三個執行rpm -qp 返回的都是"kernel"作為包名。

如你所看到,這種情況“迷惑”了 updateCD 腳本,其結果是只有最后一個得到正確的拷貝。先前的兩個雖然被拷貝了,但是被移到了 $OLD 目錄中。另外,RedHat還應當給予其不同的名稱。現在最好的解決辦法就是在運行了updateCD 之后手工地移動這些包。(感謝Kyle B. Ferrio kyle@U.Arizona.EDU)

Joshua Sarro <mthed@shore.net> 提供了一個PERL腳本叫做updateMirror.pl可以用來處理這種情況。你可以從 http://imsb.au.dk/~mok/linux/doc/updateMirror.pl獲得這個腳本。

5.3 創建一個新的hdlist文件

當從CD安裝的時候,CD中的安裝程序需要依靠文件RedHat/base/hdlist 來描述哪個包可以在CD中獲得。hdlist 文件可以通過程序misc/src/install/genhdlist所創建。這個程序必須有以發行本的根目錄到其的絕對路徑作為唯一參數運行。以下是updateHdlist ,用于調用這個程序。


#!/bin/bash

RHVERSION=6.0
ARCH=i386

echo generating hdlist...
CDDIR=/jaz/redhat-${RHVERSION}
GENHDDIR=${CDDIR}/${ARCH}/misc/src/install

chmod u+x ${GENHDDIR}/genhdlist
chmod 644 ${CDDIR}/${ARCH}/RedHat/base/hdlist
${GENHDDIR}/genhdlist ${CDDIR}/${ARCH} || echo "*** GENHDLIST FAILED ***"

exit 0

注意:當在RedHat/RPMS混合了更新之后,你的發行版的拷貝不再是一個RED HAT發行版站點的鏡象。事實上,它更新!這樣,如果你試圖鏡象這個發行版,已經被更新的舊版本的RPM將被再一次下載,而更新的版本將被刪除。

RedHat 5.2的重要注意事項

如果用RedHat version 5.2 或者更早的版本發行,如果在 RedHat/RPMS 包含了 RPM文件的話, genhdlist將會崩潰!這會導致一些問題。因為在5.2的版本中,在 RedHat/RPMS 中有一些非RPM文件叫做ls-lR以及ls-lR.gz ,這樣,你必須從這個目錄中移除所有的非RPM文件。或者,你可以使用下列的一個補丁于 misc/src/install/genhdlist.c ,然后從新編譯。這個補丁可以似得genhdlist 忽略任何非RPM的文件。


*** genhdlist.c.orig    Fri Nov 27 12:08:13 1998
--- genhdlist.c Fri Nov 27 12:08:20 1998
***************
*** 12,23 ****
--- 12,26 ----
  
  #define FILENAME_TAG 1000000
  
+ /* Not used apparently...
+ 
  int tags[] =  { RPMTAG_NAME, RPMTAG_VERSION, RPMTAG_RELEASE, RPMTAG_SERIAL,
                RPMTAG_FILENAMES, RPMTAG_FILESIZES, RPMTAG_GROUP,
                RPMTAG_REQUIREFLAGS, RPMTAG_REQUIRENAME, RPMTAG_REQUIREVERSION,
                RPMTAG_DESCRIPTION, RPMTAG_SUMMARY, RPMTAG_PROVIDES,
                RPMTAG_SIZE, RPMTAG_OBSOLETES };
  int numTags = sizeof(tags) / sizeof(int);
+ */
  
  int main(int argc, char ** argv) {
      char buf[300];
***************
*** 26,34 ****
--- 29,39 ----
      struct dirent * ent;
      int fd, rc, isSource;
      Header h;
+     /* not used 
      int count, type;
      int i;
      void * ptr;
+     */
  
      if (argc != 2) {
        fprintf(stderr, "usage: genhdlist <dir>\n");
***************
*** 74,79 ****
--- 79,85 ----
  
            rc = rpmReadPackageHeader(fd, &h, &isSource, NULL, NULL);
  
+           if (!rc) {
            headerRemoveEntry(h, RPMTAG_POSTIN);
            headerRemoveEntry(h, RPMTAG_POSTUN);
            headerRemoveEntry(h, RPMTAG_PREIN);
***************
*** 110,115 ****
--- 116,122 ----
            headerWrite(outfd, h, HEADER_MAGIC_YES);
            headerFree(h);
            close(fd);
+           }
        }
  
        errno = 0;

5.4 comps 文件

comps 文件定義了包如何在安裝的時候捆綁在一起,在RED HAT發行版中,根據他們提供的功能,例如:

有時候在安裝的過程中,用戶被提示"Components to install",有的包被預先選擇,而有的包則沒有,在組件列表中的最后一個項目叫做“everything”。根據RED HAT的穩當,選擇所有的的包大概需要接近1G的自由磁盤空間。

在對話框中,還有一個選項允許用戶確切地選擇需要安裝的包。手工定制安裝或者在組件列表中選擇“everyting”是你除了修改RedHat/base/comps file之外唯一可以使你的包被安裝的辦法。

comps 文件的格式現在用一個頭描述組件的格式,然后是一個空行。

0.1
<empty line>

在這個之后,組件被列出,用空行分離。

<component 1>
<empty line>
<component 2>
<empty line>
.
.
<component n>
<empty line>
EOF

每個組件有如下的定義:

(0|1) (--hide)? <name>
<RPM 1>
<RPM 2>
...
<RPM n>
end

在每個組件的名稱,給出0或者1。1表示這個組件被默認的選取,而0則相反。選項"--hide" 表示你看不到該條目,除非你選擇“專家(expert)”安裝。第一個組件被稱為“BASE”,這是一個特別的組件。因此它必須 而且不在對話框里出現。(這意味著你不能去初這個基本的安裝)。

然后跟著的是屬于該組件的RPM包的列表,注意在RPM文件中 存放的是包名,而不是包的文件名的任何一個部分(盡管經常是一樣的)

通過將你的包加入到 comps文件中,你可以定制你自己的發行版本,同時確認你的包被默認地安裝。有一件需要注意的事情是你的包的相互依賴性。但是在這里,你的就是你的!:-)。有一個警告:當心不要添加或者移除文件中的空格。檢查已存在的comps 文件。(制作原文件的一個拷貝),然后看它是如何被做成的。(或者檢查i386/misc/src/install/pkgs.c 查看文件是如何被分解的細節)


Next Previous Contents