5/31/2007

port 사용법

포트
포트는 FreeBSD를 사용하게 된다면 귀가 닳도록 듣게 되는 말이겠지만, 결국은 기본 시스템이 아닌 패키지를 설치/관리하기 위한 프레임워크이다. 이것은 BSD make의 각종 룰셋으로 이루어져 있으며, 실제 래드햇 리눅스의 rpm과 같이 별도의 프로그램에서 처리하는 것이 아니라, 대부분의 작업은 makefile의 룰셋을 통해 처리한다. 물론 실제 패키지 등록과 바이너리 패키지 생성을 위해 pkg_ 로 시작하는 여러가지 보조 유틸리티군이 기본 시스템에 존재하기도 한다. 포트 상에서는 포트 관리를 위한 프로그램도 있다.


원하는 포트 찾기
어떤 패키지를 설치하고 싶은데, 과연 FreeBSD 포트에 존재하는 것인지 잘 모를 때가 많다. 어떤 것은 기본 시스템에 포함되어 있고, 어떤 것은 포트로 존재할 텐데, 어떻게 알 수 있을까?

기본 시스템에 어떤 패키지가 포함되었는지 쉽게 알 수 있는 방법은 없지만, 일단은 기본 시스템이라는 이야기는 이미 설치되어 있어서 해당 명령을 즉시 실행할 수 있다는 것을 의미하므로, 찾아보면 된다.

시스템에 존재하는 어떤 파일을 찾아보기 위해서는 기본 시스템의 whereis, whatis, locate 명령을 사용하면 된다. whereis는 표준 라이브러리, 매뉴얼 페이지, 소스 디렉토리에서 검색하며, whatis는 매뉴얼 페이지, locate는 시스템 내의 파일의 색인인(주기적으로 생성한다) locate 데이터베이스에서 검색하는 역할을 한다. 가령 DNS 서버인 bind를 찾아보자.


> whereis bind
bind: /usr/src/contrib/bind
> whatis bind
bind(2) - assign a local protocol address to a socket
bindresvport(3), bindresvport_sa(3) - bind a socket to a privileged IP port
rpcb_getmaps(3), rpcb_getaddr(3), rpcb_gettime(3), rpcb_rmtcall(3), rpcb_set(3),
rpcb_unset(3) - library routines for RPC bind service
> locate bind
/usr/sbin/rpcbind
/usr/sbin/ypbind
/usr/share/doc/bind
/usr/share/doc/bind/html
/usr/share/doc/bind/html/acl.html
/usr/share/doc/bind/html/address_list.html
...
여기서 알 수 있는 것은 whereis의 실행 결과에서, /usr/src/contrib 에 bind의 소스가 존재한다는 사실을 알 수 있으므로 bind는 기본 시스템에 속한다는 사실을 알 수 있다. hanterm의 경우는 다음과 같다.


> whereis hanterm
hanterm: /usr/X11R6/bin/hanterm /usr/ports/korean/hanterm
whereis는 포트 트리에서도 검색해 주므로, hanterm 프로그램을 설치하기 위해서는 /usr/ports/korean/hanterm에서 프로그램을 설치하면 된다는 사실을 알 수 있다.


# cd /usr/ports/korean/hanterm && make install clean이러한 작업에는 항상 포트 트리를 시스템 갖고 있다는 가정이 있어야 한다. 설치시에 용량이 된다면 ports 배포본을 잊지 말고 설치하도록 하자. 혹 설치가 되어 있지 않다면(/usr/ports 디렉토리가 비어 있는지 확인한다) /stand/sysinstall을 불러서 설치하기 바란다.

포트 트리에서 직접 검색하는 방법도 있다. 검색을 하기 위해서는 /usr/ports 디렉토리에서 make search key=검색어 를 사용하면 된다. 다음은 hanterm을 검색한 결과이다.


> cd /usr/ports
> make search key=hanterm
Port: ko-hanterm-3.1.5_1
Path: /usr/ports/korean/hanterm
Info: An xterm hacked for managing Korean languages
Maint: cjh@FreeBSD.org
Index: korean x11
B-deps: XFree86-3.3.6_9
R-deps: XFree86-3.3.6_9 ko-johabfonts-3.04

Port: ko-hanterm-xf-19_1
Path: /usr/ports/korean/hanterm-xf86
Info: An X11R6-based xterm hacked for managing Korean languages
Maint: cjh@FreeBSD.org
Index: korean x11
B-deps: XFree86-3.3.6_9 iconv-2.0_1
R-deps: XFree86-3.3.6_9 iconv-2.0_1 ko-johabfonts-3.04
검색은 /usr/ports/INDEX (포트에 대한 색인 파일이다)을 검색하는데, 패키지명 뿐 아니라 의존 패키지 명 등도 모두 검색하므로 상당히 흔한 명령어(gnome등)을 입력하면 무수히 많은 검색 결과를 얻게 될 것이다. 하지만 이 명령은 패키지의 설명 안에서 검색하는데 상당히 편한 명령이다.

그외 포트에서 제공하는 어플리케이션을 찾기 위해서는 다음 사이트에 들러 보도록 하자.


http://freshports.org
http://www.freebsd.org/ports
특히 freshports.org는 포트 트리의 업데이트를 실시간으로 찾아내어 변경된 패키지 내역을 일목요연하게 정리해 주고, 간단한 검색 기능도 제공하므로 새 패키지나, 새 버전의 패키지가 나왔는지 알아보려면 꼭 들러 보도록 하자.






그림: http://freshports.org



바이너리 패키지 생성
매번 포트에서 설치하기 귀찮다면 바이너리 패키지를 생성해 둘 수 있다.


