6.3. 패키지 관리

패키지 관리를 LFS 책에서 다뤄달라는 요청이 자주 온다. 패키지 관리자를 사용하면 파일 설치를 추적하여 삭제나 업그레이드를 편리하게 할 수 있다. 바이너리와 라이브러리 파일들 뿐만 아니라, 패키지 관리자도 구성 파일들의 설치를 관리한다. 궁금해지기 전에 말해두자면, 안된다—이 절에서는 특정 패키지 관리자에 대해 이야기하거나 추천하지 않을 것이다. 이 절의 내용은 더 인기 있는 테크닉과 그 작동 원리들에 대한 정리이다. 당신을 위한 완벽한 패키지 관리자는 이런 기술들 가운데 하나일수도 둘 이상을 조합한 것일 수도 있다. 이 절에서는 패키지를 업그레이드 할 때 발생할 수 있는 문제에 대해 간략히 설명한다.

LFS나 BLFS에서 패키지 관리자를 언급하지 않는 몇 가지 이유는 다음과 같다:

패키지 관리 주제에 대해 몇 가지 힌트가 작성되어있다. 힌트 프로젝트에 방문하여 해당 프로젝트 중 필요한 것이 있는지 확인해보라.

6.3.1. 업그레이드에 관해

패키지 관리자를 사용하면 최신 버전이 배포되었을 때 쉽게 업그레이드할 수 있다. 일반적으로 LFS와 BLFS 책의 지침들을 통해 새로운 버전으로 업그레이드할 수 있다. 다음은 특히 작동 중인 시스템에서, 패키지를 업그레이드할 때 알아야 할 몇 가지 사항이다.

  • 만약 Glibc를 새로운 버전(예: glibc-2.19에서 glibc-2.20로)으로 업그레이드해야 한다면, LFS를 재빌드하는 것이 더 안전하다. 모든 패키지를 의존성 순서에 따라 다시 빌드할 수는 있지만, 권장하지는 않는다.

  • 공유 라이브러리를 포함하는 패키지가 업데이트되었다면, 또 라이브러리의 이름이 변경되었다면 그 라이브러리에 동적으로 링크된 모든 패키지를 다시 컴파일하여 새 라이브러리와 링크해야 한다(패키지 버전과 라이브러리 이름 사이에는 상관 관계가 없다는 점에 유의). 예를 들어 libfoo.so.1라는 이름의 공유 라이브러리를 설치하는 패키지 foo-1.2.3이 있다고 하자. 이 패키지를 libfoo.so.2라는 이름의 공유 라이브러리를 설치하는 최신 버전의 foo-1.2.4로 업그레이드한다고 가정하자. 이 때 libfoo.so.1에 동적으로 링크된 모든 패키지는 libfoo.so.2에 링크되도록 다시 컴파일해야 한다. 종속 패키지가 다시 컴파일될 때까지 이전 라이브러리를 제거하지 않도록 주의하라.

6.3.2. 패키지 관리 기술들

다음은 몇 가지 일반적인 패키지 관리 기법이다. 패키지 관리자를 결정하기 전에, 다양한 기술, 특히 각 기법의 단점에 대해 조사하라.

6.3.2.1. 모든 것은 내 머릿속에 있다!

그렇다, 이것은 패키지 관리 기법이다. 어떤 사람들은 패키지들을 샅샅이 알고 있고 각 패키지에 의해 어떤 파일들이 설치되는지 알기 때문에 패키지 관리자의 필요성을 느끼지 못한다. 패키지가 변경되면 전체 시스템을 재구축할 계획이어서 패키지 관리가 필요 없는 사용자도 있다.

6.3.2.2. 별도의 디렉토리들에 설치

이는 설치를 관리하는 데 별도의 패키지가 필요 없는 단순한 패키지 관리법이다. 각 패키지는 별도의 디렉토리에 설치된다. 예를 들어 /usr/pkg/foo-1.1에 foo-1.1 패키지를 설치하고 /usr/pkg/foo에서 /usr/pkg/foo-1.1로 심볼릭 링크를 만든다. 새 버전 foo-1.2를 설치하면, /usr/pkg/foo-1.2에 설치되고 이전 심볼릭링크는 새 버전의 심볼릭링크로 대체된다.

