'gentoo'에 해당되는 글 2건

  1. 2009.07.12 PostgreSQL On Gentoo
  2. 2009.06.04 패키지 관리 속도 향상법 (emerge sync)
2009.07.12 03:36

PostgreSQL On Gentoo

이 문서는 Gentoo에서 PostgreSQL을 설치하기 위한 문서입니다. http://www.gentoo.org/doc/en/postgres-howto.xml 을 원본으로 하여 번역한 것입니다.

1 소개

1.1 PostgreSQL 소개

대부분의 개발자와 다른 데이터베이스 솔루션들에 대하여 대화를 나누어 보면, 두 가지 종류의 데이터베이스가 주로 대답으로 나옵니다. 하나는 MySQL이고 다른 하나는 이 문서에서 다루고자 하는 PostgreSQL입니다. 서로간의 장단점에 대해서 오랜 시간동안 논쟁이 있어 왔지만, PostgreSQL이 MySQL보다 진정한 관계형 데이터베이스 구조에는 더 확고하다는 말이 있습니다. FOREIGN KEY와 같은 대부분의 기본적인 특징들이 MySQL 5에서 추가되었습니다. 그러나 어떤 상황이 되든, 이 문서는 여러분이 PostgreSQL을 사용할 데이터베이스로 선택했다고 가정합니다. 처음 해야 할 일은 emerge 과정을 시작하는 것입니다. 다음 섹션에서는 기본 설정 뿐만 아니라 emerge를 통한 설치 과정을 설명할 것입니다.

1.2 PostgreSQL 설치하기

시작하려면 먼저 PostgreSQL 패키지를 emerge 해야 합니다. 이렇게 하려면 다음과 같은 코드로 옵션이 제대로 설정되어 있는지를 먼저 확인해야 합니다.

코드 목록 1.1: PostgreSQL 빌드 옵션 확인
# emerge -pv postgresql

These are the packages that I would merge, in order:

Calculating dependencies ...done!
[ebuild  N    ] dev-db/postgresql-8.0.4  -doc -kerberos +libg++ +nls +pam +perl
-pg-hier -pg-intdatetime +python +readline (-selinux) +ssl -tcltk +xml2 +zlib 0 kB

여기 서로 다른 빌드 옵션이 나타내는 것의 목록이 있습니다.

USE 플래그 의미
doc 이 USE 플래그는 표준 man 페이지의 외부 문서 설치를 켜거나 끕니다. 공간이 적거나 문서를 얻을 수 있는 다른 방법(온라인 등)이 있으시면 이것을 끄시면 됩니다.
kerberos 데이터베이스에 이 옵션을 켜서 접속하면 admin이 데이터베이스로의 사용자/서비스를 검증할 때, kerberos를 사용하는 옵션을 갖습니다.
libg++ 이 옵션이 켜져 있으면 PostgreSQL의 C++ 바인딩이 설치됩니다. C++ 프로그래머가 연결할 수 있는 libpq++가 설치됩니다.
nls 이 옵션이 켜져 있으면 영어를 사용하지 않는 사용자를 위하여 번역된 문자열을 쓸 수 있습니다.
pam 이 옵션이 켜져 있고, admin이 PostgreSQL 설정 파일을 제대로 설정하면 사용자/서비스는 PAM(Pluggable Authentication Module)을 이용하여 PostgreSQL에 로그인 할 수 있게 됩니다.
perl 이 옵션이 켜져 있으면 PostgreSQL의 펄 바인딩이 설치됩니다.
pg-hier 이 옵션이 켜져 있으면 오라클 데이터베이스의 CONNECT 문에서 볼 수 있는 계층적 질의를 켜는 패치를 적용하게 됩니다. 오라클 참조 안내서에 계층적 질의에 대한 더 많은 정보가 있습니다.
pg-intdatetime 이 옵션이 켜져 있으면 PostgreSQL은 64비트 정수 날짜 형식을 지원하게 됩니다.
python 이 옵션이 켜져 있으면, PostgreSQL은 파이썬 바인딩을 설치하게 됩니다.
readline 이 옵션이 켜져 있으면, PostgreSQL은 readline 스타일의 명령줄 편집을 지원하게 됩니다. 이것은 명령 히스토리와 isearch 기능을 포함합니다.
selinux 이 옵션이 켜져 있으면, PostgreSQL의 selinux 정책이 설치 됩니다.
ssl 이 옵션이 켜져 있으면, PostgreSQL은 OpenSSL 라이브러리로 PostgreSQL 클라이언트와 서버 사이의 트래픽을 암호화하게 됩니다.
tcltk 이 옵션이 켜져 있으면, PostgreSQL은 tcl/tk 바인딩을 설치하게 됩니다.
xml2 이 옵션이 켜져 있으면, XPATH 스타일 xml 지원이 설치되게 됩니다. PostgreSQL의 xml 지원에 대한 더 자세한 정보는 PostgreSQL과 XML에서 찾으실 수 있습니다.
zlib 이것은 PostgreSQL 자체에서는 사용하지 않습니다만 pg_dump에서 생성하는 덤프를 압축합니다.