# make package
이 명령을 실행하면 현재 디렉토리에 패키지가 생성된다. 가령 korean/hanterm 디렉토리에서 이 명령을 내리면 ko-hanterm-3.1.5_1.tgz와 같은 바이너리 패키지가 생성된다. 다만 make package는 make install 후에 실행할 수 있는 명령으로, make install을 전제로 하기 때문에 설치된 바이너리를 묶어 내는 역할을 하게 된다. 즉 현재 시스템에 설치하지 않고 바이너리 패키지를 생성할 수는 없다는 이야기이다. 또한 패키지는 라이센스상 재배포나 재포장이 불가능한 경우 또는 시스템에 따라 다른 부분이 많아서 패키징을 할 수 없는 경우가 있으므로, 그러한 경우는 패키지를 생성할 수 없다. 이 경우에는 해당 포트의 Makefile을 열어 보아서 NO_PACKAGE나 RESTRICTED 행을 제거하면 패키지를 생성할 수 있지만, 권장할 만한 것은 아니다.

바이너리로 생성된 패키지가 잘 설치되는지 테스트하려면 먼저 기존에 설치된 패키지를 지우고, pkg_add로 설치하면 된다.


# make deinstall
# pkg_add ko-hanterm-3.1.5_1.tgz
물론 다른 시스템에 설치하는 경우에는 파일을 전송하고 pkg_add 명령만을 실행하면 될 것이다.

포트와 일치하지 않지만, 현재 설치되어 있는 어플리케이션을 패키지 형태로 묶을 수도 있다. misc/pkg_tarup 포트를 설치하면 현재 시스템에 설치된 바이너리 패키지를 다시 원래 패키지 형태로 되돌릴 수 있다. 완벽하지는 않겠지만, 설치/삭제용 스크립트가 많이 포함된 경우가 아니라면 패키지를 완전하게 복구할 수 있다. 포트를 설치한 후, 다음과 같이 하면 시스템에서 설치된 패키지를 도로 바이너리 패키지로 만들 수 있다. 이것은 포트가 없어도 된다는 장점이 있다.


> pkg_tarup ko-hanterm-xf-19_1
Taring up ko-hanterm-xf-19_1
Creating package /tmp/ko-hanterm-xf-19_1.tgz
Registering depends: ko-johabfonts-3.04 imake-4.0.3 iconv-2.0_1 XFree86-librari
es-4.0.3_1 XFree86-clients-4.0.3.
Creating gzip'd tar ball in '/tmp/ko-hanterm-xf-19_1.tgz'

플래그
포트는 makefile로 구성되기 때문에, 여러가지 변수를 지정하는 것으로 포트 시스템의 동작을 제어할 수 있다. 이러한 변수는 보통


make <타겟> 변수=값
의 형태로 지정하거나, 매번 지정하지 않고 기본 설정으로 만들기 위해서 /etc/make.conf에


변수=값
의 형태로 추가해 두는 것이 보통이다. 전역 설정의 경우 /etc/make.conf에, 그렇지 않다면 make시에 직접 주도록 하자. 변수의 경우 참과 거짓을 나타나는 경우도 있고, 정의만 되어 있으면 효과가 나는 경우도 있고, 값이 중요한 경우도 있다. 참과 거짓을 나타내는 경우라면 대부분


USA_RESIDENT=YES
USA_RESIDENT=NO
식으로 YES/NO로 정의하는 것이 일반적이며, 정의가 중요한 경우라면 보통 값은 YES,


FORCE_PKG_REGISTER=YES
값이 중요한 경우라면 값을 지정하면 된다.


MASTER_SITE_GNOME=ftp://ftp.kr.freebsd.org/pub/GNOME/sources/%SUBDIR%/
/etc/make.conf는 시스템에 따라 다른 값을 지정하는 파일이고, FreeBSD의 기본 설정은 /etc/defaults/make.conf를 참조한다. 따라서 한번쯤 /etc/defaults/make.conf를 살펴보기 바란다. make.conf는 먼저 /etc/defaults/make.conf를 읽어들인 후 /etc/make.conf를 읽어들이므로, /etc/make.conf에서 지정한 값이 우선한다.


USA_RESIDENT
이 값이 YES라면, 미국 내 거주자의 경우이다. 암호화 등에 관련된 미국의 일부 소프트웨어는 미국 외의 수출을 금지하는 경우가 많으므로, 이 플래그를 통해 미국 내 거주자인지의 여부를 결정할 수 있다. 물론 자신이 결정하는 것이므로 강제적인 의미는 없지만, 일부 포트는 이 플래그의 존재 여부에 따라 다른 소스에서 프로그램을 설치하기도 한다. 한국의 경우에는


USA_RESIDENT=NO
로 지정하면 된다.


FORCE_PKG_REGISTER
이 플래그는 이미 설치되어 있는 포트를 덮어쓰고자 할 때 유용하다. 현재 ko-hanterm-xf-19_1가 설치되어 있다면 korean/hanterm-xf86 포트를 설치할 때 덮어쓸 수 없다는 오류 메시지가 나는데, 정말 덮어쓰고 싶다면 다음 명령으로 기존의 설치 여부에 관계없이 덮어쓸 수 있다.


# make FORCE_PKG_REGISTER=YES install
PREFIX
PREFIX는 설치 경로를 결정한다. FreeBSD의 경우 기본적으로 패키지는 /usr/local, X 관련 패키지는 /usr/X11R6의 두 경로에 설치한다. 테스트용이거나, 다른 PREFIX를 선택하고 싶다면 이 경로를 바꾸어 지정해 주면 해당 위치에 설치한다. 어플리케이션에 따라 PREFIX가 제대로 동작하지 않는 경우도 존재할 수 있다. 단 의존성에 걸리는 패키지도 모두 PREFIX 아래에 다시 설치할 수 있으므로 주의하도록 하자.


# make PREFIX=/my/local isntall
NO_CHECKSUM
포트는 체크섬을 통해서 인터넷에서 받아온 소스가 원본 소스와 일치하는지를 판별하고 있다. 이것이 일치하지 않으면 설치가 되지 않는데, NO_CHECKSUM 플래그를 주면 소스에 대한 검사 없이 설치를 진행한다.


