 |  |
|
난이도 : 중급 John Fronckowiak, President, IDC Consulting Inc.
옮긴이: 박재호 이해영 dwkorea@kr.ibm.com
2008 년 7 월 29 일 Michael Stutz가 작성한 훌륭한 기사에 이어, 이 기사에서는 유닉스 명령행을 효과적으로 활용하기 위한 열 가지 더 좋은 습관을 소개합니다. 자주 저지르는 오류와 이를 극복하는 방법을 배우고, 정확히 이런 열 가지 유닉스(UNIX®) 습관을 익혀야 하는 이유를 살펴봅시다.
솔직히 말해, 나쁜 습관은 고치기 어렵다. 이제 편안함까지 느끼는 버릇은 더욱 고치기 어렵다. 종종 사물을 새롭게 보면 "아하, 당신이 이렇게 하는 이유를 모르겠네?"라는 순간이 찾아온다. Michael Stutz가 작성한 "열 가지 유닉스 사용 습관"이라는 훌륭한 기사에 이어 이 기사에서는 여러분을 유닉스 명령행 전문가로서 좀 더 높은 생산성을 발휘하도록 열 가지 더 좋은 유닉스 명령행, 도구, 기법을 제시한다.
익혀야 하는 열 가지 더 좋은 습관은 다음과 같다.
- 파일 이름 완성 기능을 활용하자.
- 히스토리 확장 기능을 활용하자.
- 직전에 사용한 인수를 재사용하자.
pushd와 popd로 디렉터리를 탐색하자.
- 대용량 파일을 탐색하자.
- 편집기 없이 임시 파일을 생성하자.
curl 명령행 유틸리티를 활용하자.
- 정규 표현식을 적극 활용하자.
- 현재 사용자가 누구인지 알아내자.
awk로 자료를 처리하자.
 |