주의: pg-hier 패치 작성자는 패치 업무를 중단하였으며, 다음 버전에서는 삭제될 것입니다.

PostgreSQL을 여러분의 필요에 따라서 커스터마이징 하였다면 계속 진행하여 emerge를 시작하십시오.

코드 목록 1.2: PostgreSQL emerge 하기
# emerge postgresql
(Output shortened)
>>> /usr/lib/libecpg.so.5 -> libecpg.so.5.0
>>> /usr/bin/postmaster -> postgres
 * Make sure the postgres user in /etc/passwd has an account setup with /bin/bash as the shell
 *
 * Execute the following command
 * emerge --config =postgresql-8.0.4
 * to setup the initial database environment.
 *
>>> Regenerating /etc/ld.so.cache...
>>> dev-db/postgresql-8.0.4 merged.

einfo 출력에서 나타났듯이, 설치 후에 해야 할 작업들이 있습니다. 다음 장에서 PostgreSQL의 실제 설정에 대해서 살펴볼 것입니다.

2 PostgreSQL 설정하기

2.1 초기 데이터베이스 환경 설정하기


이전의 emerge 출력에서 알려준 대로, 초기 데이터베이스 환경을 설정해야 합니다. 그러나 이것을 하기 전에 한 가지 고려해야 할 점이 있습니다. MySQL 같은 것과는 다르게, PostgreSQL의 "root" 패스워드는 실제 사용자의 패스워드라는 것입니다. 그러나 ebuild가 생성한 사용자는 패스워드가 설정되어 있지 않습니다. 따라서 시작하기 전에 postgres 사용자의 패스워드를 설정해야 합니다.

코드 목록 2.1: 패스워드 설정
# passwd postgres
New UNIX password:
Retype new UNIX password:
passwd: password updated successfully

이제 설정이 되었고, 초기 데이터베이스를 생성할 수 있습니다.

코드 목록 2.2: emerge --config로 데이터베이스 환경 설정하기
# emerge --config =postgresql-8.0.4


Configuring pkg...

 * Creating the data directory ...
 * Initializing the database ...
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale C.

fixing permissions on existing directory /var/lib/postgresql/data ... ok
creating directory /var/lib/postgresql/data/global ... ok
creating directory /var/lib/postgresql/data/pg_xlog ... ok
creating directory /var/lib/postgresql/data/pg_xlog/archive_status ... ok
creating directory /var/lib/postgresql/data/pg_clog ... ok
creating directory /var/lib/postgresql/data/pg_subtrans ... ok
creating directory /var/lib/postgresql/data/base ... ok
creating directory /var/lib/postgresql/data/base/1 ... ok
creating directory /var/lib/postgresql/data/pg_tblspc ... ok
selecting default max_connections ... 100
selecting default shared_buffers ... 1000
creating configuration files ... ok
creating template1 database in /var/lib/postgresql/data/base/1 ... ok
initializing pg_shadow ... ok
enabling unlimited row size for system tables ... ok
initializing pg_depend ... ok
creating system views ... ok
loading pg_description ... ok
creating conversions ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the -A option the
next time you run initdb.

Success. You can now start the database server using:

    /usr/bin/postmaster -D /var/lib/postgresql/data
or
    /usr/bin/pg_ctl -D /var/lib/postgresql/data -l logfile start

 *
 * You can use /etc/init.d/postgresql script to run PostgreSQL instead of pg_ctl.
 *

이제 초기 데이터베이스가 설정되었습니다. 다음 섹션에서는 설치를 검증하고 데이터베이스에 접근할 사용자를 설정하는 것을 하겠습니다.

2.2 PostgreSQL 데이터베이스 설정


이제 PostgreSQL이 설정되었습니다. 이제 설치를 검증해 보는 것이 좋을 것입니다. 먼저, 서비스가 제대로 시작되는지 확인해 봅시다.