# make NO_CHECKSUM=YES install
자신이 스스로 소스를 고친 경우 등에 유용하지만, 이 플래그는 쓰는 일이 없도록 하는 것이 정상적인 상황이라는 점에 유의하자. 소스가 올바른 것이라는 확신이 든다면 makesum 타겟을 사용해서 아예 체크섬을 업데이트하는 것이 더 좋다. 종종 릴리즈된 후 사소한 실수를 보정하기 위해 소스를 다시 업데이트하는 경우가 있는데(보통 re-roll되었다고 한다), 이 경우라면 위 플래그를 사용해도 좋을 것이다. makesum 타겟을 사용하는 경우에는 다음과 같다.


# make makesum install
PORTSDIR
포트 스켈레톤의 디렉토리를 의미한다. 일반적으로는 /usr/ports 이지만 CD-ROM등에서 포트를 사용하거나 자신이 별도의 트리를 만들어 사용한다면 다른 디렉토리일 수 있다. 단 적어도 PORTSDIR이 성립되기 위해서는 $PORTSDIR/Mk 디렉토리에 적절한 버전의 bsd.*.mk 파일군이 있어야 한다.


# make PORTSDIR=/home/foo/ports install
DISTDIR
기본적으로 make fetch 과정에서 받아온 소스는 $DISTDIR에 저장되는데, 기본값은 /usr/ports/distfiles 디렉토리이다. 이 위치를 변경하고 싶다면 DISTDIR를 다시 지정할 수 있다. 물론 의존성이 걸린 패키지가 많을 경우 모두 다시 받는다는 문제점이 있을 수 있다.


# make DISTDIR=/tmp/distfiles install
MASTER_SITE_*
많은 어플리케이션은 대표적인 사이트에서 미러링하는 경우가 많다. 가령 GNU 어플리케이션은 ftp.gnu.org, 리눅스용 일반 어플리케이션은 metalab.unc.edu, perl 모듈은 CPAN 미러(ftp.digital.com/pub/plan/perl/CPAN등)으로 구분지을 수 있고 전세계 곳곳에 이러한 사이트의 미러 사이트들이 존재한다. 보통 MASTER_SITE_카테고리는 해당 주요 어플리케이션의 미러 사이트를 재정의할 수 있도록 해 준다. 가령 GNOME 소스는 기본적으로 ftp.gnome.org에서 받아오지만, 국내 미러가 있다면 그곳에서 받는 것이 더 좋을 것이다. 이 경우 MASTER_SITE_GNOME을 재정의할 수 있다.


MASTER_SITE_GNOME=ftp://ftp.kr.freebsd.org/pub/GNOME/sources/%SUBDIR%/
%SUBDIR%은 어플리케이션에 따라 달라질 수 있는 디렉토리를 의미하므로 이 부분은 지우지 말자.

MASTER_SITE_OVERRIDE
이 변수를 정의하면 make fetch 시에 포트에 지정된 사이트을 찾아보기 전에 이 사이트부터 먼저 찾는다. FreeBSD FTP 미러의 pub/FreeBSD/ports/distfiles의 미러 사이트가 가까이에 있다면 그것을 지정하면 파일이 미러되어 있는 경우 가장 빠르게 받을 수 있다.


MASTER_SITE_OVERRIDE=ftp://ftp.kr.FreeBSD.org/pub/FreeBSD/ports/distfiles/
MASTER_SORT_REGEX
이 변수를 잘 지정하면, 소스 파일을 받아올 수 있는 사이트의 순서를 조정할 수 있다. 하나의 소스 파일은 보통 여러 곳의 미러 사이트에서 받을 수 있는데, 가령 자신의 국가 도메인에 있는 사이트에서 먼저 찾아본다면 좋을 것이다. MASTER_SORT_REGEX는 그러한 일을 해 준다. 정의하는 것은 복잡할 수 있지만, /etc/defaults/make.conf에 있는 예제를 복사해서 자신의 국가 도메인으로 바꾸어 주는 것으로 충분하다. 한국의 경우는 다음과 같이 지정해 줄 수 있다.


MASTER_SORT_REGEX= ^file: ://[^/]*\.kr/ ://[^/]*\.kr\. ^ftp://ftp\.FreeBSD\.org/pub/FreeBSD/ports/local-distfiles/
이렇게 하면 먼저 file: (지역 디렉토리), .kr 로 끝나는 사이트, .kr. 이 중간에 들어간 사이트, ftp.FreeBSD.org 순으로 찾게 된다.


WITH_와 WITHOUT_*
이 플래그는 자신의 시스템이 특정 기능을 사용하고 있는지의 여부를 지정하는 것이다. 가령 GUI 프로그램의 경우 gtk+와 qt로 된 두가지 라이브러리를 모두 지원한다면, 포트를 설치하는 사람은 이 두가지 GUI 옵션 중 하나를 선택할 수 있다. 또한 GUI 라이브러리 중에서도 gtk+를 선호하는 사람과 qt를 선호하는 사람이 있는데, 나는 gtk+를 선호하므로 qt 옵션을 사용하고 싶지 않은 경우에는 위와 같은 메카니즘을 사용할 수 있다.

가령 필자는 프로그램 설치에 있어서 gtk+ 로 빌드하는 것을 선호한다고 하자. 그러면 다음과 같이 할 수 있다.


# cd /usr/ports/x11/xscreensaver
# make install WITH_GTK=YES
이렇게 하면 GUI 옵션이 있는 어플리케이션의 경우, gtk+로 빌드할 수 있다. 이 경우 패키지 이름도 바뀌는데, 뒤에 -gtk 접미사가 붙는다.


# make package-name WITH_GTK=YES
xscreensaver-gtk-3.33
반대는 WITH_GTK=NO로 하는 것이 아니라 WITHOUT_GTK=YES이다. 이런 종류의 변수는 지정되는 것만으로도 의미가 있다는 점에 유의하자.


