2006년 3월 31일 금요일

지렁이로 음식물 쓰레기를 처리하자

지렁이를 기른다고?


예. 우리나라엔 아직 지렁이로 음식쓰레기를 처리하는 가정이 그다지 많지 않지만, 미국이나 캐나다, 호주, 영국, 일본 등에서는 수백만 가정에서 지렁이를 기를 정도로 보편화되어 있습니다. 호주에서는 지렁이 상자가 신혼부부들이 가장 받고 싶어하는 선물중 하나라고 합니다.

우리도 한번 지렁이를 길러보는 건 어떨까요?


외국의 다양한 형태의 지렁이 상자들



지긋지긋한 음식쓰레기 지렁이로 처리합시다!


물기를 빼서 전용봉투에 버리는 번거로움, 봉투가 꽉 찰 때까지 걸리는 며칠 동안에도 음식쓰레기에서는 끝없이 수분이 빠져나옵니다. 채소나 과일 등 우리가 먹는 식재료의 성분에는 대부분 수분 함량이 가장 높기 때문입니다. 지저분한 전용봉투를 보관하고 관리하는 일은 또 얼마나 귀찮은 일인가요. 더운 여름날이나 따듯한 실내에 두는 음식쓰레기 봉투에서는 끔찍한 곰팡이가 번성하거나 날파리의 산실이 됩니다. 밀폐된 용기에서 나는 고약한 냄새는 요리를 맡는 주부의 말 못할 고민이요, 요리하기를 즐기는 독신자들이 치러야 하는 '응분의 대가'가 됩니다.


하루가 멀다고 날아오는 가공식품의 안전성, 식품 위생을 생각하면 내 손으로 내가 해 먹는 요리만큼 안전한 게 또 어디 있으랴만, 살림을 하는 사람들은 압니다. 음식쓰레기가 얼마나 골칫거리인지!


  지렁이가 음식쓰레기를 먹게 해 봅시다. 잘만 보관하고 기른다면 주방의 음식쓰레기로 인한 냄새, 파리, 지저분한 물기 등은 더 이상 문제가 되지 않습니다.

 내 집 음식쓰레기로 지렁이를 기르는 일은, 멀리 나가지 않고도 집안에서 자연을 접할 수 있는 기회입니다. 우리가 먹는 음식들이 분해되어 다시 흙으로 돌아가기까지를 보여주는 자연세계의 순환, 그 과정에 동참하는 작은 생명들의 존재들은 그저 미물로만 치부하던 인간의 통념과 어리석은 우월감마저 성찰하도록 이끌어 주지요.  


지렁이가 사는 집을 <지렁이 상자>라고 부르자구요. 상자를 관리하는 건 지렁이의 사는 자연의 삶의 방식을 그대로 배워 따라줘야겠죠. 거기에 우리들의 의문을 추가합시다.

상자 안에서는 무슨 일이 일어날까? 정말로 지렁이가 음식쓰레기를 먹을까? 지렁이 말고도 세균과 원생동물, 곰팡이, 균류들이 하는 일은?  너무 산성화된 환경은 아닐까? 어떤 음식물이 산성화를 초래할까? 시간과 노력을 적게 들이고 많은 지렁이를 수확할 수 있을까? 분변토는 언제쯤 수확할 때 가장 품질이 좋을까? 우리 집 음식쓰레기를 처리할 수 있는 지렁이 상자의 크기는? ...등등

<지렁이를 기른다고?>의 저자인 메리 아펠호프는 생물학자이며 30년이 넘게 집에서 직접 지렁이를 기른 할머니입니다. 그녀는 지렁이 상자에 대한 꼬리를 무는 의문은 직접 지렁이를 길러 보면 금방 알 수 있는 일이라고 말합니다. 그저 그녀의 지렁이 상자를 한번 같이 들여다 보자는 것입니다.




첫번 째 도전>> 지렁이 상자 만들기

지렁이 상자는 못쓰는 나무박스 등을 활용할수도 있고 손재주가 있는 사람이라면 책속의 메뉴얼을 참고해 직접 디자인해 만들수도 있습니다.

      

      본문 중 지렁이 상자 도면의 예


<에코붓다> 등에서는 화분을 활용해 지렁이를 기르는데 그 방법도 좋습니다. YWCA, YMCA, 제천 지렁이가족모임 등 환경단체와 소비자단체, 생활협동조합들도 지렁이를 이용한 음식쓰레기 퇴비화 실천을 시작하고 있으니 연락해 얻을 수도 있습니다. 또 올 봄부터는 <아름다운 가게>에서도 재활용 플라스틱 지렁이 상자와 나무 지렁이 상자를 개발해서 판매할 계획이라고 합니다.(지렁이는 근처의 낚시가게에서 손쉽게 구할 수 있습니다. 땅지렁이 말고 퇴비지렁이인 줄지렁이로 구입해야 합니다)


그렇다면 이제 지렁이 상자를 만드는데 있어 필수적으로 생각해야 할 것을 알아봅시다.

1) 배출되는 음식쓰레기 양과 지렁이의 양을 가늠해 봅시다.


지렁이 상자를 만들기 위해서는 우선 음식쓰레기의 양에 맞춰 크기와 지렁이 수를 결정해야 합니다. 저자는 4인 가족의 경우, 평균 하루 500그램의 음식쓰레기가 나온다고 할 때, 필요한 지렁이 수는 1킬로그램 정도라고 말합니다. 즉 하루 발생 음식쓰레기 양의 2배가 적당한 지렁이 수라는 것이지요.

음식쓰레기를 먹기 시작한 지 4주가 지난 뒤부터는 지렁이들이 새끼를 낳게 되므로, 처음 지렁이 수를 약간 적게 시작해도 좋습니다.



2) 지렁이가 사는 상자의 크기와 모양을 정합시다.

하루 500그램, 일주일에 3~3.5킬로그램의 음식쓰레기가 발생할 경우 지렁이 1킬로그램을 기를 수 있는 상자의 크기는 깊이 30cm 정도의 가로 60cm 세로 90cm가 적당합니다. 상자의 크기를 미리 알고 결정해야 하는 이유는, 처리할 용량도 문제이지만, 부피와 무게로 인해 운반과 미관 상의 문제가 생길 수 있기 때문입니다. (저자는 1972년부터 미국에서 이미 폐플라스틱으로 제조한 지렁이 상자를 판매했는데, 수십년간 수만 명의 지렁이를 기르는 이들의 자료를 참고한 결과, 하루 100그램 이내(1주일에 500그램)의 음식쓰레기를 처리하는 지렁이 상자는 평균 0.1평방미터라는 사실을 알아냈다고 합니다)


  용기의 깊이는 공기순환의 문제를 고려해서 너무 깊지 않은 것이 좋습니다. 또 상자는 쓰지 않는 플라스틱 통이나 나무 재질의 폐품 등등 어떠한 재질로도 만들 수 있는데 중요한 것은 유독물질이 없는 재질이어야 하며 환기 구멍을 내주어 습기를 조절하는 것이 핵심!



3) 상자에 들어갈 지렁이 침대인 깔개를 넣어주어야 합니다.

지렁이들이 깔고 살며 음식물을 묻어주는 깔개(bedding)도 상자 안에 넣어주는 주요한 요소입니이다. 그런데 흙은 줄지렁이를 이용하는 음식쓰레기 처리에 꼭 필요하지 않습니다. 줄지렁이들은 자연 서식지에서 낙엽 더미나 동물성 퇴비 더미 등에서 살아 가므로 잘게 썬 신문지 주로 넣고 톱밥, 코코넛 섬유질, 퇴비, 초탄 등을 사용해도 잘 살아갑니다. 흙보다는 오히려 편안해 합니다. 깔개는 75퍼센트 정도의 수분을 함유해야 하며 이는 깔개 : 물의 비율이 곧 1:3이라는 얘기입니다.



그림과 같이 신문지를 잘 찢어서 넣어주세요


4) 지렁이 상자의 완성

  지렁이와 음식쓰레기, 수분을 함유한 깔개와 이들을 넣을 지렁이 상자가 마련됐다면 이제 흙 한 줌과 함께 내용물들을 넣어서 집안에 둘 위치로 상자를 두면 됩니다.





지렁이 기르기 체*크*리*스*트

1.   먼저, 지렁이와 지렁이 퇴비화에 대한 정보를 충분히 접하자. 특히 지렁이에 대한 올바

     르지 않은 선입관이 있는 이들이라면 더욱 더 알아야 한다. 알면 사랑하게 된다.

2.   2,3주 간 배출되는 음식쓰레기의 양을 가늠한다. 되도록 정확한 무게를 알면 좋다.

3.   음식쓰레기의 양에 맞춰 집에서 기를 지렁이의 양을 결정하자.

4.   지렁이가 살 집 <지렁이 상자>를 준비한다. 사거나 직접 만들 수도 있다.

5.   지렁이가 먹이를 먹으며 살아갈 푹신한 베딩 <깔개>를 준다. 신문지, 낙엽, 톱밥 등등

     이용할 수 있는 재료는 주변에서 쉽게 구할 수 있다.

6.   지렁이 상자에 깔개를 넣어서 해가 들지 않는 곳으로 상자를 둘 곳을 정한다.

7.   지렁이 침대 <깔개>는 적당히 수분이 있는 상태로 상자에 넣는다.

8.   지렁이를 상자에 넣는다.

9.   음식쓰레기를 깔개 속에 묻어준다. 지렁이는 빛을 싫어하므로 표면에 던져 줄 때는

     빛을 차단하는 덮개가 있어야 한다.

10.  주기적인 습도 체크가 필요하다. 지렁이는 과도한 수분이나 지나치게 건조한 환경,

     산소가 없는 혐기성 환경에서는 탈출하거나 죽어버린다. 기르기 시작한 지 4주

     후부터는 지렁이가 새끼를 낳으므로 알주머니나 새끼들을 찾아볼 수 있다.

11.  늘어난 지렁이를 수확해서 이웃에게 분양시키거나 새로운 지렁이 상자를 더 만들어

     본다. 지렁이 수확 후에는 새로운 깔개를 넣어준다.

12.  지렁이 퇴비와 분변토를 수확하여 화분과 텃밭 식물을 가꿔 보자. 풍요로운 정원의

     모습을 볼 수 있을 것이다.


두번 째 도전>> 지렁이 퇴비 수확하기




상자 세팅이 끝났다면, 이제 본격적으로 지렁이 상자를 운영해 봅시다.



1) 음식쓰레기로 먹이주기

  지렁이가 좋아하는 것들은 수분이 풍부한 수박껍질이나 멜론, 국수, 원두커피 찌꺼기 등입니다. 물론 채소류나 과일 껍질, 밥과 면류도 아주 잘 먹습니다. 문제는 육류인데 처음 시작하는 이들은 어느 정도 경험을 쌓은 후부터 지렁이에게 주라고 저자는 말합니다. 저자의 경우는 달걀 껍질이나 닭뼈 등을 일정하게 말려 주면 퇴비의 성분은 더욱 좋아진다고 합니다.  음식물은 보통 일주일에 2번 정도로 나누어서 주되 매일 주거나 일주일에 한번만 주든 그것은 사육자의 사정에 따라 자유롭게 하길 권합니다.