PATH, LD_LIBRARY_PATH, MANPATH, INFOPATH, CPPFLAGS 등의 환경 변수에 /usr/pkg/foo를 추가해야 한다. 패키지가 몇 개 이상으로 많아지면, 이 기법은 관리불능이 된다.

6.3.2.3. Symlink 스타일 패키지 관리

기존 패키지 관리 기법의 변형이다. 각 패키지는 이전 방법과 유사하게 설치된다. 그러나 symlink를 만드는 대신 각 파일이 /usr 계층으로 symlink된다. 이러면 환경 변수를 확장하기 위해 수정할 필요가 없어진다. 사용자가 심볼릭 링크를 생성해서 생성을 자동화할 순 있지만 많은 패키지 관리자가 이 방식을 사용해서 작성되었다. 인기 있는 것들 중에는 Stow, Epkg, Graft, Depot 등이 있다.

실제로는 /usr/pkg 계층에 설치되었지만 패키지가 /usr에 설치된 것으로 인식되도록 설치를 조작해야 한다. 이런 식으로 설치하는 것은 여간 복잡한 일이 아니다. 예를 들어 패키지 libfoo-1.1을 설치한다고 가정하면 다음 명령은 패키지를 제대로 설치하지 못할 수도 있다:

./configure --prefix=/usr/pkg/libfoo/1.1
make
make install

설치는 되지만 의존 패키지는 예상했던 대로 libfoo에 연결되지 않을 수 있다. libfoo에 링크되는 패키지를 컴파일하면 예상했던 /usr/lib/libfoo.so.1이 아닌 /usr/pkg/libfoo/1.1/lib/libfoo.so.1과 연결된 것을 알 수 있다. 올바른 방법은 DESTDIR 전략을 사용하여 패키지를 가짜로 설치하는 것이다. 이 방식은 이렇게 작동한다:

./configure --prefix=/usr
make
make DESTDIR=/usr/pkg/libfoo/1.1 install

대부분의 패키지가 이러한 방식을 지원하지만, 그렇지 않은 패키지도 있다. 패키지가 이 방식을 지원하지 않으면 수동으로 설치해야 하거나 문제가 있는 패키지를 /opt에 설치하는 것이 더 낫다.

6.3.2.4. 타임스탬프 기반

이 기법에서는 패키지가 설치되기 전에 파일에 타임스탬프를 찍는다. 설치 후 적절한 옵션과 함께 간단한 find 명령을 사용하면 타임스탬프 파일이 생성된 후 설치된 모든 파일의 로그를 생성할 수 있다. 이 방식을 채택한 패키지 관리자는 install-log이다.

이 방법은 단순하다는 장점이 있지만 두 가지 단점이 있다. 설치 중에 파일이 현재 시간 이외의 타임스탬프와 함께 설치되면 패키지 관리자가 해당 파일을 추적하지 않는다. 더구나 이 방법은 한 번에 하나의 패키지를 설치할 때만 사용할 수 있다. 두 개의 패키지가 서로 다른 두 개의 콘솔에 설치될 때는 로그를 신뢰할 수 없다.

6.3.2.5. 설치 스크립트 추적

이 방식은 설치 스크립트가 수행하는 명령을 기록하는 것이다. 사용할 수 있는 두 가지 기법이 있다:

LD_PRELOAD 환경변수를 설치 전에 미리 로드할 라이브러리를 가리키도록 설정할 수 있다. 설치하는 동안 이 라이브러리는 cp, install, mv 등 다양한 실행 파일에 자신을 첨부하고 파일 시스템을 수정하는 시스템콜을 추적해서 설치 중인 패키지를 추적한다. 이 방식을 사용하려면 모든 실행 파일이 suid나 sgid 비트 없이 동적으로 연결되어야 한다. 라이브러리를 미리 로드하면 설치 중에 원치 않는 부작용이 발생할 수 있다. 따라서 패키지 관리자가 아무 것도 깨뜨리지 않고 필요한 모든 파일을 기록하도록 몇 가지 테스트를 하는 것이 좋다.