# make package-name WITHOUT_GTK=YES
xscreensaver-3.33
대표적인 한글 입력기 ami의 경우 GNOME 라이브러리를 필요로 한다. 원래는 gdk-pixbuf 라이브러리가 필요하지만 FreeBSD에서 이 라이브러리는 gnomelibs에 의존하도록 컴파일되어 있기 때문이다. ami의 경우 문제가 조금 미묘한데, ami는 GNOME을 사용하지 않도록 컴파일하려고 해도 gdk-pixbuf 때문에 gnomelibs를 포함한다. 따라서 명시적으로 지정하지 않아도 ami에는 -gnome 접미사가 붙는데, -gnome 접미사는 gnomelibs에 의존하는 경우에는 자동으로 지정된다. 따라서 ami는 -gnome 접두사를 피할 수 없지만, 옵션으로 주어지는 GNOME 애플릿 모드로 컴파일하지 않으려면 gnomelibs에 의존성이 있지만 WITHOUT_GNOME=YES를 주어서 애플릿 모드를 컴파일하지 않을 수 있다.


/usr/ports/korean/ami> make package-name
ko-ami-gnome-1.0.10_1
/usr/ports/korean/ami> make package-name WITHOUT_GNOME=YES
ko-ami-1.0.10_1
어플리케이션의 존재 여부에 따라 WITH_GLIB, WITH_GTK, WITH_ESOUND, WITH_IMLIB, WITH_GNOME을 각각 사용할 수 있다. 이는 아직은 GNOME 계열 라이브러리에 대해서만 정의되어 있고, KDE 계열에 대해서는 아직 없다.

단, 이 옵션은 포트가 지원해야만 사용할 수 있다. 지원하지 않는 포트에 대해서는 사용할 수 없다는 점에 유의하자.

필자의 경우 포트 관련으로 다음과 같은 /etc/make.conf를 정의해 사용하고 있다. 물론 /etc/make.conf는 make 관련의 더 많은 플래그를 정의할 수 있어서 시스템 빌드나 커널 빌드시의 파라미터 등도 지정할 수 있다. 이외 어플리케이션마다 다른 옵션도(아래의 OPT_ARCH나 A4등) 함께 지정할 수 있다는 점에 주의하자. CPUTYPE은 기본 시스템/커널 빌드와 포트 빌드시에 모두 영향을 미치는 변수인데, i686으로 지정하면 펜티엄 프로 이상 CPU에 최적화된 바이너리를 생성하는 플래그를 컴파일시 CFLAGS에 지정해 준다. MASTER_SITE_* 등은 여러분이 더 좋은 사이트를 찾아낼 수 있을 것이다.


USA_RESIDENT=NO
XFREE86_VERSION=4
MASTER_SITE_OVERRIDE=ftp://ftp.kr.FreeBSD.org/pub/FreeBSD/ports/distfiles/
MASTER_SITE_KDE=ftp://linux.sarang.net/pub/mirror/desktop/kde/%SUBDIR%/
MASTER_SITE_RUBY=ftp://ftp.kr.freebsd.org/pub/ruby/%SUBDIR%/
MASTER_SITE_GNOME=ftp://ftp.kr.freebsd.org/pub/GNOME/sources/%SUBDIR%/
MASTER_SITE_XFREE=ftp://ftp.kr.freebsd.org/pub/XFree86/%SUBDIR%/source/
MASTER_SORT_REGEX= ^file: ://[^/]*\.kr/ ://[^/]*\.kr\. ^ftp://ftp\.FreeBSD\.org/pub/FreeBSD/ports/local-distfiles/
# other ports customization
WITH_GNOME= YES
# mpg123
OPT_ARCH= i586
# gs
A4= YES
# CPU Type
CPUTYPE= i686

패키지 삭제
패키지 삭제는 다음 세가지 방법으로 할 수 있다.


make deinstall
이것은 해당 포트 디렉토리에서 실행해야 하는데, 포트에서 가리키는 패키지의 버전과 지우려는 현재 설치된 패키지의 버전이 동일해야만 지워진다는 문제점이 있다. 따라서 포트 테스트용으로 사용하기에는 좋지만 일반적인 경우에는 별로 도움이 안 될 것이다.

pkg_delete
이 기본 명령어는 바이너리 패키지를 지울 수 있다. 이전의 pkg_delete는 기능이 상당히 미약하였는데 현재는 여러가지 다양한 기능을 제공하고 있어서 여러 패키지를 한번에 지우거나 패키지 이름만으로 지울 수 있다. pkg_delete는 패키지와 버전 이름을 모두 주어도 되고, 패키지 이름만을 주어도 가능하다. ko-hanterm 패키지를 지우고 싶다면 다음과 같이 한다.


# pkg_delete 'ko-hanterm*'
' '로 묶는 이유는 안에 * 기호를 사용하였기 때문이다. 이것의 의미는 ko-hanterm으로 시작하는 패키지를 모두 지우라는 의미이다. 이것을 붙이지 않으면 전체 패키지 이름을 모두 주어야 한다.


# pkg_delete ko-hanterm-xf-19_1
pkg_delete는 의존성 검사는 해 주지만, 의존하는 패키지까지 모두 지우지는 않는다는 것이 단점이라면 단점이다. 지우기 전에 어떤 일이 일어나는지 확인하고 싶다면 -n 옵션을 주면 지우지는 않지만 지우는 흉내를 내 준다.

pkg_remove
이 명령은 sysutils/pkg_remove 포트에서 설치하면 되며, 매우 강력한 패키지 삭제 기능을 발휘한다. 기본적으로 주어진 이름과 일치하는 모든 패키지를 지운다. 또한 지우는 패키지에 의존하는 패키지를 모두 지우는 효과가 있으므로, 주의해서 사용해야 한다. pkg_delete와 마찬가지로 지우기 전에 어떤 일이 일어나는지 알고 싶다면 -n 옵션을 사용한다.


# pkg_remove netscape-communicator
remove: ko-netscape-communicator-linux-4.77
remove: linux-netscape-communicator-4.77
실제 사용에 있어서는 pkg_remove 쪽이 더 편할 것이다. 하지만 라이브러리 등을 지울 때에는 의존 패키지가 많을 수 있으므로 주의하기 바란다.

패키지 모두 지우기?
모든 패키지를 지우고 싶다면 세 명령 중 하나를 사용하자. 단 그 결과에 대해서는 책임질 수 없다. :)