2) 지렁이퇴비 수확하기

  분변토는 지렁이의 소화기관을 통과해 배설된 물질을 말하며 지렁이퇴비는 이 분변토와 분해중인 음식물, 깔개들이 섞여 있는 것. 분변토만 얻는 것은 지렁이 상자를 6개월간 그대로 두면 간단히 얻을 수 있습니다. 지렁이들은 먹이나 깔개가 없이 자신의 배설물만 남게 될 경우 일부 개체만 살아남고 대부분 죽어서 분해됩니다. 이럴 경우엔 최소 2개 이상의 지렁이 상자를 운영합시다. 분변토와 새끼 지렁이, 갖가지 분해 중이거나 퇴비화된 물질들이 섞여 있는 지렁이 퇴비는 2-3달에 한번, 혹은 네달 한번씩 퇴비와 지렁이들을 수확하게 됩니다. 수확한 지렁이와 퇴비는 이웃에게 분양할 해 주어도 되고 퇴비와 같이 넣어 땅에 같이 주어도 됩니다.




                                            본문 중 지렁이 퇴비 분리하는 방법 중 한 예  

3) 분변토와 퇴비 이용하기

  지렁이의 배설물(분변토)이 뒤섞인 퇴비는 화분 식물 재배와 텃밭에서 채소를 가꾸고 나무를 키우는 데에 매우 유용한 거름이 됩니다. 지렁이가 만들어낸 퇴비들을 씨앗을 심을 때나, 화분을 갈아 줄 때, 텃밭에서 키우는 작물들에게 추가 거름을 줘야 할 때 사용해 봅시다. 놀라울 만큼의 효과를 기대해도 좋을 것입니다. 상추, 토마토, 고추 등의 채소는 물론 바이올렛, 데이지 등의 예쁜 화단 식물들, 심지어 싹틔우기가 아주 어려운 아보카도 나무의 씨앗도 잘 발아했다고 합니다.

책에는 아보카도 씨앗 싹틔우기에 대해서도 설명하고 있습니다.



  콘크리트로 덮혀버린 지렁이들의 세상이 지렁이 상자를 통해서라도 다시금 활짝 열릴 날이 올 것인가?  수많은 지렁이 일꾼들이 기다려지는 봄입니다.


- 책, <지렁이를 기른다고?> 중에서

2006년 3월 25일 토요일

플래시무비위에 레이어 올리기

플래시가 삽입된 html소스 <object></object>안에 <param name="wmode"
value="transparent">를 추가 하면 됩니다.

만약 드림위버 사용자라면 플래시를 html에
삽입한 뒤 삽입된 플래시를 선택합니다.

플래시가 선택되면 아래 속성창은 플래시의 옵션들을 변경할수 있는 작업모드로 전환됩니다.

이때 parameters라는 버튼을 선택하여 parameter에다가 wmode를

value에는 transparent라고 쓰면 됩니다.

2006년 3월 8일 수요일

블로그와 웹메일의 연계 방안

네이버 웹 메일이 개편된 후 메일을 보낼 때면 메일 하단의 signature에 자동으로 자신의 블로그 주소가 붙게 된다. 서로 트래픽을 주고 받으려는 의도는 이해하지만 네이버 메일로 보내는 모든 사람에게 그냥 '네이버 블로그'도 아니고 '자신의 블로그'를 광고하고 싶은 사람이 몇이나 될까? 의도는 이해가 되지만 역시나 생각이 조금 모자랐던 것 같다.

네이버 블로그가 네이버 웹메일에 기여하는 몇 가지 방법이 있는데 그 중의 하나는 오래 전에 이야기한 웹메일을 이용한 포스팅에서 힌트를 얻을 수 있다. 18개월 전쯤에 이야기했던 방식은 '메일로 쓴 내용을 포스팅한다'였다. 그러나 웹메일의 활용도가 낮은 상황이므로 역발상을 해 보는 것이 좋겠다. 즉, 블로그의 포스트를 웹메일로 특정한 사람들에게 보내는 것이다. 이미 네이버 블로그는 '이웃 공개'로 자신의 블로그를 방문하는 사람들을 임의로 구분할 수 있으므로 금새 구현할 수 있는 기능이다. 기능의 구현은 포스트 작성창에 '이웃에게 메일 보내기' 기능을 추가하면 된다. 기능은 다음과 같다.

1. '서로 이웃' 혹은 '이웃'으로 등록한 사람에게 작성한 내용을 메일로 보낸다.

2. 메일을 받은 사람은 메일 박스 안에 즉시 코멘트를 달 수 있다.

3. 메일을 받은 사람은 메일 박스 안에 즉시 답신을 할 수 있다.

4. '코멘트'는 작성한 포스트에 코멘트로 생성된다.

5. '답신'은 자신의 블로그에 이웃 공개 포스트로 작성되어 트랙백(엮인글)된다.

이 기능을 잘 이용한다면 블로그의 공개성으로 인해 말할 수 없는 내용을 이메일이라는 개인적인 커뮤니케이션 수단으로 보충할 수 있다. 이 기능은 모더레이터(관리자)가 있는 그룹 메일의 속성을 모방할 수도 있다. 기능적으로 복잡할 것은 전혀 없지만 잘못 구현하면 쓸데없는 기능이 될 수 있음에 유의해야 한다. 기능상 구현의 어려움보다는 이렇게 구현된 기능이 블로그 사용자들에게 "이웃들과 나누고 싶은 반(半)공개적인 이야기의 채널"을 제공한다는 의미가 크다. 감성을 자극하는 프로모토가 중요하게 작용할 것이다.

** 메일 박스에서 열리는 메시지와 블로그에서 (이웃공개)로 열리는 메시지의 차이점을 이해 못한다면 이 기능의 의미를 전혀 납득하지 못할 것이다.

이 기능은 "공개성의 다층화 욕구"에 대한 분석에 근거한 것이다. 블로그를 쓰는 모든 사람이 모든 포스트를 공개하고 싶어하지 않는다. 그러나 기본적으로 공개와 그것을 통한 소통(커뮤니케이션)의 욕구가 있으므로 포스트를 작성한다. 포스트에서 '공개설정' 옵션이 존재하는 것은 이러한 다층화된 공개의 욕구를 시스템으로 구현한 것이다. 웹메일로 포스트의 내용을 보내는 것은 '서로 이웃 공개'와 가장 유사한 특성을 갖는다.

이러한 내용은 네이버 뿐만 아니라 엠파스, 다음, 야후!코리아 등에도 공통적으로 적용될 수 있다. 일견 예측하건데 웹메일이 가장 강력한 다음이 이런 기능을 구현하면 최고의 효과를 거둘 것 같지만 꼭 그렇게 볼 수는 없다. 다음 웹메일은 자신에 대한 메일을 찾기 힘들 정도로 엄청난 스팸메일이 쏟아져 들어오기 때문에 오히려 오픈율이 떨어진다. 네이버의 경우엔 오히려 이런 면에서 다음보다 유리할 수 있다. 반면 네띠앙이나 드림위즈같은 중간급 포탈 사이트에게는 꽤 유용한 방법이 될 수 있다. 자사 내부의 트래픽을 몇 바퀴 돌릴 수 있는 계기가 될 것이며, 커뮤니티로 웹메일 사용자를 유도할 수 있는 방안이 될 수도 있다.

출처 : http://blog.naver.com/kickthebaby/20011186174

2006년 3월 7일 화요일

Error: cannot restore segment prot after reloc: Permission denied

Article Title:Error: cannot restore segment prot after reloc: Permission denied
Article ID:3092
Article Name:INSTALL88
Last Updated:8/5/2005 4:55:50 PM
Products:IDL; ENVI
OS Platforms:Linux-Intel

Topic:

Some Linux distributions with SELinux enabled may prevent IDL from running under the default security context. This TechTip is a workaround for CR#41937

Discussion:

Newer Linux distributions have enabled new kernel security extensions from the SELinux project at the NSA. These extensions allow finer-grained control over system security. However, SELinux also changes some default system behaviors, such as shared library loading, that can be problematic to third party programs.

If you receive the error message "cannot restore segment prot after reloc: Permission denied" when launching IDL, then your SELinux configuration is preventing IDL from launching.

To rectify this issue, you can either:

  • Change the default security context for IDL by issuing the command:

    chcon -t texrel_shlib_t /usr/local/rsi/idl_6.1/bin/bin.linux.x86/*.so

  • Disabling SELinux altogether by setting the line

    SELINUX=disabled

    in your /etc/sysconfig/selinux file.

For more information about SELinux, please consult your Linux distribution vendor.

FC4 를 깔고 호스팅 서버처럼 꾸미기

나를 엄청 고생한게 만든 FC4

원인은... 바로.. SElinux 이놈 때문에... 보안이 좋긴 좋지만... 어디 확실하게 설정하는곳도

없고... 아 열받는다.

========================================================================

계정별로 트래픽을 제어하는 부분과 하드 할당량을 설정할 수 있습니다.
단, 중간에 오류가 발생하는 부분이 생길 수도 있습니다.



# 페도라 코어 4 최소 설치 후 (이 부분은 따로 설명하지 않습니다.)



# yum 설치를 위해 GPG-KEY 포함
rpm --import /usr/share/rhn/RPM-GPG-KEY-fedora



# yum 업데이트
yum -y update



# 한글 설정
/etc/sysconfig/i18n

LANG="ko_KR.eucKR"
SUPPORTED="en_US.iso885915:en_US:en:ko_KR.eucKR:ko_KR:ko"
SYSFONT="lat0-sun16"
SYSFONTACM="iso15"



# 매뉴얼 설정 수정
vi /etc/man.config

수정
PAGER          /usr/bin/less -isr




# 디렉토리 색상 수정
vi /etc/DIR_COLORS.xterm

수정
DIR 00;33



# 소스 컴파일을 위한 컴파일러 및 각종 모듈 yum 설치
yum -y install gcc cpp gcc-c++ compat-gcc-32-g77 flex libjpeg-devel libpng-devel libtiff-devel freetype-devel openldap-devel pam-devel sendmail-cf vsftpd telnet-server




# zlib 소스 설치
cd /usr/local/src
wget
http://www.zlib.net/zlib-1.2.3.tar.bz2
tar xfj zlib-1.2.3.tar.bz2
cd zlib-1.2.3
make
make install




# freetype 2 설치
글짜를 그릴 때 쓰는 라이브러리 입니다.
wget
http://ftp.superuser.co.kr/pub/etc/freetype-2.1.5.tar.gz
tar xvfz freetype-2.1.5.tar.gz
cd freetype-2.1.5
./configure
make
make install




# openssl 소스 설치
cd /usr/local/src
wget
http://www.openssl.org/source/openssl-0.9.8a.tar.gz
tar xfz openssl-0.9.8a.tar.gz
cd openssl-0.9.8a
./config
make
make install




# curl 소스 설치
cd /usr/local/src
wget
http://curl.haxx.se/download/curl-7.15.1.tar.bz2
tar xfj curl-7.15.1.tar.bz2
cd curl-7.15.1
. /configure --with-ssl
make
make install




# gd lib 설치
cd /usr/local/src
wget
http://www.boutell.com/gd/http/gd-2.0.33.tar.gz
tar xfz gd-2.0.33.tar.gz
cd gd-2.0.33
./configure
make
make install




# webalizer 소스 설치
cd /usr/local/src
wget
ftp://ftp.mrunix.net/pub/webalizer/webalizer-2.01-10-src.tgz
tar xfz webalizer-2.01-10-src.tgz
cd webalizer-2.01-10
./configure --with-language=korean
make
make install



# mysql 4.1.x 설치
cd /usr/local/src
wget
http://mysql.byungsoo.net/Downloads/MySQL-4.1/mysql-4.1.16.tar.gz
tar xfz mysql-4.1.16.tar.gz
cd mysql-4.1.16
./configure --prefix=/usr/local/mysql --localstatedir=/usr/local/mysql/data --with-charset=euckr
make
make install

/usr/local/mysql/bin/mysql_install_db
groupadd mysql
useradd -M -c MySQL_Server -d /usr/local/mysql -g mysql -s /bin/nologin mysql
chown root.mysql -R /usr/local/mysql
chown mysql.mysql -R /usr/local/mysql/data
cp /usr/local/mysql/share/mysql/my-huge.cnf /etc/my.cnf
echo "/usr/local/mysql/bin/mysqld_safe &" >> /etc/rc.local



# apache 1.3.x 설치
cd /usr/local/src
wget
http://ftp.apache-kr.org/httpd/apache_1.3.34.tar.gz
tar xfz apache_1.3.34.tar.gz
cd apache_1.3.34
./configure --prefix=/usr/local/apache --enable-module=so
make
make install
echo "/usr/local/apache/bin/apachectl start" >> /etc/rc.local


#freetype 소스설치후 적용하기위세 freetype 옵션추가
# php 소스 설치
cd /usr/local/src
wget
http://kr.php.net/get/php-4.4.2.tar.bz2/from/this/mirror
tar xfj php-4.4.2.tar.bz2
cd php-4.4.2
./configure --with-apxs=/usr/local/apache/bin/apxs --with-mysql=/usr/local/mysql --with-config-file-path=/usr/local/apache/conf --with-zlib-dir=/usr/local --with-jpeg-dir=/usr/local --with-png-dir=/usr/local --with-tiff-dir=/usr/local --with-freetype-dir=/usr/local --with-ttf --with-gd --with-openssl --with-gettext --with-kerberos --with-swf-dir=/usr/local --with-mod_charset --with-regex=php --with-curl --with-ldap --with-iconv --enable-gd-native-ttf --enable-ftp --enable-sockets --disable-debug  --enable-calendar --enable-sigchild --enable-magic-quotes --enable-bcmath --enable-exif --enable-mbstring --enable-dbase --enable-sysvmsg --enable-sysvsem --enable-sysvshm --enable-yp --with-jpeg-dir --with-freetype-dir
make
make install
cp php.ini-dist /usr/local/apache/conf/php.ini


vi /usr/local/apache/conf/httpd.conf

수정
DirectoryIndex index.html index.htm index.php

수정 (public_html -> www)
UserDir www
#<Directory /home/*/www>



