다음 이전 차례

5. 업데이트 반영하기

업데이트를 반영하려면 제대로 작동하는 rpm 이 설치되어 있어야 하고 리눅스 머신에서 배포판 디렉토리에 쓰기 권한이 있어야 한다. 아래와 같은 세 단계를 거쳐야 한다.

  1. 파일 보호 모드 수정하기
  2. 업데이트된 RPM 파일 바꾸기
  3. hdlist 파일 생성하기

만약 updates 디렉토리의 미러링을 유지하고 있다면 이러한 단계를 반복함으로써 언제든지 현재의 업데이트를 포함하는 CD를 만들 수 있다.

5.1 파일 보호 모드 수정하기

설치하는 도중에 어떤 프로그램들은 CD로부터 직접 실행된다. 불행하게도 FTP 프로그램은 복사되는 파일과 디렉토리의 보호 모드를 언제나 보존하지는 않는다. 따라서 디렉토리를 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라고 불리는 아래의 스크립트는 updates 디렉토리로부터 모든 파일을 RPMS 디렉토리로 옮긴다. 이 스크립트는 updates 디렉토리에서 어떤 파일이 더 최근의 것인지를 판별하기 위해 몇 개의 재치있는 rpm 트릭을 사용한다. 오래 된 패키지들은 ${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을 위한 중요한 노트

특히 kernel과 kernel-smp 패키지 같은 특정 RPM들은 파일 이름에는 플랫폼이 포함되어 있지만 패키지 이름에는 포함되어 있지 않다. 예를 들면 "kernel" 패키지는 아래와 같이 몇 종류로 공급된다.

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

하지만 세 개 모두에서 -qp 로 검사해 보면 패키지 이름으로 그냥 "kernel"이라고 나온다.

보면 알겠지만 이렇게 되면 updateCD 스크립트가 오동작을 하게 된다. 그 결과로 마지막 파일만 제대로 복사된다. 앞의 두 개도 복사가 되긴 하지만 바로 $OLD 디렉토리로 옮겨져 버린다. 레드햇에서 이들의 이름을 다르게 붙이면 좋겠지만, 지금 현재로써는 가장 간단한 해결책은 updateCD 를 실행시킨 후에 수작업으로 옮기는 것이다. ( Kyle B. Ferrio에게 감사드립니다.)

이러한 문제를 해결할 수 있는 펄 스크립트를 Joshua Sarro가 만들었다. http://imsb.au.dk/~mok/linux/doc/updateMirror.pl에서 구할 수 있다.

5.3 새로운 hdlist 파일 생성하기

CD로부터 설치할 때 CD에 있는 설치 프로그램은 어떤 RPM 패키지들이 사용가능한지를 기술하는 RedHat/base/hdlist 파일에 의존한다. 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

NOTE: RedHat/RPMS 디렉토리에 업데이트를 반영한 후에는 당신의 배포판 복사본은 더 이상 레드햇 배포판 사이트의 미러가 아니다. 사실, 그것은 더욱 최신의 것이다! 따라서 배포판을 미러하려고 시도한다면 업데이트된 RPM들의 이전 버전들이 다시 다운로드 될 것이며, 업데이트들은 지워질 것이다.

RedHat 5.2를 위한 중요한 note

레드햇 5.2 이전부터 배포된 genhdlistRedHat/RPMS 디렉토리에 RPM 파일이 아닌 파일이 있으면 충돌을 일으킨다. 5.2 배포판에는 ls-lRls-lR.gz 라는 RPM 이 아닌 파일이 있기 때문에 문제를 일으키게 된다. 따라서 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 파일은 설치 과정에서 패키지들이 어떻게 꾸려지는지를 정의한다. 레드햇 보파판에서 이 과정은 패키지들의 기능에 따라 분리된다. 아래의 예를 보라:

설치하는 도중에 사용자는 "Components to install"이라는 대화상자를 보게 된다. 어떠한 컴포넌트들은 미리 선택되어 있고 어떤 것들은 그렇지 않다. 컴포넌트들의 리스트에는 마지막에 "Everything"이 있다. 레드햇 문서에 따르면 모든 패키지를 설치하려면 거의 1 Gb에 달하는 디스크의 여유공간이 필요하다고 한다.

대화상자에는 사용자가 설치할 패키지를 일일이 설치할 수 있도록 해 주는 옵션도 있다. RedHat/base/comps 파일을 변경하지 않는다면 일일이 패키지를 골라서 설치하던지 아니면 모든 패키지를 설치하는 수밖에 없다.

comps 파일은 현재 comps 양식의 버전을 기술하는 것으로 시작하며, 바로 아래에는 빈 줄이 와야 한다.

0.1
<빈 줄>

그 뒤에는 컴포넌트들이 나열되며, 빈 줄로 구분한다.

<첫번째 컴포넌트>
<빈 줄>
<두번째 컴포넌트>
<빈 줄>
.
.
<n번째 컴포넌트>
<빈 줄>
EOF

각각의 컴포넌트는 아래와 같이 정의된다:

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

각 컴포넌트의 이름 앞에 0이나 1이 주어진다. 여기서 1은 그 컴포넌트가 기본적으로 선택된다는 것을, 0은 그렇지 않음을 의미한다. "--hide" 옵션은 "expert" 설치과정을 선택하지 않는다면 목록을 볼 수 없음을 의미한다. 첫번째 컴포넌트는 "Base"이고, 반드시 존재해야 하며 대화상자에 나타나지 않는다는 점에서 특별하다.(당연히 기본 설치는 선택하지 않을 수 없다...)

다음에는 그 컴포넌트에 해당하는 rpm 패키지들의 목록이 나온다. 이름들이 패키지의 파일 이름의 일부분이 아니고 rpm 파일 안에 저장되어 있는 이름이 라는 점에 유의하여야 한다. (대개 같기는 하지만...)

comps 파일에 당신의 패키지를 추가함으로써 당신만의 배포판을 구성할 수 있고 확실하게 당신의 패키지가 기본으로 설치되도록 할 수 있다. 한 가지 주의해야 할 점은 당신의 패키지 안에서의 상호의존성이다. 자기 자신만의 것을 만들고 있긴 하지만... :-) 충고 한 마디: 파일 안에 여분의 공백을 추가하거나 제거하지 않도록 주의하라. 현재 있는 comps 파일(원본을 복사해 두어라)을 살펴보면 어떻게 되어 있는지를 알 수 있다. (또는 그 파일이 어떻게 parse되는지 알고 싶다면 i386/misc/src/install/pkgs.c 를 확인해 보아도 된다.)


다음 이전 차례