# pkg_delete -a
# pkg_remove ALL (sysutils/pkg_remove 포트)
# pkg_deinstall -a (sysutils/portsupgrade 포트)




업데이트
이전의 FreeBSD 포트 시스템의 가장 큰 문제는 바로 업데이트가 어렵다는 것이었다. 하지만 최근에는 많이 상황이 개선되어, FreeBSD도 포트나 패키지를 통한 기존 패키지의 업데이트가 가능하게 되었다. 물론 아주 완벽한 방법은 아니지만, 이러한 포트 업데이트 방법에 대해 알아보기로 하자.


포트 트리 업그레이드
가장 먼저 해야 할 것은 /usr/ports 디렉토리의 업그레이드이다. 업그레이드라는 것이 새 버전을 설치하는 것을 의미한다면, 먼저 새 버전이 어떤 것인지를 알고 있어야 하기 때문이다. 포트를 업데이트하는 방법에는 여러가지가 있을 수 있지만 가장 널리 사용되는 방법은 CVSup을 사용하는 것이다. 일단 시스템에 cvsup 명령이 있는지 확인해 보고, 없다면 net/cvsup-bin이나 net/cvsup 패키지를 설치하도록 하자.

cvsup이 설치되어 있다면, 포트 트리의 업그레이드는 다음 명령으로 쉽게 할 수 있다.


# cvsup -g -L2 -h cvsup.kr.freebsd.org /usr/share/examples/cvsup/ports-supfile
-g 옵션은 GUI를 부르지 않도록 하는 옵션이고(-g 옵션을 주지 않으면 CVSup 동작을 위한 윈도우가 뜬다), -L2는 로그의 수준을 정하는 것인데, -L2는 가장 자세한 출력을 제공한다. 어떤 파일이 업그레이드되고 새로 생성되거나 지워지는 것을 확인하기에 좋다. -h 다음에는 CVSup 미러 사이트 이름을 지정한다. 국내 미러는 cvsup.kr.freebsd.org와 cvsup2.kr.freebsd.org 가 제공되므로 가까운 것을 사용하면 된다. 그리고 supfile이라고 하는 업데이트할 소스 트리가 정의된 파일을 지정하는데, 시스템에 예제로 제공되는 /usr/share/examples/cvsup/ports-supfile이면 충분하다. 그 파일에서 주석을 제외한다면 내용은 다음과 같다.


*default host=CHANGE_THIS.FreeBSD.org
*default base=/usr
*default prefix=/usr
*default release=cvs tag=.
*default delete use-rel-suffix
*default compress
ports-all
host= 는 -h 옵션에 지정하는 호스트 이름과 동일하므로 굳이 수정할 필요는 없고, base와 prefix도 대부분의 경우에는 수정할 일이 없을 것이다. release에 나오는 tag=.에서 .은 최신 버전을 의미하는 것으로, 이 태그를 바꾸면 특정 릴리즈의 포트 트리를 가져오는 것도 가능하다. 나머지 옵션은 그대로 두도록 하자. 그 뒤의 ports-all은 포트 트리 전체를 업데이트하겠다는 의미인데, 일부 카테고리만을 업데이트하는 것도 가능하지만 의존성이 많이 복잡한 관계로 용량이 된다면 전체 트리를 업데이트하는 것이 더 좋다.

가령 cvsup.kr.freebsd.org에서 4.3-RELEASE의 포트 트리를 가져오고 싶다면 다음과 같이 supfile을 작성해도 좋다.


*default host=cvsup.kr.freebsd.org
*default base=/usr
*default prefix=/usr
*default release=cvs tag=RELEASE_4_3_0
*default delete use-rel-suffix
*default compress
ports-all
tag에 지정된 RELEASE_4_3_0은 4.3-RELEASE를 의미하는 포트 트리의 CVS 태그이다. (태그에 대한 자세한 내용에 대해 알고 싶으면 info cvs 명령을 내려 CVS에 대한 자세한 사항을 살펴보기 바란다) 포트 트리는 FreeBSD의 기본 시스템 소스와는 별개로 운영되기 때문에, 기본 시스템을 업그레이드하지 않아도 최신 포트 트리에서 패키지를 설치할 수 있다. 만약 포트 트리가 시스템에서 중요한 변경을 해야만 동작한다면, 릴리즈 사용자의 경우 업그레이드 키트라는 것을 별도로 설치해야 하지만, 4.3 릴리즈 사용자는 아직 업그레이드해야 할 필요는 없다. 만약 4.2 이하 버전을 사용한다면 http://www.freebsd.org/ports/ 페이지에서 Upgrade kits를 받아서 pkg_add 하기 바란다.

보통 업데이트는 최신 트리로 하는 것이 일반적이므로, 앞서 제시한 명령을 그대로 사용하면 최신 트리로 업데이트할 수 있다.


# cvsup -g -L2 -h cvsup.kr.freebsd.org /usr/share/examples/cvsup/ports-supfile
Parsing supfile "/usr/share/examples/cvsup/ports-supfile"
Connecting to cvsup.kr.freebsd.org
Connected to cvsup.kr.freebsd.org
Server software version: REL_16_1
Negotiating file attribute support
Exchanging collection information
Establishing multiplexed-mode data connection
Running
Updating collection ports-all/cvs
Edit ports/INDEX
Add delta 1.344 2001.08.16.21.21.26 asami
Edit ports/Mk/bsd.ruby.mk
Add delta 1.54 2001.08.16.11.38.44 knu
Edit ports/archivers/rpm/Makefile
Add delta 1.36 2001.08.15.20.33.12 knu
Edit ports/audio/aureal-kmod/Makefile
Add delta 1.10 2001.08.13.13.20.28 sobomax
Edit ports/audio/aureal-kmod/distinfo
Add delta 1.6 2001.08.13.13.20.28 sobomax
Edit ports/audio/cymbaline/Makefile
Add delta 1.8 2001.08.14.10.35.09 ijliao
Edit ports/audio/cymbaline/distinfo
Add delta 1.8 2001.08.14.10.35.09 ijliao
...
Edit ports/x11-wm/wmakerconf/Makefile
Add delta 1.29 2001.08.15.20.33.12 knu
Edit ports/x11-wm/wmanager/Makefile
Add delta 1.9 2001.08.14.10.09.15 sobomax
Edit ports/x11-wm/wmanager/files/patch-aa
Add delta 1.1 99.12.06.00.50.06 cpiazza
Add delta 1.2 2001.08.14.10.09.15 sobomax
Shutting down connection to server
Finished successfully
포트 트리에는 항상 /usr/ports/INDEX 라는 파일이 있어서 이 파일에는 현재 포트 트리에 대한 패키지 목록이 들어 있다. 하지만 INDEX 파일은 포트의 일부가 업데이트될 때 마다 갱신되는 것이 아니고 주기적으로 생성되기 때문에 항상 최신 정보를 담고 있는 것은 아니다. 그러나 릴리즈 시에는 모든 포트의 업데이트를 중지하고 INDEX 파일을 생성하기 때문에, 릴리즈의 경우에 한해서 INDEX 파일은 실제 포트 트리와 일치한다. 그 외의 경우에는 일치하는 일이 거의 없을 것이다.