# vi /usr/local/apache/conf/mime.types
두줄 추가 (확장자는 탭키로 띄운다)
application/x-httpd-php        php ph inc
application/x-httpd-php-source  phps



# php 파일 이외에 다른파일명으로 php해석할수있게 설정 ex) htm html
# vi /usr/local/apache/conf/httpd.conf
-  .php 파일 및 html 파일에서 php 코드 실행되게 설정하려면
AddType application/x-httpd-php .php .phtml .php3 .html .htm
AddType application/x-httpd-php-source .phps



# vi /usr/local/apache/conf/php.ini
- 그림 파일 및 프래쉬 파일 로그 남기지 않게 설정
방문자 수가 많아지면 웹로그가 엄청 쌓이게 되고, 그 로그는 크기가  2G를 넘게 되면 웹페이지에 이상현상이 생깁니다. 그렇다고 로그를 안 남길 수는 없는 것이고, 이미지 파일들은 로그남기는 것에서 제외합니다.
CustomLog logs/access_log common 이렇게 되어 있는 것을 ..
SetEnvIfNoCase Request_URI (gif|png|jpg|css|js|bmp|jpeg|swf)$ IMAGE=1
CustomLog /usr/local/apache/logs/access_log common env=!IMAGE
이렇게 바꾸면^^; 쉽게 가능합니다.
- 업로드 용량 제한 풀기
기본적으로 업로드는 2M로 제한되어 있습니다. 만약 2M 이상으로 하면 여러 가지 설정들을 바꾸어 줘야 합니다. 업로드 되는 시간을 길 게 해 주어야 하고, 한번에 잡아먹을 메모리를 크게 해 주어야 합니다.
default_socket_timeout = 600
post_max_size = 20M
memory_limit = 20M
upload_max_filesize = 20M



- 업로드 용량 제한 풀기
# vi /usr/local/apache/conf/php.ini
기본적으로 업로드는 2M로 제한되어 있습니다. 만약 2M 이상으로 하면 여러 가지 설정들을 바꾸어 줘야 합니다. 업로드 되는 시간을 길 게 해 주어야 하고, 한번에 잡아먹을 메모리를 크게 해 주어야 합니다.
default_socket_timeout = 600
post_max_size = 20M
memory_limit = 20M
upload_max_filesize = 20M



- post, get , 쿠키 , 세션등의 변수를 일반변수로 (개인 서버용일경우 보안상 OFF 권장)
예전에 php는 기본적으로 위 변수를 일반변수로 사용할 수 있었습니다. 하지만 보안에 취약 하기 때문에 php 설치시 기본적으로 일반변수로 사용못하게 설정합니다. 이렇게 되면 문제가 예전에 사용하던 짜여졌던 프로그램은 정상적으로 실행되지 않습니다. 보안보다는 호환성이 더 중요하죠^^;
register_globals=On  이렇게 설정합니다.




# ZendOptimizer 설치
cd /usr/local/src
wget
ftp://ftp.sir.co.kr/zendoptimizer/ZendOptimizer-2.5.10a-linux-glibc21-i386.tar.gz
tar xfz ZendOptimizer-2.5.10a-linux-glibc21-i386.tar.gz
cd ZendOptimizer-2.5.10a-linux-glibc21-i386
./install.sh

php.ini 경로
/usr/local/apache/conf



# mod_throttle 소스 설치
cd /usr/local/src
wget
ftp://ftp.sir.co.kr/etc/mod_throttle-3.1.2.tgz
tar xfz mod_throttle-3.1.2.tgz
cd mod_throttle-3.1.2/
make install

#####################################################
##### 인스톨시 다음과 같은 에러시 다음과 같이 하세요.            ############
##### make: *** [install] Error 127make: *** [install] Error 127 ############
####################################################
---> 해당 디렉토리에 Makefile 에 APXS 경로를 지정해준다.


(참고 인스톨시 에러가 발생한다. 그리고 APM세팅 방식을 DSO방식으로 설치한다.
STATIC방식으로 설치해도 되지만, 그 부분은 다시 설정해야한다.)

* static방식으로 설치 했을 경우 ...
configure 시--add-module=$mod_throttle_source_PATH/mod_throttle.c 추가.

* 그럼 DSO방식으로 설치 했을 경우...
* 모듈을 만들어준다.
[
root@abcd mod_throttle-3.1.2]# /usr/local/apache/bin/apxs -c mod_throttle.c(모듈을 만들어준다)
gcc -DLINUX=22 -DUSE_HSREGEX -fpic -DSHARED_CORE -DSHARED_MODULE
-I/usr/local/apache/include -c mod_throttle.c
gcc -shared -o mod_throttle.so mod_throttle.o

* 에러부분에 추가 해주면 된다.

