2010/09/23

Perl 스크립트에 필요한 모듈 같이 넣기 App::FatPacker

Perl 스크립트를 만들다 보면 기본 Perl 배포본에는 기본으로 들어가는 코어모듈 이외에 추가로 모듈을 설치하여 사용하게 되는데, 만약 자신에 배포해야 하는 스크립트에 어떤 모듈을 사용해야 하지만 이것을 사용자가 사용할 때 모듈에 대한 의존성을 신경 쓰지 않으며 추가로 모듈을 설치해야하는 수고를 덜어주고 싶을 때가 있다.

이럴 때 유용하게 써먹을 수 있는 모듈이 바로 App::FatPacker 모듈이다.

그럼 예를 들어서 한 번 App::FatPacker를 사용해보자.
CPAN에는 Linux머신의 다양한 성능정보 및 시스템정보를 접근할 수 있는 Sys::Statistics::Linux 라는 훌륭한 모듈이 있다. ( vmstat,iostat 명령등의 결과 ,/proc 디렉토리를 수동으로 노가다 파싱해서 수치를 뽑아내서 썼던 사람이 보면 이렇게 잘 차려진 밥상을 보며 허무감의 눈물을 흘릴만한~ )

예를 들어 Sys::Statistics::Linux::SysInfo 를 사용하여 Linux머신의 각종 정보를 뽑아내는 Perl 스크립트를 다음과 같이 만들었다고 했을 때

<sysinfo.pl>
#!/usr/bin/env perl
use strict;
use warnings;
use Sys::Statistics::Linux::SysInfo;

my $lxs = Sys::Statistics::Linux::SysInfo->new;
my $info = $lxs->get;
print "$_ : $info->{$_}\n" for keys %$info;

<실행결과 예>
swaptotal : 11881464 kB
arch : x86_64
version : #43-Ubuntu SMP Thu Sep 16 16:05:42 UTC 2010
release : 2.6.32-24-server
hostname : somehost
countcpus : 8
domain : (none)
idletime : 63d 23h 59m 42s
kernel : Linux
memtotal : 4055708 kB
uptime : 7d 23h 30m 3s

이것을 사용하려면 Sys::Statistics::Linux 모듈을 따로 설치해야 한다. 만약에 수백,수천대의 서버에 복사해서 각 시스템의 정보를 뽑아오는 작업을 한다고 하면 그 많은 서버에 이 간단한 스크립트 하나를 위해 Sys::Statistics::Linux 를 일일이 설치하기는 부담스럽고 귀찮을 것이다.

바로 이럴 때 App::FatPacker가 빛을 발한다. 그러면 위에서 예를 든 sysinfo.pl 스크립트에 Sys::Statistics::Linux 모듈을 포함시키는 작업을 진행해보자.

App::FatPacker 모듈을 설치한 다음

$ fatpack trace sysinfo.pl
라고 명령을 내리면 필요한 추가 모듈을 분석하여 fatpacker.trace 란 파일을 생성한다.

$ fatpack packlists-for `cat fatpacker.trace` > packlists
의 명령으로 fatpacker.trace 파일에서 포함할 파일의 리스트를 packlists 파일로 뽑는다.

$ fatpack tree `cat packlists`
packlists 에 있는 모듈 파일들을 패키징 할 준비를 한다.

$ (fatpack file; cat sysinfo.pl) > sysinfo.packed.pl
sysinfo.pl에 모듈을 같이 패키징해서 sysinfo.packed.pl 이란 스크립트를 생성한다.
(여기서 홈디렉토리에 ~/lib 디렉토리가 없다고 에러가 나는 경우가 있는데 이때는 lib 디렉토리를 그냥 만들어 주면 된다.)

이제 sysinfo.packed.pl 스크립트는 자체적으로 의존성 있는 모듈을 파일의 첫 부분에 적절히 패키징하여 포함하므로 따로 필요한 모듈이 설치되어 있지 않아도 잘 실행되게 된다.

주의점:
App::FatPacker는 순수한 Perl모듈에 대해서만 동작한다. C라이브러리등과 연동되어서 돌아가는 XS모듈은 동작하지 않는다. 그리고 만능이 아니므로 비교적 크기가 작고 적은 수의 모듈에 대해서만 사용하는 것이 좋다. 아주 많은 모듈을 포함하고 Perl이 독립적으로 패키징되어서 돌아가도록 하고 싶으면 PAR::Packer 모듈을 참고하길 바란다.

2010/09/16

설치된 Perl CPAN 모듈 목록 뽑아서 다시 설치하기

Perl 버젼이 새로나오면 perlbrew를 이용해서 새로운 버젼의 Perl을 설치할 경우 문제가 되는 것은 기존에 설치한 모듈들을 어떻게 다시 다 설치할 것 인가이다.

모듈을 별도의 디렉토리를 지정해서 설치해서 사용하면 모듈의 Path를 그대로 지정해주면 사용할 수 있겠지만 여기서 문제는 C라이브러리 및 코드와 연동되어 컴파일되어 설치되는 일명 XS모듈들이다. 이런 모듈들은 Perl 버젼에 따라 호환이 되지 않은 경우가 있기 때문에 깔끔하게 다시 설치해주는 것이 좋은데 그러려면 일단 현재 설치된 모듈들의 목록을 뽑아야 한다.

현재 설치된 모듈들의 목록을 얻으려면 ExtUtils::Installed 모듈을 이용하여 다음과 같이 명령을 내린다.

perl -MExtUtils::Installed -le 'print for ExtUtils::Installed->new->modules'

그러면 다음처럼 설치된 모듈들의 목록이 쭉 출력되게 되는데
Algorithm::Diff
Algorithm::Permute
Any::Moose
AnyEvent
AnyEvent::HTTP
App::CPAN::Fresh
App::Cmd
.
.
.


다음과 같이 리다이렉션으로 목록을 텍스트 파일로 저장해 놓고

perl -MExtUtils::Installed -le 'print for ExtUtils::Installed->new->modules' > modules.txt

perlbrew로 새 버젼의 Perl을 설치한 다음

cat modules.txt | xargs cpan -i

명령이나 cpanm 을 사용한다면

cat modules.txt | cpanm -v

명령을 내리면 목록의 모듈들을 모두 다시 설치한다.