포트 트리는 하루에 한번 정도 또는 패키지 업데이트 하기 바로 전에 하는 것으로 충분하다. crontab에 넣어 둔다면 자동 업데이트하게 할 수도 있다.


업그레이드해야 하는 패키지의 판별: pkg_version
pkg_version이라는 기본 프로그램은 재미있는 일을 할 수 있는데, 바로 포트 트리의 INDEX 파일과 현재 설치된 프로그램의 버전을 비교해서 프로그램의 업데이트 여부를 판별해 주는 것이다. 즉 최신 버전으로 갱신된 INDEX 파일이 있다면, 다음 명령을 사용하여 패키지의 갱신 여부를 확인할 수 있다.


# pkg_version
Hermes =
ImageMagick <
Mesa =
ORBit =
XFree86 <
XPostitPlus =
a2ps-a4 =
aalib =
acroread-commfont =
acroread4 =
analog <
apache =
...
xscreensaver-gtk <
xv <
zh-ghostscript <
zh-ttfm =
zip =
각 패키지명 다음에 나오는 것은 갱신 상태이다. 의미는 다음과 같다.


=
설치된 패키지의 버전이 포트 색인에 있는 패키지의 버전과 일치
<
설치된 패키지의 버전이 포트 색인에 있는 패키지의 버전보다 낮음
이 경우는 포트 트리에서 패키지를 업데이트하는 것이 좋다.
>
설치된 패키지의 버전이 포트 색인에 있는 패키지의 버전보다 높음
이 경우는 포트 트리의 버전이 현재 시스템보다 낮은 경우이거나 잘못된 버전이 설치된 경우이다.
?
포트 색인에 없는 패키지
자작 포트이거나, 아주 오래되어 더이상 존재하지 않는 패키지의 경우이다.
*
패키지의 여러 버전이 동시에 설치되었음
한 패키지의 두개 이상의 버전이 설치된 경우이다. 가령 emacs 버전 19와 20을 동시에 설치한 경우를 생각하면 된다.
pkg_version의 매뉴얼 페이지를 보면 여러가지 옵션이 있는데, 가령 업데이트 대상의 패키지만을 출력하고 싶다면 출력 범위를 제한하면 된다.


# pkg_version -l '<'
ImageMagick <
XFree86 <
analog <
...
xscreensaver-gtk <
xv <
zh-ghostscript <

pkg_version의 재미있는 점은 간단한 업그레이드 스크립트를 작성해 줄 수 있다는 것이다.


# pkg_version -c > update.sh이렇게 하면 쉘 스크립트의 형태로 출력해 주는데, 기존 패키지를 지우고 새 패키지를 포트 트리에서 설치하도록 하는 스크립트이다. 완벽하지는 않지만, 일단 pkg_version에서 생성된 스크립트는 sh로 직접 실행할 수는 없으므로, 수동으로 편집한 후(업데이트 대상이 아닌 것을 지우거나, 포트 빌드시에 특정한 플래그를 주어야 하는 경우 등) 앞부분의 exit 1 이 있는 행까지를 지우고 sh 로 실행하면 업그레이드의 효과를 얻을 수 있다. 다음은 pkg_version -c의 출력의 예이다.


echo "The commands output of pkg_version cannot be executed without editing."
echo "You MUST save this output to a file and then edit it, taking into"
echo "account package dependencies and the fact that some packages cannot"
echo "or should not be upgraded."
exit 1
#
# ImageMagick
# needs updating (port has 5.3.6_2)
#
cd /usr/ports/graphics/ImageMagick
make clean && make && pkg_delete -f ImageMagick-5.3.1
make install clean

#
# XFree86
# needs updating (port has 4.1.0_4)
#
cd /usr/ports/x11/XFree86-4
make clean && make && pkg_delete -f XFree86-4.0.3_3
make install clean
...
#
# zh-ghostscript
# needs updating (port has 6.50_1)
#
cd /usr/ports/chinese/ghostscript6
make clean && make && pkg_delete -f zh-ghostscript-6.50
make install clean
편집이 끝났으면 이 스크립트를 실행하면 된다. 앞부분의 다섯 행은 반드시 지워야 한다는 점에 유의하자. 실행한 후에는 느긋하게 끝날때까지 기다리면 되지만, 꼭 그렇지는 않고 중간중간에 어떤 이유로 멈추게 되는지 살펴보아야 한다.


# sh update.sh
다만 pkg_version이 출력하는 스크립트의 단점은 기존 패키지를 무리하게 지우고 새 패키지를 설치하는 것이므로, 설치 도중에 의존성이 잘못되는 경우나 메타 포트를 적절하게 업데이트시켜 주지 않는다는 단점이 있으므로 수동 편집시에 충분히 주의하도록 하자.