[
root@abcd mod_throttle-3.1.2]# /usr/local/apache/bin/apxs -i -a -n 'throttle' mod_throttle.so
[activating module `throttle' in /usr/local/apache/conf/httpd.conf]
cp mod_throttle.so /usr/local/apache/libexec/mod_throttle.so
chmod 755 /usr/local/apache/libexec/mod_throttle.so
cp /usr/local/apache/conf/httpd.conf /usr/local/apache/conf/httpd.conf.bak
cp /usr/local/apache/conf/httpd.conf.new /usr/local/apache/conf/httpd.conf
rm /usr/local/apache/conf/httpd.conf.new

 
##############################################



vi /usr/local/apache/conf/httpd.conf

<IfModule mod_throttle.c>
    ThrottlePolicy Volume 500M 1d

    <Location /throttle-status>
        SetHandler throttle-status
    </Location>

    <Location /throttle-me>
        SetHandler throttle-me
    </Location>

    <Location /~*/throttle-me>
        SetHandler throttle-me
    </Location>
</IfModule>

<VirtualHost 211.xx.xxx.xxx>
    ServerAdmin
root@xxx.com
    ServerName xxx.com
    DocumentRoot /home/xxx
    # 하루 500M
    ThrottlePolicy Volume 500M 1d
    # 하루 천번
    ThrottlePolicy Request 1000 1d
</VirtualHost>





# quota 설정

1. fstab 옵션추가 (usrquota,grpquota) :
vi /etc/fstab
/home 에 usrquota 추가
default,usrquota


2. remount (umount , mount) :
mount -o remount /home


3. 데이터베이스 파일생성(quota.user , quota.group) :
touch /home/quota.user
chmod 600 /home/quota.user
quotacheck -av
convertquota -u /home

4. 사용자마다 적용수치 기록 :
edquota 계정
repquota -a


5. 활성화 :
quotaon /home





# qpopper 4.0.8 소스 설치
cd /usr/local/src
wget
ftp://ftp.qualcomm.com/eudora/servers/unix/popper/qpopper4.0.8.tar.gz

tar xvfz qpopper4.0.8.tar.gz
cd qpopper4.0.8
./configure --enable-specialauth --enable-servermode --enable-shy
make
cp popper/popper /usr/sbin/popper

vi /etc/xinetd.d/pop3

service pop3
{
    disable        = no
    socket_type    = stream
    wait            = no
    user            = root
    server          = /usr/sbin/popper
    log_on_success  += HOST DURATION
    log_on_failure  += HOST
}

# /etc/rc.d/init.d/xinetd restart




# sendmail 수정 및 실행
vi /etc/mail/sendmail.mc

TRUST_AUTH_MECH(`EXTERNAL DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
define(`confAUTH_MECHANISMS', `EXTERNAL GSSAPI DIGEST-MD5 CRAM-MD5 LOGIN PLAIN')dnl
DAEMON_OPTIONS(`Port=smtp,Addr=0.0.0.0, Name=MTA')dnl





# 계정당 용량 설정
vi  /etc/sendmail.cf
Mlocal,        P=/usr/bin/procmail, F=lsDFMAw5:/|@qSPfhn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL,
                M=20495360, <-- 이 부분만 추가 :  byte 단위 (예:20메가)
                T=DNS/RFC822/X-Unix,
                A=procmail -t -Y -a $h -d $u


m4 /etc/mail/sendmail.mc > /etc/mail/sendmail.cf
#/etc/rc.d/init.d/sendmail restart
#/etc/rc.d/init.d/saslauthd restart





# 기본 서비스

ntsysv 실행

auditd
crond
iptables
kudzu
named
network
pop3
saslauthd (보내는 메일서버 패스워드 인증?)
sendmail
sshd
syslog
telnet
vsftpd
xinetd



# 그룹사용자 추가
groupadd webhost





# path 추가

vi /etc/profile

pathmunge /usr/X11R6/bin after
pathmunge /usr/local/mysql/bin after
pathmunge /usr/local/apache/bin after





# vsftpd 설정 변경

vi /etc/vsftpd/vsftpd.conf

주석제거
xferlog_file=/var/log/vsftpd.log





# 재시작

2006년 3월 4일 토요일

척노리스에 대한 추가된 사실

Superman owns a pair of Chuck Norris pajamas.

사실: 수퍼맨은 밤에 척 노리스 잠옷을 입고 잔다.


Chuck Norris can speak braille.

사실: 척 노리스는 점자로 말할 수 있다.


Contrary to popular belief, George Bush is a great speaker and rarely mispronounces words. He appears incompetent because he knows Chuck Norris is watching.

사실: 세간에 알려진 바와는 달리 조지 부시 대통령은 사실 매우 능숙한 달변가이며 좀처럼 발음을 틀리는 법이 없다. 그가 어리숙해 보이는 것은 척 노리스가 지켜 보고 있다는 사실을 잘 알기 때문이다.


There are currently 5 viruses in population that could eradicate the worlds' population in less than a week. They are lying low because Chuck Norris does not like competition.

사실: 이 세상에는 1 주일 안에 전 인류를 말살시킬 수 있는 힘을 가진 바이러스가 5종 존재하지만 이 바이러스들은 지금 잠복기에 있다. 척 노리스는 경쟁자를 싫어한다는 사실을 잘 알기 때문이다.

If you see Chuck Norris crying he will grant you a wish, if your wish is dying.

사실: 당신이 만약 척 노리스가 눈물을 흘리는 모습을 목격할 수만 있다면 척 노리스가 당신의 소원을 하나 들어 줄 것이다. 당신의 소원이 죽음인 경우에 한하여.


Chuck Norris does not leave messages. Chuck Norris leaves warnings.

사실: 척 노리스는 메시지를 남기지 않는다. 척 노리스는 경고를 남긴다.


Chuck Norris once had a near death experience. Needless to say, Death now refuses to come near him.

사실: 척 노리스는 딱 한 번 죽음에 직면한 적이 있었다. 그 사건 이후로 죽음이 척 노리스를 슬슬 피해 다닌 것은 말할 것도 없다.


Chuck Norris gave cats nine lives so he could kill them more.

사실: 고양이에게 9개의 목숨을 준 것은 척 노리스였다. 더 많은 살상을 즐기기 위하여.


The most effective form of suicide known to man is to type "Chuck Norris" into Google and hit "I'm Feeling Lucky!".

사실: 인간에게 알려진 가장 효과적인 자살 방법은 구글 검색창에 "척 노리스"를 쳐 넣은 후 "운 좋은 예감(I'm Feeling Lucky!)" 버튼을 누르는 것이다.

Chuck Norris clogs the toilet even when he pisses.

사실: 척 노리스는 오줌을 눌 때도 변기가 막힌다.


When Chuck Norris was in middle school, his English teacher assigned an essay: "What is Courage?" Chuck Norris received an "A+" for writing only the words "Chuck Norris" and promptly turning in the paper.

사실: 중학교 시절 척 노리스는 영어 선생님으로부터 "용기란 무엇인가?"라는 주제로 작문 숙제를 받은 적이 있었다. 척 노리스는 그 즉시 종이쪼가리에 "척 노리스"라고 휘갈겨 적은 후 제출하여 A+를 받았다.


Chuck Norris owns the greatest Poker Face of all-time. It helped him win the 1983 World Series of Poker despite him holding just a Joker, a Get out of Jail Free Monopoloy card, a 2 of clubs, 7 of spades and a green #4 card from the game UNO.

사실: 척 노리스의 포커 페이스는 세계적으로 유명하다. 척 노리스는 자신의 포커 페이스 덕분에 1983년 월드 시리즈 포커 대회에서 조커 한 장, 부루마불 게임의 무인도 탈출권, 스페이드 2, 스페이드 7, 그리고 초록색 4 우노(UNO) 카드 한 장만으로도 우승을 거머쥘 수 있었다.


Teenage Mutant Ninja Turtles is based on a true story: Chuck Norris once ate a turtle whole, and when he crapped it out, the turtle was six feet tall and had learned karate.

사실: 돌연변이 닌자 거북이의 이야기는 사실 실화이다. 어느 날 척 노리스가 거북이 한 마리를 통째로 삼켰는데 그가 변을 보자 키가 180이고 어느 새 가라데를 완벽히 익힌 거북이가 튀어 나왔다.


Chuck Norris is allowed to talk about Fight Club.

사실: 척 노리스는 파이트 클럽에 대해 이야기해도 된다.

Chuck Norris does not know where you live, but he knows where you will die.

사실: 척 노리스는 당신이 어디에 사는지 모른다. 그러나 당신이 어디에서 죽을 것인지는 안다.


Chuck Norris refers to himself in fourth person.

사실: 척 노리스는 자기 자신을 지칭하여 말할 때 4인칭을 사용한다.


They say that lightning never strikes the same place twice. Niether does Chuck Norris. He doesn't have to.

사실: 흔히 말하길 번개는 절대로 한 곳을 두 번 치지 않는다고 한다. 척 노리스도 마찬가지다. 그럴 필요가 없기 때문이다.


A man once attempted to give Chuck Norris a hug. Chuck proceeded to kick the crap out of the man. Chuck Norris' father was confined to a wheelchair from that day on.

사실: 한 번은 어떤 남자가 척 노리스를 껴안아 주려고 했다. 척 노리스는 이내 그 남자에게 돌려차기를 날려 묵사발을 만들어 놓았다. 그 날 이후로 척 노리스의 아버지는 불구가 되어 휠체어 신세를 지고 있다.


God created heaven and earth, he then created man. Man overpopulated the earth, so, God created Chuck Norris.

사실: 신은 하늘과 땅을 창조한 후 인간을 만들었다. 인간들이 번성하여 지구를 가득 메우게 되자 신은 척 노리스를 창조하였다.

Chuck Norris once took part in a Civil War reenactment. It was the bloodiest day in American history.

사실: 언젠가 한 번 노리스가 남북 전쟁을 재연하는 행사에 참여한 적이 있었다. 그 날은 미국 역사상 가장 피비린내 나는 날로 기록되고 있다.


We all know the magic word is please. As in the sentence, "Please don't kill me." Too bad Chuck Norris doesn't believe in magic.

사실: 사람들은 "please"라는 말이 어떤 부탁이든 들어주게 만드는 마법의 단어라고 말하곤 한다. 예문을 들자면 "제발 제 목숨만 살려 주십시오(Please don't kill me)" 같은 것이 있다. 불행히도 척 노리스는 마법을 믿지 않는다.


Every dinosaur skull ever found has the imprint of a size 15 cowboy boot on its jaw. Scientists are baffled, but we know damn well why.

사실: 지금까지 발견된 공룡 화석들에는 모두 하나같이 그 턱뼈에 사이즈 330짜리 카우보이 부츠의 발자국이 선명하게 찍혀있다. 과학자들은 놀라움을 감추지 못하며 고개를 갸우뚱하고 있지만 우리들은 그 원인을 너무나도 잘 알고 있다.


Before he visits anywhere, international law dictates that Chuck Norris must inform the area's inhabitants at least seven days before his arrival. The necessary funeral arrangements can then be made.

사실: 국제법에 의하면 척 노리스는 타지를 방문하기에 앞서 적어도 7일 전에 반드시 방문 예정 사실을 해당 지역 주민들에게 통보해야만 한다. 이것은 필요한 장례식 절차를 미리 밟아 놓을 수 있도록 하기 위한 배려이다.


Aliens do exist. They're just waiting for Chuck Norris to die before they attack.

사실: 외계인은 실제로 존재한다. 척 노리스가 죽을 때까지 지구 침략 시기를 늦추고 있을 뿐.


The reason newborn babies cry is because they know they have just entered a world with Chuck Norris.

사실: 아기가 태어날 때 우는 이유는 자신이 이제 척 노리스와 한 세상에 살게 되었음을 본능적으로 직감하기 때문이다.


Switzerland isn't really neutral. They just haven't figured out what side Chuck Norris is on yet.

사실: 스위스는 사실 중립국이 아니다. 척 노리스가 어느 편에 속하는지 파악 중일 뿐.


Chuck Norris owns 3 pit bulls and 2 dobermans, yet if you go near his property the only sign you see is "Beware of Chuck Norris".

사실: 척 노리스는 3 마리의 사나운 핏불과 2 마리의 도베르만을 기른다. 그러나 척 노리스의 집 담장에 걸려 있는 경고문은 여전히 "척 노리스 조심"이다.


Navy SEALS utilize the training regimen Chuck Norris used in middle school.

사실: 미 해군 특수 부대 SEAL은 척 노리스가 중학교 때 쓰던 훈련 과정으로 훈련을 받는다.


Chuck Norris can open beer cans with his teeth. He still prefers to use other people's teeth, though.

사실: 척 노리스는 자신의 이빨로 맥주 캔을 딸 수 있다. 그렇지만 여전히 남의 이빨로 따는 것을 더 선호한다.

Chuck Norris's friends once threw him a surprise birthday party. Unfortunately, when Chuck Norris unexpectedly saw all those people in his house, his mind involuntarily went into "defense/kill" mode. Chuck Norris lost many dear friends that day.

사실: 한 번은 척 노리스의 친구들이 척 노리스를 위해 깜짝 생일 파티를 열어 준 적이 있었다. 자신의 집에 허락없이 들어온 인파를 발견한 순간 불행히도 척 노리스의 두뇌는 무의식 중에 "방어/살상" 모드로 돌입하고 말았다. 척 노리스는 그 날 수많은 친구들을 잃었다.


Chuck Norris can divide by zero.

사실: 척 노리스는 0으로 나눗셈을 할 수 있다.


Chuck Norris once roundhouse kicked Bruce Lee, breaking him in half. The result was Jet Li and Jackie Chan.

사실: 한 번은 척 노리스가 돌려차기를 날려서 이소룡을 두 동강을 낸 적이 있었다. 그 결과물로서 이연걸과 성룡이 탄생했다.


Chuck Norris has never used a question mark in his entire life. He believes that the interrogative tense is a sign of weakness.

사실: 척 노리스는 평생동안 단 한 번도 물음표를 사용해 본 적이 없다. 의문문은 나약함의 증거라는 척 노리스의 신념 탓이다.


Chuck Norris doesn't have friends, just enemies he hasn't killed.

사실: 척 노리스에게는 친구가 없다. 아직까지 살려 둔 적들만이 있을 뿐.

2006년 3월 3일 금요일

척노리스에 관한 진실

작년 말경부터 미국 네티즌들 사이에서 척 노리스 놀이라는 게 유행이라고 한다. 이소룡이나 성룡이 위대한 무술인으로 추앙받아도 척 노리스라는 이름을 들으면 왠지 피식하고 웃음이 먼저 나오게 되는 것은 우리나라 사람들뿐 아니라 미국에서도 마찬가지였다. 한 때는 나름대로 잘 나갔지만 지금은 "텍사스 레인저"나 "델타 포스" 등으로 기억되는 80년대 액션 스타의 대명사가 되어 버린 척 노리스. 그러나 최근에 인터넷을 통해 그에 대한 "사실"들이 하나 둘씩 밝혀지기 시작하면서 그가 다시 뜨고 있다. 다음의 발췌문은 그 수많은 진실들의 극히 일부분에 불과하다...
사실: 척 노리스의 눈물은 암을 치료할 수 있다. 그러나 안타깝게도 척 노리스는 눈물을 흘리지 않는다.

사실:
척 노리스는 잠을 자지 않는다. 오직 기다릴 뿐.

사실:
척 노리스는 사냥을 하지 않는다. "사냥"이란 단어가 실패의 가능성을 내포하므로. 척 노리스에겐 오직 "살상"만이 있다.

사실:
척 노리스는 무한대까지 세어 보았다. 그것도 두 번씩이나.

사실:
척 노리스는 그의 수려한 용모와 빼어난 무술 실력을 손에 넣기 위해 악마에게 자신의 영혼을 팔았다. 악마와의 거래가 성사되자마자 척 노리스는 악마의 면상에 돌려차기를 날린 후 자신의 영혼을 되찾았다. 악마는 현 상황의 아이러니함을 깨닫고 화를 풀고 미소를 지으며 그 정도는 자신도 예상할 수 있었어야 했음을 인정했다. 그 사건 이후로 척 노리스와 악마는 매달 수요일 저녁이면 함께 포커를 친다.

사실:
유령은 잠자리에 들기 전에 침대 밑에 척 노리스가 있는지 없는지 확인한다.

사실:
당신이 척 노리스를 볼 수 있다면 척 노리스도 당신을 볼 수 있다. 당신이 척 노리스를 볼 수 없다면 당신은 수 초 내로 죽음을 맞이할 것이다.

사실:
척 노리스의 주요 수출품은 고통이다.

사실:
척 노리스는 세금 신고를 할 때에 빈 서류에다가 공격 자세로 몸을 숙이고 있는 자신의 사진 한
장만을 첨부하여 보낸다. 척 노리스는 단 한 번도 세금을 낸 적이 없다.

사실:
한 번은 공룡들이 척 노리스를 째려본 적이 있었다. 처음이자 마지막으로.

사실:
척 노리스는 잠자리에 들 때 불을 켜 놓는다. 척 노리스가 어둠을 두려워하기 때문이 아니다. 어둠이 척 노리스를 두려워 하기 때문이다.

사실: 척 노리스는 케네디 암살사건을 저지하기 위해 타임머신을 만들어서 과거로 간 적이 있었다. 오스왈드가 총을 쏘자 척 노리스는 자신의 턱수염으로 세 방의 탄알을 모두 튕겨내었다. 케네디는 이 경이로운 광경을 목격하고는 놀라서 죽었다.

사실: 척 노리스는 이미 화성에 다녀왔다. 화성에 생명체가 존재하지 않는 것은 바로 이 때문이다.

사실: 한 맹인이 실수로 척 노리스의 발을 밟았다. 척 노리스가 "내가 누군지나 아시오? 내가 바로 척 노리스요!"라고 말하자, 척 노리스라는 그 이름만 듣고도 장님이 눈을 떴다. 그러나 애석하게도 그가 자신의 두 눈으로 난생 처음이자 마지막으로 본 유일한 장면은 필살의 돌려차기를 날리는 척 노리스의 모습이었다.

사실: 언젠가 어떤 한 사람이 척 노리스에게 돌려차기는 그다지 효율적인 발차기 기술이 아니라고 말해 준 적이 있었다. 역사가들은 이 사건을 인류 역사상 최대의 실수로 기록하고 있다.

사실:
척 노리스는 10년 전에 이미 죽었다. 저승사자가 쫄아서 여태 그 소식을 전하지 못했을 뿐.

사실: 척 노리스는 책을 읽지 않는다. 원하는 정보를 얻어낼 때까지 책을 노려볼 뿐.

사실: 척 노리스가 미소를 한 번 지으면 죽어가던 사람도 되살아난다. 아이러니한 사실은 척 노리스는 오직 누군가를 죽인 후에만 미소를 짓는다는 점이다.

사실: 척 노리스는 수시로 적십자에 헌혈을 한다. 그러나 자신의 피는 한 번도 헌혈해 본 적이 없다.

사실: 척 노리스는 엄마 배에서 나올 때 머리보다 발이 먼저 나왔다. 시건방진 의사 선생의 면상에 돌려차기를 날려 주기 위해서이다. 척 노리스의 분만은 척 노리스만이 할 수 있다.

사실: 척 노리스에게 선물을 안 주기 전까지만 해도 산타 클로스는 진짜였다.

사실: 척 노리스가 버거킹에서 빅맥을 주문하면 빅맥이 나온다.

사실: 척 노리스는 MC 해머를 만질 수 있다.

사실: 실제로 아인슈타인의 상대성이론에 의하면 척 노리스는 당신에게 "어제" 돌려차기를 날리는 것이 가능하다.

사실: 척 노리스는 스트리트 파이터 II 비디오 게임에 원래 포함되어 있었으나 베타 테스터들이 제거하였다. 어떤 버튼을 누르든지간에 무조건 돌려차기밖에 안 했기 때문이다. 훗날 척 노리스에게 이 "버그"가 왜 생긴 것이냐고 묻자 척 노리스는 "그건 버그가 아니었다"라고 대답했다.

사실: 장애인 전용 주차공간 표시는 사실 그것이 장애인을 위한 주자공간임을 나타내는 것이 아니다. 그것은 그 공간이 척 노리스의 자리이며 만약 그 자리에 주차를 하는 사람은 곧 장애인이 될 것임을 시사하는 경고 표지일 뿐이다.

사실: 남의 잔디밭은 언제나 더 푸르러 보인다(남의 떡이 더 커 보인다는 의미의 영미 속담). 그러나 척 노리스가 다녀간 잔디밭이라면 이야기가 틀리다. 척 노리스가 다녀간 잔디밭은 피와 눈물에 젖어서 시뻘겋다.

사실: 한 번은 회색곰이 척 노리스를 잡아먹으려고 했다. 척 노리스가 자신의 주먹을 곰에게 보여주자 곰은 이내 곧 자기 자신의 몸뚱아리를 잡아먹기 시작했다. 현명한 곰은 덜 고통스러운 죽음을 택한 것이다.

사실: 산소는 생명 유지를 위해 척 노리스를 필요로 한다.

사실: 척 노리스가 자신이 식물인간으로 만들어 놓은 사람을 부르는 말이 있다. 바로 "운 좋은 놈"이다.

사실: 척 노리스는 칼로 사람을 죽이는 것이 너무 쉬워서 숟가락을 발명했다.

사실: 척 노리스에게 시간을 물어 보면 척 노리스는 언제나 "2초 전"이라고 대답한다. 이 때 당신이 "무슨 2초 전이냐?"라고 되물으면 바로 그 순간 당신의 면상에 척 노리스의 회심의 돌려차기가 날아온다.

사실: 척 노리스는 네 번째 동방박사였다. 척 노리스는 아기 예수에게 "턱수염"을 선물하였으며 예수는 죽을 때까지 이 수염을 착용하였다. 다른 동방박사들은 자신들의 선물이 무시당한 것에 질투심이 일어나 척 노리스를 성경에서 삭제하였다. 얼마 후 세 명의 동방박사들의 죽은 시체가 발견되었다. 사인은 돌려차기로 추정되고 있다.

사실: 45~65세의 여성들에게 있어 사망 원인 1위는 심장 질환이지만 0~125세의 남성들에게 있어 가장 큰 사망 원인은 여전히 척 노리스다.

사실: 척 노리스는 자신의 동상과 눈싸움을 해서 이겼다.

사실: 드라마 텍사스 레인저를 찍을 때마다 척 노리스는 치사량의 5배에 해당하는 코끼리 마취제를 맞는다. 이것은 그의 근력과 순발력을 마비시켜 동료 배우들의 사망률을 낮추어 보고자 함이다.

사실: 척 노리스는 팔굽혀펴기를 할 때 자신을 밀어 올리지 않는다. 지구를 밀어내릴 뿐.

사실: 일식은 척 노리스가 태양과 눈싸움을 할 때 일어나는 현상이다. 척 노리스는 눈싸움에서 절대 지는 법이 없다.

위의 내용은 캐나다의 4q.cc라는 사이트에서 처음 나타났으며 그 밖에 이 사이트에서는 "빈 디젤에 관한 사실"과 "미스터 T에 관한 사실"(80년대에 "A 특공대"에서 B.A.로 출연한 바 있었던 액션 배우. "I pity the fool"이란 유행어를 탄생시켰다)도 찾아 볼 수 있다.


나는 잘 몰랐던 사실인데 위키피디아를 통해 알게 한 가지 놀라운 사실은 척 노리스가 처음으로 무술에 입문을 하게 된 것이 바로 우리나라에서였다는 사실이다. 원래 무술과는 거리가 멀었던 소심한 성격의 척 노리스는 미 공군에 입대하게 되고 주한미군으로 오산 공군기지에 주둔을 하게 되는데 바로 그곳에서 당수도(수박도)와 태권도를 배우게 된다. (현재 태권도 검은띠 8단이란다.) 척 노리스는 영화 배우가 되기 전에 실제로 진정한 무술인으로서 명성을 날리게 되는데 가라데, 유도 등을 섭렵한 종합 무술인으로서 다년간의 가라데 챔피언쉽 우승 경력을 가지고 있다. 척 노리스는 훗날 자신만의 무술을 완성시켜 이를 천국도라 명하였다.천국도 공식 사이트:

United Fighting Arts Federation: http://www.ufaf.org



자, 여러분들도 이제 척 노리스에 관한 진실을 알게 되었으니 우리가 할 수 있는 유일한 일이라고는 언제 어디서 날아올지 모르는 척 노리스의 돌려차기를 두려워하며 떨고 있는 수밖에. 덜덜덜덜덜덜.....

Diff, Patch, CVS 사용법

리눅스 개발자들에게 중요한 것 중의 하나가 오픈소스 프로젝트 진행이다. 사실 국내에서도 오픈소스 프로젝트는 많은 사람들이 관심을 갖고 있지만 막상 프로젝트에 참여하는 사람들의 숫자는 여전히 부족하다. 여기서는 여러 개발자들이 동시에 오픈소스 프로젝트에 참가할 때 거의 필수적으로 쓰이는 diff, patch, CVS(Concurrent Versions System)와 같은 소스코드 버전 관리툴에 대해 살펴 보고 오픈소스 프로젝트를 진행할 때 알아두면 좋은 특성이나 작업 방식에 대해서도 알아 본다.

오픈소스 프로젝트란 도대체 어떤 것일까? 리눅스와 오픈소스의 부상과 더불어 오픈소스 개발 방식은 기존의 상용 소프트웨어 개발 방식에 비해 적은 비용으로 양질의 소프트웨어를 개발할 수 있으며 소프트웨어 시장 독점의 문제가 없다는 의견이 설득력을 계속 높여가고 있다.

그러나 필자가 보기에는 오픈소스 개발 방식은 그 효율성을 논의하기 전에 왜 이런 식의 개발 방식이 만들어 졌으며 왜 오픈소스 스타일의 개발 방식이 자연스럽게 정착되었는지를 이해하는 것이 더욱 중요하다고 생각한다. 필자의 의견으로는 오픈소스는 소프트웨어를 소프트웨어 그 자체가 지닌 특성에 맞도록 자연스럽게 개발하는 한 방법이라고 생각한다.

당연한 얘기지만 어떠한 소프트웨어의 소스코드를 공개하면 그 소프트웨어가 계속 바뀌어 나갈 수 있는 길이 열리게 된다. 소스코드를 공개해서 개발 작업을 진행하는 오픈소스 개발 방법이 두드러지게 나타난 것은 1970년대 초 AT&T에서 자사의 운영체제인 유닉스의 소스코드를 공개한 이후부터라고 보는 것이 정설이다. AT&T에서는 대학과 같은 교육, 연구 기관에 자사의 제품인 유닉스를 공급하면서 돈을 받고 소스코드를 그대로 제공하는 라이선스 방식을 취했다.

소프트웨어를 배포할 때 소스가 아닌 바이너리를 주로 배포하는 지금으로서는 언뜻 상상하기 어려운 관행일 수도 있지만 컴퓨터의 종류가 통일되어 있지 않고, 소수의 전문가 집단에서 유닉스를 주로 사용했다는 점을 생각해 본다면 AT&T 입장에서 유지보수 비용을 줄여주는 이러한 소스코드 형태의 배포는 나름대로 합리적인 선택이라고도 할 수 있겠다.

그러나 여기서 예상하지 못한 일이 벌어진 것이 이들 사용자, 혹은 사용자이면서 개발자이기도 한 사람들이 마음대로 뜯어고치고 덧붙이기 시작한 코드들이 오리지널 AT&T 유닉스보다 오히려 더 중요한 위치를 차지하게 된 것이다(BSD 유닉스의 발전도 이러한 관습에 뿌리를 두고 있다).

따라서 자유 소프트웨어나 오픈소스와 같은 용어들은 소프트웨어 개발 방식의 측면에서 볼 때 이미 존재하고 있던 개발 방식을 새롭게 재조명하고 있다고 생각할 수 있다. 자유 소프트웨어에서는 소스코드가 공개된 소프트웨어의 보호에 좀 더 중점을 두고 있으며 오픈소스에서는 소스코드가 공개된 채로 개발되는 소프트웨어의 개발 효율성에 좀 더 관심을 집중하는 편이다. 어느 경우이든 간에, 소스코드를 공개해서 개발자의 참여를 이끌어 내는 소프트웨어 개발 방식은 변함이 없으며, 오픈소스라는 단어가 아예 없던 시절에도 이것은 마찬가지인 것이다.

그렇다면, 이제 간단한 상황 하나를 가정해 보기로 하자. 여러분들이 초기 유닉스 시절 대학 전산실에 근무하던 도중 유닉스가 도입되었다고 생각해보자. 고된 포팅과 설정 작업 끝에 시스템이 제대로 돌아가기 시작했는데 이 와중에서 버그를 하나 발견하고 그 부분의 소스코드를 수정했다. 이럴 때 다음 버전의 유닉스에 여러분들이 고친 부분이 반영되도록 하려면 어떻게 해야 할까?

이럴 때 가장 상식적인 해법은 고친 부분의 소스코드를 원저자에게 보내주면 될 것이다. 그리고 그 방법으로 가장 편리한 것은 아마도 이메일이 좋을 것이다. 인터넷이 없던 시절이라면 아마도 일반 메일을 이용했을 것이다. 약간은 논외의 이야기지만, 인터넷 초창기에는 국내에서 유즈넷 뉴스그룹에 올라온 글을 보기 위해 정기적으로 뉴스서버 데이터 백업을 외국에서 자기 테이프에 받아 소포로 전송받기도 했다고 한다. 어쨌든 이러한 이메일의 간편함 덕분에 이메일은 오픈소스 개발 작업에서 가장 중요한 통신 수단이며 패치 전송 수단으로 자리 잡게 된다.

여기서 하나 생각해 봐야 할 것이 원저자의 입장이다. 이렇게 패치를 담고 있는 메일의 숫자가 적을 때는 원저자는 그저 전송된 패치를 고맙게 받아 적용하기만 하면 되겠지만 패치의 숫자가 늘어나고, 같은 버그에 대해서도 두 종류 이상의 중복 패치가 생기게 되면 어떤 패치를 선택할 것인지, 그리고 모은 패치를 어떻게 통합해서 하나의 소스코드 트리로 만들고 그것을 배포(public release)할 것인지 선택해야 하는 문제가 생긴다. 이런 경우, 보통 오픈소스계의 관습은 원저자, 혹은 프로젝트 리더에게 어떤 패치를 받아들일 것인지의 결정권을 맡겨버리는 경향이 있다. 이럴 때 원저자나 프로젝트 리더는 ‘자비로운 독재자(benevolent dictator)’라는 역할을 맡게 되는 것이다.

또한, 패치가 전송될 때 사람들마다 통일되지 않은 방식으로 패치를 전송하게 되면 프로젝트 리더의 입장에서는 여러 종류의 패치를 하나의 소스코드 트리에 적용시키는 데 많은 혼란을 겪게 될 것이다. 이를 해결하기 위해 등장한 심플한 도구가 바로 diff와 patch이다.

diff와 patch
diff는 유닉스 사용자 튜토리얼에도 가끔씩 등장하는 간단한 유틸리티이다. diff의 역할은 두 파일간의 차이점을 보여주는 데 소스코드의 바뀐 부분을 보여 줄 때 많이 쓰인다. patch는 이러한 diff의 출력 결과를 이용해서 이 바뀐 부분을 원래의 소스코드에 업데이트할 때 쓰는 유틸리티이다.

diff의 일반용법
우선, diff의 형식은 다음과 같다.

diff [options] from-file to-file

diff는 두 개의 파일을 필요로 한다는데 주의하자. from-file은 원래의 파일, 즉 구 버전의 파일이며, to-file은 새로이 바뀐 새 버전의 파일이다. diff는 이렇게 하면 from-file에서 to-file로 어떠한 변화가 있었는지를 출력해 준다. from-file과 to-file은 모두 디렉토리가 올 수도 있는데 디렉토리가 오는 경우는 조금 뒤에 살펴보기로 하자. 참고로 간단한 예제 hello1.c와 hello2.c의 예를 들어보자. 다음에서 볼 수 있듯이 hello2.c는 hello1.c에서 hello, world 부분이 hello, the world of linux로 대치되었고 그 아랫줄에 공백 라인 하나와 printf("Testing one two three.\n");가 추가되었음을 볼 수 있다.

*** hello1.c:
#include
#include
main()
{
   printf("hello, world.\n");
}

*** hello2.c:
#include
main()
{
   printf("hello, the world of Linux.\n");
   printf("Testing one two three.\n");
}

diff 결과는 다음과 같다.

$ diff hello1.c hello2.c
2d1
< #include
6c5,7
<     printf("hello, world.\n");
---
>     printf("hello, the world of Linux.\n");
>
>     printf("Testing one two three.\n");

첫 줄의 2d1은 hello1의 두 번째 줄에서 한 줄을 삭제(delete)하는 변화가 일어났다는 의미이다. 그리고 조금 아래의 6c5,7은 hello1의 6번째 줄을 아랫부분으로 바꾸는데(change) 그 결과가 5번째부터 7번째 라인까지 들어가게 된다는 의미이다. 그러나 실제로 프로그램 소스코드에서는 오리지널 diff의 결과물보다는 unified format의 diff 출력을 쓰는 경우가 많다. unified format을 쓰려면 diff에 -u 옵션을 추가한다.

$ diff -u hello1.c hello2.c
--- hello1.c    Tue Aug  3 14:34:46 2004
+++ hello2.c    Tue Aug  3 13:25:49 2004
@@ -1,7 +1,8 @@
#include
-#include

main()
{
-    printf("hello, world.\n");
+    printf("hello, the world of Linux.\n");
+
+    printf("Testing one two three.\n");
}

참고로 unified format에서는 변경되는 부분만이 아닌 변경되는 부분 근처의 내용(context)도 같이 출력됨을 볼 수 있다. 사람이 좀 더 읽기 편리한 context format 출력 옵션인 -c를 사용한 결과는 다음과 같다. context format 역시 바뀌는 부분 근처의 내용도 참고하기 좋게 출력을 해 준다. 어쨌거나 오픈소스 프로젝트에서는 diff를 쓸 때 주로 -u 옵션을 붙인다는 점을 꼭 외워 두도록 하자.

$ diff -c hello1.c hello2.c
*** hello1.c    Tue Aug  3 14:34:46 2004
--- hello2.c    Tue Aug  3 13:25:49 2004
***************
*** 1,7 ****
#include
- #include
 
main()
{
!     printf("hello, world.\n");
}
--- 1,8 ----
#include
 
main()
{
!     printf("hello, the world of Linux.\n");
!
!     printf("Testing one two three.\n");
}

이렇게 diff로 소스코드의 변경된 부분을 저장한 다음 이것을 원저자에게 메일로 보내면 된다.

$ diff -u hello1.c hello2.c > hello.diff

여러 개의 소스 파일을 diff로 비교하기
앞의 경우는 소스코드 파일 하나만이 변경되었지만 상황에 따라서는 패치 과정에 여러 파일이 수정되고 새로운 파일이 추가되는 경우가 발생할 수도 있다. diff는 디렉토리 단위의 파일 비교도 가능하다. 우선, 다음 예제를 보자.

$ pwd
/home/foobar
$ ls -F
src1/  src2/            # src1은 원본, src2는 새로운 기능 추가본
$ ls src1
hello1.c  hello2.c
$ ls src2
hello1.c  hello2.c  hello3.c
$ more src1/*c
::::::::::::::
src1/hello1.c
::::::::::::::
#include
#include

main()
{
   printf("hello, world.\n");
}
::::::::::::::
src1/hello2.c
::::::::::::::
#include

main()
{
   printf("hello, the world of Linux.\n");

   printf("Testing one two three.\n");
}
$ more src2/*c
::::::::::::::
src2/hello1.c
::::::::::::::
#include

main()
{
   printf("hello, world.\n");
}
::::::::::::::
src2/hello2.c
::::::::::::::
#include

main()
{
   printf("hello, the world of Linux.\n");

   printf("Testing one two three four.\n");
}
::::::::::::::
src2/hello3.c
::::::::::::::
#include
#include

main()
{
   /* needs to be filled in */
}

src2에서는 hello3.c 파일이 새로 추가되었으며, hello2.c에서 수정 부분이 있고, hello1.c에서 빠진 부분이 있다. 이 두 디렉토리 사이에서 diff를 실행하려면 다음과 같은 명령을 쓴다.

$ pwd
/home/foobar
$ ls -F
src1/ src2/             # 경로를 제대로 확인한 뒤 diff를 실행한다
$ diff -urN src1 src2
diff -urN src1/hello1.c src2/hello1.c
--- src1/hello1.c       Tue Aug  3 14:34:46 2004
+++ src2/hello1.c       Tue Aug  3 13:35:44 2004
@@ -1,5 +1,4 @@
#include
-#include

main()
{
diff -urN src1/hello2.c src2/hello2.c
--- src1/hello2.c       Tue Aug  3 13:25:49 2004
+++ src2/hello2.c       Tue Aug  3 13:35:57 2004
@@ -4,5 +4,5 @@
{
    printf("hello, the world of Linux.\n");

-    printf("Testing one two three.\n");
+    printf("Testing one two three four.\n");
}
diff -urN src1/hello3.c src2/hello3.c
--- src1/hello3.c       Thu Jan  1 09:00:00 1970
+++ src2/hello3.c       Tue Aug  3 13:37:02 2004
@@ -0,0 +1,7 @@
+#include
+#include
+
+main()
+{
+    /* needs to be filled in */
+}

diff 명령에서 -r 옵션은 recursive 옵션으로 서브 디렉토리까지 diff가 모두 탐색하라는 의미이고, -N 옵션은 hello3.c와 같이 새로 만들어진 파일까지도 포함해 diff 출력을 생성하라는 의미다. 이 옵션 역시 -urN으로 외워 두는 것이 좋다.

patch 사용하기
이렇게 만들어진 diff의 결과물은 patch 명령을 통해서 원저자의 소스코드로 업데이트된다. patch 명령은 -p 옵션만 정확히 이해하면 사용하는데 무리가 없다.
-p 옵션은 strip 옵션이라고 부르는데 diff 파일에 명시되어 있는 디렉토리에서 몇 단계를 벗겨(strip)낼 것인가를 결정한다. -p0 옵션은 디렉토리 단계를 하나도 벗겨내지 않겠다는 것이고, -p1 옵션은 한 단계를 벗겨낸다는 의미이고 -p2는 두 단계를 의미한다. 쉽게 이해하기 위해 <표 1>를 보자. foobar/include/net 디렉토리가 있다고 할 때 p 옵션을 적용하면 다음과 같이 디렉토리가 벗겨져 나간다.

p0 foobar/include/net
p1 include/net
p2 net

이것이 diff로 생성시킨 패치를 적용할 때 어떤 의미를 가지게 될까? 우선, 파일 두 개를 비교했을 때 생성된 diff 패치와 디렉토리 두 개를 비교했을 때 생성된 diff 패치의 헤더 부분을 비교해보자.

◆ 파일 두 개를 비교했을 경우:
$ diff -u hello1.c hello2.c
--- hello1.c    Tue Aug  3 14:34:46 2004
+++ hello2.c    Tue Aug  3 13:25:49 2004
(이하 생략)

◆ 디렉토리 두 개를 비교했을 경우:
$ diff -urN src1 src2
diff -urN src1/hello1.c src2/hello1.c
--- src1/hello1.c       Tue Aug  3 14:34:46 2004
+++ src2/hello1.c       Tue Aug  3 13:35:44 2004
(이하 생략)

즉, diff가 생성한 패치 파일에는 원본 파일과 바뀐 파일의 디렉토리가 명시되어 있음을 알 수 있다. patch 명령을 사용할 때는 이 경로명을 고려해서 patch 명령을 실행시켜 줘야 한다.

패치 적용하기
여러분이 원저자의 입장에서 제공받은 패치를 적용시키려면 다음과 같은 방법을 사용하면 된다. 패치 파일은 표준 입력(standard input)으로 들어가며, 항상 -p 옵션을 주의 깊게 사용해야 한다. 이번 예제에서는 디렉토리 두 개를 비교한 패치가 전송되었다고 가정해 보자. 원저자는 diff 패치의 헤더 부분을 읽고 패치의 경로명을 확인한 다음 적절한 디렉토리로 가서 patch 명령을 실행한다. 우선, -p0 옵션 사용 예부터 보자. diff 패치의 헤더 부분은 다음과 같다.

diff -urN src1/hello1.c src2/hello1.c
--- src1/hello1.c       Tue Aug  3 14:34:46 2004
+++ src2/hello1.c       Tue Aug  3 13:35:44 2004
... 이하 생략 ...

따라서 원저자는 이 패치를 hello.diff로 저장한 다음 자신의 소스코드가 있는 src1까지 가서 패치를 적용한다.

$ cd projects
$ pwd
/home/foobar/projects
$ ls -F
hello.diff   src1/

diff 파일에 기술된 경로명과 현재 경로명이 일치하고 있음을 주의깊게 보자.

$ patch -p0 < hello.diff
$ patch -p0 < hello.diff
patching file src1/hello1.c
patching file src1/hello2.c
patching file src1/hello3.c

패치 전과 패치 후의 결과를 비교해 보면 다음과 같다.

패치 전:

$ pwd
/home/foobar/projects/src1
$ ls -al
total 16
drwxr-xr-x    2 jwsohn   jwsohn       4096  8월  3 16:35 .
drwxr-xr-x    3 jwsohn   jwsohn       4096  8월  3 16:35 ..
-rw-r--r--    1 jwsohn   jwsohn         82  8월  3 14:34 hello1.c
-rw-r--r--    1 jwsohn   jwsohn        116  8월  3 13:25 hello2.c

패치 후:

$ pwd
/home/foobar/projects/src1
$ ls -al
total 20
drwxr-xr-x    2 jwsohn   jwsohn       4096  8월  3 16:41 .
drwxr-xr-x    3 jwsohn   jwsohn       4096  8월  3 16:35 ..
-rw-r--r--    1 jwsohn   jwsohn         62  8월  3 16:41 hello1.c
-rw-r--r--    1 jwsohn   jwsohn        121  8월  3 16:41 hello2.c
-rw-r--r--    1 jwsohn   jwsohn         83  8월  3 16:41 hello3.c

이제 -p1 옵션을 적용해서 patch 명령을 써 보자. diff 파일에 기술된 경로명에서 디렉토리를 한 단계 벗겨내면 src1 디렉토리가 없어지므로 다음과 같은 방식으로 패치 파일이 적용된다.

$ pwd
/home/foobar/projects
$ ls -F
hello.diff  src1/
$ cd src1
$ patch -p1 < ../hello.diff
patching file hello1.c
patching file hello2.c
patching file hello3.c

참고로 diff 파일의 경로는 어디에 위치하든 상관이 없다. 파일 하나에 대한 패치를 적용할 때는 -p0 옵션을 쓰면 될 것이다.

CVS 사용
CVS는 약자 중 Concurrent가 의미하듯이 한번에 여러 명의 개발자가 동일한 소스코드 트리에 동시에 수정을 가하면서 작업을 할 수 있도록 도와주는 도구이다. 사실 오픈소스 프로젝트에 참가하는 일반 개발자의 입장에서는 CVS에 대한 일반적인 지식은 별다른 필요가 없다고 생각해도 무방하다. 실제 소스코드 트리를 수정할 수 있는 권한을 갖고 있는 사람들은 프로젝트 리더인 자비로운 독재자 한 사람이나 프로젝트와 관련이 깊은 소수의 개발자들일 것이기 때문이다.

즉, 소스코드 수정 사항이 생기면 CVS를 굳이 쓸 필요가 없이 그냥 FTP나 http로 다운받은 소스코드 위에 diff를 돌려서 패치만 이메일과 같은 수단으로 보내 주면 소스코드 수정 권한이 있는 그쪽 사람들이(보통 ‘커미터’라고 부른다) 알아서 처리를 해 줄 것이기 때문이다.
하지만 가장 최신 버전의 nightly build된 소프트웨어는 CVS 서버에 접속해야만 구할 수 있는 경우가 대부분이다. 따라서 오픈소스 개발 프로젝트에 관심이 있는 개발자라면 다음 측면에서 CVS 사용법을 알아야 할 필요가 있을 것이다.

[1] FTP나 http 서버에서 소스코드를 다운받는 대신에
[2] CVS 서버에서 가장 최신 소스코드를 다운 받고
[3] 자신이 패치한 소스코드와 CVS 서버의 소스코드의 diff를 생성하는 방법

익명 CVS 체크아웃
이제 CVS에서 소스코드를 다운받는 방법을 알아보기로 하자. 일반적으로 오픈소스 프로젝트들은 대부분 CVS 서버를 읽기 전용으로 세팅해 놓고 누구든지 들어와서 소스코드를 다운받아 갈 수 있도록 해 놓고 있다. 익명 FTP(anonymous FTP)와 비슷한 개념으로 생각하면 되겠다. CVS 서버에 사용자가 접속을 해서 소스코드를 한 카피 다운받아 가는 것을 CVS에서는 체크아웃(check-out)이라는 용어로 표현한다.
참고로 CVS는 로컬 서버에서 사용할 수도 있고, 따로 CVS 서버를 두고 원격으로 접속할 수도 있다. 여기서는 CVS가 원격 서버라고 가정하기로 한다. CVS 서버에서 소스코드를 다운받는 명령은 다음과 같다. KLDP.net 서버에 위치한 moniwiki 프로젝트를 예로 들어 보겠다.

$ cvs -d:pserver:anonymous@cvs.kldp.net:cvsroot/moniwiki login
$ cvs -d:pserver:anonymous@cvs.kldp.net:cvsroot/moniwiki checkout moniwiki

익명 FTP에 접속할 때 보다는 조금 복잡해 보인다. 우선, 첫줄의 cvs 명령은 CVS 서버에 anonmous, 즉 익명 사용자로 로그인하는 과정이다. CVS 서버가 암호를 요구하면 그냥 엔터 키를 쳐 주면 인증이 끝나고 읽기 권한이 부여된다. 일단 로그인을 한번 한 다음부터는 사용자의 홈 디렉토리에 .cvspass 파일이 생기면서 인증 절차가 생략된다. 즉, 매번 접속할 때마다 anonymous 인증 과정을 거쳐야 하는 익명 FTP와는 달리, CVS에서는 한번만 익명 로그인을 해서 .cvspass 파일을 생성하고 나면 다시 cvs login 명령으로 인증 과정을 거칠 필요가 없다.

그 다음 -d 옵션은 CVS 서버에서 제공하고 있는 루트 디렉토리를 의미한다. moniwiki 프로젝트의 경우는 cvsroot/moniwiki로 지정되어 있다. 앞의 pserver는 CVS 명령이 소스코드를 다운받으면서 쓸 프로토콜명이며 뒤의 anonymous@cvs.kldp.net은 CVS 로그인시 사용할 계정이다.

두 번째 cvs 명령은 소스코드 한 카피를 다운받는 체크아웃 과정을 실행하게 된다. 체크아웃(checkout)한 다음의 moniwki는 CVS 서버에서 지정해 놓은 프로젝트 이름이며(모듈이라고 부른다) 이곳 CVS 서버에서는 moniwki로 지정해 두었다. 두 번째 명령을 실행하면 사용자의 현재 디렉토리에 moniwiki라는 디렉토리가 생성되고 소스코드 다운로드가 시작된다. 여기에, -z3 옵션을 주면 전송시 압축을 사용하기 때문에 전송 속도가 빨라진다.

$ cvs -z3 -d:pserver:anonymous@cvs.kldp.net:cvsroot/moniwiki checkout moniwiki

그런데 CVS 서버에 접속할 때마다 -d 옵션 뒤의 긴 디렉토리 이름을 타이핑하기는 아무래도 불편한 감이 있다. -d 옵션을 생략하려면 환경변수 CVSROOT에 -d 옵션을 등록해 둔다.

$ export CVSROOT=:pserver:anonymous@cvs.kldp.net:/cvsroot/moniwiki

그 다음부터는 다음 명령으로도 충분하다.

$ cvs login
$ cvs checkout moniwiki

소스코드를 받은 지 시간이 어느 정도 지났다면 그동안 CVS 서버의 내용이 새롭게 업데이트되어 있을 수도 있다. 바뀐 부분을 다운받으려면 CVS에서 update 명령을 사용한다.

$ cvs update -dP

여기서 -P 옵션은 Prune 옵션으로 비어있는 디렉토리를 자동으로 삭제해 주는 역할을 한다. -d 옵션은 그동안 서버 쪽에 새로 만들어진 디렉토리가 있으면 다운 받은 이쪽에도 동일한 디렉토리를 만들어 준다.

CVS 서버 원본에서 diff로 패치 파일 만들기
이제 기본적인 CVS 서버에서 소스코드 다운로드 방법을 알았으니 직접 CVS 서버의 소스코드를 이용해서 패치 파일을 만들어 보자. CVS는 diff 명령을 아예 자체적으로 내장하고 있다. 조금 전 다운받은 moniwiki의 소스코드를 예로 들어보자. 여기서, 필자는 monisetup.php 파일에 간단히 /* testing one two three */라는 주석문을 하나 삽입했다.

$ cd moniwiki
$ ls
COPYING                 doc                     secure.sh
CVS                     imgs                    theme
INSTALL                 index.html              tools
README                  lib                     wiki.php
THANKS                  locale                  wikihttpd.php
applets                 monisetup.bat           wikilib.php
config.php.default      monisetup.php           wikismiley.php
css                     monisetup.sh
data                    plugin
$ cvs diff -u -p monisetup.php
Index: monisetup.php
===================================================================
RCS file: /cvsroot/moniwiki/moniwiki/monisetup.php,v
retrieving revision 1.11
diff -u -p -r1.11 monisetup.php
--- monisetup.php       3 Jan 2004 14:26:50 -0000       1.11
+++ monisetup.php       3 Aug 2004 09:14:21 -0000
@@ -486,4 +486,5 @@ if ($_SERVER['REQUEST_METHOD']!="POST")

}

+/* testing one two three */
?>

cvs diff 명령이 마치 로컬에서 monisetup.php 파일에 diff 명령을 실행한 것과 같은 결과가 나왔음을 알 수 있다. cvs diff 명령 뒤의 -u 옵션은 diff와 마찬가지로 unified format을 의미하며 -p 옵션은 cvs diff 의 출력을 표준 출력(standard output)으로 보내라는 의미이다. 디렉토리 안의 모든 파일에 대해 diff 명령으로 비교를 하려면 다음과 같은 방법을 사용한다.

$ cvs -Q diff -u -p              
Index: monisetup.php
===================================================================
RCS file: /cvsroot/moniwiki/moniwiki/monisetup.php,v
retrieving revision 1.11
diff -u -p -r1.11 monisetup.php
--- monisetup.php       3 Jan 2004 14:26:50 -0000       1.11
+++ monisetup.php       3 Aug 2004 09:19:27 -0000
@@ -486,4 +486,5 @@ if ($_SERVER['REQUEST_METHOD']!="POST")

}

+/* testing one two three */
?>
Index: css/log.css
===================================================================
RCS file: /cvsroot/moniwiki/moniwiki/css/log.css,v
retrieving revision 1.1
diff -u -p -r1.1 log.css
--- css/log.css 11 Feb 2004 08:48:27 -0000      1.1
+++ css/log.css 3 Aug 2004 09:19:27 -0000
@@ -1,4 +1,5 @@
/* MoniWiki CSS 2003/11/01 by wkpark */
+/* another testing comment */
body {
  font-family:Georgia,Verdana,Lucida,sans-serif;font-size:12px;
  background-color:#FFFFFF;

여기서는 monisetup.php 파일과 css/log.css 파일에 수정된 부분이 있음을 알 수 있다. cvs diff 명령에서 -Q 옵션은 Quiet 옵션으로 diff 출력 이외의 다른 메시지를 출력하지 않도록 해 준다. 그런데 여기서 하나 의문이 들 수 있다. 분명히 CVS에서는 cvs를 이용해서 직접 소스코드에 수정을 가할 수 있을 것인데 여기에서 왜 굳이 구식 diff를 이용한 방법을 또 사용하고 있는 것을까?

그 이유는 앞에서도 잠깐 언급했듯이, CVS 서버의 내용을 수정할 수 있는 권한이 있는 개발자는 소수이기 때문이다. 그리고 자비로운 독재자라는 용어에서 알 수 있듯이 제출된 패치를 받아들일지 아닐지의 여부는 관습적으로 보통 그쪽 프로젝트 리더들의 몫이 된다.

따라서 CVS 서버에 읽기 전용의 권한만을 갖고 있는 일반 오픈소스 프로젝트 참가자들은 이메일이나 혹은 메일링 리스트에 diff를 이용해서 패치 파일을 포스팅하는 것이 오픈소스 프로젝트에 참가하는 가장 무난한 방법이다. 일반적으로 프로젝트의 참가자가 지나치게 많지 않은 경우를 제외하고는 오픈소스 프로젝트에 올라오는 패치는 아무리 사소한 것이라도 쉽게 CVS 서버의 원본 소스코드에(repository라고 부른다) 반영 된다.

따라서 일반 개발자의 입장에서는 프로젝트 리더나 메인 개발자가 되기 전에는 CVS 서버에서 쓰기 권한이 그다지 필요하지는 않다. 이제 간단하게 CVS 서버에서 자주 쓰이는 기본적인 개념과 용어에 대해 알아보기로 하자.

CVS의 개념과 여러 용어
CVS 모델, copy-moodify-merge model
CVS는 이전에 많이 쓰이던 RCS(Revision Control System)과는 달리 lock-modify-unlock이 아닌 copy-modify-merge 모델을 사용한다. 여러 명의 개발자가 하나의 소스코드 트리에서 개발 작업을 할 때 가장 큰 문제는 같은 부분의 소스코드에 두 명 이상의 개발자가 서로 다른 소스코드를 작성하고 있을 때 발생한다. 이것을 CVS에서는 conflict이 발생했다고 한다.

RCS의 lock-modify-unlock 접근방식은 이러한 conflict를 한번에 두 명 이상의 개발자가 같은 소스코드 부분에 접근할 수 없도록 해서 conflict 상황을 미연에 방지한다. 하지만 CVS에서는 이러한 conflict 상황이 발생하는 것을 허용한다. 그렇다면 CVS에서는 이런 소스코드 conflict 상황이 발생하면 어떻게 대처할까?

재미있게도 CVS에서는 이런 상황에서 아무 일도 하지 않는다. 다만, CVS는 어느 부분에서 소스코드 conflict가 발생했는지, 그리고 어떤 사람이 conflict에 관계되어 있는지만 정확하게 알려 준다. 따라서 소스코드의 conflict 문제를 해결하는 것은 기계가 아닌 사람의 몫이 된다.

lock-modify-unlock 모델은 프로젝트의 전체 개발자 숫자가 소수이고 각각의 개발자들이 다른 개발자들이 현재 어떤 작업을 하고 있는지 쉽게 알 수 있는 상황에 유리하다. 그러나 개발자의 숫자가 많아지면 이미 잠금이 걸려 있는 파일에는 다른 개발자들이 접근할 수 없기 때문에 전체적인 업데이트가 늦어지는 문제가 발생하게 되고 좀 더 유연한 환경을 제공하기 위해 CVS가 도입되기에 이르렀다. 따라서 copy-modify-merge 모델의 CVS를 사용하는 개발자는 기본적으로 다음과 같은 과정을 거치며 개발 작업을 진행해 나가게 된다.

[1] 개발자는 CVS 서버로부터 소스코드 카피를 다운로드(check-out)한 다음
[2] 소스코드를 수정하고
[3] 완료된 작업은 다시 CVS 서버로 올려준다(check-in, commit)

여기서 conflict의 발생 여부는 commit 작업 단계에서 알 수 있다. 그리고 조금 전에 잠깐 살펴보았듯이 현재 개발자의 컴퓨터의 소스코드를 cvs 서버 쪽과 가능한 한 동일하게 유지하려면 update를 자주 해 주는 것이 좋다.

CVS와 관련된 용어
CVS와 관련된 용어는 통일된 번역이 아직 존재하지 않는 것 같아 원문 그대로 싣고 여기에 설명을 덧붙이도록 하겠다.

◆ repository : CVS 서버에 들어가 있는 바로 그 원본(master copy) 소스코드를 의미한다. 나중에 최종 출시가 되는 소스코드가 바로 이 repository이며 repository는 그동안 버전업되어 온 정보를 모두 포함하고 있다. cvs respository의 개수는 하나가 된다.

◆ working copy : 각각의 개발자가 작업을 위해 cvs repository에서 복사해 갖고 나간(check-out) 소스코드가 working copy이다. 따라서 working copy는 개발자의 수만큼 존재한다고 볼 수 있다. 개발자는 이 working copy에서 소스코드 수정 작업을 한 다음 나중에 check-in 혹은 commit 단계를 거쳐 원본 cvs repository에 수정을 가하게 된다.

◆ check-out : 개발자가 자신이 작업할 working copy를 CVS 서버에서 한 카피 복사해 가는 것을 check-out이라고 한다.

◆ update : update는 check-out과 비슷하게 cvs repository에서 원본 소프트웨어를 한 카피 가져오는 역할을 하지만, update는 단어의 원래 뜻 그대로 수정된 부분만 가져와서 현재 개발자가 쓰고 있는 working copy가 항상 최신의 갱신본이 될 수 있도록 해 준다. 일반적으로, 개발자는 한번 working copy를 check-out 한 뒤에는 최신의 소스코드를 유지하기 위해 이 update 명령을 주로 쓰게 된다.

◆ check-in 혹은 commit : 여기서 잠깐 조심해서 봐야 할 것이 update와 check-in의 관계이다. 얼핏 보기에는 CVS에서 check-out과 check-in이 반대의 개념이 되어야 할 것 같은데 실상 check-in의 반대 개념은 update이다. check-in은 내가 작성한 소스코드를 repository에 병합시켜서 다른 개발자들도 내가 작성한 수정 부분을 볼 수 있게 해 주는 소위 publish 작업이기 때문이다. 따라서 그 반대 개념은 내가 다른 사람들이 작성한 소스코드 수정본을 나의 working copy에 반영시키는 것인데 이 작업이 update 과정이다. 따라서 check-in 과정은 오히려 commit이라는 단어를 써서 표현하는 것이 혼동을 미리 방지하는 효과가 있지 않나 싶다. 참고로 commit 권한은 잠시 언급했듯이 소수의 주요 프로젝트 리더들이 갖게 되는 경우가 많다. 어떤 오픈소스 프로젝트에서 커미터의 역할을 담당한다는 것은 그 사람의 기여도가 높고 그만큼 높은 위치를 배정받았다는 뜻이 된다.

update와 commit에 관해서 또 하나 알아놓을 상식은 update와 commit 작업은 가능하면 자주 해 주는 것이 좋다는 사실이다. 다른 사람들이 내가 어떤 작업을 하는지 잘 알고, 나 역시 다른 사람들이 어떤 작업을 하고 있는지 잘 아는 것이 효율적인 협업(collaboration)의 기초가 됨은 두말할 필요가 없다. 추가적으로 CVS의 commit 명령 사용 예는 다음과 같다. -m 옵션 뒤에는 이번 commit에 대한 간략한 설명이나 주석문이 따라온다.

$ cvs commit -m "added additioinal messages" hello2.c   # 파일 하나 commit 예

$ pwd
/home/foobar/projects/src1
$ cvs commit -m "removed redundant declarations"       # 전체 디렉토리 commit 예

◆ log message : 수정된 소스코드를 commit할 때 이 소스코드가 어떤 역할을 하는지, 어떤 부분이 바뀌었는지 등을 기술하는 주석문 역할의 메시지이다. 이것 역시 코딩시 주석문 작성에 신경을 많이 쓰는 것처럼 수정된 소스코드를 commit할 때 마다 간결하고 정확하게 써 주는 것이 좋다.

오픈소스 프로젝트에 많은 참여를
지금까지 여러 명의 개발자, 특히 오픈소스 프로젝트에 참가할 때 필수적으로 쓰이는 유틸리티인 diff와 patch, 그리고 CVS의 기본 사용법에 대해서 알아보았다. 최근 들어서는 문서 작성도 오픈소스와 비슷하게 여러 사람이 동시에 같은 페이지를 고쳐 나가는 방식이 정착되어 가고 있다. 위키(wiki)의 사용이 늘어나고 있는 것이 바로 그것인데 위키는 내부적으로 RCS를 사용해서 문서의 버전 컨트롤을 해 나가는 경우가 많다. 즉, 위키를 통한 문서 작성 방식도 CVS를 이용한 오픈소스 소프트웨어 개발과 근본적으로 다르지 않은 것이다.

앞에서도 강조했듯이, 오픈소스 프로젝트에 참여하기 위해서 가장 중요한 것은 diff와 patch의 사용법을 아는 것이다. 일견 간단해 보이는 이 유틸리티들이 이메일, 그리고 이메일의 확장판인 메일링 리스트와 초기 유즈넷 뉴스그룹과 결합되면서 인터넷상에서 중요 오픈소스 소프트웨어 개발의 문을 열어젖힌 주역들이다.

또한, 이렇게 오픈소스 프로젝트에 참여하는 것이 생각만큼 어렵지 않다는 점을 일반 개발자들이 인지하는 것도 중요하다고 하겠다. 필자 역시 CVS의 사용법을 알기 전에는 내가 CVS의 사용법을 모르는데 오픈소스 프로젝트 참여가 가능하겠는가라는 쓸모없는 생각을 했던 적이 있다. 필자의 경우는 실제 떨어지는 코딩 능력이 오픈소스 프로젝트 참여에 장벽이 되고 있는데 이 글을 읽는 많은 독자들이 이번 연재를 계기로 오픈소스 프로젝트에 좀 더 많이 참여해 보는 기회를 가질 수 있으면 좋겠다는 것이 필자의 바람이다. 단 한 줄의 diff로 만든 패치라도 오픈소스 개발자에게는 많은 도움이 되며 또한 격려의 응원이 된다.