ERITEIA - 협력

2008년 1월 25일 금요일

Ext3 - 저널링 파티션

<번역글 출처 >

저도 원글의 저자와 같은 ext3팬 입니다. 좋아하는 이유는 리눅스 커널에 기본으로 포함됬다는 것과 여러 방면에서 테스트 되어 안정성이 입증되었다는 공통적인 생각을 가지고 있다는 것 입니다. 그리고 오래전 부터 시스템을 새로 구성하거나 하드를 추가할 경우에 이 문서를 봐왔었는데 나름대로 정리하고 싶었고 특히 저의 블로그의 취지가 "협력 - eristeia" 이기도 한 만큼 공유를 하고 싶어서 번역을 시도해 보았습니다. 이 글의 라이선스는 원자의 글에 표시된 GNU Free Documentation License 1.2에 의해서 복사, 수정, 재배포가 가능하겠습니다. :>

1. ext3 만들기

ext3 화일 시스템을 생성하는 것은 아주 간단합니다. 거의 모든 리눅스 배포판의 커널에 기본 포함되어있고 최소한 /boot 시스템은 사용되기 때문에 관련 툴과 메뉴얼을 기본 포함하게 됩니다. 새롭게 fs를 생성하기 위해서는 관리자 권한으로 아래와 같이 명령을 주면 됩니다. 여기서 /dev/hdXY은 Primary Master의 첫번째 파티션인 경우 /dev/hda1 이라고 바꾸면 됩니다. sata의 경우에는 /dev/sda1 등으로 바꿀 수 있습니다.

$ mkfs.ext3 /dev/hdXY

2. Directory Indexing 사용하기

이 부분은 화일 하부 디렉토리 구조가 거대한 경우와 그 디렉토리에 많은 화일 있을 경우에 hashed 이진트리를 이용하여 디렉토리 정보를 구성해 두는 것이다. 상당히 안정화된 상태이며 꼭 화일 규모가 대량이 아닌 경우에도 유용할 수 있을 것임.

$ tune2fs -O dir_index /dev/hdXY

위의 부분은 tune2fs가 실행되 후에 새롭게 생성되는 디렉토리에만 적용된다. 새롭게 fs이 아니라(포맷) 기존에 사용하던 fs에 적용시킬 경우에는 e2fsck 명령을 사용하여 아래의 명령을 수행하여 최적화 및 reindex를 적용할 수 있다.

$ e2fsck -D /dev/hdXY

주: 위 명령은 ext2에도 동일하게 적용 가능한 부분이다. 기존의 화일 시스템 크기에 비례해 시간이 좀 오래 걸릴 수도 있다. 이럴 땐 커피한 잔 하러 가는게 상책!

3. Full Journaling 활성화 하기

기본적으로 ext3 파티션은 'ordered' data mode로 마운트 된다. 이 모드에서는 모든 데이타가 main fs에 쓰이게 되고 메타 데이타는 journal에 집중어서 이론적으로 작업이 그룹으로 나누어지므로 disk I/O 줄어들게 된다. 여기서는 Journaling을 화일과 데이타 자체 모두에 적용하여 성능의 향상과 신뢰성을 동시에 확보할 수 있게된다('Journal' data mode로 알려져있음). 혹자는 모든 정보를 journaling하면 오히려 성능을 떨어 뜨린다고 생각한다. 그 이유인 즉, data가 디스크에 복수 번 기록된다는 것인데 - 처음에는 journal에 다음에는 메인fs에- 이 것 때문에 성능이 떨어지거나 하지는 않는다. 사실 대형 화일을 삭제하는 경우에는 조금 성능이 떨어지기는 하는데 일반적으로 read, write가 많은 실무 컴퓨팅 환경에서는 오히려 성능의 향상으로 더욱 이익이 되지 않을까 싶다.

Journal Data mode를 활성화하는 방법에는 2가지 방법이 있는데, 첫번째는 마운트 옵션에 data=journal 라고 넣으면 된다. 만약 이렇게하여 넣었고 root fs에서 이 마운트를 사용하게 하려면 rooflags = data=journal 를 커널 부트 옵션으로 넣어줘야한다. 두 번째 방법은 rune2fs를 사용하여 파일시스템의 superblock게 기본 마운트 옵션이 들어가게 된다.

$ tune2fs -O has_journal -o journal_data /dev/hdXY

이 방법은 커널 2.4.20이하 버젼에서는 작동하지 않는다. 그리고 아래처럼 저널 싸이즈를 지정함으로서 더욱 세밀한 튜닝을 할 수 있다. 저널이 클 수록 더욱 높은 성능을 발휘할 수 있지만 이럴 경우 disk 공간이 화일이 많으면 많을 수록 공간은 많이 줄어들게 되고 무었보다도 복구하는 경우에 시간과 노력이 더 든다고 할 수 있겠다. 요 옵션을 사용할 경우에는 관련 문서를 참조하실 것!

$ tune2fs -J size=$SIZE /dev/hdXY

4. 부팅 시 정기적인 filesystem 검사 항목 제거하기

리눅스 초보 일 때, 특히 ext fs에 대해서 잘 모를때 가장 귀찮았던 것이 30번 마운트 마다 즉, 부팅시에 도중에 멈출 수도 없는 fs 검사를 강제적으로 한다는 것이였습니다. 물론 리눅스가 서버로 주로 사용되어지기 때문에 마운트 횟수가 그리 많지 않을 수도 있고 특히 갑자기 시스템이 다운되는 경우도 종종 있을 수 있으므로 문제가 누적되어 더 이상 복구가 불가능한 상황에 처하는 것 보다 정기적인 검사를 수행하는 것이 좋을 것 입니다. 하지만 이것도 데스크톱 사용자로서는 참기 정말 힘든 부분이라 할 수 있는데 아래의 명령으로 mount-count와 time-depenedent 를 조절함으로써 이를 피할 수 있습니다. 이 것을 적용하여 부팅하기 전에 /etc/fstab에서 마운트할 root 화일 시스템의 6번째 필드가 (pass)가 되야 합니다.

$ tune2fs -c 0 -i 0 /dev/hdXY

5. 지금까지 적용한 옵션 확인하기

지금까지 따라오면서 적용했던 여러 옵션들이 있을 것 입니다. journaling이나 부팅 검사 항목 등이죠. 이들이 잘 적용되었는지 확인하는 것이 tune2fs 명령을 이용하이 -l 옵션을 주는 것 입니다. 이 옵션을 많은 정보를 출력하는데 block/inode 정보나 fs의 특징, 기본 마운트 옵션을 출력하게 됩니다. 이 출력되는 내용 중에서 우리가 특히 주목할 부분은 dir_index와 has_journal flag가 fs features에 출력되냐는 것과 default mount option에 journal_data 가 출력되느냐 입니다. 아래의 명령으로 확인 하세요.

$ tune2fs -l /dev/hdXY

이제 모든 ext3 journaling 설정이 끝 났습니다. ext3의 파워를 만끽하세요!!

2008년 1월 24일 목요일

루비로 쉘 명령 내리는 방법 6가지

루비를 공부하면서 종종 사용하다보니 이제는 왠만한 것도 다 루비로 하고 싶어졌달까... 예전에는 bash 스크립트로 간단하게 스크립트를 작성하던가 c언어의 execl같은 함수를 썼었는데 루비는 어떻게 할까 궁극해서 rdoc을 뒤지다 안되어 인터넷에서 찾은 방법을 정리하여 보았다.

Exec

irb에서 커널의 exec로 명령을 수행하는 방법


$ irb
>> exec 'echo "hello $HOSTNAME"'
hello nate.local
$

이 방법은 irb가 exec를 통해서 echo프로세스를 전달받아서 수행됨을 알 수 있다.간단하지만결과가성공됐는지아닌지를판별할방법이없다.

System

시스템(system) 명령을 사용하는 것인데 exec와의 차이는 프로세스가 그대로 전달되지 않고 subshell을 통해 수행된다는 점이다. 그래서 결과를 얻을 수 있는데 성공일 경우 true, 아닐때는 false를 반환한다


$ irb
>> system 'echo "hello $HOSTNAME"'
hello nate.local
=> true
>> system 'false'
=> false
>> puts $?
256
=> nil
>>

위에서 system이 전역변수인 $%를 프로세스의 exit상태 값으로 set함을 확인할 수 있다. false 명령의 exit 상태를 확인할 수 있는데(항상 non-zero 값이다) 이렇게 exit값을 확인하므로서 예외 처리가 가능할 수 있겠다.

system은 단지 명령의 성공여부를 알고 싶을 때는 최상이라 말할 수 있겠지만, 어떨때는 표준 출력 내용도 확인할 필요가 있을 텐데 그때는 위의 2 방법은 아니겠다.

Backticks (`)

Backticks (또는 “backquotes”)은 명령을 subshell에서 수행하고 표준 출력을 반환받아 출력한다.


$ irb
>> today = `date`
=> "Mon Mar 12 18:15:35 PDT 2007n"
>> $?
=> #<Process::Status: pid=25827,exited(0)>
>> $?.to_i
=> 0

이 방법은 유닉스에도 가장 많이 쓰이는 방법인데 명령을 subshell에서 수행하여 얻는 출력을 일반 string으로 재사용하기 쉽게할 수 있다. $%을 보면 단순히 상태 값을 반환하는 것은 아니나 실제로 Process::Status 객체임을 알 수 있다. 단순히 exit 상태 값만이 아니라 프로세스 id도 얻을 수 있는 것이다. Process::Status#to_i 는 integer값으로 exit 상태 값을 반환하고, #to_s는 exit상태를 string으로 반환한다. backticks를 사용하면 얻게되는 결과는 단순히 stdout(표준 출력)만이지 stderr는 얻을 수 없다는 것이다. 아래는 perl을 이용하여 string을 stderr로 출력하는 예이다.


$ irb
>> warning = `perl -e "warn 'dust in the wind'"`
dust in the wind at -e line 1.
=> ""
>> puts warning

=> nil

여기서 변수 warning이 set되지 않은 것을 알 수 있는데. 이것은 위에서 perl의 예에서처럼 backticks으로 얻지 못한 stderr 이다.

IO#popen

IO#popen 은 subprocess로 명령을 수행할 수 있는 또 하나의 방법이라 할 수 있겠다. popen은 조금의 추가적인 명령을 더 줄수 있는데 subprocess의 stdin과 stdout가 IO객체와 서로 연결가능하다는 것이다.


$ irb
>> IO.popen("date") { |f| puts f.gets }
Mon Mar 12 18:58:56 PDT 2007
=> nil

IO#popen 가 괜찮긴 하지만 아래에 소개할 Open3#popen3이 더욱 세밀한 제어가 가능할 듯 하다.

Open3#popen3

루비 표준 라이브러리에 포함된 Open3 클래스는 사용이 아주 간단하고 stdin, stdoutstderr을 다 반환한다. 아래의 예에서는 질의식(Interactive) 명령인 dc를 이용한다. dc는 RPN(Reverse Polish Notation) 계산기로 stdin으로 입력을 받는다. 2개의 숫자와 연산자를 스택에 push하고 p 명령을 이용하여 결과를 얻는 예이다.


$ irb
>> stdin, stdout, stderr = Open3.popen3('dc')
=> [#<IO:0x6e5474>, #<IO:0x6e5438>, #<IO:0x6e53d4>]
>> stdin.puts(5)
=> nil
>> stdin.puts(10)
=> nil
>> stdin.puts("+")
=> nil
>> stdin.puts("p")
=> nil
>> stdout.gets
=> "15n"

여기서 우리는 출력을 읽을 수 있는 것만이 아닌 입력을 쓸 수 있음을 알 수 있다. 이렇게 Open3 객체로 유연성 높은 쉘 명령 사용이 가능하겠다. popen3로 stderr도 확인이 가능한데...


# (irb continued...)
>> stdin.puts("asdfasdfasdfasdf")
=> nil
>> stderr.gets
=> "dc: stack emptyn"

다만 1.8.5버젼의 루비에서는 exit 상태 값이 $?로 제대로 반환되지 않는 문제가 있다.


$ irb
>> require "open3"
=> true
>> stdin, stdout, stderr = Open3.popen3('false')
=> [#<IO:0x6f39c0>, #<IO:0x6f3984>, #<IO:0x6f3920>]
>> $?
=> #<Process::Status: pid=26285,exited(0)>
>> $?.to_i
=> 0

0? false는 반드시 non-zero인 exit 상태값을 반환해야한다! 이 결점이 우리를 Open4 객체로 안내한다고 볼 수 있겠다.

Open4#popen4

Open4#popen4 은 루비 젬에서 Ara Howard에 의해 추가됐다. Open3와 동작이 같은데, 단지 exit 상태 값을 반환 받을 수 있다는게 다르다. popen4는 subshell의 프로세스 id를 반환하고 exit 상태 값을 waiting 상태에서 받을 수 있다. (gem install open4 로 설치가 가능)


$ irb
>> require "open4"
=> true
>> pid, stdin, stdout, stderr = Open4::popen4 "false"
=> [26327, #<IO:0x6dff24>, #<IO:0x6dfee8>, #<IO:0x6dfe84>]
>> $?
=> nil
>> pid
=> 26327
>> ignored, status = Process::waitpid2 pid
=> [26327, #<Process::Status: pid=26327,exited(1)>]
>> status.to_i
=> 256

Open4의 좋은 점은 popen4를 하나의 block으로 호출할 수 있고 자동으로 반환 상태를 기다리는 대기가 가능하다는 점이다.


$ irb
>> require "open4"
=> true
>> status = Open4::popen4("false") do |pid, stdin, stdout, stderr|
?> puts "PID #{pid}"
>> end
PID 26598
=> #<Process::Status: pid=26598,exited(1)>
>> puts status
256
=> nil

이상으로 6가지의 쉘 명령 방법을 정리하였는데 명령어의 이름에서도 볼 수 있듯이 일반적인 unix의 명령과 c의 함수와 이름이 유사하여 사용하거나 기억하기 편한 장점과 루비 특유의 순수 객체지향 언어 다움의 간결함으로 앞으로 쉘 스크립트 명령을 사용하는데에 루비의 사용이 많이 증가할 듯 하다는 생각이 든다. 출처 : http://pasadenarb.com/2007/03/ruby-shell-commands.html