바이너리 업그레이드: pkg_update
4.3 이후에 pkg_update라는 명령어가 새로 생겼는데, 이 명령어를 이용하면 바이너리 패키지 업데이트를 할 수 있다. 방법은 매우 간단하다. 가령 현재 시스템에 transfig-3.2.3c 패키지가 깔려 있는데, 3.2.3d 버전으로 업데이트하고 싶다면, 3.2.3d 버전의 패키지를 구해서


# pkg_update transfig-3.2.3d.tgz를 실행하면 된다. 최신 바이너리 패키지를 구하는 가장 좋은 방법은 FreeBSD FTP 사이트를 찾는 것이다. 보통 -stable의 패키지는

ftp://ftp.freebsd.org/pub/FreeBSD/ports/i386/packages-stable/

또는 해당 미러 사이트에서 구할 수 있다. 바이너리 패키지를 받았으면 pkg_update 명령으로 업데이트하면 된다.

문제는 업데이트하는 경우에, 의존성에 일치하지 않는 경우 업데이트가 실패할 수도 있다는 것이다. 이는 단순히 pkg_update 명령이 기존 패키지를 지우고 새 패키지를 쓰고 의존성을 기존에 설치된 것 기준이 아니라 자신의 빌드 환경의 의존성으로 업데이트하려 하기 때문이다. 따라서 pkg_update는 의존성이 일치하지 않는 경우가 아니면 업데이트할 수 없다는 단점이 있다.


sysutils/portupgrade: 포트/패키지 업그레이드 유틸리티
FreeBSD의 활발한 포트 커미터 중 한명인 Akinori MUSHA 는 ruby 언어를 사용하여 유용한 패키지 관리 도구를 몇가지 만들었는데, 이 도구는 기존 시스템에 존재하는 pkg_version, pkg_update보다 향상된 기능을 제공한다. 즉 pkg_version 대신 portversion, pkg_update 대신 portupgrade 명령이 있는데, 이들은 각각 포트에서 패키지를 업데이트하는데 사용할 수 있다. portversion의 경우 pkg_version과 사용법이 같지만, pkg_delete와 make install 대신 portupgrade 명령을 사용하여 패키지를 업데이트할 수 있고, INDEX 파일 대신 포트 트리에서 최신의 INDEX를 생성할 수 있다.

이러한 도구는 sysutils/portupgrade를 설치하면 되는데, 일단 포트 트리를 업데이트하고 설치하기 바란다. portupgrade는 여러가지 유틸리티를 제공하는데, 그 일부를 살펴보자.


pkg_deinstall
pkg_remove와 비슷하나, 역의존성 삭제 기능도 할 수 있다. 가령 ko-netscape-communicator패키지는 netscape-communicator에 의존하는데, 일반적으로는 ko-netscape-communicator를 삭제하는 것 만으로 netscape-communicator까지 삭제할 수는 없지만 pkg_deinstall의 -R 옵션을 사용하면 상위 의존성도 삭제 가능하다. 단 이 옵션은 다른 어플리케이션을 광범위하게 지울 가능성이 높으므로 -n 옵션을 사용해서 어떤 결과가 일어나는지 먼저 확인해 보고 지우기 바란다.

pkg_glob
pkg_info와 비슷하지만 목록만 나열해 준다. 해당 패키지의 의존성 등을 얻을 수도 있다. 해당 패키지에 의존하는 패키지는 -r, 해당 패키지가 의존하는 패키지는 -R로 얻을 수 있다.


# pkg_glob -r linux-netscape-communicator-4.77
linux-netscape-communicator-4.77
ko-netscape-communicator-linux-4.77
# pkg_glob -R linux-netscape-communicator-4.77
XFree86-libraries-4.0.3_1
imake-4.0.3
netscape-remote-1.0_1
netscape-wrapper-2000.07.07
linux_base-6.1
linux-netscape-communicator-4.77
linux-로 시작하는 패키지를 모두 보고 싶다면 다음과 같은 명령을 준다.


# pkg_glob 'linux-*'
linux-lesstif-ns-0.92.6
linux-realplayer-8.cs1
linux-netscape-communicator-4.77
glob용 와일드카드를 사용하려면 반드시 ' '으로 둘러쌓아야 한다는 점 잊지 말자.


pkgdepfix
패키지 의존성이 깨어진 것을 찾아내어 복구시켜 준다. 한번 실행하게 되면 현재 패키지 데이터베이스를 돌아다니면서 실제 존재하지 않는 의존성의 경우 가장 가까운 것을 찾아 복구시켜 주는데, 자동 판단이 불가능하면 사용자에게 물어보게 된다. 패키지를 여러번 설치/삭제하였다면 한번쯤 실행해 보도록 하자. 자주 할 필요는 없다.


portsclean
포트 디렉토리에서 이것저것 설치하다 보면 작업 디렉토리를 지우지 않아 곳곳에 work/ 디렉토리가 남아 있는 경우가 있을 것이다. 이런 경우에는 /usr/ports에서 make clean 하면 되지만 시간이 너무 오래 걸리는 단점이 있다. portsclean은 디렉토리를 찾아다니며 남아있는 작업 디렉토리나 사용하지 않는 원본 소스 파일을 지워 준다. 작업 디렉토리를 지우려면


# portsclean -C쓰지 않는 소스를 지우려면


# portsclean -D를 하면 된다.


portsdb
현재 포트 트리를 바탕으로 /usr/ports/INDEX 파일을 최신 트리에 맞게 생성해 준다. 생성하면서 정리된 데이터베이스 색인 파일인 INDEX.db와 INDEX.rbo을 생성하게 할 수도 있다. 보통 CVSup 후에


# portsdb -uU
Updating the ports database in /usr/ports ...........done
Updating the ports index ... done
로 생성시켜 두면 충분하다.


portversion
pkg_version과 유사하지만, -c 옵션의 경우 portupgrade를 사용하는 업데이트용 쉘 스크립트 출력을 내 준다. 사용법은 pkg_version과 같다.


# portversion -c > update.sh
# sh update.shportupgrade가 유연한 도구이므로 업데이트시의 문제가 많이 줄어들 것이다.