자주 사용하는 약어
-
MB: Megabyte
-
HTTP: Hypertext Transfer Protocol
-
HTTPS: HTTP over Secure Sockets Layer
-
FTP: File Transfer Protocol
-
FTPS: FTP over Secure Sockets Layer
-
LDAP: Lightweight Directory Access Protocol
|
|
파일 이름 완성 기능을 활용하자.
명령행에서 길고 복잡한 이름을 입력하지 않으면 얼마나 좋을까? 글쎄, 여기서 그럴 필요가 없다는 사실이 밝혀진다. 대다수 인기있는 유닉스 셸에서 긴 이름 입력을 대신하는 파일 이름 완성 기능을 켤 수 있다. 이런 기능은 각 셸에서 조금 다르게 동작하므로, 대다수 인기 있는 셸에서 어떻게 파일 이름 완성 기능을 활용할지 보여주겠다. 파일 이름 완성 기능은 입력을 빨리하도록 돕고 오류를 줄여준다. 게으르다고? 아마도. 좀 더 효율적이라고? 당연하지!
현재 돌리고 있는 셸이 무엇일까?
현재 돌리고 있는 셸이 무엇인지 알고 싶다면 어떻게 할까? 물론 열 가지 더 좋은 습관에 공식적으로 포함되어 있지 않은 기법이지만, 여전히 알아두면 유용하다. Listing 1에서 echo $0이나 ps -p $$ 명령을 사용해 사용 중인 셸을 출력할 수 있다. 내 경우에는 배시 셸이다.
Listing 1. 사용 중인 셸 파악하기
$ echo $0
-bash
$ ps -p $$
PID TTY TIME CMD
6344 ttys000 0:00.02 -bash
|
C 셸
C 셸은 가장 직관적인 파일 이름 완성 기능을 지원한다. filec 변수를 설정하면 끝난다(명령어 set filec를 사용하자). 파일 이름을 입력하기 시작한 다음에, ESC 키를 누르면, 셸은 가능한 많이 파일 이름을 채워준다. 예를 들어 file1, file2, file3이라는 파일이 있다고 가정하자. f를 입력하고 ESC를 누르면 file이 채워지고, 적절한 파일 이름을 완성하기 위해 1, 2, 3을 입력하면 된다.
배시 셸
배시 셸 또한 파일 이름 완성 기능을 제공하지만, ESC 키 대신에 TAB 키를 사용한다. 배시 셸에서 파일 이름 완성 기능을 활성화하기 위해 특별히 설정할 필요는 없다. 기본으로 설정되어 있기 때문이다. 배시 셸은 또한 추가 기능을 구현했다. 파일 이름 일부를 입력하고, 탭을 누르면, 이 시점에서 요청을 만족하는 여러 파일을 보여주고, 이 파일 중 하나를 선택하도록 텍스트를 추가하고 싶을 경우, 탭을 두 번 눌러서 지금까지 입력한 이름과 일치하는 파일 목록을 보여준다. file1, file2, file3이라는 직전 예제를 그대로 사용해보자. f를 입력하고 탭을 한번 누르면, 배시 셸은 파일 이름을 완성한다. 탭을 두 번 누르면 file1 file2 file3 목록을 확장한다.
콘 셸
콘 셸 사용자라면, 파일 이름 완성 기능은 EDITOR 환경 변수에 의존한다. EDITOR를 vi로 설정했다면, 이름을 입력하고 ESC에 이어 역슬래시(\) 문자를 입력한다. EDITOR를 emacs로 설정했다면, 이름을 입력하고 파일 이름 완성을 위해 ESC를 두 번 누른다.
히스토리 확장 기능을 활용하자.
일련의 명령어에서 동일한 파일 이름을 사용하려면 어떻게 할까? 여러분이 사용했던 마지막 파일 이름을 빨리 꺼낼 수 있는 지름길이 있다. Listing 2에서 !$ 명령은 직전에 사용했던 명령어 파일 이름을 돌려준다. this-is-a-long-lunch-menu-file.txt라는 파일에서 pickles라는 단어를 탐색하자. 탐색을 끝내고 vi 명령어로 this-is-a-long-lunch-menu-file.txt라는 파일을 편집하려면, 파일 이름을 다시 입력할 필요가 없다. !를 사용해 히스토리에 접근하고 $를 이용해 직전 명령어의 마지막 필드를 반환하게 만들자. 긴 이름을 반복해 사용할 때 훌륭한 도구가 된다.
Listing 2. !$ 명령으로 사용했던 마지막 파일 이름을 꺼내자.
$ grep pickles this-is-a-long-lunch-menu-file.txt
pastrami on rye with pickles and onions
$ vi !$
|
직전에 사용한 인수를 재사용하자.
!$ 명령은 명령어에 사용했던 마지막 인수를 반환한다. 명령어에 사용한 인수가 여러 개며, 그 중에 하나만 사용하려면 어떻게 할까? !:1 연산자는 명령에서 사용한 인수를 반환한다. Listing 3에 나온 예는 !$ 연산자와 결합해 이 연산자를 활용하는 방법을 보여준다. 첫 번째 명령어에서, 파일에 좀 더 의미 있는 이름을 붙인다. 하지만 원본 파일 이름을 보존하기 위해 심볼릭 링크를 생성한다. 파일 kxp12.c를 대상으로 좀 더 읽기 쉬운 방식으로 이름을 바꾸고, link 명령을 사용해 원본 파일 이름에 심볼릭 링크를 걸어 다른 곳에서 사용하도록 만들자. !$ 연산자는 file_system_access.c를 반환하며, !:1 연산자는 직전 명령에서 첫 번째 인수인 kxp12.c를 반환한다.
Listing 3. !$와 !:1를 조합해 사용하기
$ mv kxp12.c file_system_access.c
$ ln -s !$ !:1
|
pushd와 popd로 디렉터리를 탐색하자.
유닉스는 다양한 디렉터리 탐색 도구를 지원한다. 내가 가장 좋아하는 두 가지 생산성 높은 도구로 pushd와 popd를 든다. 여러분은 cd 명령이 현재 디렉터리를 바꾼다는 사실 정도는 확실하게 알고 있다. 하지만 여러 디렉터리를 탐색한 다음에 원래 위치로 바로 돌아오기를 원한다면 어떻게 할까? pushd와 popd 명령은 가상 디렉터리 스택을 생성하는데, pushd 명령은 현재 디렉터리를 바꾸는 동시에 스택에 저장하고, popd 명령은 스택 상단에서 디렉터리를 제거해서 이 위치로 이동한다. dirs 명령어를 사용해 새로운 디렉터리를 밀어넣거나 뽑아내지 않고서 현재 디렉터리 스택 내용을 출력할 수 있다. Listing 4는 pushd와 popd 명령을 사용해서 디렉터리 트리 구조를 빨리 탐색하는 예를 보여준다.
Listing 4. pushd와 popd를 사용해서 디렉터리 트리 탐색하기
$ pushd .
~ ~
$ pushd /etc
/etc ~ ~
$ pushd /var
/var /etc ~ ~
$ pushd /usr/local/bin
/usr/local/bin /var /etc ~ ~
$ dirs
/usr/local/bin /var /etc ~ ~
$ popd
/var /etc ~ ~
$ popd
/etc ~ ~
$ popd
~ ~
$ popd
|
pushd와 popd 명령은 또한 디렉터리 스택을 다루기 위한 매개변수를 지원한다. +n이나 -n 매개변수(n은 숫자)를 사용해 스택을 왼쪽이나 오른쪽으로 회전할 수 있다. Listing 5를 살펴보자.
Listing 5. 디렉터리 스택 회전하기
$ dirs
/usr/local/bin /var /etc ~ ~
$ pushd +1
/var /etc ~ ~ /usr/local/bin
$ pushd -1
~ /usr/local/bin /var /etc ~
|
대용량 파일을 탐색하자.
남은 디스크 용량이 다 어디로 사라졌는지 궁금한가? 여기에 저장 공간을 관리하는 데 필요한 몇 가지 도구를 소개한다. Listing 6에서 df 명령은 가용 볼륨에서 사용된 블록 전체 숫자와 남은 공간을 퍼센트로 보여준다.
Listing 6. 볼륨 사용량 확인
$ df
Filesystem 512-blocks Used Available Capacity Mounted on
/dev/disk0s2 311909984 267275264 44122720 86% /
devfs 224 224 0 100% /dev
fdesc 2 2 0 100% /dev
map -hosts 0 0 0 100% /net
map auto_home 0 0 0 100% /home
|
가장 큰 파일을 찾고 싶은가? find 명령에 -size 매개변수를 붙이자. Listing 7은 10MB를 초과하는 파일을 찾기 위해 find 명령을 활용하는 예를 보여준다. -size 매개변수는 크기를 킬로바이트 단위로 받아들인다는 사실에 유의하자.
Listing 7. 10MB를 초과하는 모든 파일 탐색
$ find / -size +10000k -xdev -exec ls -lh {}\;
|
편집기 없이 임시 파일을 생성하자.
아주 간단한 방법이 하나 있다. 간단한 임시 파일을 바로 생성해야 하는데, 편집기를 띄우고 싶지는 않다. cat 명령어와 > 파일 재지정 연산자를 활용하자. Listing 8에서 파일 이름을 지정하지 않은 cat 명령어는 표준 입력으로 들어오는 내용을 그대로 출력한다. > 파일 재지정 연산자는 이 내용을 지정된 파일에 저장한다. 입력이 끝나면 컨트롤+D를 눌러 파일 입력 완료를 알려줘야 함에 유의하자.
Listing 8. 임시 파일 바로 만들기
$ cat > my_temp_file.txt
This is my temp file text
^D
$ cat my_temp_file.txt
This is my temp file text
|
같은 작업을 수행하고 싶지만 새로 만드는 대신에 기존 파일에 덧붙이고 싶다면 어떻게 할까? Listing 9에 나온 >> 연산자를 대신 사용하자. >> 파일 재지정 연산자는 존재하는 파일 뒤에 내용을 덧붙인다.
Listing 9. 파일 내용 바로 덧붙이기
$ cat >> my_temp_file.txt
More text
^D
$ cat my_temp_file.txt
This is my temp file text
More text
|
curl 명령행 유틸리티를 활용하자.
명령행에서 웹에 접근할 수 있을까? 제정신이라고? 맞다. 우리에게는 curl이 있다! curl 명령은 HTTP, HTTPS, FTP, FTPS, Gopher, DICT, TELNET, LDAP, FILE 프로토콜을 사용해서 서버에서 자료를 가져올 수 있다. Listing 10에서 curl 명령을 사용해 미 기상과(NWS, National Weather Service)가 제공하는 현재 지역 기상 정보에 접근하는 방법을 보여준다(뉴욕 버팔로). grep 명령어와 결합하면, 버팔로 기상 상태를 가져올 수 있다. -s 명령행 옵션은 curl 처리 결과를 보여주지 않도록 만든다.
Listing 10. curl로 현재 기상 상태를 가져오기
$ curl -s http://www.srh.noaa.gov/data/ALY/RWRALY | grep BUFFALO
BUFFALO MOSUNNY 43 22 43 NE13 30.10R
|
Listing 11에서 curl 명령을 사용해서 HTTP 호스트가 제공하는 파일을 내려받는 방법을 보여준다. -o 매개변수를 사용해서 결과 저장 위치를 지정하자.
Listing 11. curl을 사용해서 HTTP 호스트가 제공하는 파일을 내려받기
$ curl -o archive.tar http://www.somesite.com/archive.tar
|
curl로 할 수 있는 일을 맛만 보여줬다. 명령행 프롬프트에서 man curl 명령을 내려서 curl 명령에 대한 완벽한 활용 정보를 출력해서 읽어보자.
정규 표현식을 적극 활용하자.
다양한 유닉스 명령어가 인수로 정규 표현식을 받아들인다. 기술적으로 말하자면, 정규 표현식은 0개 이상 문자열을 정의하는 패턴을 나타내는 문자열이다(글자, 숫자, 심볼을 결합한 연속된 글자 모음). 정규 표현식은 메타 문자(예를 들어 별[*]과 물음표[?] 심벌)를 사용해서 전체 문자열이나 일부 문자열에 일치하는지 알려준다. 정규 표현식은 와일드카드를 포함할 필요는 없지만, 와일드카드 사용은 패턴 탐색과 파일 처리 과정에서 정규 표현식을 좀 더 유용하게 만든다. 표 1에 몇몇 기본 정규 표현식을 정리했다.
표 1. 정규 표현식
| 순서 | 설명 |
|---|
캐릿(^) | ^A와 같이 행 시작을 표현한다. | 물음표(?) | A$?와 같이 행 끝을 표현한다. | 역슬래시(\) | \^와 같이 다음에 따라나오는 문자의 특수한 의미를 없앤다. | 대괄호([]) | [aeiou]와 같이(범위를 표현하려면 [0-9]처럼 하이픈([-])을 사용한다) 대괄호로 감싼 문자 중에서 일치하는 문자를 표현한다. |
[^ ]
| [^0-9]와 같이 대괄호로 감싼 문자 중에서 일치하지 않는 문자를 표현한다. | 마침표(.) | 행끝을 제외한 문자 하나를 표현한다. | 별(*) | 0개 이상 이어지는 문자나 표현식을 표현한다. |
\{x,y\}
| x번에서 y번까지 이어지는 문자나 표현식을 표현한다. |
\{x\}
| 정확하게 x번 이어지는 문자나 표현식을 표현한다. |
\{x,\}
| x번 이상 이어지는 문자나 표현식을 표현한다. |
Listing 12는 grep 명령어에 사용되는 기본적인 정규 표현식 몇 가지를 보여준다.
Listing 12. grep으로 정규 표현식 활용하기
$ # 편지 목록
$ grep '^From: ' /usr/mail/$USER
$ # 최소한 글자 하나를 포함한 행
$ grep '[a-zA-Z]' search-file.txt
$ # 숫자나 문자가 아닌 모든 글자
$ grep '[^a-zA-Z0-9] search-file.txt
$ # 999-9999 형식을 다루는 전화번호
$ grep '[0-9]\{3\}-[0-9]\{4\}' search-file.txt
$ # 정확하게 한 글자를 포함한 행
$ grep '^.$' search-file.txt
$ # 마침표로 시작하는 행
$ grep '^\.' search-file.txt
$ # 마침표와 소문자 두 개로 시작하는 행
$ grep '^\.[a-z][a-z]' search-file.txt
|
여러 책에서 정규 표현식을 설명하고 있다. 명령행 정규 표현식을 좀 더 심도 깊게 익히려면, ""Speaking UNIX, Part 9: Regular expressions"라는 developerWorks 기사를 추천한다.
현재 사용자가 누구인지 알아내자.
종종 특정 사용자가 어떤 명령을 실행하고 있는지 아닌지를 확인하는 관리 스크립트를 작성하고 싶을 경우가 있다. 사용자를 찾아내려면 현재 사용자 이름을 반환하는 whoami 명령을 활용할 수 있다. Listing 13은 whoami 명령을 자기 자신에게 내린 결과를 보여준다. Listing 14는 현재 사용자가 root가 아님을 확인하기 위해 whoami를 사용하는 배시 스크립트 일부 코드 내용을 보여준다.
Listing 13. 명령행에서 whoami 사용하기
Listing 14. 스크립트에서 whoami 사용하기
if [ $(whoami) = "root" ]
then
echo "You cannot run this script as root."
exit 1
fi
|
awk로 자료를 처리하자.
awk 명령은 항상 펄의 그늘에 가려져 있는 듯이 보인다. 하지만 간단한 명령행 기반 자료 처리에 사용하는 간편하고 유용한 도구다. Listing 15는 awk 명령어를 활용하는 간단한 방법을 보여준다. text 파일에서 각 행 길이를 구하려면, length() 함수를 사용하자. 문자열 ing가 text 파일에 있는지 살펴보려면 ing가 처음 나타난 위치를 반환하는 index() 함수를 사용해서 이어지는 문자열 처리 과정에 함수 결과를 활용할 수 있다. 문자열을 토큰으로 분리하려면(행을 단어로 분리하려면), split() 함수를 사용하자.
Listing 15. 간단히 awk 활용하기
$ cat text
testing the awk command
$ awk '{ i = length($0); print i }' text
23
$ awk '{ i = index($0,"ing"); print i}' text
5
$ awk 'BEGIN { i = 1 } { n = split($0,a," "); while (i <= n) {print a[i]; i++;} }' text
testing
the
awk
command
|
텍스트 파일에서 지정된 필드 출력은 간단한 awk 명령으로 끝난다. Listing 16에서 sales 파일은 각 판매원 이름과 월별 매출액 현황을 포함한다. awk 명령을 사용하면 매출액 합계를 바로 계산할 수 있다. 기본적으로 awk는 필드 구분 문자로 ,를 사용한다. $n 연산자를 사용하면 개별 필드에 접근도 가능하다.
Listing 16. 자료 요약에 awk 활용하기
$cat sales
Gene,12,23,7
Dawn,10,25,15
Renee,15,13,18
David,8,21,17
$ awk -F, '{print $1,$2+$3+$4}' sales
Gene 42
Dawn 50
Renee 46
David 46
|
awk 명령은 복잡하며 다양한 상황에서 사용할 수 있다. awk 명령어를 더욱 완벽하게 익히려면 참고자료 절에 있는 내용을 살펴보고 man awk 명령을 내려 매뉴얼 페이지부터 시작하자.
결론
명령행 전문가가 되려면 연습이 많이 필요하다. 동일한 방식으로 작업 수행이 쉬운 이유는 점점 익숙해지기 때문이다. 명령행 활용법을 확장해서 생산성을 높이고 유닉스 명령행 전문가를 향해 한 걸음 전진하자!
참고자료 교육
- "Use free software within commercial UNIX"(David Dougall, developerWorks, 2006년 2월 9일): 이 기사는 상용, 독점 유닉스 운영체제에서 수 많은 오픈 소스 소프트웨어를 활용하는 것에 대한 짧은 입문 내용을 담고 있다.
- "Working in the bash shell"(Robert Brunner, developerWorks, 2006년 5월 30일): 인기 좋은 배시 셸에 대한 소개 튜토리얼이다.
- "Get started with GAWK: AWK language fundamentals"(Michael Stutz, developerWorks, 2006년 9월 19일): 이 기사는 AWK 언어로 텍스트를 처리하는 방법을 보여준다.
- "Hone your regexp pattern-building skills(Michael Stutz, developerWorks, 2006년 7월 18일):
grep을 활용하는 좀 더 유용한 방법을 다룬다.
- 유닉스 팁: "유닉스 팁" 연재의 다른 기사를 읽어보자.
- "Common threads: Awk by example, Part 1," "Common threads: Awk by example, Part 2," "Common threads: Awk by example, Part 3"(Daniel Robbins, developerWorks, 2001-2002):
awk 활용에 있어 휼륭한 입문 내용을 살펴보자.
- "Speaking UNIX, Part 9: Regular expressions"(Martin Streicher, developerWorks, 2007년 4월 17일): 헷갈리는 내용을 제대로 이해하기 위해 정규 표현식 사용법을 익히자.
- AIX와 UNIX 영역: developerWorks AIX와 UNIX 영역을 방문해 기술을 향상시킬 참고자료를 살펴보자.
- AIX와 UNIX 입문: AIX와 UNIX 초보라자면 방문해 더 많은 지식을 익히자.
- 기술 온라인 서점: 기술 온라인 서점을 검색해서 여러 기술 주제에 대한 책을 찾아보자.
토론
필자소개
기사에 대한 평가
 |
| 이 문서 북마킹 하기
|
|  |