열세번째 날: 설치한 모듈 목록 확인하기

저자

@keedi - Seoul.pm 리더, Perl덕후, 거침없이 배우는 펄의 공동 역자, keedi.k at gmail.com

시작하며

펄을 사용하다보면 CPAN을 사용하는 것은 아주 자연스러운 일입니다. CPAN을 이용해서 다양한 모듈을 설치하고 사용하다보면 어느 순간 지금까지 설치한 모듈의 전체 목록이 필요할 때가 있습니다. 단순한 호기심 때문일 수도 있고, 펄을 새로 설치한 후 필요한 모듈이 없어서 일 수도 있으며, 펄로 만든 서비스를 다른 시스템에 옮기기 위해서 일 수도 있습니다. 지금까지 그렇지 않았다하더라도, 여러분은 현재 시스템에 설치한 모듈의 목록을 확인하는 방법이 머지않아 필요할 것입니다. :)

준비물

필요한 모듈은 다음과 같습니다.

직접 CPAN을 이용해서 설치한다면 다음 명령을 이용해서 모듈을 설치합니다.

$ sudo cpan ExtUtils::Install

사용자 계정으로 모듈을 설치하는 방법을 정확하게 알고 있거나 perlbrew를 이용해서 자신만의 Perl을 사용하고 있다면 다음 명령을 이용해서 모듈을 설치합니다.

$ cpan ExtUtils::Install

사실 ExtUtils::Install 모듈은 코어 모듈이므로 따로 설치하지 않고, 펄과 함께 설치된 버전을 사용해도 무방합니다. :)

원리

CPAN의 모듈을 정석으로 설치할 경우 설치하는 각각의 모듈은 설치되는 디렉터리에 .packlist 파일을 생성합니다. 따라서 이 .packlist 파일을 모두 모아 각 파일의 경로와 내용을 참고하면 간단히 설치한 모듈의 전체 목록을 확인 할 수 있습니다. 그러므로 설치한 모듈의 전체 목록을 찾고 싶다면 우선 .packlist 파일을 확보해야 합니다. 당연하지만 .packlist 파일은 모듈을 설치한 디렉터리에 존재하며, 일반적으로 이 디렉터리는 @INC에서 명시하는 경로입니다. @INC의 값은 여러분의 시스템 및 펄 환경에 따라 다릅니다. @INC를 확인하려면 다음 명령을 실행합니다.

$ perl -E 'say for @INC'
/etc/perl
/usr/local/lib/x86_64-linux-gnu/perl/5.20.1
/usr/local/share/perl/5.20.1
/usr/lib/x86_64-linux-gnu/perl5/5.20
/usr/share/perl5
/usr/lib/x86_64-linux-gnu/perl/5.20
/usr/share/perl/5.20
/usr/local/lib/site_perl
.
$ 

확인해야 할 디렉터리 목록을 확보했으니 이제 .packlist를 찾아볼까요? 명령줄에서 다음 명령을 실행합니다.

$ perl -MFile::Find -E 'find( sub { return unless $_ eq ".packlist"; say $File::Find::name }, @INC )'

출력되는 .packlist 파일의 전체 경로로 이 값을 이용해 설치한 모듈의 목록을 구해야 합니다. 다만 목록이 꽤 길게 나올텐데 원라이너로 처리하기는 조금 버겁군요. 원라이너를 스크립트로 변경해봅시다.

#!/usr/bin/env perl

use v5.20;
use strict;
use warnings;

use File::Find;

find(
    sub {
        return unless $_ eq ".packlist";
        say $File::Find::name;
    },
    @INC,
);

.packlist 파일은 /path/to/auto/Foo/Bar/Baz/.packlist와 같은 식의 경로를 가지는데 .../auto/ 뒷 부분부터 /.packlist 앞 부분 까지의 경로에서 / 구분자를 ::으로 바꾸면 설치한 모듈의 실제 이름입니다. 스크립트를 조금 더 고쳐볼까요?

#!/usr/bin/env perl

use v5.20;
use strict;
use warnings;
use Config;

use File::Find;

my %modules;
find(
    sub {
        return unless $_ eq ".packlist";
        return if     $File::Find::dir eq $Config{archlibexp};

        my $module = $File::Find::name;
        $module =~ s{^.*?/auto/(.*)/.packlist}{$1}s;
        $module =~ s{/}{::}g;

        ++$modules{$module};
    },
    @INC,
);

say for keys %modules;

이전과 달라진 부분은 다음과 같습니다.

사용법

설치한 모듈의 목록을 얻는 원리를 설명하다보니 조금 멀리 돌아왔군요. 모듈을 구하고 싶을 때마다 이렇게 스크립트를 짜는 것은 번거롭겠죠. 준비물을 보면서 눈치채셨겠지만, 이미 펄은 코어 모듈로써 ExtUtils::Install 모듈을 제공하며, 이 모듈은 지금까지 설명한 기능을 이미 포함하고 있습니다. 따라서 여러분은 복잡한 부분은 다 건너뛰고 손쉽게 원하는 결과를 얻을 수 있습니다. 명령줄에서 다음 명령을 실행해보세요.

$ perl -MExtUtils::Installed -E 'say for ExtUtils::Installed->new->modules'
Acme::AsciiArtFarts
Acme::AsciiArtinator
Acme::EyeDrops
Algorithm::C3
...
CPAN::Meta
CPAN::Meta::Check
CPAN::Uploader
CSS::Tiny
$

간단하죠? :)

여러분이 perlbrew를 이용해서 펄 환경을 구축해 쓰고 있다면 더욱 간단한 명령으로 동일한 결과를 얻을 수 있습니다.

$ perlbrew list-modules
Acme::AsciiArtFarts
Acme::AsciiArtinator
Acme::EyeDrops
Algorithm::C3
...
CPAN::Meta
CPAN::Meta::Check
CPAN::Uploader
CSS::Tiny
$

perlbrewlist-modules 옵션은 내부적으로 ExtUtils::Installed 모듈을 사용해 설치한 모듈의 목록을 출력하도록 구현되어 있으며 지금까지 살펴본 내용과 대동소이합니다.

#
# perlbrew 소스 코드 중 일부
#
sub run_command_list_modules {
    my ($self) = @_;
    my $class = ref($self) || __PACKAGE__;
    my $app = $class->new(
        qw(--quiet exec --with),
        $self->current_env,
        'perl', '-MExtUtils::Installed', '-le',
        'BEGIN{@INC=grep {$_ ne q!.!} @INC}; print for ExtUtils::Installed->new->modules;'
    );
    $app->run;
}

정리하며

막상 알고보면 간단하지만 현재 시스템 및 사용 중인 펄 환경에 설치한 모듈의 목록을 구하는 방법을 모르는 경우가 생각보다 많은 편입니다. 대부분의 경우 설치한 모듈의 목록을 구하는 것은 다시 동일한 모듈을 설치해야 할 필요가 (갑자기) 생겼기 때문입니다. 지금까지 알아본 여러가지 방법을 이용하거나 응용하면 손쉽게 모듈의 목록을 확보할 수 있으며 cpan 쉘이나 cpanm을 이용해 새로운 환경에 이전에 설치했던 펄 모듈을 동일하게 설치할 수 있을 것입니다.

Enjoy Your Perl! ;-)

EOT

R.I.P. @am0c

blog comments powered by Disqus