UNIX에서 가장 강력하고 뛰어난 혁신 기술 중 하나는 쉘이다. GUI보다 효율적인 쉘에서는 스크립트를 작성하여 여러 작업을 자동화할 수 있다. 게다가 pipe 연산자를 사용하면 명령행에서 직접 임시 프로그램을 작성할 수 있다. 파이프 연산자는 명령을 차례로 연결하며, 이 경우 선행 명령의 출력이 후속 명령의 입력이 된다.
하지만 파이프에는 한 가지 큰 단점이 있다. 그것은 바로 파이프가 일종의 블랙 박스와 같다는
것이다. 여러 명령을 순차적으로 연결한 경우 일련의 명령 중 마지막 명령의 출력을 통해서만
진행 상태를 확인할 수 있다. 물론 명령 시퀀스 중간에 tee를 끼워
넣을 수도 있고 tail을 사용하여 출력 파일을 확인할 수도 있지만
이러한 방법은 일회성 해결책에 불과하며 여러 단계의 표준 출력(stdout)과
표준 오류(stderr)가 뒤섞이지 않도록 주의해야 한다. 게다가 두
해결책 모두 단순한 표시기에 불과하기 때문에 각 단계에 얼마나 많은 계산이 필요한지 제대로
파악할 수 없다.
물론 복잡한 시퀀스를 단계별로 중간 출력 파일이 있는 여러 개별 단계로 나눠서 다시 작성할 수 있다. 그리고 실제로도 간격별로 결과를 확인하려는 경우에는 분할하는 방법이 이상적이다. 이 방법은 스크립트를 작성하고, 단계별로 하나의 데이터 파일을 생성하며, 각 단계 쌍 간에 데이터 파일을 입력으로 사용하고, 최종 파일을 최종 결과로 수집한다. 하지만 이 방법을 사용하면 명령행의 특징 중 하나인 즉흥성을 살릴 수가 없다.
우리에게 필요한 것은 명령행에 포함시켜서 처리량을 측정할 수 있는 진행 상태 측정기이다. 이 측정기가 반복해서 각 단계를 벤치 마크할 수 있고 Linux®, Mac OS X 등의 여러 UNIX 계열 시스템에도 이식할 수 있는 오픈 소스 도구라면 매우 이상적일 것이다.
이러한 요구를 완전히 충족시키는 이상적인 도구가 바로 Pipe Viewer(pv)이다. 이
도구는 지난 4년 동안 시스템 관리자인 Andrew Wood가 작성하고 다른 여러 개발자가 향상시키는
과정을 거쳐 개발되었으며 명령행 "연결"을 확인할 수 있는 기능을 제공한다. 해당 프로젝트
페이지에 언급된 대로 pv는 "두 프로세스 사이의 파이프라인에
삽입하여 데이터의 진행 상태, 경과된 시간 및 남은 시간을 시각적으로 표시할 수 있다." 또한
동일한 명령행에 여러 pv 인스턴스를 삽입하여 상대적인 처리량을
표시할 수도 있다.
이 기사에서는 UNIX 시스템에서 pv를 빌드한 후 단순 및 복합
명령행 조합에 적용하는 방법을 보여 준다. 먼저, 파이프를 이용해서 프로세스를 연결하는 방법부터
살펴보자.
그림 1에서는 두 개의 개별 프로세스를 연결하는 파이프를 작성하는 단계를 보여 준다.
그림 1. 두 프로세스를 연결하는 파이프 작성하기
먼저 1단계에서는 최초 프로세스가 표준 입력 stdin으로부터
입력을 읽고, stdout에 출력을 쓰고, stderr에
오류를 표시한다. 각각의 stdin, stdout 및
stderr는 파일 디스크립터이거나 파일에 대한 핸들이다. 파일 핸들에
대한 각 작업(예: open, read, write,
rewind, truncate 및 close)은
파일의 상태에 영향을 미친다.
그런 다음 2단계에서는 최초 프로세스에서 파이프를 작성한다. 파이프는 하나의 큐와 두 개의 파일 디스크립터로 구성되며, 파일 디스크립터 중 하나는 데이터를 큐에 넣고 다른 하나는 데이터를 큐에서 삭제한다. 파이프는 선입선출(FIFO) 데이터 구조이다.
파이프 자체만으로는 거의 사용할 데가 없지만 파이프는 주로 생성자 프로세스를 사용자 프로세스에 연결하는 데 사용된다. 이제 3단계에서는 최초 프로세스가 포크하거나 두 번째 프로세스를 작성하며, 이 두 번째 프로세스는 상대 프로세스의 역할을 수행한다.
4단계(새 프로세스가 사용자 프로세스라고 가정)에서는 원래 프로세스가 stdout을
파이프의 생성자 종단으로 바꾼 후 파이프의 사용자 종단과 stdin을 처리할
새로 포크된 프로세스를 다시 연결한다. 이러한 조정 이후 원래 프로세스(현재는 생성자)의 각
write는 큐에 입력되며 그런 다음 새 프로세스(현재는 사용자)가
큐에 입력된 데이터를 읽는다.
1 - 4단계는 쉘에서 명령행 파이프 연산자(|)를 사용하여 한
유틸리티를 다른 유틸리티에 연결하는 프로세스를 보여 준다. 하지만 이 경우 쉘은 각 유틸리티에
대한 새 프로세스를 생성하며 쉘 자체에는 영향을 주지 않고 작업을 제어한다.
예를 들어, 그림 2에서는 파이프를 통해 find,
grep 및 wc 명령을 연결하여 소문자 a로
시작하는 모든 파일을 찾아서 그 수를 계산하는 방법을 보여 준다. 쉘은 독립적으로 유지되며, find는
생성자이고, grep은 find에 대한 사용자와
wc에 대한 생성자 역할을 수행한다. wc 또한
생성자와 사용자 역할을 수행한다. 즉, grep을 사용하고 stdout에
대한 출력을 생성한다. 일반적으로 쉘은 stdout을 단말기에 연결하지만
리디렉션을 통해 출력을 파일로 리라우트할 수 있다.
그림 2. 파이프로 명령 연결하기
두 UNIX 프로세스를 연결하려면 파이프 두 개를 작성한 후 두 프로세스 모두 생성자 및 사용자 역할을
수행하도록 각 프로세스의 파일 디스크립터를 다시 연결한다. 그림 3에서는 두 프로세스의
stdin과 stdout을 모두 재정의하는 인터프로세스
교환을 보여 준다.
그림 3. 두 개의 UNIX 프로세스 살펴보기
지금까지 간략하게 검토해 보았으므로 이제 Pipe Viewer에 대해 살펴보자.
Pipe Viewer는 오픈 소스 애플리케이션이다. 소스 코드를 다운로드하여 애플리케이션을 처음부터 빌드할 수 있으며, 가능한 경우, UNIX 배포판의 저장소에서 기존 바이너리를 가져와서 사용할 수 있다.
처음부터 빌드하려면 Pipe Viewer 프로젝트 페이지(참고자료 참조)에서
최신 소스 tar 파일을 다운로드한다. 2009년 9월 중순을 기준으로 이 코드의 최신 버전은 1.1.4이다. Tar
파일의 압축을 풀고 새로 작성한 디렉토리로 이동한 후 ./configure, make
및 sudo make install을 차례로 입력한다. 기본적으로 빌드 프로세스가 완료되면
/usr/local/bin에 pv라는 실행 파일이 설치된다. (./configure --help를
입력하면 구성 옵션 목록을 볼 수 있다.) Listing 1에서는 설치 코드를 보여 준다.
Listing 1. Pipe Viewer 설치 코드
$ wget http://pipeviewer.googlecode.com/files/pv-1.1.4.tar.bz2 $ tar xjf pv-1.1.4.tar.bz2 $ cd pv-1.1.4 $ ./configure $ make $ sudo make install $ which pv /usr/local/bin/pv |
저장소에 있는 pv 바이너리를 가져오려면 사용 중인 배포판의
패키지 관리 프로그램을 사용하여 pv 또는 pipe viewer를
검색한다. 예를 들어, Ubuntu 버전 9의 APT 패키지 관리 프로그램을 사용하여 검색을 수행하면
다음과 같은 결과를 얻을 수 있다.
$ apt-cache search part viewer pv - Shell pipeline element to meter data passing through |
계속해서 패키지 관리 프로그램을 사용하여 패키지를 다운로드하고 설치한다. Ubuntu의
경우 다음과 같이 apt-get install 명령을 사용한다.
$ sudo apt-get install pv |
설치가 완료되었으면 pv를 사용해 보자. 가장 쉽게 사용할 수 있는
방법으로는 일반적인 cat 유틸리티 대신 pv를
사용하여 바이트를 다른 프로그램에 제공한 후 전체 처리량을 측정하는 방법이 있다. 예를 들어, 다음과
같이 pv를 사용하여 시간이 오래 걸리는 압축 작업을 모니터링할 수 있다.
$ ls -lh listings.txt -r--r--r-- 1 supergiantrobot staff 109M Sep 1 20:47 listings.txt $ pv listings.txt | gzip > listings.gz 96.1MB 0:00:09 [11.3MB/s] [=====================> ] 87% ETA 0:00:01 |
명령이 실행되면 pv는 진행 표시줄을 표시한 후 지속적으로
게이지를 갱신하여 진행률을 표시한다. 일반적인 pv 화면에는
지금까지 처리된 데이터의 용량, 경과 시간, 처리 속도(MB/초), 작업 완료율에 대한 시각적
및 숫자 표현, 예상하는 남은 시간이 왼쪽부터 차례대로 표시된다. 위 화면을 보면 109MB 중
96.1MB가 처리되었으며 파일의 약 13%가 남아 있고 앞으로 9초 후에 완료될 예정이라는
것을 알 수 있다.
기본적으로 pv는 값을 계산할 수 있는 모든 상태 표시기를
표시한다. 예를 들어, pv에 대한 입력이 파일이 아니고 특정
크기를 수동으로 지정하지 않은 경우 진행 표시줄은 왼쪽에서 오른쪽으로 진행되면서 활동을
보여 주지만 기준이 없기 때문에 완료율을 측정하지 못한다. 다음은 이러한 경우를 보여
주는 예제이다.
$ ssh faraway tar cf - projectx | pv --wait > projectx.tar Password: 4.34MB 0:00:07 [ 611kB/s] [ <=> ] |
이 예제에서는 원격 시스템에서 tar를 실행한 후 원격 명령의
출력을 로컬 시스템에 보내서 projectx.tar를 작성한다. pv는 전송에 예상하는 총 바이트를 계산할 수 없기 때문에 현재까지 처리된 용량, 경과 시간 및 활동을 반영하는
특수 표시기만 보여 준다. 이 경우에는 데이터가 처리되는 동안 작은 "자동차"(<=>)가
왼쪽에서 오른쪽으로 이동하는 모습이 계속 표시된다.
--wait 옵션을 사용하면 첫 번째 바이트가 실제로 수신될 때까지
진행 표시줄의 표시가 지연된다. 이 예제의 경우 ssh 명령이 암호를
요청하므로 --wait 옵션을 유용하게 사용할 수 있다.
원하는 경우 고유한 플래그를 사용하여 개별 표시기를 활성화할 수 있다.
$ ssh faraway tar cf - projectx | \ pv --wait --bytes > projectx.tar Password: 268kB |
다음 명령은 --bytes를 사용하여 실행 중인 바이트 수를
계산한다. 기타 옵션으로는 --progress, --timer,
--eta, --rate 및 --numeric
등이 있다. 하나 이상의 표시 옵션을 지정한 경우에는 이름 지정되지 않는 나머지 모든 표시기가 자동으로
비활성화된다.
또한 pv에 --rate-limit 옵션을
사용하여 처리 속도를 제한할 수 있다. 이 옵션의 인수로는 하나의 숫자와 하나의 접미어(예:
MB/초를 나타내는 m)가 있다.
$ ssh faraway tar cf - projectx | \ pv --wait --quiet --rate-limit 1m > projectx.tar |
이전 명령은 모든 표시기를 숨기고(--quiet) 처리 속도를 1MB/s로 제한한다.
지금까지는 단일 인스턴스의 Pipe Viewer를 명령 쌍의 생성자나 사용자로 사용하는
예제만을 살펴보았다. 하지만 더 복잡한 조합도 사용할 수 있다. 동일한 명령행에서
pv를 여러 번 사용할 수 있으며, 이를 위해서는 약간의
조건을 충족해야 한다. 즉, --name을 사용하여 각 pv
인스턴스에 이름을 지정하고 --cursor를 사용하여
멀티라인 모드를 활성화해야 한다. 이렇게 두 옵션을 함께 사용하면 레이블이 지정된
일련의 표시기가 작성된다. 이 경우 이름 지정된 인스턴스 하나당 하나의 표시기가
작성된다.
예를 들어, 데이터 전송과 데이터 압축의 진행 상태를 개별적으로 동시에 모니터링하려는
경우 다음과 같이 pv 인스턴스 하나를 전송 작업에 할당하고 또 하나의
인스턴스를 압축 작업에 할당할 수 있다.
$ ssh faraway tar cf - projectx | pv --wait --name ssh | \ gzip | pv --wait --name gzip > projectx.tgz |
암호를 입력하면 다음과 같이 두 줄로 된 진행 상태 측정기가 생성된다.
ssh: 4.17MB 0:00:07 [ 648kB/s] [ <=> ]
gzip: 592kB 0:00:06 [62.1kB/s] [ <=> ]
|
ssh라는 레이블이 지정된 첫 번째 행은 전송 작업의 진행
상태를 보여 주며, gzip이라는 레이블이 지정된 두 번째 행은
압축 작업의 진행 상태를 보여 준다. 각 명령이 해당 작업의 바이트 수를 파악할 수 없기
때문에 누적 총계 및 활동 표시줄이 각 행에 표시된다.
한 작업의 바이트 수를 대략적으로 알 수 있거나 계산할 수 있다면 --size
옵션을 사용한다. 이 옵션을 추가하면 진행 표시줄에서 진행 상태를 세분해서 표시할 수 있다.
예를 들어, 중요한 아카이브 작업의 진행 상태를 모니터링하려는 경우 다른 UNIX
유틸리티를 사용하여 원래 파일의 대략적인 전체 크기를 계산할 수 있다. df
유틸리티는 전체 파일 시스템에 대한 통계를 표시할 수 있는 반면 du는
임의 깊이의 계층 구조의 크기를 계산할 수 있다.
$ tar cf - work | pv --size `du -sh work | cut -f1` > work.tar |
여기서, 서브쉘 명령 du -sh work | cut -f1이 work 디렉토리의
전체 크기를 pv와 호환되는 형식으로 생성한다. 즉, du -h는
사람이 읽을 수 있는 형식(예: 17MB의 경우 17M)으로 표현하므로 pv와
함께 사용하기에 적합하다. (ls 및 df 명령도
사람이 읽을 수 있는 형식을 제공하기 위해 -h 옵션을 지원한다.) 이제 pv는
파이프를 통해 전송할 바이트의 특정 수를 예상하고 있으므로 정상적인 진행 표시줄을 표시할 수 있다.
700kB 0:00:07 [ 100kB/s] [> ] 4% ETA 0:02:47 |
마지막으로 한 가지 더 유용한 기술이 있다. 바이트 계산 외에도 Pipe Viewer에서는 행
수를 계산하여 진행 상태를 시각화할 수 있다. 한정자 --line-mode를
지정한 경우 pv는 줄 바꾸기가 나타날 때마다 진행 상태 측정기를
진행시킨다. --size를 제공할 수도 있으며 해당 숫자는 예상 행 수로 해석된다.
이제 예제를 살펴보자. 때때로 find는 모래 사장에서 바늘을
찾을 때 유용하게 사용할 수 있다. 예를 들어, 대용량의 애플리케이션 코드 본문에 사용된 특정
시스템 호출을 모두 찾는 작업을 효과적으로 수행할 수 있다. 그러한 환경에서 다음과 같은 명령을
실행할 수 있다.
$ find . -type f -name '*.c' -exec grep --files-with-match fopen \{\} \; > results
|
이 코드는 모든 C 소스 파일을 검색하여 파일 내에 문자열
fopen이 포함된 파일의 이름을 출력한다. 그리고 출력은 results라는
이름의 파일에 수집된다. 활동 상태를 표시하기 위해 다음과 같이 pv를 위 코드에 추가한다.
$ find . -type f -name '*.c' -exec grep --files-with-match fopen \{\} \; | \
pv --line-mode > results
|
find와 같은 많은 UNIX 명령은 파일의 컨텐츠가 아닌 파일의
메타데이터에 대해 작동하므로 행 모드의 경우 빠른 성능을 제공한다. 특히, 행 모드는 대용량의
파일 콜렉션을 복사하거나 압축하는 시스템 관리 스크립트에 이상적이다.
일반적으로 Pipe Viewer는 속도를 측정할 수 있는 모든 명령행 및 스크립트에 삽입할
수 있지만 창의적인 아이디어가 필요한 경우도 있다. 예를 들어, 디렉토리의 복사 속도를
측정하기 위해 cp -pr를 tar로 바꿀
수 있다.
$ # an equivalent of cp -pr old/somedir new $ (cd old; tar cf - somedir) | pv | (cd new; tar xf - ) |
또한 행 모드는 wget, curl,
scp 등의 네트워킹 유틸리티와 함께 사용할 수 있다. 예를 들어,
pv를 사용하여 대용량 업로드의 진행 상태를 측정할 수 있다. 그리고
많은 네트워킹 도구는 파일을 입력으로 받기 때문에 파일의 길이를 --size에
대한 인수로 사용할 수 있다.
Pipe Viewer는 잘 알려져 있지는 않지만 한번 발견하고 나면 절대 떼어놓을 수 없는 보물과
같다. pv는 일상적인 명령행 작업에서도 활용할 수 있지만 대부분의
경우에는 자동화 스크립트에서 주로 사용하게 된다. 지금까지는 깜박이는 커서만을 바라보면서 작업
완료를 나타내는 표시를 기다릴 수 밖에 없었지만 이제는 탐지기를 삽입하여 실시간 피드백을 확인할
수 있다. Pipe Viewer를 사용하면 시스템의 실시간 상황을 역동적으로 보여 준다.
교육
-
Speaking UNIX에서는 이 시리즈의 다른 부분을 볼 수 있다.
-
UNIX 쉘을 학습할 수 있다.
-
developerWorks의 AIX 및 UNIX 영역에서는 AIX 시스템 관리의 모든 기능에 관한 다양한 정보와 UNIX 능력을 개선할 수
있는 정보를 볼 수 있다.
-
New to AIX and UNIX에서 AIX와 UNIX에 대한 자세한 정보를 볼 수 있다.
-
기술 서점에서 다양한 기술 주제와 관련된 서적을 살펴보자.
제품 및 기술 얻기
-
Pipe Viewer에 대한 자세한 정보를 살펴보고 Pipe Viewer를 다운로드할 수 있다.
토론
-
developerWorks 포럼 & 블로그를 통해 developerWorks 커뮤니티에 참여하자.
- Twitter의 developerWorks 페이지를 살펴보자.
- My developerWorks 커뮤니티에 참여하자.
-
AIX 및 UNIX 포럼에 참여하자.
- AIX Forum
- AIX Forum for developers
- Cluster Systems Management
- IBM Support Assistant Forum
- Performance Tools Forum
- Virtualization Forum
- 기타 AIX and UNIX Forums