두 번째 방식은 설치 스크립트를 실행하는 동안 발생하는 모든 시스템콜을 기록하는 strace를 사용하는 것이다.

6.3.2.6. 패키지 아카이브 생성

이 방식에서는 앞서 Symlink 스타일 패키지 관리에서 설명한 대로 패키지 설치를 별도의 트리로 위장한다. 설치가 끝나면 설치된 파일들로 패키지 아카이브를 생성한다. 이 보관 파일은 로컬 컴퓨터나 다른 컴퓨터에 패키지를 설치하는 데 사용할 수 있다.

이 방식은 상용 배포판에서 찾을 수 있는 대부분의 패키지 관리자들이 사용한다. 이 방식을 따르는 패키지 관리자의 예로는 RPM (참고로, Linux Standard Base Specification에 필요), pkg-utils, 데비안의 apt, 그리고 젠투의 Portage system이 있다. LFS 시스템에 이런 스타일의 패키지 관리 방식을 채택하려면 http://www.linuxfromscratch.org/hints/downloads/files/fakeroot.txt을 참고하라.

의존성 정보를 포함하는 패키지 파일의 생성은 복잡할 뿐더러 LFS의 범위를 벗어난다.

슬랙웨어는 패키지 아카이브에 tar 기반 시스템을 사용한다. 이 시스템은 더 복잡한 패키지 관리자들같이 의도적으로 패키지 의존성을 처리하지 않는다. 슬랙웨어 패키지 관리에 대한 자세한 내용은 http://www.slackbook.org/html/package-management.html을 참고하라.

6.3.2.7. 유저 기반 관리

이 LFS만의 독특한 방식은 Matthias Benkmann이 고안했으며 힌트 프로젝트에서 이용할 수 있다. 이 방식에서 각 패키지는 표준 위치에 별도의 사용자로 설치된다. 패키지에 속하는 파일은 사용자 ID를 확인하여 쉽게 식별할 수 있다. 이 방식의 특징과 단점은 이 절에서 설명하기에 너무 복잡하다. 자세한 내용은 http://www.linuxfromscratch.org/hints/downloads/files/more_control_and_pkg_man.txt의 힌트를 참고하라.

6.3.3. 여러 시스템에 LFS 배포하기

LFS 시스템의 장점 중 하나는 디스크에서의 위치에 좌우되는 파일이 없다는 것이다. LFS 빌드를 동일한 아키텍쳐의 다른 컴퓨터에 기반 시스템으로 복제하는 것은 간단하다. root 디렉토리(압축되지 않은 기본 LFS 빌드 기준 약 250 MB)가 포함된 LFS 파티션에서 tar를 사용하고, 네트워크나 CD-ROM을 통해 새 시스템으로 복사하고 확장하는 것으로 복제할 수 있다. 그 후에 몇 개의 구성 파일을 변경해야 할 것이다. 업데이트가 필요할 수 있는 구성 파일로는 /etc/hosts, /etc/fstab, /etc/passwd, /etc/group, /etc/shadow, /etc/ld.so.conf, /etc/sysconfig/rc.site, /etc/sysconfig/network, /etc/sysconfig/ifconfig.eth0 등이 있다.

시스템 하드웨어와 원래 커널 구성의 차이에 따라 새로운 시스템을 위한 커스텀 커널을 빌드해야 할 수도 있다.

[참고]

참고

유사하지만 동일하지 않은 아키텍쳐 간에는 복사할 때 일부 문제가 있다는 보고가 있었다. 예를 들어 인텔 시스템의 명령어 세트는 AMD 프로세서와 동일하지 않으며 일부 프로세서의 이후 버전에는 이전 버전에서 사용할 수 없는 명령이 있을 수 있다.

마지막으로 8.4절. “GRUB을 사용하여 부팅 프로세스 설정”을 통해 새 시스템을 부팅 가능하도록 만들어야 한다.