portupgrade/portinstall
포트 기반의 패키지 업그레이드 도구이다. portupgrade의 좋은 점은 포트에서 빌드하여 설치할 때 의존성 문제를 깔끔하게 해결해 준다는 점이며, 더욱 좋은 점은 의존하는 패키지와 의존받는 패키지에 대해 재귀적 업데이트가 가능하다는 점이다. 이는 메타 포트등의 업데이트에도 유용한데, 가령 gnome 시스템을 업데이트하고자 한다면 gnome 패키지에 의존하는 패키지를 찾아다니며 일일이 업데이트해야 했지만, portupgrade를 사용하면


# portupgrade -R gnome으로 쉽게 해결할수 있다. 이 명령은 gnome(x11/gnome 메타포트)에 의존하는 패키지를 모두 찾아 업데이트해 준다. portinstall은 업데이트용이 아니라 새로 패키지를 설치하는 경우인데, portupgrade에 -N 옵션을 준 것과 동일하다. portupgrade는 스스로 업데이트하는 일도 가능하다. portupgrade는 최근에 급속히 버전이 올라가고 있으므로 자주 업데이트하도록 하자.


# portupgrade -r portupgrade가령 버전이 낮은 wget 을 현재 포트 트리에 맞는 최신 버전으로 업그레이드하려고 해 보자. 포트 트리만 최신으로 유지하고 있다면 다음 명령으로 간단하게 처리할 수 있다.


# portupgrade wget
===> Cleaning for gettext-0.10.35
===> Cleaning for gmake-3.79.1
===> Cleaning for libtool-1.3.4_2
===> Cleaning for wget-1.7_2
===> Extracting for wget-1.7_2
>> Checksum OK for wget-1.7.tar.gz.
>> Checksum OK for wget-17-v6-20010716a.diff.gz.
===> wget-1.7_2 depends on executable: gmake - found
===> wget-1.7_2 depends on shared library: intl.1 - found
...
===> Generating temporary packing list
install-info /usr/local/info/wget.info /usr/local/info/dir
===> Compressing manual pages for wget-1.7_2
===> Registering installation for wget-1.7_2
===> Cleaning for gettext-0.10.35
===> Cleaning for gmake-3.79.1
===> Cleaning for libtool-1.3.4_2
===> Cleaning for wget-1.7_2
만약 기존 시스템에 wget이 설치된 적 없어서 새로이 설치하려 한다면 portinstall 명령이나 portupgrade -N 을 사용하면 된다. 만약 해당 패키지에 의존하는 패키지까지 모두 업데이트하고자 한다면 -r, 해당 패키지가 의존하는 패키지까지 모두 업데이트하고자 한다면 -R 옵션을 주면 좋다. 포트 빌드시에 줄 수 있는 옵션은 -m 옵션 뒤에 주면 된다. -m 옵션은 여러번 줄 수 있다. 옵션을 기본적으로 주고 싶은 것이 여럿 있다면 PORTUPGRADE 환경변수에 적어주면 된다.


# portupgrade -m WITH_GTK=YES xscreensaver
바이너리 패키지가 존재한다면, PKGREPOSITORY 환경변수를 적절하게 설정하고 그 디렉토리의 All(또는 PKGREPOSITORYSUBDIR환경변수가 지정하는) 디렉토리에 바이너리 패키지를 넣은 다면 -p 옵션을 주면 바이너리 패키지를 통한 업그레이드도 가능하다. 기본값은 /usr/ports/packages/All 에 바이너리 패키지를 넣어두면 된다.

portupgrade 도구를 사용하면 지금까지 어렵게만 느껴졌던 FreeBSD의 업그레이드를 비교적 쉽게 해결할 수 있다. 지금까지 시스템 업그레이드에 도전해 본 적이 없거나, 패키지 업데이트에 어려움을 느꼈다면 지금 포트 트리를 업데이트하고 패키지 업데이트를 위한 여러 도구를 시험해 보자.

이러한 업데이트가 비교적 손쉽게 가능해진 것은 최근 들어서 포트에 ORIGIN이라는 속성이 추가되었기 때문인데, 이는 설치된 패키지가 어떤 포트에서 설치되었는지를 기록하는 속성이다. 오래전에 설치된 시스템에는 패키지 데이터베이스(/var/db/pkg)에 ORIGIN이 기록되어 있지 않으므로 portupgrade 실행시 -o 옵션으로 ORIGIN을 주어야 할 경우도 있다.


# portupgrade -o archivers/zip zip


ruby 언어
ruby는 일본의 마쯔모토 유키히로씨가 만든 객체지향 스크립트 언어로, 전체적으로는 python과 유사한 구조를 갖고 있는 스크립트 언어이다. 최근에 일본을 중심으로 사용자층이 두터워지고 있으며, FreeBSD에도 수많은 ruby 모듈이 포트에 존재한다. ruby- 로 시작하는 패키지는 모두 ruby 모듈이라고 생각하면 된다. 국내에서는 거의 알려지지 않은 언어인데, 스크립트 언어에 관심 있는 사용자라면 한번 살펴보는 것도 좋으리라 생각한다. ruby의 홈페이지는 http://www.ruby-lang.org 이다.




끝으로
이번에는 포트의 조금 더 고급스런 사용법에 대해 알아 보았다. 이전 FreeBSD의 포트는 여러가지 제한점이 있었으나 최근에는 여러가지 도구의 등장으로 그러한 제한이 점점 없어져가고 있으니, Debian GNU/Linux의 dselect나 apt-get와 같은 조금 더 사용자에게 편리한 도구의 출현을 기대해 볼 수 있지 않을까 한다. 하지만 본질적으로 FreeBSD 포트는 직접 소스에서 빌드하여 설치하는 방식이므로, 바이너리 업데이트 위주인 Debian의 도구와는 많은 점이 다르다. 포트는 컴파일 관계로 시간은 좀 걸리겠지만(패키지 바이너리를 사용할 수 있지만 FreeBSD에서는 바이너리가 주 업데이트 방식이 아니다) 가장 확실하고 사용자에게 많은 선택을 줄 수 있는 유연한 패키징 방식이라고 생각한다.

댓글 없음: