split (파일 나누기)

 

1. 형식

split [옵션] [입력 파일[출력 파일]]

 

2. 명령어 위치

/usr/bin/split

 

3. 옵션

-b, --bytes=SIZE : 나누는 단위를 지정한다.

-l, --lines=NUMBER : 지정한 라인 수 만큼 파일을 나눈다.

 

4. 설명

 

하나의 파일을 여러개의 작은 파일로 나눈다. 용량이 큰 파일을 잘게 나누어 플로피 디스켓에 담아 이용할 수 있다. 지정한 입력 파일(파일 이름 대신 -를 입력하면 표준 입력으로부터 입력받음)을 일정 라인마다 잘라서 다른 파일로 저장하며 원 파일은 그대로 있다. 파일을 foobar라로 지정해 두었다면 결과적으로 생기는 출력 파일의 이름은 foobara, foobarb ... 가 되며, 출력 파일을 지정하지 않으면 xaa, xab ... 의 이름을 가지게 된다. split를 실행시키면 기본적으로 1000행의 단위로 파일을 자른다.

 

5. 예제

 

  1) 자를 때


$ split -xxx file_name (-> 파일을 여러단위로 자른다.) 
(--> xaa, xab, xac,... 등의 파일 생성) 

 

$ split -b 1400k file_name (-> 1400k 단위로 파일을 자름) 

  2) 합칠 때


- 각각을 한 디렉토리로 복사한다. 
$ cat x* > file_name 

 

- tar 와 gz로 만들어진 파일일 경우 
$ cat x** > file_name.tar.gz


고급 Linux 커맨드 마스터 가이드, 제 2 부


저자 - Arup Nanda Oracle ACE

게시일: 2007년 2월

이번 시리즈의제 1 부에서는 잘 알려지지 않은 커맨드, 또는 매개변수의 몇 가지 유용한 활용 방법에 대해 소개하였습니다. 이번에는 좀 더 고급 레벨의 커맨드 중에서 오라클 개발자, DBA 들에게 유용한 명령들을 설명하고자 합니다.

alias와 unalias

쉘에서 설정된 ORACLE_SID 환경 변수를 점검해야 하는 경우를 생각해 봅시다. 이때 사용되는 명령이 아래와 같습니다.

echo $ORACLE_HOME

DBA 또는 개발자들은 이 명령을 매우 자주 사용합니다. 하지만 16 자나 되는 커맨드를 매번 입력하는 것이 귀찮은 경우가 많습니다. 좀 더 간단한 방법은 없을까요?

이런 경우에 유용한 것이 alias 커맨드입니다. 예를 들어, 위와 같은 상황에서는 "os"와 같은 짧은 앨리어스를 생성하여 전체 커맨드를 축약할 수 있습니다.

alias os='echo $ORACLE_HOME'

이제 ORACLE_SID를 확인할 때 "os"만 입력하면 Linux가 앨리어스 처리된 커맨드를 실행합니다.

하지만 사용자가 시스템에서 로그아웃 했다가 다시 로그인하면, 앨리어스 설정은 사라지고 다시 alias 명령을 실행해야 합니다. 이 작업을 반복하지 않으려면 쉘의 프로파일 파일에 커맨드를 저장해 두면 됩니다. bash 쉘의 프로파일 파일은 홈 디렉토리에 위치한 .bash_profile입니다(파일 앞에 "." 기호가 있음에 주의하십시오). bourne, korn 쉘의 경우에는 .profile, 그리고 c 쉘의 경우에는 .chsrc입니다.

앨리어스는 어떤 이름으로든 설정할 수 있습니다. 예를 들어 rm이라는 앨리어스에 rm -i 커맨드를 설정하면 rm 커맨드는 항상 인터액티브 방식으로 실행됩니다.

alias rm=’rm -i’

따라서 사용자가 rm 커맨드를 입력할 때마다 Linux는 확인을 요구하며, 사용자가 "y"를 입력하지 않으면 파일을 삭제하지 않기 때문에 실수로 중요한 파일을 삭제하는 경우를 예방할 수 있습니다. 필자는 (새로운 이름으로 파일을 이동하는 명령인) mv 커맨드와 (파일 복제를 위한) cp 커맨드에도 같은 방법을 사용하고 있습니다.

필자가 자주 이용하는 몇 가지 유용한 앨리어스의 목록이 아래와 같습니다:

alias bdump='cd $ORACLE_BASE/admin/$ORACLE_SID/bdump'
alias l='ls -d .* --color=tty'
alias ll='ls -l --color=tty'
alias mv='mv -i'
alias oh='cd $ORACLE_HOME'
alias os='echo $ORACLE_SID'
alias rm='rm -i'
alias tns='cd $ORACLE_HOME/network/admin'

쉘에 어떤 앨리어스가 정의되어 있는지 확인하려면 매개변수 없이 alias를 입력합니다.

하 지만 여기 작은 문제가 있습니다. 앞에서 rm 앨리어스에 rm -i 커맨드를 적용하였습니다. 이 커맨드는 사용자가 파일을 삭제하려 할 때마다 확인 프롬프트를 띄울 것입니다. 그렇다면 확인 과정을 거치지 않고 많은 수의 파일을 삭제하려 한다면 어떻게 해야 할까요?

방법은 간단합니다. 앨리어스를 비활성화하고 커맨드가 직접 실행되도록 하기 위해서는 아래와 같이 커맨드에 작은 따옴표 두 개를 넣어주면 됩니다.

$ ''rm *

앞의 기호가 큰 따옴표(")가 아닌 두 개의 작은 따옴표('')임에 주의하시기 바랍니다. 이와 같은 방법으로 rm 앨리어스를 비활성화할 수 있습니다. 또 다른 방법으로 백슬래쉬를 이용할 수 있습니다.

$ \rm *

앞에서 정의한 앨리어스를 제거하려면 unalias 커맨드를 사용합니다.

$ unalias rm

ls

ls 커맨드는 가장 자주 사용되는 명령의 하나이지만, 그 잠재력이 충분히 활용되는 경우는 드뭅니다. 매개변수를 사용하지 않은 경우, ls 커맨드는 테이블 포맷으로 모든 파일과 디렉토리를 표시합니다.

$ ls
admin has mesg precomp
apex hs mgw racg
assistants install network rdbms
... 뒷부분 생략 ...

리스트 포맷으로 결과를 확인하려면 -1(문자 "l"이 아닌 숫자 1임에 주의합니다) 옵션을 사용합니다.

$ ls -1
admin
apex
assistants
... 뒷부분 생략 ...

이 옵션은 커맨드 실행 결과로부터 값을 추출하여 처리 작업을 수행하는 쉘 스크립트 환경에서 유용하게 활용됩니다.

파일, 디렉토리의 모든 속성을 표시하는 -l (숫자 "1"이 아닌 문자"l") 옵션은 자주 사용해 보셨을 것입니다. 이 옵션에 대해 좀 더 알아 봅시다.

$ ls -l 
total 272
drwxr-xr-x 3 oracle oinstall 4096 Sep 3 03:27 admin
drwxr-x--- 7 oracle oinstall 4096 Sep 3 02:32 apex
drwxr-x--- 7 oracle oinstall 4096 Sep 3 02:29 assistants

첫 번째 컬럼은 파일의 타입과 권한 설정을 표시하고 있습니다. 여기서 "d"는 디렉토리, "-"는 일반 파일, "c"는 캐릭터 디바이스, "b"는 블록 디바이스, "p"는 파이프, "l"(대문자 I가 아닌 소문자 l)은 심볼릭 링크를 의미합니다.

여기서 매우 유용한 옵션의 하나로 --color가 있습니다. 이 옵션은 파일의 유형을 기준으로 색상을 다르게 표시합니다. 스크린샷의 예가 아래와 같습니다:

file1과 file2는 일반 파일입니다. link1은 심볼릭 링크이며 붉은색으로 표시되어 있습니다. dir1은 디렉토리로 노란색으로 표시됩니다. pipe1은 네임드 파이프로 역시 구분이 쉽도록 다른 색으로 표현되고 있습니다.

I 일부 Linux 배포판의 경우 ls 커맨드에 ls --color;와 같은 앨리어스가 기본적으로 적용되어 있기도 합니다. 이러한 접근법은 그리 바람직하지 않습니다. 결과가 위와 같이 표시되는 경우는 더욱 그러합니다. 위 결과의 색상을 변경할 수는 있지만 앨리어스를 비활성화하는 것이 더 빠른 방법일 것입니다.

$ alias ls="''ls"  

또 다른 유용한 옵션으로 -F가 있습니다. 이 매개변수는 각 파일의 타입별로 심볼을 덧붙입니다. 디렉토리에는 "/"가, 심볼릭 링크에는 "@"이, 네임드 파이프에는 "l"이 붙습니다.

$ ls -F
dir1/ file1 file2 link1@ pipe1|

디렉토리 내에 서브디렉토리가 존재하고 이 디렉토리의 구조만을 확인하고자 하는 경우를 생각해 봅시다. ls -l을 사용하면 서브디렉토리의 컨텐트도 함께 표시됩니다. 아래와 같은 디렉토리 구조를 가정해 봅시다.

/dir1
+-->/subdir1
+--> subfile1
+--> subfile2

디렉토리 dir1은 서브디렉토리 subdir1과 두 개의 파일, subfile1과 subfile2를 가집니다. 디렉토리의 속성만을 확인하고자 하는 경우 아래와 같이 실행합니다.

$ ls -l dir1
total 4
drwxr-xr-x 2 oracle oinstall 4096 Oct 14 16:52 subdir1
-rw-r--r-- 1 oracle oinstall 0 Oct 14 16:48 subfile1
-rw-r--r-- 1 oracle oinstall 0 Oct 14 16:48 subfile2

여기에서는 디렉토리 dir1이 표시되지 않고 있습니다. 그 대신 디렉토리의 컨텐트가 표시됩니다. 이러한 결과는 일반적으로 우리가 기대하는 것과는 다릅니다. 디렉토리 dir1만을 조회하고자 할 때에는 -d 커맨드를 사용해야 합니다.

$ ls -dl dir1
drwxr-xr-x 3 oracle oinstall 4096 Oct 14 16:52 dir1

If you notice the output of the following ls -l output:

-rwxr-x--x    1 oracle   oinstall 10457761 Apr  6  2006 rmanO
-rwxr-x--x 1 oracle oinstall 10457761 Sep 23 23:48 rman
-rwsr-s--x 1 oracle oinstall 93300507 Apr 6 2006 oracleO
-rwx------ 1 oracle oinstall 93300507 Sep 23 23:49 oracle

파일의 사이즈는 바이트 단위로 표시되고 있습니다. 파일의 크기가 작을 때에는 문제가 없지만 파일 용량이 큰 경우에는 길게 나열된 숫자를 읽기가 어려울 수 있습니다. 이 경우 "-h" 옵션을 사용하면 보다 읽기 쉬운 포맷으로 파일 사이즈가 표시됩니다.

$ ls -lh

-rwxr-x--x 1 oracle oinstall 10M Apr 6 2006 rmanO
-rwxr-x--x 1 oracle oinstall 10M Sep 23 23:48 rman
-rwsr-s--x 1 oracle oinstall 89M Apr 6 2006 oracleO
-rwx------ 1 oracle oinstall 89M Sep 23 23:49 oracle

위에서 파일 사이즈가 M(메가바이트) 또는 K(킬로바이트)로 표시됨을 확인할 수 있습니다.

$ ls -lr

매개변수 -r은 역순으로 결과를 표시합니다. 아래 커맨드를 실행하면 결과가 알파벳 역순으로 표시됩니다.

$ ls -lR

-R 옵션을 사용하면 ls 커맨드가 재귀적으로 실행되며, 따라서 서브디렉토리와 서브디렉토리의 컨텐트가 함께 표시됩니다.

파일 크기의 순서대로 표시하고 싶다면 어떻게 해야 할까요? 이를 위해 -S 매개변수가 지원되고 있습니다.

$ ls -lS

total 308
-rw-r----- 1 oracle oinstall 52903 Oct 11 18:31 sqlnet.log
-rwxr-xr-x 1 oracle oinstall 9530 Apr 6 2006 root.sh
drwxr-xr-x 2 oracle oinstall 8192 Oct 11 18:14 bin
drwxr-x--- 3 oracle oinstall 8192 Sep 23 23:49 lib

xargs

대부분의 Linux 커맨드는 파일 목록, 문자열 등의 결과를 출력하는 것을 목적으로 실행됩니다. 하지만 앞에서 실행된 결과의 일부를 다른 커맨드의 매개변수로 활용해야 하는 경우가 있습니다. 예를 들어 파일의 유형(실행 파일, ASCII 텍스트 등)을 확인하기 위한 file 커맨드에서 파일네임만을 출력하도록 한 뒤, 이 결과를 ls -l 커맨드에 매개변수로 전달하여 타임스탬프를 확인하고자 하는 상황을 생각해 볼 수 있습니다. xargs 커맨드가 바로 이러한 목적으로 사용됩니다. 이 커맨드를 실행하면 다른 커맨드의 결과를 매개변수로 활용할 수 있습니다. 아래와 같은 명령을 가정해 봅시다.

file -Lz * | grep ASCII | cut -d":" -f1 | xargs ls -ltr
위 커맨드의 문자열을 자세히 분석해 보겠습니다. 먼저, file -Lz *는 파일이 심볼릭 링크인지 또는 압축 파일인지를 확인합니다. 그리고 결과는 다음 커맨드인 grep ASCII 전달됩니다. 여기서 "ASCII" 문자열이 검색되어 아래와 같은 형태의 출력이 생성됩니다.
alert_DBA102.log:        ASCII English text
alert_DBA102.log.Z: ASCII text (compress'd data 16 bits)
dba102_asmb_12307.trc.Z: ASCII English text (compress'd data 16 bits)
dba102_asmb_20653.trc.Z: ASCII English text (compress'd data 16 bits)
여기에서는 파일네임만이 관심 사항이기 때문에 다음 커맨드 cut -d":" -f1을 실행하여 첫 번째 필드만 표시되도록 합니다.
alert_DBA102.log
alert_DBA102.log.Z
dba102_asmb_12307.trc.Z
dba102_asmb_20653.trc.Z

이제 ls -l 커맨드에 한 번에 하나씩 위의 목록을 매개변수로 전달합니다. xargs 커맨드가 바로 이러한 목적으로 사용됩니다. 마지막에서 xargs ls -ltr 명령은 전달된 결과에 대해 ls -ltr을 실행합니다. 결과적으로 아래와 같은 명령이 순차적으로 실행됩니다.

ls -ltr alert_DBA102.log
ls -ltr alert_DBA102.log.Z
ls -ltr dba102_asmb_12307.trc.Z
ls -ltr dba102_asmb_20653.trc.Z

xargs은 독자적으로 사용되는 명령은 아니지만, 다른 커맨드와 조합되었을 때 매우 강력한 기능을 발휘합니다.

또 다른 예로 파일의 라인 수를 카운트하는 경우를 생각해 볼 수 있습니다.

$ file * | grep ASCII | cut -d":" -f1  | xargs wc -l
47853 alert_DBA102.log
19 dba102_cjq0_14493.trc
29053 dba102_mmnl_14497.trc
154 dba102_reco_14491.trc
43 dba102_rvwr_14518.trc
77122 total

(참고: 위와 동일한 작업을 아래 명령을 통해 실행할 수도 있습니다.)

$ wc -l ‘file * | grep ASCII | cut -d":" -f1 | grep ASCII | cut -d":" -f1‘

Linux는 여러 가지 방법으로 동일한 작업을 실행할 수 있도록 지원하고 있습니다. 사용자는 상황에 따라 가장 적절한 방법을 사용하면 됩니다.

같은 방법을 사용하여 디렉토리 내의 여러 파일의 이름을 한꺼번에 변경할 수 있습니다.

$ ls | xargs -t -i mv {} {}.bak

"-i" 옵션은 xargs 커맨드가 "{}" 부분을 각 아이템의 이름으로 대치하도록 지시하고 있습니다. 또 "-t" 옵션은 xargs가 실행 이전에 커맨드를 출력하도록 합니다.

vi를 이용하여 편집할 파일을 여는 과정에서도 활용이 가능합니다.

$ file * | grep ASCII | cut -d":" -f1 | xargs vi

이 커맨드는 vi를 사용하여 파일을 한 번에 하나씩 열도록 지시하고 있습니다. 이 방법은 여러 개의 파일을 검색한 후 편집을 위해 여는 경우 유용합니다.

xargs 커맨드는 다양한 옵션을 지원합니다. 가장 유용한 옵션으로 "-p"를 들 수 있을 것입니다. "-p"는 인터액티브 작업을 위해 사용됩니다.

$ file * | grep ASCII | cut -d":" -f1 | xargs -p vi
vi alert_DBA102.log dba102_cjq0_14493.trc dba102_mmnl_14497.trc
dba102_reco_14491.trc dba102_rvwr_14518.trc ?...

위에서 xarg는 각 커맨드가 실행하기 전에 확인 프롬프트를 띄우고 있습니다. 사용자가 "y"를 누르면 커맨드가 실행됩니다. 파일의 이동, 덮어쓰기 등 잠재적인 위험성을 갖는 작업을 사용하는 경우 이 방법이 매우 유용하게 활용될 수 있을 것입니다.

"t" 옵션은 "verbose" 모드입니다. 실행될 커맨드가 무엇인지 표시하므로 디버깅 과정에서 유용합니다.

xargs 커맨드의 매개변수로 아무런 출력도 입력되지 않는 경우에는 어떻게 될까요? 다음과 같은 경우를 생각해 봅시다.

$ file * | grep SSSSSS | cut -d":" -f1 | xargs -t wc -l
wc -l
0
$
"SSSSSS" 문자열의 검색 결과 매치가 반환되지 않았습니다. 따라서 xargs에는 아무런 입력도 전달되지 않습니다(-t 옵션을 이용해서 이를 확인할 수 있습니다). 경우에 따라서는 처리할 대상이 존재하지 않는 경우 xargs의 실행을 중단해야 할 수도 있습니다. 이를 위해 사용되는 것이 -r 옵션입니다.
$ file * | grep SSSSSS | cut -d":" -f1 | xargs -t -r wc -l
$

이 커맨드는 실행할 대상이 존재하지 않는 경우 종료 처리합니다.

rm 커맨드와 xargs 커맨드를 함께 사용해서 여러 파일을 한꺼번에 삭제하는 경우를 생각해 봅시다. rm이 받아들일 수 있는 매개변수의 수에는 한계가 있습니다. 입력되는 매개변수의 수가 이를 초과하는 경우에는 어떻게 해야 할까요? -n 옵션을 사용하면 xargs에서 사용하는 매개변수의 수를 제한할 수 있습니다.

커맨드 라인 별로 매개변수의 수를 2 개로 제한하는 방법이 아래와 같습니다. 5 개의 파일이 xargs ls -ltr로 전달되었더라도, 2 개의 파일만이 한 번에 ls -ltr로 전달됩니다.

$ file * | grep ASCII | cut -d":" -f1 | xargs -t -n2 ls -ltr  
ls -ltr alert_DBA102.log dba102_cjq0_14493.trc
-rw-r----- 1 oracle dba 738 Aug 10 19:18 dba102_cjq0_14493.trc
-rw-r--r-- 1 oracle dba 2410225 Aug 13 05:31 alert_DBA102.log
ls -ltr dba102_mmnl_14497.trc dba102_reco_14491.trc
-rw-r----- 1 oracle dba 5386163 Aug 10 17:55 dba102_mmnl_14497.trc
-rw-r----- 1 oracle dba 6808 Aug 13 05:21 dba102_reco_14491.trc
ls -ltr dba102_rvwr_14518.trc
-rw-r----- 1 oracle dba 2087 Aug 10 04:30 dba102_rvwr_14518.trc

같은 방법을 사용하여 디렉토리 내의 여러 파일의 이름을 한꺼번에 변경할 수 있습니다.

$ ls | xargs -t -i mv {} {}.bak

"-i" 옵션은 xargs 커맨드가 "{}" 부분을 각 아이템의 이름으로 대치하도록 지시하고 있습니다.

rename

잘 아시는 것처럼 mv 커맨드는 파일의 이름을 변경하는 용도로 사용됩니다. 예를 들어,

$ mv oldname newname
위 명령은 파일네임을 oldname에서 newname으로 변경합니다. 하지만 파일네임을 미리 알고 있지 못한 경우에는 어떻게 해야 할까요? 이 경우 rename 커맨드가 매우 유용하게 활용됩니다.
rename .log .log.‘date +%F-%H:%M:%S‘ *

위 명령은 .log 확장자를 갖는 모든 파일을 .log. 확장자로 변경하도록 지시하고 있습니다. 따라서 sqlnet.log 파일은 sqlnet.log.2006-09-12-23:26:28과 같은 이름으로 변경됩니다.

find

오 라클 사용자들이 가장 자주 사용하는 커맨드 중 하나가 find입니다. 이미 여러분들도 find를 이용하여 디렉토리 내의 파일을 검색하는 방법에 대해 알고 있을 것입니다. 현재 디렉토리에서 "file"이라는 문자열로 시작되는 파일을 검색하는 예가 아래와 같습니다.

$ find . -name "file*"
./file2
./file1
./file3
./file4

만일 FILE1, FILE2와 같은 이름을 검색하려면 어떻게 해야 할까요? 이 경우 -name "file*" 옵션으로는 매치가 불가능합니다. 검색 과정에서 대소문자 구분을 하지 않으려면 -iname 옵션을 사용해야 합니다.

$ find . -iname "file*"
./file2
./file1
./file3
./file4
./FILE1
./FILE2

검색 결과를 특정 유형의 파일로만 제한할 수도 있습니다. 예를 들어, 위 커맨드는 일반 파일, 디렉토리, 심볼릭 링크 등의 모든 파일 유형을 표시합니다. 일반 파일로만 검색을 한정하려는 경우에는 -type f 매개변수를 사용할 수 있습니다.

$ find . -name "orapw*" -type f 
./orapw+ASM
./orapwDBA102
./orapwRMANTEST
./orapwRMANDUP
./orapwTESTAUX

-type에는 f(일반 파일), l(심볼릭 링크), d(디렉토리), b(블록 디바이스), p(네임드 파이프), c(캐릭터 디바이스), s(소켓) 등의 옵션이 지원됩니다.

위 커맨드를 약간 수정해서 제 1 부에서 설명한 file 커맨드와 조합해 보겠습니다. file 커맨드를 사용하면 파일의 유형을 확인할 수 있습니다. 이 명령을 이용하여 find 커맨드의 출력을 후처리해 봅시다. -exec 매개변수는 매개변수 뒤에 위치한 커맨드를 실행합니다. 위의 경우 find를 실행한 후 file를 실행해야 합니다.

$ find . -name "*oraenv*" -type f -exec file {} \;
./coraenv: Bourne shell script text executable
./oraenv: Bourne shell script text executable

위 명령은 ASCII 텍스트 파일이 쉘 스크립트인지의 여부를 확인하려는 경우 유용합니다.

-exec을 -ok로 대체하는 경우에는 커맨드가 실행되기 전에 확인 프롬프트가 표시됩니다. 그 예가 아래와 같습니다.

$ find . -name "sqlplus*" -ok {} \;      
< {} ... ./sqlplus > ? y

SQL*Plus: Release 9.2.0.5.0 - Production on Sun Aug 6 11:28:15 2006

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.

Enter user-name: / as sysdba

Connected to:
Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production

SQL> exit
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production
< È* ... ./sqlplusO > ? n
$
위에서는 쉘에서 "sqlplus"로 시작하는 모든 프로그램을 검색한 후, 검색된 프로그램을 실행하도록 명령하고 있습니다. -ok와 {} 사이에 아무 것도 없기 때문에, 커맨드는 검색된 파일을 그저 실행하기만 합니다. 결과로 두 개의 파일(sqlplus와 sqlplusO)가 검색되었으며, 각 커맨드에 대해 실행 여부를 묻는 프롬프트가 뜹니다. 사용자는 "sqlplus"에 대한 프롬프트에서 "y"를 입력하여 커맨드를 실행하였습니다. 커맨드 실행이 완료되면 두 번째 파일(sqlplusO)의 실행 여부를 묻는 프롬프트가 뜹니다. 여기에서는 "n"을 입력하였으므로 실행되지 않았습니다.

오라클 사용자를 위한 팁

오라클은 트레이스 파일, 로그 파일, 덤프 파일 등의 다양한 파일을 생성, 관리합니다. 이 파일을 정기적으로 삭제하지 않는 경우 파일 시스템의 용량 부족으로 데이터베이스 실행이 중단될 수도 있습니다.

이런 문제를 예방하기 위해, "trc" 확장자를 갖는 파일을 검색한 후 3 일 이상 경과한 파일을 삭제하도록 명령할 수 있습니다. 이를 위한 명령이 아래와 같습니다.

find . -name "*.trc" -ctime +3 -exec rm {} \;

3일 이상 경과한 파일을 강제로 삭제하려면 -f 옵션을 사용합니다.

		
find . -name "*.trc" -ctime +3 -exec rm -f {} \;

아래 명령은 파일의 목록만을 표시합니다.

find . -name "*.trc" -ctime +3 -exec ls -l {} \;

m4

이 커맨드는 입력 파일을 받아들인 뒤 파일 내의 문자열을 매개변수 값으로 대체합니다. 입력 파일의 예가 아래와 같습니다.

$ cat temp
The COLOR fox jumped over the TYPE fence.

여기서 "COLOR"를 "brown"으로, "TYPE"을 "broken"으로 대체해 봅시다.

$ m4 -DCOLOR=brown -DTYPE=broken temp
The brown fox jumped over the broken fence.
또 같은 방법으로 "white", "high" 문자열로 대체해 보겠습니다.

$ m4 -DCOLOR=white -DTYPE=high temp
The white fox jumped over the high fence.

whence와 which

이 두 가지 커맨드는 실행파일이 사용자의 PATH 환경 변수에 저장되어 있는지 확인하기 위해 사용됩니다. 실행 파일이 경로 상에 존재하는 경우, 두 명령은 유사한 결과를 표시합니다.


$ which sqlplus
/u02/app/oracle/products/10.2.0.1/db1/bin/sqlplus
$ whence sqlplus
/u02/app/oracle/products/10.2.0.1/db1/bin/sqlplus

위의 결과는 동일합니다. 하지만 실행 파일이 경로 상에 존재하지 않는 경우에는 출력 결과가 달라집니다. which 커맨드는 메시지를 명시적으로 표시합니다.

$ which sqlplus1
/usr/bin/which: no sqlplus1 in (/u02/app/oracle/products/10.2.0.1/db1/bin:/usr
/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin)

이에 반해 whence 커맨드는 아무런 메시지도 표시하지 않으며,

$ whence sqlplus1]

바로 쉘 프롬프트를 반환합니다. 이 명령은 실행 파일이 경로 상에 존재하지 않는 경우 (메시지를 확인하지 않고) 실행을 바로 취소하고자 하는 경우 유용합니다.

  
$ whence invalid_command
$ which invalid_command
which: no invalid_command in (/usr/kerberos/sbin:/usr/kerberos/bin:/bin:/sbin:
/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:
/usr/bin/X11:/usr/X11R6/bin:/root/bin)

whence 명령은 경로 상에 실행 파일이 검색되지 않은 경우 메시지를 반환하지 않으며, 대신 0이 아닌 리턴 코드를 반환합니다. 쉘 스크립트에서 반환된 리턴 코드를 이용할 수도 있습니다.

RC=‘whence myexec‘
If [ $RC -ne "0" ]; then
echo "myexec is not in the $PATH"
fi

유용한 옵션으로 -i 옵션이 있습니다. 이 옵션은 실행파일과 앨리어스를 함께 표시해 줍니다. 앞에서 rm 커맨드를 앨리어스로 설정한 바 있습니다. 따라서 rm은 커맨드로도, 앨리어스로도 존재합니다.

$ which ls
/bin/ls

$ which -i ls
alias ls='ls --color=tty'
/bin/ls

which 커맨드는 기본적으로 경로 상에서 검색된 첫 번째 실행파일만을 표시합니다. 따라서 경로 상의 다른 디렉토리에 위치한 실행파일은 무시됩니다. -a 옵션을 사용하면 모든 실행파일의 목록을 확인할 수 있습니다.

$ which java   
/usr/bin/java

$ which -a java
/usr/bin/java
/home/oracle/oracle/product/11.1/db_1/jdk/jre/bin/java

top

Linux 데이터베이스를 관리하는 오라클 DBA에게 가장 유용한 커맨드로 top을 꼽을 수 있을 것입니다. 시스템의 성능이 저하되어 어떤 프로세스가 CPU와 메모리를 잡아먹고 있는지 확인해야 하는 경우를 예로 들어 봅시다. 이때 Top 프로세스 리스트를 반환하기 위해 사용되는 명령이 바로 top입니다.

다 른 커맨드들과 달리 top은 결과 출력 후에도 실행을 종료하지 않으며, 스크린 상에 계속적으로 새로운 정보를 뿌립니다. 그러므로 top을 실행한 후 스크린을 그대로 내버려 두면 최신의 정보를 계속 확인할 수 있습니다. 커맨드를 종료하고 쉘로 빠져나가려면 Control-C를 눌러야 합니다.

$ top

18:46:13 up 11 days, 21:50, 5 users, load average: 0.11, 0.19, 0.18
151 processes: 147 sleeping, 4 running, 0 zombie, 0 stopped
CPU states: cpu user nice system irq softirq iowait idle
total 12.5% 0.0% 6.7% 0.0% 0.0% 5.3% 75.2%
Mem: 1026912k av, 999548k used, 27364k free, 0k shrd, 116104k buff
758312k actv, 145904k in_d, 16192k in_c
Swap: 2041192k av, 122224k used, 1918968k free 590140k cached

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND
451 oracle 15 0 6044 4928 4216 S 0.1 0.4 0:20 0 tnslsnr
8991 oracle 15 0 1248 1248 896 R 0.1 0.1 0:00 0 top
1 root 19 0 440 400 372 S 0.0 0.0 0:04 0 init
2 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 keventd
3 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kapmd
4 root 34 19 0 0 0 SWN 0.0 0.0 0:00 0 ksoftirqd/0
7 root 15 0 0 0 0 SW 0.0 0.0 0:01 0 bdflush
5 root 15 0 0 0 0 SW 0.0 0.0 0:33 0 kswapd
6 root 15 0 0 0 0 SW 0.0 0.0 0:14 0 kscand
8 root 15 0 0 0 0 SW 0.0 0.0 0:00 0 kupdated
9 root 25 0 0 0 0 SW 0.0 0.0 0:00 0 mdrecoveryd
... 뒷부분 생략 ...

위의 실행 결과를 자세히 살펴 봅시다. 첫 번째 라인이 아래와 같습니다.

18:46:13  up 11 days, 21:50,  5 users,  load average: 0.11, 0.19, 0.18

여기에서는 현재 시간(18:46:13)과 함께 시스템이 11일간 실행되었으며 21시간 50초에 걸쳐 시스템이 작업을 실행했음을 표시하고 있습니다. 시스템의 부하는 최근 1분, 5분, 15분의 평균(0.11, 0.19, 0.18)으로 표시됩니다. (위의 정보는 uptime 커맨드에서도 확인할 수 있습니다.)

평균 부하 정보가 필요하지 않은 경우라면 "l"을 입력하여 출력을 비활성화할 수 있습니다. 다시 l을 누르면 정보가 표시됩니다. 두 번째 라인은 아래와 같습니다.

151 processes: 147 sleeping, 4 running, 0 zombie, 0 stopped

위에서는 프로세스의 수, 실행 중인 프로세스, 슬립 상태의 프로세스 수가 표시됩니다. 다음은 3 번째, 4 번째 라인입니다.

CPU states:  cpu    user    nice  system    irq  softirq  iowait    idle 
total 12.5% 0.0% 6.7% 0.0% 0.0% 5.3% 75.2%

여기서는 CPU 사용률 정보가 표시되고 있습니다. 위에서는 사용자 프로세스가 12.5%를, 시스템이 6.7%를 사용하고 있음을 확인할 수 있습니다. 오라클 프로세스는 사용자 프로세스에 포함됩니다. "t"를 누르면 위의 라인을 활성화/비활성화할 수 있습니다. CPU가 두 개 이상 존재하는 경우에는, 각 CPU별로 하나의 라인이 표시됩니다.

그 다음 2 개의 라인을 봅시다.

Mem:  1026912k av, 1000688k used,  26224k free,    0k shrd,  113624k buff 
758668k actv, 146872k in_d, 14460k in_c
Swap: 2041192k av, 122476k used, 1918716k free 591776k cached

사용 가능한 메모리와 사용 중인 메모리 용량이 표시되고 있습니다. 전체 메모리는 "1026912k av", 약 1GB이며 이중 26224k(26MB)가 여유 상태입니다. 스왑 공간은 2GB이지만 거의 사용되지 않고 있습니다. 이 부분을 비활성화/활성화하려면 "m"을 누릅니다.

출력의 나머지 부분은 프로세스를 테이블 형태로 표시하고 있습니다. 각 컬럼에 대한 설명이 아래와 같습니다.

컬럼 설명
PID 프로세스의 프로세스 ID
USER 프로세스를 실행 중인 사용자
PRI 프로세스의 우선순위
NI nice 값: 값이 높을 수록 태스크의 우선순위가 낮음을 의미
SIZE 프로세스가 사용하는 메모리 (코드+데이터+스택)
RSS 프로세스가 사용하는 물리적 메모리
SHARE 프로세스가 사용하는 공유 메모리
STAT

프로세스의 상태 정보로 다음과 같은 코드로 표시됨:
R – Running
S –Sleeping
Z – Zombie
T – Stopped

또는 다음과 같은 문자가 함께 표시될 수도 있음:
W – Swapped out process
N – positive nice value
%CPU 프로세스의 CPU 사용률
%MEM 프로세스의 메모리 사용률
TIME 프로세스가 사용하는 전체 CPU 타임
CPU 멀티-프로세서 시스템의 경우 이 컬럼은 프로세스가 실행 중인 CPU의 ID를 의미함
COMMAND 프로세스가 실행한 커맨드

top 명령이 실행되는 동안 키를 눌러 디스플레이 포맷을 변경할 수도 있습니다. 대문자 M 키를 누르면 출력이 메모리 사용률 순서로 정렬됩니다. (소문자 m을 누르면 메모리 사용량 요약 라인이 비활성화됨을 참고하시기 바랍니다.) 이 명령은 어떤 프로세스가 메모리를 가장 많이 사용하고 있는지 확인할 때 유용합니다. 출력 예가 아래와 같습니다:

PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND 
31903 oracle 15 0 75760 72M 72508 S 0.0 7.2 0:01 0 ora_smon_PRODB2
31909 oracle 15 0 68944 66M 64572 S 0.0 6.6 0:03 0 ora_mmon_PRODB2
31897 oracle 15 0 53788 49M 48652 S 0.0 4.9 0:00 0 ora_dbw0_PRODB2

지금까지 출력 결과를 분석해 보았습니다. 이제 커맨드 라인 매개변수를 이용하는 방법을 알아 봅시다.

가장 유용한 매개변수인 -d는 스크린 리프레시 간격을 조정합니다. 1 초 단위로 화면을 갱신하려면 top -d 1을 입력합니다.

그 밖에 유용한 옵션으로 -p가 있습니다. 이 옵션은 몇 가지 프로세스에 대해서만 모니터링을 수행하고자 하는 경우 사용합니다. 13609, 13608, 13554 프로세스를 모니터링하는 방법이 다음과 같습니다.

top -p 13609 -p 13608 -p 13554

이 명령은 지정된 프로세스에 대해서만 top 커맨드를 실행합니다.

오라클 사용자를 위한 팁

top 유틸리티가 데이터베이스 서버의 성능 분석을 위해 매우 유용하게 활용된다는 사실은 굳이 강조할 필요도 없을 것입니다. top 커맨드 실행 결과의 일부가 아래와 같습니다.

20:51:14  up 11 days, 23:55,  4 users,  load average: 0.88, 0.39, 0.27 
113 processes: 110 sleeping, 2 running, 1 zombie, 0 stopped
CPU states: cpu user nice system irq softirq iowait idle
total 1.0% 0.0% 5.6% 2.2% 0.0% 91.2% 0.0%
Mem: 1026912k av, 1008832k used, 18080k free, 0k shrd, 30064k buff
771512k actv, 141348k in_d, 13308k in_c
Swap: 2041192k av, 66776k used, 1974416k free 812652k cached

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND
16143 oracle 15 0 39280 32M 26608 D 4.0 3.2 0:02 0 oraclePRODB2...
5 root 15 0 0 0 0 SW 1.6 0.0 0:33 0 kswapd
... 뒷부분 생략 ...

위 결과를 자세히 분석해 봅시다. 먼저 CPU states 항목의 "idle" 컬럼을 주목하십시오. 0.0%로 표시되고 있습니다. 이는 CPU가 100% 사용 중임을 의미합니다. 그렇다면 어떤 작업에 CPU가 사용되고 있는지 궁금해 하는 것이 당연합니다. 왼쪽의 "system" 컬럼을 보면 5.6%로 표시되고 있습니다. 따라서 시스템 자체적으로는 많은 작업을 실행하고 있지 않습니다. 좀 더 왼쪽의 "user" 컬럼은 1.0%로 표시되고 있습니다. 여기서 사용자 프로세스에는 오라클이 포함됩니다. 따라서 오라클이 CPU 사이클을 많이 소모하지 않고 있음을 알 수 있습니다. 그렇다면 CPU 사용의 주범은 무엇일까요?

그 해답을 같은 라인에서 확인할 수 있습니다. "iowait" 컬럼 하단의 오른쪽을 보면 91.2%가 표시되고 있습니다. 이제 답이 나왔습니다. CPU는 전체 시간 중 91.2%를 IO를 대기하는데 소비하고 있는 것입니다.

그 렇다면 IO wait가 이처럼 높은 이유는 무엇일까요? 그 해답도 확인할 수 있습니다. 바로 가장 많은 CPU를 사용하는 프로세스의 PID입니다: 16143. 아래 쿼리를 실행하여 프로세스가 어떤 작업을 실행 중인지 확인할 수 있습니다.

select s.sid, s.username, s.program
from v$session s, v$process p
where spid = 16143
and p.addr = s.paddr
/

SID USERNAME PROGRAM
------------------- -----------------------------
159 SYS rman@prolin2 (TNS V1-V3)

바로 rman 프로세스가 많은 IO wait를 발생시키고 있습니다. 이 분석 결과를 바탕으로 후속 조치를 취할 수 있을 것입니다.

skill과 snice

앞 에서 CPU를 가장 많이 사용하는 리소스를 확인하는 방법에 대해 배워 보았습니다. 프로세스가 많은 CPU와 메모리를 사용하고 있지만 이 프로세스를 kill하기를 원치 않는 경우에는 어떻게 해야 할까요? 아래와 같은 top 출력 결과를 생각해 봅시다.

$ top -c -p 16514

23:00:44 up 12 days, 2:04, 4 users, load average: 0.47, 0.35, 0.31
1 processes: 1 sleeping, 0 running, 0 zombie, 0 stopped
CPU states: cpu user nice system irq softirq iowait idle
total 0.0% 0.6% 8.7% 2.2% 0.0% 88.3% 0.0%
Mem: 1026912k av, 1010476k used, 16436k free, 0k shrd, 52128k buff
766724k actv, 143128k in_d, 14264k in_c
Swap: 2041192k av, 83160k used, 1958032k free 799432k cached

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND
16514 oracle 19 4 28796 26M 20252 D N 7.0 2.5 0:03 0 oraclePRODB2...

프로세스 16514가 가장 많은 메모리를 사용하고 있음을 확인했다면 skill 커맨드를 사용해서 이 프로세스를 죽이는(kill) 대신 얼려버릴(freeze) 수 있습니다.

$ skill -STOP 1

그런 다음 top을 다시 실행해 봅시다.

23:01:11  up 12 days,  2:05,  4 users,  load average: 1.20, 0.54, 0.38 
1 processes: 0 sleeping, 0 running, 0 zombie, 1 stopped
CPU states: cpu user nice system irq softirq iowait idle
total 2.3% 0.0% 0.3% 0.0% 0.0% 2.3% 94.8%
Mem: 1026912k av, 1008756k used, 18156k free, 0k shrd, 3976k buff
770024k actv, 143496k in_d, 12876k in_c
Swap: 2041192k av, 83152k used, 1958040k free 851200k cached

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND
16514 oracle 19 4 28796 26M 20252 T N 0.0 2.5 0:04 0 oraclePRODB2...

CPU는 94%에서 0%로 떨어졌습니다. 프로세스의 실행이 실질적으로 동결된 것입니다. 사용자는 나중에 원하는 시점에 이 프로세스를 다시 깨울 수 있습니다.

$ skill -CONT 16514

이 방법은 다른 중요한 프로세스의 실행을 위해 프로세스를 임시로 중단하려는 경우 매우 유용합니다.

커맨드의 활용 방법은 매우 다양합니다. "oracle" 사용자의 모든 프로세스를 중단하는 방법이 아래와 같습니다.

$ skill -STOP oracle

사용자 이외에도 커맨드, 터미널 ID 등의 정보를 매개변수로 사용할 수 있습니다. 아래 명령은 모든 rman 커맨드의 실행을 중단합니다.

$ skill -STOP rman

skill은 입력된 매개변수가 프로세스 ID인지, 사용자 아이디인지, 커맨드인지를 자체적으로 파악한 후 그에 따라 행동을 취합니다. 이러한 동작 방식이 때로는 문제가 될 수도 있습니다. 예를 들어 사용자와 커맨드가 동일한 이름을 갖는 경우를 생각해 볼 수 있습니다. 그 대표적인 예가 "oracle" 사용자에 의해 실행되는 "oracle" 프로세스입니다. 따라서 "oracle"이라는 이름의 프로세스 실행을 중단하기 위해 아래와 같이 입력한 경우,

$ skill -STOP oracle

"oracle" 사용자의 모든 프로세스와 세션도 함께 중단됩니다. 이러한 불확실성을 해소하려면 매개변수의 유형을 별도로 지정해 주어야 합니다. 예를 들어 "oracle"이라는 이름의 커맨드 실행을 중단하기 위한 명령이 아래와 같습니다.

$ skill -STOP -c oracle

snice 커맨드의 실행 방법도 위와 유사합니다. 이 커맨드는 프로세스를 중단하는 대신 프로세스의 우선순위를 낮춥니다. 먼저, top 실행 결과를 점검해 봅시다.

  PID USER     PRI  NI  SIZE  RSS SHARE STAT %CPU %MEM   TIME CPU COMMAND 
3 root 15 0 0 0 0 RW 0.0 0.0 0:00 0 kapmd
13680 oracle 15 0 11336 10M 8820 T 0.0 1.0 0:00 0 oracle
13683 oracle 15 0 9972 9608 7788 T 0.0 0.9 0:00 0 oracle
13686 oracle 15 0 9860 9496 7676 T 0.0 0.9 0:00 0 oracle
13689 oracle 15 0 10004 9640 7820 T 0.0 0.9 0:00 0 oracle
13695 oracle 15 0 9984 9620 7800 T 0.0 0.9 0:00 0 oracle
13698 oracle 15 0 10064 9700 7884 T 0.0 0.9 0:00 0 oracle
13701 oracle 15 0 22204 21M 16940 T 0.0 2.1 0:00 0 oracle

이제 "oracle" 프로세스의 우선순위를 4 단계 낮춥니다. 여기서는 숫자가 높을 수록 우선순위가 낮음을 의미합니다.

$ snice +4 -u oracle

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME CPU COMMAND
16894 oracle 20 4 38904 32M 26248 D N 5.5 3.2 0:01 0 oracle

NI 컬럼(nice 값)이 4, priority가 15에서 4로 변경되었음을 확인할 수 있습니다.


Arup Nanda (arup@proligence.com )는 12 년 이상의 경력을 보유한 오라클 DBA로, 성능 튜닝, 보안, 재해 복구 등 다방면에 걸친 데이터베이스 운영 경험을 가지고 있습니다. 그는 의 공저자이며, 오라클 매거진에 의해 2003년 올해의 DBA로 선정되었으며, 현재 Oracle ACE 자격을 보유하고 있습니다.

[출처] http://www.oracle.com/technology/global/kr/pub/articles/advanced-linux-commands/part2.html

'LinuX' 카테고리의 다른 글

[Linux] sar 명령어를 통한 시스템 모니터링  (0) 2015.02.12
split 명령어  (0) 2014.10.13
고급 Linux 커맨드 마스터 가이드  (0) 2009.06.23
Linux find 명령어 완전 정복 가이드  (0) 2009.06.18
klogin과 rlogin  (0) 2009.06.08

고급 Linux 커맨드 마스터 가이드


저자 – Arup Nanda Oracle ACE

게시일: 2006년 8월

쉐릴 칼리시가 Linux 입문자들을 위해 기고한 “Linux 파일 커맨드 마스터 가이드(한글)"를 통해 일반적으로 자주 사용되는 Linux 커맨드에 대해 설명 드린 바 있습니다. 이제 기본을 마스터하였다면, 다음 단계로 넘어가 좀 더 복잡하지만 활용도가 높은 커맨드들에 배워 볼 차례입니다.

4 부에 걸쳐 연재되는 이번 시리즈에서는, 여러분이 알고 있는 커맨드들의 잘 알려지지 않은 사용법에 대해 소개하고 커맨드의 활용도를 높이기 위한 여러 가지 변칙적인 용례들을 설명합니다. 또 연재가 진행되면서 좀 더 난이도가 높은 커맨드들에 대해 배우실 수 있을 것입니다.

여기에서 소개되는 커맨드들이 Linux 버전 또는 커널 버전에 따라 차이가 있을 수 있음을 참고하시기 바랍니다(하지만 그 차이는 미미한 수준입니다).

오너, 그룹, 권한의 변경

쉐릴의 아티클에서 chown, chgrp 커맨드를 이용하여 파일의 오너십과 그룹을 변경하는 방법을 이미 설명하였습니다. 아래와 같은 파일이 있다고 가정해 봅시다.

# ls -l
total 8
-rw-r--r-- 1 ananda users 70 Aug 4 04:02 file1
-rwxr-xr-x 1 oracle dba 132 Aug 4 04:02 file2
-rwxr-xr-x 1 oracle dba 132 Aug 4 04:02 file3
-rwxr-xr-x 1 oracle dba 132 Aug 4 04:02 file4
-rwxr-xr-x 1 oracle dba 132 Aug 4 04:02 file5
-rwxr-xr-x 1 oracle dba 132 Aug 4 04:02 file6

이제 모든 파일의 권한을 첫 번째 파일과 동일하게 변경해야 합니다. 물론 “chmod 644 *”를 실행하면 간단하게 해결이 가능합니다. 하지만 스크립트를 작성하면서 첫 번째 파일의 권한을 모르고 있는 경우라면 어떻게 해야 할까요? 또 여러 번의 권한 변경 작업을 반복적으로 수행해야 하는 상황에서, 각각의 파일 권한을 일일이 확인하기 어려운 경우에는 어떻게 할 수 있을까요?

이런 경우 파일의 권한을 다른 파일과 동일하게 설정하는 명령을 활용할 수 있습니다. 아래 커맨드는 파일2의 권한을 파일 1과 동일하게 설정합니다.

chmod --reference file1 file2 

이제 설정된 권한을 확인해 보면 아래와 같이 나타납니다.

# ls -l file[12]
total 8
-rw-r--r-- 1 ananda users 70 Aug 4 04:02 file1
-rw-r--r-- 1 oracle dba 132 Aug 4 04:02 file2

파일 2의 권한이 파일 1와 같게 변경되었습니다. 파일 1의 권한을 먼저 확인할 필요는 없었습니다.

같은 방법을 파일의 그룹 멤버십 설정에 이용할 수도 있습니다. 파일 2의 그룹을 파일 1과 동일하게 설정하기 위한 명령이 아래와 같습니다:

# chgrp --reference file1 file2
# ls -l file[12]
-rw-r--r-- 1 ananda users 70 Aug 4 04:02 file1
-rw-r--r-- 1 oracle users 132 Aug 4 04:02 file2

물론 오너십의 설정에도 같은 방법을 적용할 수 있습니다. 오너십을 변경하는 방법이 아래와 같습니다. 권한이 아래와 같이 설정되어 있는 경우,

# ls -l file[12] 
-rw-r--r-- 1 ananda users 70 Aug 4 04:02 file1
-rw-r--r-- 1 oracle dba 132 Aug 4 04:02 file2

오너십을 아래와 같은 방법으로 변경할 수 있습니다.

# chown --reference file1 file2
# ls -l file[12]
-rw-r--r-- 1 ananda users 70 Aug 4 04:02 file1
-rw-r--r-- 1 ananda users 132 Aug 4 04:02 file2

위의 경우 그룹과 오너가 함께 변경되었습니다.

오라클 사용자를 위한 팁

이 방법을 사용하여 특정 실행 파일을 기준으로 디렉토리 내의 전체 오라클 실행 파일에 설정된 오너십과 권한을 일괄 변경하는 것이 가능합니다. 이 방법은 다른 사용자 계정으로 마이그레이션하거나 기존에 설치된 환경을 다른 오라클 소프트웨어 소유자에게 할당할 때 유용하게 활용됩니다.

기타 파일 관련 커맨드

ls 명령과 매개변수를 이용하여 파일에 관련한 매우 유용한 정보들을 확인할 수 있습니다. stat 커맨드는 ls보다 덜 알려지긴 했지만, 더욱 유용한 정보들을 제공합니다.

stat 커맨드를 이용해서 $ORACLE_HOME/bin 디렉토리에 위치한 “oracle” 실행 파일의 정보를 확인하는 방법이 아래와 같습니다.

# cd $ORACLE_HOME/bin
# stat oracle
File: `oracle'
Size: 93300148 Blocks: 182424 IO Block: 4096 Regular File
Device: 343h/835d Inode: 12009652 Links: 1
Access: (6751/-rwsr-s--x) Uid: ( 500/ oracle) Gid: ( 500/ dba)
Access: 2006-08-04 04:30:52.000000000 -0400
Modify: 2005-11-02 11:49:47.000000000 -0500
Change: 2005-11-02 11:55:24.000000000 -0500

위 커맨드를 통해 출력된 정보를 눈 여겨 보시기 바랍니다. (ls -l을 통해서도 얻을 수 있는) 파일 사이즈 정보와 별도로, 파일이 점유하고 있는 블록의 수가 표시되고 있습니다. 일반적으로 Linux의 블록 사이즈는 512 바이트입니다. 따라서 93,300,148 바이트는 (93300148/512=) 182226.85 개의 블록을 점유합니다. 블록은 한꺼번에 채워지므로, 이 파일은 이렇게 계산한 결과와 근사한 수의 블록을 사용하고 있을 가능성이 높습니다. 하지만 이렇게 추측을 하는 대신, stat 커맨드를 이용해서 정확한 블록 수를 산정할 수 있습니다.

또 위의 실행 결과에서 파일 오너십의 GID, UID와 권한의 8진법 표현(6751)을 확인할 수 있습니다. 나중에 파일의 권한을 현재의 상태로 되돌리고 싶으면, 명시적으로 권한을 표시하는 대신 “chmod 6751 oracle ”과 같이 명령을 실행할 수 있습니다.

위의 출력 결과에서 가장 유용한 부분이 바로 파일 액세스 타임스탬프 정보입니다. 위에서는 파일이 2006-08-04 04:30:52(“Access”의 오른쪽 부분), 즉 2006년 8월 4일 오전 4:30:52에 마지막으로 액세스되었음을 알 수 있습니다. 이 값은 사용자가 데이터베이스에 최초 접근한 시점을 의미합니다. 파일은 2005-11-02 11:49:47(Modify의 오른쪽)에 수정되었습니다. 마지막으로 “Change” 옆의 타임스탬프는 파일의 상태가 변경된 시점을 의미합니다.

stat 커맨드의 –f 옵션은 파일이 아닌 파일 시스템의 정보를 표시하라는 의미를 갖습니다:

# stat -f oracle
File: "oracle"
ID: 0 Namelen: 255 Type: ext2/ext3
Blocks: Total: 24033242 Free: 15419301 Available: 14198462 Size: 4096
Inodes: Total: 12222464 Free: 12093976

–t는 동일한 정보를 하나의 라인으로 표시하는 옵션입니다.

# stat -t oracle 
oracle 93300148 182424 8de9 500 500 343 12009652 1 0 0 1154682061
1130950187 1130950524 4096

이 옵션은 커맨드 실행 결과로부터 값을 추출하여 처리 작업을 수행하는 쉘 스크립트 환경에서 유용하게 활용됩니다.

오라클 사용자를 위한 팁

오라클을 ”relink”하는 경우 (이 작업은 패치 설치 과정에서 자주 발생합니다), 오라클은 새로운 실행 파일을 생성하기 전에 기존의 실행 파일을 다른 이름으로 저장합니다. 예를 들어 아래 명령을 이용하여 전체 유틸리티를 relink 할 수 있습니다.

relink utilities

위 명령을 수행하면 sqlplus 실행 파일이 다른 유틸리티와 함께 재컴파일 됩니다. 기존의 sqlplus 실행 파일은 sqlplusO라는 이름으로 저장됩니다. 재컴파일 작업이 실패하는 경우, relink 프로세스는 sqlplusO의 파일 이름을 다시 sqlplus로 변경함으로써 기존 상태를 복구합니다. 또 패치 적용 후 문제가 발견된 경우, 직접 기존 파일의 이름을 다시 변경하는 방법으로 상태를 원상 복귀시킬 수 있습니다.

이 파일에 stat 명령을 실행한 결과입니다:

# stat sqlplus*
File: 'sqlplus'
Size: 9865 Blocks: 26 IO Block: 4096 Regular File
Device: 343h/835d Inode: 9126079 Links: 1
Access: (0751/-rwxr-x--x) Uid: ( 500/ oracle) Gid: ( 500/ dba)
Access: 2006-08-04 05:15:18.000000000 -0400
Modify: 2006-08-04 05:15:18.000000000 -0400
Change: 2006-08-04 05:15:18.000000000 -0400

File: 'sqlplusO'
Size: 8851 Blocks: 24 IO Block: 4096 Regular File
Device: 343h/835d Inode: 9125991 Links: 1
Access: (0751/-rwxr-x--x) Uid: ( 500/ oracle) Gid: ( 500/ dba)
Access: 2006-08-04 05:13:57.000000000 -0400
Modify: 2005-11-02 11:50:46.000000000 -0500
Change: 2005-11-02 11:55:24.000000000 -0500

sqlplusO가 2005년 11월 11일에 수정된 반면 sqlplus는 2006년 8월 4일에 수정되었음을 확인할 수 있습니다. 이 결과는 sqlplusO의 상태가 마지막으로 변경된 시점과도 일치합니다. 따라서 sqlplus의 기존 버전이 2005년 11월 11일에서 2006년 8월 4일까지 사용되었음을 알 수 있습니다. 기능적인 문제의 원인을 해명하고자 한다면, 이 데이터가 좋은 참고가 될 수 있습니다. 또 파일 변경 시점과 권한 변경 시점을 함께 연계하여 문제 해결 작업에서 참고할 수 있습니다.

위 실행 결과에서 또 한 가지 중요한 점은 두 파일의 사이즈가 다르다는 사실입니다(sqlplus는 9865 바이트인 반면 sqlplusO는 8851 바이트입니다). 그러므로 파일이 단순히 재컴파일된 것이 아니며 새로운 라이브러리가 추가되었을 가능성이 높다고 추측할 수 있습니다. 또는 현재 겪고 있는 문제의 원인이 여기에 숨어 있을 수도 있습니다.

파일 타입

파일이 어떤 타입인지 확인하려면 어떻게 해야 할까요? 이를 위해 사용되는 명령이 바로 file 커맨드입니다. 실행 예가 아래와 같습니다:

# file alert_DBA102.log
alert_DBA102.log: ASCII text

alert_DBA102.log는 ASCII 텍스트 파일임을 알 수 있습니다. 다른 예를 살펴 봅시다:

# file initTESTAUX.ora.Z
initTESTAUX.ora.Z: compress'd data 16 bits

파일이 압축된 파일임을 알 수 있습니다. 하지만 압축된 파일 안에 어떤 타입의 파일이 포함되어 있는지 어떻게 알 수 있을까요? 물론 파일의 압축을 풀고 다시 file 커맨드를 실행하면 되겠지만, 이는 결코 효율적인 방법이 아닙니다. 훨씬 간단한 방법으로 –z 옵션을 사용할 수 있습니다.

# file -z initTESTAUX.ora.Z
initTESTAUX.ora.Z: ASCII text (compress'd data 16 bits)

또 문제가 될 수 있는 예로 심볼릭 링크(symbolic link)를 들 수 있습니다:

# file spfile+ASM.ora.ORIGINAL   
spfile+ASM.ora.ORIGINAL: symbolic link to
/u02/app/oracle/admin/DBA102/pfile/spfile+ASM.ora.ORIGINAL

물론 위 출력만으로도 유용한 정보입니다. 하지만 링크가 가리키는 파일의 유형은 어떻게 확인할까요? file 명령을 반복해서 수행하는 대신, -l 옵션을 사용하면 됩니다.

# file -L spfile+ASM.ora.ORIGINAL
spfile+ASM.ora.ORIGINAL: data

파일이 데이터 파일임을 쉽게 확인할 수 있습니다. init.ora와 달리 spfile은 바이너리 파일이며 따라서 데이터 파일로 표시됨을 참고하시기 바랍니다.

오라클 사용자를 위한 팁

사용자 덤프 디렉토리에 위치한 트레이스 파일을 찾고 있지만, 파일이 실제로는 다른 디렉토리에 위치하고 있고 이 디렉토리에는 심볼릭 링크만이 존재할 수 있습니다. 또는다른 사용자가 파일을 압축하거나 이름을 변경했을 수도 있습니다. 우리가 분명하게 아는 사실은 단 한 가지뿐, 즉 이 파일이 아스키 파일이라는 사실입니다. 이런 경우라면 아래와 같은 명령을 활용할 수 있습니다.

file -Lz * | grep ASCII | cut -d":" -f1 | xargs ls -ltr

이 커맨드는 디렉토리에 있는 ASCII 파일을 점검하고, 파일이 압축된 경우에도 시간 순서대로 정렬하여 표시합니다.

파일의 비교

서로 다른 두 개의 파일이 동일한 내용임을 어떻게 확인할 수 있을까요? 여러 가지 방법이 가능하며, 각각 나름의 장단점이 있습니다.

diff. 가장 간단한 커맨드인 diff는 두 파일 간의 차이를 비교하여 보여 줍니다. 두 파일의 내용이 아래와 같습니다:

# cat file1
In file1 only
In file1 and file2
# cat file2
In file1 and file2
In file2 only

diff 커맨드를 사용하면 아래와 같이 두 파일의 차이를 확인할 수 있습니다

# diff file1 file2
1d0
< In file1 only
2a2
> In file2 only
#

첫 번째 라인의 "<" 기호는 해당 라인이 첫 번째 파일, 즉 file1에만 존재함을 의미합니다. 마찬가지로 “>” 기호는 해당 라인이 두 번째 파일(file2)에만 존재함을 의미합니다. 출력 결과의 첫 번째 라인에서 문자 1d0은 file1을 file2와 동일하게 만들기 위해 sed 유틸리티에서 사용하는 옵션을 의미합니다.

-y 옵션을 사용하면 결과를 나란히 비교할 수 있습니다:

# diff -y file1 file2 -W 120
In file1 only <
In file1 and file2 In file1 and file2
> In file2 only

-W 옵션은 출력 결과의 길이를 지정합니다. 위에서는 120 문자 길이의 화면을 사용하도록 지정하고 있습니다.

파일이 같은지 다른지의 여부만을 확인하고 싶다면 –q 옵션을 사용합니다.

# diff -q file3 file4
# diff -q file3 file2
Files file3 and file2 differ

file3과 file4의 내용은 동일하므로 아무 결과도 출력되지 않습니다. –q 옵션은 파일의 내용이 서로 다른 경우에만 결과를 보고합니다.

쉘 스크립트를 작성하는 경우에는, 파싱이 가능한 형태로 결과를 출력하는 것이 유용할 수 있습니다. 이런 경우라면 -u 옵션이 유용하게 활용됩니다:

# diff -u file1 file2        
--- file1 2006-08-04 08:29:37.000000000 -0400
+++ file2 2006-08-04 08:29:42.000000000 -0400
@@ -1,2 +1,2 @@
-In file1 only
In file1 and file2
+In file2 only

위의 결과는 두 가지 파일의 컨텐트를 비교하면서 중복되지 않은 컬럼에 대해서만 +, - 기호를 사용하여 비교하고 있습니다. 앞 컬럼에 아무 기호도 표시되지 않은 라인은 해당 컨텐트가 두 파일에 모두 존재함을 의미합니다.

이 커맨드는 공백 기호도 함께 비교합니다. 공백 기호를 무시하고 싶다면 –b 옵션을 사용합니다. 빈 라인을 무시하려면 –B 옵션을 사용합니다. 마지막으로 대소문자 구분을 무시하려면 –i 옵션을 사용합니다.

diff 커맨드를 디렉토리 비교를 위해 사용할 수도 있습니다. 아래 명령을 실행하면,

diff dir1 dir2

양쪽 디렉토리 모두, 또는 한 쪽 디렉토리에만 포함된 파일이 구분되어 표시됩니다. 동일한 이름의 서브디렉토리가 발견되는 경우, 서브디렉토리에 포함된 파일은 비교하지 않습니다. 실행 예가 아래와 같습니다:

# diff DBA102 PROPRD     
Common subdirectories: DBA102/adump and PROPRD/adump
Only in DBA102: afiedt.buf
Only in PROPRD: archive
Only in PROPRD: BACKUP
Only in PROPRD: BACKUP1
Only in PROPRD: BACKUP2
Only in PROPRD: BACKUP3
Only in PROPRD: BACKUP4
Only in PROPRD: BACKUP5
Only in PROPRD: BACKUP6
Only in PROPRD: BACKUP7
Only in PROPRD: BACKUP8
Only in PROPRD: BACKUP9
Common subdirectories: DBA102/bdump and PROPRD/bdump
Common subdirectories: DBA102/cdump and PROPRD/cdump
Only in PROPRD: CreateDBCatalog.log
Only in PROPRD: CreateDBCatalog.sql
Only in PROPRD: CreateDBFiles.log
Only in PROPRD: CreateDBFiles.sql
Only in PROPRD: CreateDB.log
Only in PROPRD: CreateDB.sql
Only in DBA102: dpdump
Only in PROPRD: emRepository.sql
Only in PROPRD: init.ora
Only in PROPRD: JServer.sql
Only in PROPRD: log
Only in DBA102: oradata
Only in DBA102: pfile
Only in PROPRD: postDBCreation.sql
Only in PROPRD: RMANTEST.sh
Only in PROPRD: RMANTEST.sql
Common subdirectories: DBA102/scripts and PROPRD/scripts
Only in PROPRD: sqlPlusHelp.log
Common subdirectories: DBA102/udump and PROPRD/udump

위 결과에서 공통되는 서브디렉토리를 보고하고 있지만, 서브디렉토리의 비교는 수행되지 않고 있음을 참고하십시오. 서브디렉토리 레벨까지 파일을 비교하려면 아래와 같이 커맨드를 실행합니다:

diff -r dir1 dir2

이 커맨드는 재귀적인 방법을 각각의 서브디렉토리를 비교하고, 동일한 이름을 갖는 파일들의 차이를 보고합니다.

오라클 사용자를 위한 팁

오라클 환경에서 diff 커맨드를 활용하는 대표적인 예로 서로 다른 init.ora 파일 간의 차이를 비교하는 경우를 들 수 있습니다. 필자는 안전을 보장 위해 init.ora 파일을 변경하지 전에 항상 파일을 다른 이름으로 복사해 둡니다. (예: initDBA102.ora를 initDBA102.080306.ora로 변경하여 2006년 8월 3일 변경한 내용임을 명시해 둡니다.) 이렇게 저장된 여러 버전의 파일에 대해 diff 커맨드를 실행하여 어떤 내용이 언제 변경되었는지 확인할 수 있습니다.

diff는 오라클 Home 관리를 위한 매우 유용한 커맨드로 활용됩니다. 필자는 패치를 적용할 때 Oracle Home을 업데이트하지 않는 원칙을 세우고 있습니다. 예를 들어, 현재 오라클 버전이 10.2.0.1이라 가정해 보겠습니다. ORACLE_HOME은 /u01/app/oracle/product/10.2/db1으로 설정되어 있습니다. 여기에 10.2.0.2 버전의 패치를 적용할 때, 필자는 Oracle Home에 패치를 적용하지 않습니다. 그 대신 /u01/app/oracle/product/10.2/db2 디렉토리를 새로 구성하고 이 디렉토리에 패치를 적용합니다. 그런 다음, 아래와 같이 실행합니다:

# sqlplus / as sysdba
SQL> shutdown immediate
SQL> exit
# export ORACLE_HOME=/u01/app/oracle/product/10.2/db2
# export PATH=$ORACLE_HOME/bin:$PATH
# sqlplus / as sysdba
SQL> @$ORACLE_HOME/rdbms/admin/catalog
...

and so on.

이 방법은 기존의 Oracle Home을 건드리지 않고, 나중에 문제가 생기더라도 쉽게 환경을 복구할 수 있다는 장점이 있습니다. 또 데이터베이스의 셧다운, 재시작 과정이 매우 신속하게 진행된다는 부가적 이점이 있습니다. Oracle Home에 패치를 직접 적용하는 경우라면, 패치 애플리케이션이 실행되는 동안 데이터베이스를 내내 셧다운 상태로 유지해야 할 것입니다. 또 패치 애플리케이션이 어떤 이유로든 정상적으로 동작하지 않는다면, 온전한 Oracle Home을 다시 구성하기 어려울 것입니다.

이렇게 해서 여러 개의 Oracle Home이 만들어졌다고 가정해 봅시다. 변경된 내용을 어떻게 확인할 수 있을까요? 그 방법은 아주 간단합니다:

diff -r /u01/app/oracle/product/10.2/db1 /u01/app/oracle/product/10.2/db2 | 
grep -v Common

위 명령은 두 Oracle Home 간의 차이를 비교하고, 동일한 이름을 갖는 파일 간의 차이를 비교합니다. tnsnames.ora, listener.ora, sqlnet.ora와 같은 중요한 파일에 변경된 사항이 많다면, 그 이유가 무엇인지 확인해 보아야 합니다.

cmp. cmp 커맨드는 diff와 유사합니다.

# cmp file1 file2   
file1 file2 differ: byte 10, line 1

diff 커맨드는 두 파일에서 차이가 발생하는 첫 번째 위치를 반환합니다. 이 커맨드를 이용하여 파일의 내용이 다른 위치를 분석할 수 있습니다. cmp 와 마찬가지로 diff에도 다양한 옵션이 제공됩니다. 그 중 가장 중요한 옵션인 -s는 아래와 같은 코드를 반환합니다:

  • 0 – 두 파일이 동일한 경우
  • 1 – 두 파이에 차이가 존재하는 경우
  • 다른 숫자 – 비교 작업이 수행될 수 없는 경우

실행 예가 아래와 같습니다:

# cmp -s file3 file4
# echo $?
0

특수 변수 $?는 마지막으로 실행된 커맨드에서 반환된 코드를 의미합니다. 위의 경우 0이 반환되었으며, 결국 file1과 file2가 동일함을 알 수 있습니다.

# cmp -s file1 file2
# echo $?
1

위 결과는 file1과 file2가 서로 다름을 의미합니다.

cmp 커맨드의 -s 옵션은 두 파일에 차이가 있는지의 여부만을 검사하는 스크립트에서 매우 유용합니다. 또 cmp 커맨드는 바이너리 파일을 비교하는 경우에도 사용됩니다. diff는 바이너리 파일에 대해 안정적으로 동작하지 않습니다.

오라클 사용자를 위한 팁

앞에서 설명한, 오라클 실행 파일의 relink 작업 과정에서 이전 버전의 파일을 별도 저장하는 방법에 대한 팁을 상기하시기 바랍니다. relink를 수행하는 과정에서, sqlplus 실행 파일의 이름은 “sqlplusO”로 변경되고 새로 컴파일된 sqlplus가 $ORACLE_HOME/bi에 저장됩니다. 그렇다면 새로 생성된 sqlplus가 이전 버전과 어떤 차이를 갖는지 어떻게 비교할 수 있을까요? 아래와 같이 실행하면 됩니다:

# cmp sqlplus sqlplusO
sqlplus sqlplusO differ: byte 657, line 7

이번에는 파일의 크기를 비교해 봅시다.

# ls -l sqlplus*
-rwxr-x--x 1 oracle dba 8851 Aug 4 05:15 sqlplus
-rwxr-x--x 1 oracle dba 8851 Nov 2 2005 sqlplusO

파일의 크기가 같음에도 불구하고 두 프로그램의 내용이 다르다는 사실을 cmp 커맨드로 확인할 수 있었습니다.

comm.comm 커맨드는 앞의 두 가지와 유사하지만, 결과가 탭으로 구분된 3 개의 컬럼으로 표시된다는 차이를 갖습니다. 실행 예가 아래와 같습니다:

# comm file1 file2
In file1 and file2
In file1 only
In file1 and file2
In file2 only

설명된 커맨드의 요약


커맨드 사용법

chmod

파일의 권한을 변경 (- -참조 매개변수 사용)

chown

파일의 소유자를 변경 (- -참조 매개변수 사용)

chgrp

파일의 그룹을 변경 (- -참조 매개변수 사용)

stat

파일의 세부적인 속성 확인 (예: 마지막 접근한 날짜)

file

파일의 타입 확인 (ASCII, 데이터 등)

diff

두 파일 간의 차이 확인

cmp

두 파일의 비교

comm

두 파일의 차이를 비교하고 그 결과를 3 개의 컬럼에 표시

md5sum

파일의 MD5 체크섬을 계산하고, 파일이 변경되었는지의 여부를 확인

이 커맨드는 다른 파일에 존재하지 않고 특정 파일에만 존재하는 컨텐트를 직접 확인하고자 하는 경우에 유용합니다(이런 점에서 SQL 언어의 MINUS 유틸리티와 유사합니다). -1옵션을 사용하면 첫 번째 파일에서만 확인되는 컨텐트가 표시되지 않게끔 할 수 있습니다:

# comm -1 file1 file2
In file1 and file2
In file2 only

md5sum. 이 커맨드는 파일의 32비트 MD5 해쉬 값을 생성합니다:

# md5sum file1
ef929460b3731851259137194fe5ac47 file1

동일한 체크섬(checksum)을 갖는 파일은 동일하다고 인정됩니다. 이 커맨드는 파일 간의 비교만을 위해 사용되는 것이 아닙니다. md5sum 커맨드는 파일의 무결성을 보장하기 위한 메커니즘을 제공하기도 합니다.

보호 대상에 포함되는 두 개의 중요한 파일(file1과 file2)이 있다고 가정해 봅시다. --check 옵션을 사용하면 파일이 변경되지 않았음을 확인할 수 있습니다. 먼저 두 파일의 체크섬을 생성하여 안전한 장소에 보관합니다:

# md5sum file1 file2 > f1f2 

나중에 파일이 변경되지 않았음을 확인하려면 아래와 같이 실행합니다:

# md5sum --check f1f2      
file1: OK
file2: OK

파일이 변경되지 않았음을 분명히 확인할 수 있습니다. 이제 파일 하나를 변경한 뒤 다시 MD5 해쉬 값을 비교해 봅시다:

# cp file2 file1
# md5sum --check f1f2
file1: FAILED
file2: OK
md5sum: WARNING: 1 of 2 computed checksums did NOT match

file1이 변경되었음을 분명히 확인할 수 있습니다..

오라클 사용자를 위한 팁

md5sum는 보안 구현 과정에서 매우 유용하게 활용됩니다. listener.ora, tnsnames.ora, init.ora와 같은 설정 파일은 오라클 인프라스트럭처에서 매우 중요하며, 잘못 변경된 경우 다운타임을 초래할 수 있습니다. 따라서 변경 관리 프로세스에 이 파일들을 포함시키는 것이 일반적인 관행입니다. 다른 사용자의 말만 믿고 이 파일이 변경되지 않은 것으로 간주하는 대신, MD5 체크섬을 사용하여 변경 여부를 검증할 수 있습니다. 변경 작업을 수행하거나 파일을 재생성해야 하는 경우, 항상 사전에 체크섬을 생성해 둡니다. 그리고 md5sum 커맨드를 이용하여 파일을 정기적으로 점검합니다. 다른 사용자가 실수로 이 파일들을 변경한 경우에도, 변경 내역을 즉각적으로 감지할 수 있습니다.

또 $ORACLE_HOME/bin 디렉토리에 존재하는 모든 실행 파일에 대해 MD5 체크섬을 생성하고 정기적으로 비교하여 불법적인 변경 작업이 발생하지 않았는지 확인할 수 있습니다.

결론

지금까지 여러분의 작업 효율성을 개선하는데 도움이 될 만한 몇 가지 Linux 커맨드를 소개 드렸습니다. 다음 연재에서는 strace, whereis, renice, skill 등 조금 더 복잡하지만 유용한 커맨드들을 소개하도록 하겠습니다.


Arup Nanda (arup@proligence.com )는 12 년 이상의 경력을 보유한 오라클 DBA로, 성능 튜닝, 보안, 재해 복구 등 다방면에 걸친 데이터베이스 운영 경험을 가지고 있습니다. 그는 PL/SQL for DBAs (O'Reilly Media, 2005)>의 공저자이며, 2003년에는 오라클 매거진의 “올해의 DBA” 상을 수상하였습니다. 또 Oracle ACE 자격증을 보유하고 있습니다.


[출처] http://www.oracle.com/technology/global/kr/pub/articles/advanced-linux-commands/part1.html

'LinuX' 카테고리의 다른 글

split 명령어  (0) 2014.10.13
고급 Linux 커맨드 마스터 가이드, 제 2 부  (0) 2009.06.23
Linux find 명령어 완전 정복 가이드  (0) 2009.06.18
klogin과 rlogin  (0) 2009.06.08
linux 파티션 나누기  (0) 2009.05.08

저자 - Sheryl Calish

가장 강력하면서도 한편으로는 혼란스러운 유비쿼터스 명령어인 find 명령어에 대한 개요.

게시일 : 2008년 7월

Linux find 명령어는 모든 Linux 명령어 가운데 가장 유용하면서도 혼란스러운 명령어 가운데 하나입니다. 다른 Linux 명령어의 표준 구문과 다른 구문을 가지고 있다는 점에서 어렵습니다. 하지만, 파일명, 파일 유형, 사용자, 더 나아가 타임 스탬프 별로 파일을 찾을 수 있다는 점에서 강력한 명령어이기도 합니다. find 명령어를 사용하면 이러한 속성을 자유롭게 조합해 파일의 위치를 찾을 수 있을 뿐만 아니라, 찾은 파일에 대해 연산을 수행할 수 있습니다.

본 글의 목적은 find 명령어와 그 잠재적 이점을 개략적으로 설명함으로써 find 명령어를 손쉽게 학습 및 사용할 수 있도록 돕는 것입니다. 동시에, find 명령어의 특성 중 가장 강력하면서도 한편으로는 혼란스러운 측면에 대한 개요 및 참조를 제공할 것입니다.

[주: 여기에서 사용된 find 명령어는 GNU 버전이기 때문에 일부 세부 내용은 다른 버전의 find 명령어와 다를 수 있습니다.]

기본 형식

먼저, find 명령어의 기본 구조부터 살펴보겠습니다:

find   start_directory  test  options   criteria_to_match
action_to_perform_on_results
                       
아래 명령어에서 find는 이름에 “java” 확장자를 가지고 있는 모든 파일을 대상으로 “.”가 표시된 현재 디렉토리를 찾기 시작할 것입니다:
find . -name  "*.java"   

아래에는 검색 결과에 대한 간단한 목록이 나열되어 있습니다:

find . -name  "*.java"
./REGEXPvalidate/src/oracle/otnsamples/plsql/ConnectionManager.java
./REGEXPvalidate/src/oracle/otnsamples/plsql/DBManager.java
..

[주: 본 글에서 잘라 붙이기를 해 find 명령어를 실행하는 경우에는 자체 키보드를 사용해 큰따옴표(“”)를 바꿔야 올바른 결과를 얻을 수 있습니다.]

아 래 명령어 역시 동일한 연산을 수행할 것입니다. 어떤 경우든, find 명령어에 전달되도록 escape 문을 통해 와일드카드 문자를 일반 문자로 처리해야 하며 쉘에 의해 해석되지 않아야 합니다. 따라서, 검색 문자열에 큰타옴표를 붙이거나 그 앞에 역슬래시(\)를 붙이십시오:

find . -name  \*.java

find 에 대한 인수는 옵션이기는 하지만, 검색 시작 위치를 지정하지 않은 경우에는 현재 디렉토리에서 기본적으로 검색이 시작됩니다. 옵션 사항이기는 하지만 테스트 조건을 지정하지 않은 경우에는 불완전하거나 선별되지 않은 결과값이 출력됩니다.
 
아래 3개의 find 명령어를 실행하면 똑같이 현재 디렉토리와 숨겨진 파일을 포함하는 모든 서브디렉토리의 모든 파일 목록이 검색됩니다:

find 
find .
find . -print

이는 –la 옵션을 가진 ls 명령어를 실행하는 것과 비슷합니다. 백업을 위해 위 명령어의 출력물에 전체 경로 이름이 포함되기를 원하는 경우라면 시작 디렉토리에 대한 전체 경로를 지정해야 합니다:

find /home/bluher -name \*.java
/home/bluher/plsql/REGEXPvalidate/src/oracle/otnsamples/plsql/ConnectionManager.java
/home/bluher/plsql/REGEXPvalidate/src/oracle/otnsamples/plsql/DBManager.java/
...

또 한, 검색 문자열에 1개 이상의 시작 디렉토리를 지정할 수도 있습니다. 적정 권한을 가진 사용자로서 실행되는 경우, 아래 명령어는 모든 jar 파일을 찾기 위해 /usr, /home 및 /tmp 디렉토리 순서로 내려갈 것입니다:  

find /usr /home  /tmp -name "*.jar"

적정 권한이 없는 사용자라면 많은 시스템 디렉토리를 검색하기 시작할 때 다음과 같은 오류 메시지가 나올 수 있습니다:

find:  /tmp/orbit-root: Permission denied

다음과 같이 검색 문자열을 추가함으로써 불명확한 결과가 나오는 것을 피할 수 있습니다:

find /usr /home  /tmp -name "*.jar" 2>/dev/null

이렇게 하면 모든 오류 메시지가 널(null) 파일로 전송되기 때문에 보다 정제된 출력물이 제공됩니다.

기본적으로 find 명령어는 대/소문자를 구별합니다. 대/소문자가 구별되는 find에서는 -name 테스트를 대신해 -iname 테스트를 사용하십시오.

find downloads  -iname "*.gif"
downloads/.xvpics/Calendar05_enlarged.gif
downloads/lcmgcfexsmall.GIF
또한, 파일명 외에도 유형에 따라 파일을 검색할 수 있습니다. 예를 들어, 아래 명령어를 통해 디렉토리의 모든 서브디렉토리를 찾을 수 있습니다:
find . -type d          

아래 명령어를 사용하면 /usr 디렉토리의 모든 심볼릭 링크(symbolic link)를 찾을 수 있습니다:

find /usr -type l

위 명령어를 실행하면 3,000개 이상의 링크 목록이 나타날 것입니다. 슈퍼유저(root) 권한을 통해 아래 명령어 가운데 하나를 실행하면 /usr 디렉토리의 링크 목록과 이것이 가리키는 파일이 나타납니다:

# find /usr/bin  -type l  -name "z*" -exec ls  -l {} \;
lrwxrwxrwx 1 root root 8 Dec 12 23:17 /usr/bin/zsh -> /bin/zsh
lrwxrwxrwx 1 root root 5 Dec 12 23:17 /usr/bin/zless -> zmore
lrwxrwxrwx 1 root root 9 Dec 12 23:17 /usr/bin/zcat -> /bin/zcat
find /usr/bin -type  l  -name "z*" -ls

하지만, 보다 짧은 두 번째 명령어를 실행하면 디렉토리와 inode 정보를 가진 긴 파일 목록이 나올 것입니다. -exec 및 –ls 실행에 대해서는 후반부에서 다룰 것입니다

find가 찾을 수 있는 다른 파일 유형으로는 다음과 같은 것들이 있습니다

• b—block (buffered) special
• c—character (unbuffered) special
• p—named pipe (FIFO)
• s—socket

find 명령어의 시작점으로 루트를 사용하면 시스템 속도가 크게 느려질 수 있습니다. 반드시 명령어를 실행해야 하는 경우에는 사용량이 적은 시간대나 야간에 실행하는 것이 좋습니다. 아래 구문을 사용해 출력물을 파일로 보낼 수 있습니다.:

find  /   -print > masterfilelist.out

원치 않는 출력물을 대량 생산하는 find 명령어를 실수로 입력한 경우에는 CTRL-C를 누르기만 하면 가장 최근에 실행된 명령어가 중단됩니다.

여 러 파일 시스템을 갖춘 엔터프라이즈 네트워크에서는 특히 find 명령어가 검색한 파일을 제한하는 것이 좋습니다. 필요한 수 만큼 옵션 및 테스트를 사용함으로써 시스템 상의 로드를 줄일 수 있습니다. 이를 위해 가장 유용하게 사용할 수 있는 옵션은 –xdev와 -mount입니다. 이들 옵션은 find 명령어가 MS-DOS, CD-ROM 또는 AFS와 같은 다른 파일 시스템 상의 디렉토리로 내려가지 않도록 함으로써 검색 범위를 좁혀줍니다. 따라서, 시작 디렉토리와 동일한 유형의 파일 시스템으로 검색을 제한할 수 있습니다.

듀얼 부팅 시스템 사용자는 mount 명령어가 실행되는 경우에 이러한 옵션을 사용할 수 있습니다. Windows 파티션이 관련되어 있다고 가정하면, 아래와 같은 명령어를 통해 마운팅 할 수 있습니다.:

mount -t vfat  /dev/sda1 /mnt/msdos

여러분이 사용하는 실제 명령어는 시스템 설정 방법에 따라 달라집니다. df를 실행하거나 아래 명령어를 수행함으로써 파티션 마운팅 여부를 확인할 수 있습니다:

find /mnt/msdos  -name "*.txt" 2> /dev/null

MS Windows 파티션에서는 파일 목록이 길 수 밖에 없습니다. 이제부터는 -mount 또는 -xdev 옵션을 통해 아래 명령어를 실행하십시오:

find / -name  "*.txt" -mount 2> /dev/null

또는

find / -name  "*.txt" -xdev 2> /dev/null

아래 예에서와 같이 -fstype 테스트를 사용해 find 명령어에 찾고자 하는 파일 시스템을 명확하게 알려줄 수도 있습니다:

find / -name  "*.txt" -fstype vfat 2> /dev/null

시간 찾기

find 명령어는 시스템의 타임 스탬프를 토대로 파일 검색에 사용할 수 있는 여러 개의 옵션을 가지고 있습니다. 이러한 타임 스탬프로는 다음이 포함됩니다

mtime파일 내용이 마지막으로 수정된 시간
atime—파일을 읽기 또는 액세스한 시간
ctime—파일 상태가 변경된 시간

mtime 및 atime의 의미는 그 자체로 쉽게 알 수 있지만, ctime는 좀 더 설명이 필요합니다. inode는 각 파일에 메타 데이터를 가지고 있기 때문에 파일에 연결된 메타 데이터가 변경되면 inode 데이터도 변경됩니다. 파일에 대한 심볼릭 링크 생성, 파일에 대한 권한 변경, 파일 이동 등과 같은 다양한 작업으로 인해 이러한 메타 데이터 변경이 야기될 수 있습니다. 이러한 경우, 파일 내용에 대한 읽기나 수정은 수행되지 않기 때문에 themtime 및 atime은 변하지 않지만 ctime은 변합니다. 

이러한 시간 옵션은 각기 -n, n 또는 +n로 지정된 n 값을 함께 사용해야 합니다.

• -n은 n 이하를 반환
• +n은 n 이상을 반환
• n은 정확히 n에 해당되는 값을 반환

보다 명확한 설명을 위해 몇 가지 예를 살펴 보겠습니다. 아래 명령어는 최근 1시간 동안 수정된 모든 파일을 찾아줍니다:

find . -mtime -1
./plsql/FORALLSample
./plsql/RegExpDNASample
/plsql/RegExpSample

-1 대신 1을 가진 동일 명령어를 실행하면 정확하게 1시간 전에 수정된 모든 파일을 찾을 수 있습니다:

find . -mtime 1 

위 명령어는 정확하게 일치하는 값을 요청하기 때문에 모든 결과값이 나오지는 않습니다. 아래 명령어는 1시간 이전에 수정된 파일을 찾아줍니다:

find . -mtime +1 
기본적으로 -mtime, -atime 및 –ctime는 최근 24 시간에 대한 타임 스탬프입니다. 하지만, 뒤에 daystart 옵션을 붙이면 오늘을 시작으로 24시간 주기가 시작됩니다. 또한, mmin, amin 및 cmin을 사용하면 분 단위로 변경된 타임 스탬프를 찾을 수 있습니다.

여러분의 계정으로 로그인한 후 즉시 아래 명령어를 실행하면 최근 1분 내에 읽은 모든 파일을 찾을 수 있습니다:

find . -amin -1
./.bashrc
/.bash_history
./.xauthj5FCx1

find 명령어만으로 파일의 위치를 찾으면 메타 데이터의 일부인 파일의 액세스 시간이 변경된다는 사실에 유의하십시오.

-newer, -anewer 및 –cnewer 옵션을 사용하면 특정 파일과 비교해 수정 또는 액세스된 파일을 찾을 수도 있습니다. 이는 -mtime, -atime 및 –ctime과 비슷합니다.
 
• -newer : 보다 최근에 내용이 수정된 파일
• -anewer : 보다 최근에 읽기가 수행된 파일
• -cnewer : 보다 최근에 상태가 변경된 파일

마지막 tar 파일 이후로 어떤 방법으로든지 수정된 홈 디렉토리의 파일을 모두 찾으려면 아래 명령어를 사용하십시오:

find . -newer  backup.tar.gz

크기에 따른 파일 찾기

-size 옵션은 지정된 크기 기준에 부합하는 파일을 찾아줍니다. 크기가 5MB 이상인 모든 파일을 찾으려면 아래와 같이 하십시오

find / -size  +5000000c 2> /dev/null
/var/log/lastlog
/var/log/cups/access_log.4
/var/spool/mail/bluher

마 지막에 “c”를 붙이면 결과가 바이트 단위로 보고됩니다. 기본적으로 find 명령어는 512 바이트 블록의 수로 크기를 보고합니다. 또한, “c”를 “k”로 교체하는 경우에는 킬로바이트 수로, “w”를 사용하는 경우에는 2바이트 워드의 수로 결과를 표시할 수 있습니다.

-size 옵션은 모든 제로 바이트 파일을 찾거나 이들 파일을 /tmp/zerobyte 폴더로 이동하기 위해 자주 사용됩니다. 아래 명령어가 바로 이러한 연산을 수행합니다.

find test -type f  -size 0 -exec mv {} /tmp/zerobyte \;

-exec 옵션은 find 명령어가 만나게 되는 파일의 모든 쉘 명령어를 수행할 수 있도록 해줍니다. 후반부에서 이 옵션의 보다 다양한 사용 예를 확인할 수 있습니다. 중괄호를 사용하면 빈 파일 각각을 이동시킬 수 있습니다

또한, -empty 옵션을 사용하면 빈 파일을 찾을 수 있습니다.

find test -empty        
test/foo
test/test

권한 및 소유권에 따른 파일 찾기

find 명령어는 시스템 보안 모니터링을 위해 없어서는 안될 명령어입니다. 아래와 같이 기호법이나 8진법을 통해 사용 권한이 널리 열려있는 파일을 찾을 수 있습니다.

find . -type f  -perm a=rwx -exec ls -l {} \; 

또는

find . -type f  -perm 777 -exec ls -l {} \;
-rwxrwxrwx 1 bluher users 0 May 24 14:14 ./test.txt

위의 명령어나 아래 명령어의 경우 -exec ls –l을 수행하고 있기 때문에, 반환된 파일의 실제 사용 권한을 확인할 수 있습니다. 이 명령어는 “기타 사용자” 및 그룹이 모두 쓰기를 수행할 수 있는 파일을 찾아줍니다.

find plsql -type f  -perm -ug=rw -exec ls -l {} \; 2>/dev/null

또는

find plsql -type f  -perm -220 -exec ls -l {} \; 2>/dev/null 
-rw-rw-rw- 1 bluher users 4303 Jun  7  2004 plsql/FORALLSample/doc/otn_new.css
-rw-rw-rw- 1 bluher users 10286 Jan 12  2005 plsql/FORALLSample/doc/readme.html
-rw-rw-rw- 1 bluher users 22647 Jan 12  2005 plsql/FORALLSample/src/config.sql
..
아래 명령어들을 실행하면 사용자, 그룹 또는 둘 모두가 쓰기 작업을 할 수 있는 파일을 찾을 수 있습니다  
find plsql -type f  -perm /ug=rw -exec ls -l {} \; 2>/dev/null, or,
find plsql -type f -perm /220 -exec ls -l {} \; 2>/dev/null
-rw-r--r-- 1 bluher users 21473 May  3 16:02 plsql/regexpvalidate.zip
-rw-rw-rw- 1 bluher users 4303 Jun  7  2004 plsql/FORALLSample/doc/otn_new.css
-rw-rw-rw- 1 bluher users 10286 Jan 12  2005 plsql/FORALLSample/doc/readme.html
-rw-rw-rw- 1 bluher users 22647 Jan 12  2005 plsql/FORALLSample/src/config.sql

웹이나 기존 매뉴얼에는 아래 명령어로 나와 있을 것입니다.

find . -perm +220  -exec ls -l {} \; 2> /dev/null 

+ 기호는 / 기호와 동일한 역할을 하지만, 새로운 버전의 GNU findutils에서는 권장되지 않고 있습니다.

시스템에서 쓰기 가능한 모든 파일을 찾으려면 아래 명령어를 사용하십시오

find / -wholename  '/proc' -prune  -o  -type f -perm -0002 -exec ls -l {} \;
-rw-rw-rw- 1 bluher users 4303 Jun  7  2004/home/bluher/plsql/FORALLSample/doc/otn_new.css
-rw-rw-rw- 1 bluher users 10286 Jan 12  2005 /home/bluher/plsql/FORALLSample/doc/readme.html
...

4 번째 사용 권한에 대해 앞으로 조금 더 다루겠지만, 마지막 필드의 “2”는 쓰기 비트로도 알려져 있는 파일 사용 권한의 “기타 사용자”에 해당됩니다. 우리는 설정된 다른 사용 권한이 무엇이든 관계 없이 기타 사용자를 위해 설정된 쓰기 권한을 가진 파일을 보고 싶다는 표시로 0002라는 사용 권한 모드 앞에 대시를 사용했습니다.

위의 명령어에서는 3가지 새로운 개념이 도입되었습니다. 패턴이 발견된 경우, – prune은 파일 패턴 “/proc”에서 -wholename 테스트를 사용함으로써 find 명령어가 이 디렉토리로 내려오지 않도록 막아줍니다. 불린 연산자 “-o”를 통해 find 명령어는 다른 디렉토리에서 명령어의 나머지 부분을 처리할 수 있습니다. 각 표현식 간에 가정된 암시적 and 연산자(-a)가 있기 때문에 좌측 표현식이 거짓(false)으로 평가된 경우 and 뒤에 나오는 표현식은 평가되지 않습니다. 따라서, -o 연산자가 필요합니다. 강제 우선 순위 적용을 위해 괄호를 사용하는 것처럼 find 명령어는 불린 연산자 -not, !,도 지원합니다.

시스템 관리자는 자주 find 명령어를 통해 해당 사용자나 그룹의 이름 또는 ID를 사용해 특정 사용자나 그룹의 정규 파일을 검색하고 있습니다:

[root] $  find / -type f -user bluher -exec ls -ls {}  \;

여기, 이러한 명령어의 출력에 대한 간단한 예제가 나와 있습니다:

4 -rw-r--r-- 1 bluher users 48  May  1 03:09  /home/bluher/public_html/.directory
4 -rw-r--r-- 1 bluher users 925 May  1 03:09 /home/bluher/.profile

또한, find 명령어를 사용해 그룹 별로 파일을 검색할 수도 있습니다:

[root] $ find /  -type f -group users
find / -type d -gid  100

이 명령어를 실행하면 그룹 ID 100이 소유하고 있는 디렉토리 목록이 나옵니다. 해당되는 uid 또는 gid를 찾기 위해 /etc/passwd 또는 /etc/group 파일에서 more 또는 cat 명령어를 실행할 수 있습니다

이 명령어는 알려진 특정 사용자 및 그룹에 관한 파일을 찾는 것 외에도 사용자나 그룹이 지정되지 않은 파일을 찾는 데도 유용합니다. 아래 명령어는 /etc/passwd 또는 /etc/group 파일에서 리스트를 가지고 있지 않은 파일을 식별합니다.

find / -nouser -o  -nogroup

위 명령어는 실제로 시스템 상에 결과를 제공하는 것은 아니지만, 파일을 이동한 후에 사용자나 그룹이 지정되지 않은 파일을 식별하는 데 사용할 수 있습니다

이제, 본 섹션 초반부에 언급한 별도의 높은 사용 권한 문제를 해결할 수 있게 되었습니다.

SGID 및 SUID는 UNIX 기반 운영 체제 상의 파일 및 디렉토리에 할당할 수 있는 특별 액세스 권한 플래그입니다. 컴퓨터 시스템 액세스에 있어 일반 권한을 가진 사용자가 일시적으로 높아진 권한을 가지고 바이너리 실행 파일을 수행할 수 있습니다.

find /  \( -perm -2000 -o -perm -4000 \) -ls
167901   12 -rwsr-xr-x   1 root     root         9340 Jun 16  2006 /usr/bin/rsh
167334   12 -rwxr-sr-x   1 root     tty         10532 May  4  2007 /usr/bin/wall

위 명령어에서 괄호가 escape 처리된 것을 볼 수 있습니다. 또한, 권한 간의 차이점을 확인할 수 있습니다. 첫 번째 파일에는 SGID 권한이 설정되어 있으며 두 번째 파일에는 SUID 권한이 설정되어 있습니다. 위 명령어의 마지막 연산은 -exec ls -dils 연산의 find 명령어와 유사합니다

find 명령어 제어

Linux 의 많은 명령어와 달리, find 명령어는 -r 또는 -R 옵션이 없이도 서브디렉토리로 내려가지 않습니다. 이는 기본적으로 지원됩니다. 하지만, 때에 따라 이를 제한하고 싶을 수 있습니다. 이럴 경우, -depth, -maxdepth 및 –mindepth 옵션과 –prune 연산이 유용합니다

-prune이 얼마나 유용한지는 이미 확인했기 때문에 이제는 -depth, -maxdepth 및 -mindepth 옵션에 대해 살펴보겠습니다.

-maxdepth 및 -mindepth 옵션을 사용하면 find 명령어를 통해 검색하고자 하는 디렉토리 트리의 수준을 지정할 수 있습니다. find 명령어가 단 한 수준의 디렉토리를 찾도록 하고 싶은 경우에는 maxdepth 옵션을 사용할 수 있습니다.

아래 명령어를 실행해 디렉토리 트리의 상위 3개 수준의 로그 파일을 검색하면 –maxdepth의 효과를 확인할 수 있습니다. 이렇게 하면 –maxdepth 없이 실행할 때 보다는 훨씬 적은 출력 결과가 나옵니다

find / -maxdepth 3  -name "*log"

또한, find 명령어에게 디렉토리 트리에서 최소 3개 수준까지 디렉토리를 검색할 것을 지시할 수 있습니다.

find / -mindepth 3  -name "*log"

-depth 옵션은 내용 평가에 앞서 디렉토리를 평가할 수 있도록 해줍니다. 아래 명령어는 한 예입니다.:

find -name "*test*" -depth
./test/test
./test
./localbin/test
./localbin/test_shell_var
./localbin/test.txt
./test2/test/test
./test2/test
./test2

find 명령어의 세계

지 금까지 find 명령어의 유용하지만 다소 혼란스러운 일부 기능에 대해 알아보았지만, find 명령어가 수행할 수 있는 추가 작업이 있습니다. 예를 들어, find 명령어가 기존 버전의 UNIX 및 기타 운영 체제와 호환 가능하도록 하고 여러 파일로 출력을 인쇄하도록 하는 등 연산을 수행할 수 있도록 하는 옵션이 있습니다. 본 자료를 읽은 다음에는 find 명령어에 대한 맨페이지(man page)를 이해할 수 있는 배경 지식을 갖추었을 것으로 생각하기 때문에 이 강력하면서도 유용한 툴을 직접 경험해 볼 것을 권합니다


Sheryl Calish는 Linux 전문 IT 컨설턴트입니다. Blue Heron Consulting을 거쳐 현재는 EquityBuild에서 IT 디렉터를 맡고 있습니다

[출처] http://www.oracle.com/technology/global/kr/pub/articles/calish-find.html

'LinuX' 카테고리의 다른 글

고급 Linux 커맨드 마스터 가이드, 제 2 부  (0) 2009.06.23
고급 Linux 커맨드 마스터 가이드  (0) 2009.06.23
klogin과 rlogin  (0) 2009.06.08
linux 파티션 나누기  (0) 2009.05.08
Cron  (0) 2008.11.24

+ Recent posts