코드 목록 2.3: PostgreSQL 서비스 시작하기
# /etc/init.d/postgresql start
* Starting PostgreSQL ...                                          [ ok ]

이것이 제대로 동작하는지 확인이 되면, 부팅될 때마다 시작할 수 있도록 기본 runlevel에 추가해 주는 것이 좋을 것입니다.

코드 목록 2.4: 기본 runlevel에 추가하기
# rc-update add postgresql default
* postgresql added to runlevel default

이제 서비스가 시작되었고 데이터베이스를 검사해 볼 시간입니다. 시작하려면 createdb 명령을 써서 test 데이터베이스를 만들어 봅시다. -U 옵션을 넘겨서 사용자 이름(넘기지 않으면 기본값으로 현재 사용자 이름이 됩니다)를 정하고, -W 옵션으로 이전에 만들었던 암호를 요청합니다. 결국 만들고자 하는 데이터베이스에 이름을 정해 주었습니다.

코드 목록 2.5: createdb로 데이터베이스 생성하기
$ createdb -U postgres -W test
Password:
CREATE DATABASE

데이터베이스가 성공적으로 만들어졌으며, 데이터베이스가 기본적인 작업을 수행할 수 있는지 확인해 볼 수 있습니다. 계속해서 dropdb 명령으로 데이터베이스를 떨어뜨리고(지워버리고) 다음에 다시 쓸 데이터베이스를 생성할 것입니다.

코드 목록 2.6: dropdb로 데이터베이스 떨어뜨리기
$ dropdb -U postgres -W test
Password:
DROP DATABASE

이제, postgres 사용자만 명령을 수행할 수 있습니다. 분명히 다중 사용 환경은 설정의 일종은 아닙니다. 다음 섹션에서 사용자 계정에 대한 것을 살펴볼 것입니다.

2.3 데이터베이스 사용자 계정 설정하기


이미 언급했듯이, postgres 사용자로 로그인 해야 한다는 것은 다중 사용자 환경에서는 적합하지 않습니다. 대부분의 경우에 다양한 사용자와 서비스가 서버에 접근할 것이고 각각은 서로 다른 퍼미션이 필요할 것입니다. 따라서 이것을 다루려면 createuser 명령을 사용합니다. 이 명령은 몇몇 SQL 질의문을 수행하는 대신에 쓸 수 있고, admin의 관점에서 훨씬 더 유연합니다. 계속해서 두 명의 사용자, 즉 다른 사용자와 관리자를 추가할 수 있는 'superuser'와 일반 사용자를 생성할 것입니다.

코드 목록 2.7: superuser 설정하기
(replace chris with the username you'd like to use)
$ createuser -a -d -P -E -U postgres -W chris
Enter password for new user:
Enter it again:
Password:
CREATE USER

이제 superuser를 생성하였습니다. 명령줄 옵션 -a는 다른 사용자를 추가할 수 있는 사용자라는 것을 나타냅니다. -d는 데이터베이스를 만들 수 있는 사용자라는 것을 의미합니다. -P는 이 사용자의 암호를 입력할 수 있게 해 주고, -E는 보안 목적을 위하여 그것을 암호화합니다. 이제 일반 사용자를 설정하면서 이 새로운 사용자의 퍼미션을 검사해 봅시다.

코드 목록 2.8: 일반 사용자 설정하기
(replace chris with the username you've just created)
$ createuser -A -D -P -E -U chris -W testuser
Enter password for new user:
Enter it again:
Password:
CREATE USER

성공했습니다! 새 사용자를 이전에 만들었던 superuser를 통하여 만들었습니다. -A와 -D 옵션은 -a와 -d의 반대로써, 다른 사용자와 데이터베이스의 사용을 거부합니다. 이제 작업을 할 수 있는 사용자가 만들어졌고 새로운 데이터베이스가 만들어졌으므로 다음 장에서는 새 데이터베이스를 만드는 것을 살펴보겠습니다.

3 PostgreSQL 사용하기

3.1 퍼미션 설정하기

새 데이터베이스에 데이터베이스를 새로 만들고 다른 사용자를 추가할 수 있는 사용자가 있고 무엇이든 할 수 있는 메인 postgres 사용자가 있습니다. 이전에 만들었던 사용자는 현재 서버에 로그인할 수 있고, 그것에 대한 것입니다. 일반적으로 사용자는 데이터를 삽입하고 꺼낼 수 있어햐 하며, 때로는 다른 여러 작업을 할 수 있어야 합니다. 따라서 이 새 사용자가 어떤 것이든 할 수 있어야 하고, 적합한 퍼미션을 설정하여야 합니다. 이것은 -O 매개변수를 createdb에 넘겨주는 것으로 쉽게 할 수 있습니다. superuser로 MyDB라는 새 데이터베이스를 만들고 그것을 이전의 testuser의 소유로 만드는 것부터 시작할 것입니다.

코드 목록 3.1: MyDB 데이터베이스 만들기
$ createdb -O testuser -U chris -W MyDB
Password:
CREATE DATABASE

되었습니다. 이제는 새 MyDB 데이터베이스를 만들었고, testuser가 그것에 접근할 수 있습니다. 이것을 검사하기 위하여 testuser로 이 새 MyDB 데이터베이스에 로그인하여 볼 것입니다. psql 프로그램으로 이것을 할 수 있습니다. 이 프로그램은 명령줄에서 PostgreSQL 데이터베이스로 연결하는데 사용하는 프로그램입니다. 따라서 새 데이터베이스에 이렇게 연결합니다.

코드 목록 3.2: testuser로 MyDB 데이터베이스에 로그인하기
$ psql -U testuser -W MyDB
Password:
Welcome to psql 8.0.4, the PostgreSQL interactive terminal.

Type:  \copyright for distribution terms
       \h for help with SQL commands
       \? for help with psql commands
       \g or terminate with semicolon to execute query
       \q to quit

MyDB=>

이제 testuser로 데이터베이스에 로그인하였으며, 몇 가지 명령을 시작할 수 있습니다. PostgreSQL을 이용하는 느낌을 받으려면 다음 섹션에서 psql 클라이언트를 돌아다니는 기본 명령에 대하여 살펴보십시오.

3.2 기본 PostgreSQL 명령과 테이블 작성하기


MySQL을 사용해 본 적이 있으신 분들을 위하여 꼭 읽어야 할 것이 있습니다. 여기서 PostgreSQL이 명령을 수행하는 것과 관련하여 독특한 무언가를 알 수 있을 것입니다. 시작하려면 여기에서 논의하고자 하는 명령의 목록을 보십시오.

명령 사용법 동등한 MySQL 명령
\connect [DBNAME|- USER] 다른 데이터베이스에 연결한다 USE DATABASE
\q psql 클라이언트를 종료한다 quit
\i FILE FILE에서 명령을 수행한다 source FILE
\o FILE 질의문의 결과를 FILE로 보낸다 INTO OUTFILE, but outputs everything (not just SELECTS)
\d NAME (다른 아이템도 물론이며) 데이터베이스나 테이블을 묘사한다 DESC(RIBE)
\db PATTERN PATTERN에 맞는 쓸 수 있는 테이블의 목록을 나열한다 (패턴을 주지 않으면 모든 테이블을 나열) SHOW TABLES

\connect를 제외하고 모든 명령은 이 섹션의 뒤에서 보여줄 것입니다. 따라서 지금은 데이터베이스가 비어 있습니다. 그 말은 데이터를 삽입할 필요가 있다는 것입니다. 그러나 데이터를 삽입하는 첫 걸음은 테이블에 넣는 것입니다. 지금 현재로서는 테이블이 데이터베이스에 없으므로, 이것을 먼저 만들어야 합니다. CREATE TABLE 명령으로 이것을 할 수 있습니다. 항목의 테이블을 만들 것입니다. 상품 ID와 설명, 가격이 들어간 테이블을 만들 것입니다.

코드 목록 3.3: 상품 테이블 만들기
MyDB=> CREATE TABLE products (
MyDB(>   product_id SERIAL,
MyDB(>   description TEXT,
MyDB(>   price DECIMAL
MyDB(> );
NOTICE:  CREATE TABLE will create implicit sequence "products_product_id_seq"
for serial column "products.product_id"
CREATE TABLE

NOTICE는 무시하여도 되고 완전히 무해합니다. 함수의 마지막 줄인 CREATE TABLE을 보면 명령이 성공적으로 이루어졌다는 것을 알 수 있습니다. 그러나 계속해서 테이블이 정말 성공적으로 만들어졌는지 \d 명령을 통하여 알아봅시다.

코드 목록 3.4: 새로 작성한 테이블 살펴보기
MyDB=> \d products
                                 Table "public.products"
   Column    |  Type   |                            Modifiers
-------------+---------+------------------------------------------------------------------
 product_id  | integer | not null default nextval('public.products_product_id_seq'::text)
 description | text    |
 price       | numeric |

정말로 테이블이 만들어졌습니다. 이제 테이블이 만들어졌으니 데이터를 집어넣어야 합니다. 다음 섹션에서 데이터베이스에 데이터를 집어넣는 것을 살펴볼 것입니다.

3.3 데이터를 데이터베이스에 삽입하기


이 섹션은 새로 만들어진 테이블에 데이터를 집어넣는 두 가지 방법을 살펴볼 것입니다. 첫 번째로 가장 기본적인 명령인 INSERT를 알아봅시다.

코드 목록 3.5: INSERT 구문
INSERT INTO [tablename] (column1,column2,column3) VALUES(value1,value2,value3)

테이블 이름은 데이터를 집어넣을 테이블의 이름을 포함합니다. (column1,column2,column3)은 특정 컬럼에 값을 넣을 수 있게 해 줍니다. VALUES(value,value2,value3)은 값의 나열입니다. 이 값들은 컬럼과 같은 순서(column1이 value1을 갖고, column2가 value2를 갖고, column3이 value3를 갖는다)가 됩니다. 이들의 수는 서로 같아야 합니다. 계속해서 항목을 테이블에 넣어 봅시다.

중요: 데이터베이스에서 오랫동안 작업하면서 개인적으로 INSERT 명령문을 위와 같이 정확하게 할 것을 추천합니다. 개발자들은 INSERT INTO에서 컬럼 이름을 명시하지 않고 실수로 종종 사용합니다. 새 컬럼이 데이터베이스에 추가될 수도 있어서 이것은 비생산적입니다. 값과 컬럼의 수가 서로 같지 않아서 에러가 발생할 수 있습니다. 새로운 컬럼을 추가할 것을 300% 확신하지 않는다면 항상 컬럼을 명시해 주세요.

코드 목록 3.6: 테이블에 데이터를 삽입하기
MyDB=> INSERT INTO products (description,price) VALUES('A test product', 12.00);
INSERT 17273 1

마지막 줄은 약간 설명이 필요합니다. insert 명령의 반환값은 OID (객체 식별자)와 삽입된 줄의 수입니다. OID는 이 가이드의 범위를 조금 넘어선 것이고 PostgreSQL 매뉴얼에 좋은 정보가 있을 것입니다. 이제 20,000 상품을 가지고 있는 상황에서 이 insert 문은 조금 번거로울 수 있습니다. 그러나 모든 것을 잃는 것은 아닙니다. COPY 명령이 파일이나 stdin에서 테이블을 삽입할 수 있습니다. 이 예제에서는 csv(컴마로 구분된 값) 파일이 있다고 하고, 이것에 상품 id, 설명, 가격이 있다고 합시다. 파일은 다음과 같을 것입니다.

코드 목록 3.7: products.csv
2,meat,6.79
3,soup,0.69
4,soda,1.79

이제 COPY 명령으로 데이터를 집어넣어 봅시다.

중요: postgres 사용자만이 파일에서 데이터를 집어넣을 수 있기 때문에 COPY FROM STDIN 명령을 사용하였습니다. (명백한 보안상의 이유)

코드 목록 3.8: COPY를 사용하여 상품 테이블에 집어넣는 모습
MyDB=> COPY products FROM STDIN WITH DELIMITER AS ',';
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> 2,meat,6.79
>> 3,soup,0.69
>> 4,soda,1.79
>> \.

불행히도, 이 줄이 INSERT INTO 명령어와 같은 상태 정보를 보여주지는 않습니다. 데이터가 들어갔는지 어떻게 알 수 있을까요? 다음 섹션에서 데이터를 확인하기 위하여 실행하는 질의문을 살펴볼 것이빈다.

3.4 PostgreSQL 질의 사용하기


이번 섹션에서는 테이블 내에 있는 정보를 보는 SELECT문에 대하여 설펴 볼 것입니다. 기본적인 SELECT 형식은 다음과 같습니다.

코드 목록 3.9: SELECT 구문
SELECT (column1,column2|*) FROM (table) [WHERE (conditionals)]

컬럼을 선택하는 방법은 두 가지가 있습니다. 첫 번째 것은 *로 모든 컬럼을 선택하는 방법이고 두 번째는 보고자 하는 특정 컬럼의 목록을 명시하는 것입니다. 두 번째는 큰 목록을 보기보다는 특정 컬럼만 보려고 하는 경우에 꽤나 편리합니다. SELECT에 *로 모든 컬럼을 명시하는 것부터 시작해 봅시다.

코드 목록 3.10: 상품 테이블 보기
MyDB=> SELECT * FROM products;
 product_id |  description   | price
------------+----------------+-------
          1 | A test product | 12.00
          2 | meat           |  6.79
          3 | soup           |  0.69
          4 | soda           |  1.79
(4 rows)

여기서 나타난 대로, 모든 데이터가 정말로 테이블에 들어갔습니다. 이제 설명과 가격만 보고자 한다고 하고, 상품 id는 보고 싶지 않다고 합시다. 이제 컬럼을 명시한 SELECT 형태를 사용할 것입니다.

코드 목록 3.11: 상품 테이블에서 특정 컬럼을 보기
MyDB=> SELECT description,price FROM products;
  description   | price
----------------+-------
 A test product | 12.00
 meat           |  6.79
 soup           |  0.69
 soda           |  1.79
(4 rows)

이제 상품과 가격만 보이기 때문에 중요한 자료에 집중할 수 있게 되었습니다. 이제 $2.00이 넘는 항목만을 보고자 한다고 합시다. 여기 WHERE 절을 간편하게 쓸 수 있습니다.

코드 목록 3.12: 상품 테이블의 특정 행을 보기
MyDB=> SELECT description,price FROM products WHERE price > 2.00;
  description   | price
----------------+-------
 A test product | 12.00
 meat           |  6.79
(2 rows)

이제 $2.00이 넘는 상품이 화면에 나타나서 더욱 집중할 수 있게 되었습니다. 정보 질의의 이런 형태는 아주 강력하고 극도로 유용한 보고를 만들 수 있습니다.

3.5 맺음말


PostgreSQL의 가이드가 여기서 끝이 납니다. 저의 질문에 대답을 해 주시어 도와주신 젠투 PostgreSQL 유지를 맡고 있는 마사도모 나가노씨에게 크게 감사합니다. 이 가이드에 어떤 제안이라도 있으시면 chriswhite@gentoo.org 에 보내 주십시오. 더 확장적인 문서를 원하시면 PostgreSQL 웹사이트를 보십시오.


출처 : http://wiki.kldp.org/

Trackback 0 Comment 0
2009.06.04 15:23

패키지 관리 속도 향상법 (emerge sync)

Speeding up portage with cdb -- UPDATE

When it comes to speed the database backend of portage is rather slow because it's implemented as a raw abstraction in the filesystem. It is possible to replace this with a mysql backend which is not ideal, if you don't want to start a full-blown RDBMS. My solution is rather tiny, if you compare the code and the packages you need for that:

  1. You'll need the python interface python-cdb for DJB's cdb
    Code:
    emerge python-cdb

  2. Create /usr/lib/portage/pym/portage_db_cdb.py and put this in it:
    Code:
    # Copyright 2004, 2005 Tobias Bell <tobias.bell@web.de>
    #
    # This program is free software; you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation; either version 2 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    import portage_db_template
    import os
    import os.path
    import cPickle
    import cdb


    class _data(object):

        def __init__(self, path, category, uid, gid):
            self.path = path
            self.category = category
            self.uid = uid
            self.gid = gid
            self.addList = {}
            self.delList = []
            self.modified = False
            self.cdbName = os.path.normpath(os.path.join(
                self.path, self.category) + ".cdb")
            self.cdbObject = None

        def __del__(self):
            if self.modified:
                self.realSync()

            self.closeCDB()

        def realSync(self):
            if self.modified:
                self.modified = False
                newDB = cdb.cdbmake(self.cdbName, self.cdbName + ".tmp")
               
                for key, value in iter(self.cdbObject.each, None):
                    if key in self.delList:
                        if key in self.addList:
                            newDB.add(key, cPickle.dumps(self.addList[key], cPickle.HIGHEST_PROTOCOL))
                            del self.addList[key]
                    elif key in self.addList:                   
                        newDB.add(key, cPickle.dumps(self.addList[key], cPickle.HIGHEST_PROTOCOL))
                        del self.addList[key]
                    else:
                        newDB.add(key, value)
                   

                self.closeCDB()

                for key, value in self.addList.iteritems():
                    newDB.add(key, cPickle.dumps(value, cPickle.HIGHEST_PROTOCOL))
               
                newDB.finish()
                del newDB
               
                self.addList = {}
                self.delList = []

                self.openCDB()

        def openCDB(self):
            prevmask = os.umask(0)
           
            if not os.path.exists(self.path):
                os.makedirs(self.path, 02775)
                os.chown(self.path, self.uid, self.gid)
               
            if not os.path.isfile(self.cdbName):
                maker = cdb.cdbmake(self.cdbName, self.cdbName + ".tmp")
                maker.finish()
                del maker
                os.chown(self.cdbName, self.uid, self.gid)
                os.chmod(self.cdbName, 0664)

            os.umask(prevmask)
               
            self.cdbObject = cdb.init(self.cdbName)

        def closeCDB(self):
            if self.cdbObject:
                self.cdbObject = None


    class _dummyData:
        cdbName = ""

        def realSync():
            pass
        realSync = staticmethod(realSync)


    _cacheSize = 4
    _cache = [_dummyData()] * _cacheSize


    class database(portage_db_template.database):   

        def module_init(self):
            self.data = _data(self.path, self.category, self.uid, self.gid)

            for other in _cache:
                if other.cdbName == self.data.cdbName:
                    self.data = other
                    break
            else:
                self.data.openCDB()
                _cache.insert(0, self.data)           
                _cache.pop().realSync()
               
        def has_key(self, key):
            self.check_key(key)
            retVal = 0

            if self.data.cdbObject.get(key) is not None:
                retVal = 1

            if self.data.modified:
                if key in self.data.delList:
                    retVal = 0
                if key in self.data.addList:
                    retVal = 1
               
            return retVal

        def keys(self):
            myKeys = self.data.cdbObject.keys()

            if self.data.modified:
                for k in self.data.delList:
                    myKeys.remove(k)
                for k in self.data.addList.iterkeys():
                    if k not in myKeys:
                        myKeys.append(k)
                       
            return myKeys

        def get_values(self, key):
            values = None
           
            if self.has_key(key):
                if key in self.data.addList:
                    values = self.data.addList[key]
                else:
                    values = cPickle.loads(self.data.cdbObject.get(key))

            return values
       
        def set_values(self, key, val):
            self.check_key(key)
            self.data.modified = True
            self.data.addList[key] = val

        def del_key(self, key):
            retVal = 0
           
            if self.has_key(key):
                self.data.modified = True
                retVal = 1
                if key in self.data.addList:
                    del self.data.addList[key]
                else:
                    self.data.delList.append(key)

            return retVal
                       
        def sync(self):
            pass
       
        def close(self):
            pass


    if __name__ == "__main__":
        import portage
        uid = os.getuid()
        gid = os.getgid()
        portage_db_template.test_database(database,"/tmp", "sys-apps", portage.auxdbkeys, uid, gid)


  3. Create /etc/portage/modules and fill in
    Code:
    portdbapi.auxdbmodule = portage_db_cdb.database
    eclass_cache.dbmodule = portage_db_cdb.database


  4. Now you'll have to regenerate the portage cache with
    Code:
    emerge metadata

Now try some searches with emerge especially with --searchdesc :wink:
Code:
emerge --searchdesc python
should be much faster than before. You can compare the performance by switching back to the normal
db module. Just make a
Code:
mv /etc/portage/modules /etc/portage/__modules
I hope you enjoy your accelerated portage.



Default portage
Code:
cd /var/cache/edb/dep/usr
rm * -Rf
time emerge metadata
real    0m40.575s
user    0m26.260s
sys     0m9.592s

time emerge -S mozilla
real    1m46.003s
user    1m36.215s
sys     0m8.721s

time emerge -upDv world
real    0m14.678s
user    0m13.289s
sys     0m1.130s


python-cdb powered portage
Code:
cd /var/cache/edb/dep/usr
rm * -Rf
time emerge metadata
real    2m18.022s
user    0m26.538s
sys     0m31.505s

time emerge -S mozilla
real    1m39.624s
user    1m32.628s
sys     0m5.418s

time emerge -upDv world
real    0m13.856s
user    0m12.986s
sys     0m0.727s



## emerge 명령어 사용법 ##


emerge 옵션 테이블

Option1 Option2 기능
-s search 프로그램 찾기 및 각 프로그램에 대한 설명 참조 가능
-p pretend 프로그램 설치 이전, 설치를 가정하고 어떤 일이 벌어지는지 확인 가능
-v -- pretend 옵션과 더불어 쓰이며, 설정 혹은 비설정 use 옵션 확인 가능
unmerge 설치된 패키지 삭제 옵션,(>,<,=)기호 사용시 특정 버젼선택 삭제가능
help 자세한 설명 필요할때
rsync 포테이지 트리 업데이트 옵션
fetchonly 필요한 압축파일을 다운로드(컴파일안함)
emptytree 포테이지가 패키지및 의존성을 만족하는 패키지들이 모두 설치되지 않은것으로 인식
nodeps 의존성을 무시하고 패키지 설치(컴파일 실패 가능성..있음)
onlydeps 패키지의 의존성을 만족시키기 위한 것들만 설치(지정 패키지 설치안됨)
noreplace 이미 설치되어 있다면 패키지 설치를 생략
usepkg 컴파일이 아닌 이미 컴파일된 바이너리로 설치시도(PKGDIR 환경변수값 이용)
debug ebuild에 기초한 bash스크립트 문법적 에러를 추적할때 사용
autoclean emerge가 패키지의 빌드를 시작하기전에 임시 빌드 디렉토리 강제 청소
verbose emerge가 더 많은 정보를 표시
update 패키지 업데이트시 사용
prune 가장 마지막으로 설치된 버전을 제외하고 모든 패키지의 모든 버전들을 제거


사용법 emerging

사용법 1. emerge package_name
 # emerge mozilla
사용법 2. emerge dir/package_name rsync처럼 패키지명이 emerge의 특정 옵션으로 사용될 경우에 사용
# emerge net-misc/rsync
사용법 3. emerge emergefile 특정 버전을 설치할 때 사용
# emerge mozilla-1.3-r1.ebuild


portage tree 동기화

# emerge sync
or
# emerge rsync

/usr/portage의 개인 설정이 있다면 전부 삭제됨
sync와 rsync는 완전히 동일하게 작동합니다. /lefthander
메뉴얼에서는 rsync가 sync보다 서버의 부하를 덜 주어서 될수 있으면 rsync를 이용해 달라는 당부의 글이 있습니다.
아마도 sync는 모든 파일을 갱신하고 rsync는 없는 파일만 갱신하는것이 아닌가 싶습니다.

# emerge-webrsyncsync

보다 속도가 더 빠름. 스냅샷 압축파일을 받아와서 동기화


portage tree 갱신

# emerge -up system
# emerge -up world 
업데이트할 수 있는 system, world 패키지 확인

# emerge system
시스템 패키지 업데이트

# emerge world
world 패키지 업데이트

system과 world를 업데이트할 때 -u (--update) 옵션을 사용하면 의존성 있는 패키지도 함께 갱신한다.
이 의존성에 걸리는 패키지는 다운그레이드될 수 있다.


패키지 인스톨 전 확인

# emerge --pretend [package name]
or
# emerge -p pornview
# emerge -pv [package_name | ebuildfile]
설치할 패키지가 이미 설치되어 있는지, 의존관계 등의 정보를 확인


패키지 인스톨

#emerge [package name]


변경점 확인

#emerge --changelog [package name] or emerge -pl [package name]
이미 설치된 패키지와 portage상의 최신 패키지와의 차이 표시


패키지 갱신

#emerge [package name]



## 패키지 관리 명령어 비교 (yum / emerge / apt-get) ##


1. 패키지 목록 업데이트

====Fedora====
root@Fedora # yum check-update 
====Gentoo====
root@Gentoo # emerge --sync
====Debian====
root@Debian # apt-get update

2. 최신 패키지로 업데이트
====Fedora====
root@Fedora # yum update
====Gentoo====
root@Gentoo # emerge -DNu world
====Debian====
root@Debian # apt-get upgrade

3. 패키지 설치
====Fedora====
root@Fedora # yum install <packagename>
====Gentoo====
root@Gentoo # emerge <packagename>
====Debian====
root@Debian # apt-get install <packagename>

4. 패키지 재설치
====Fedora====
root@Fedora # yum update <packagename>
====Gentoo====
root@Gentoo # emerge --oneshot <packagename>
====Debian====
root@Debian # apt-get install --reinstall <packagename>

5. 패키지 검색
====Fedora====
root@Fedora # yum search <packagename>
====Gentoo====
root@Gentoo # emerge --searchdesc <packagename>
====Debian====
root@Debian # apt-cache search <packagename>

6. 패키지 삭제
====Fedora====
root@Fedora # yum remove <packagename>
====Gentoo====
root@Gentoo # emerge --unmerge <packagename>
====Debian====
root@Debian # apt-get remove <packagename>
 
참고 : http://wiki.kldp.org/wiki.php/PackageMgmt

Trackback 1 Comment 0