블로그 이미지
redkite

카테고리

분류 전체보기 (291)
00.SI프로젝트 산출물 (0)
00.센터 운영 문서 (0)
01.DBMS ============.. (0)
01.오라클 (117)
01.MS-SQL (15)
01.MySQL (30)
01.PostgreSql (0)
01.DB튜닝 (28)
====================.. (0)
02.SERVER ==========.. (0)
02.서버-공통 (11)
02.서버-Linux (58)
02.서버-Unix (12)
02.서버-Windows (2)
====================.. (0)
03.APPLICATION =====.. (11)
====================.. (0)
04.ETC =============.. (0)
04.보안 (5)
====================.. (0)
05.개인자료 (1)
06.캠핑관련 (0)
07.OA관련 (1)
Total
Today
Yesterday

달력

« » 2024.5
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

공지사항

최근에 올라온 글

0024. [유닉스] 고급사용자들의 비밀

Speaking UNIX

UNIX 고급 사용자들이 철저히 지키는 일급 비밀

UNIX? 고급 사용자들의 비밀을 파헤치기 위해 워터게이트 사무실에 침입하는 것과 같은 모험을 할 필요가 없습니다. 고급 정보를 제공하는 사람이 있는데, 이번 달에는 Martin Streicher가 비밀 이야기를 털어놓는다.

내가 검은 선글라스를 끼고 가짜 콧수염을 달고 프로 컬링 팀 The Floating Stones의 로고가 부착된 야구 모자를 쓰고 있는 이유가 궁금할 텐데, 나는 지금 체포망을 뚫고 도망 중이기 때문이다. 나는 지금 독자들에게 UNIX? 고급 사용자들이 철저히 지키고 있는 비밀 중 몇 가지를 알려 주기 위해 리모컨으로 조종되는 검은 헬리콥터 편대와 인정 따위는 없어 보이는 창백하게 흰 얼굴의 시스템 관리자들, 귀신같은 솜씨를 지닌 수많은 추적자들의 눈을 피해 이리저리 도망 다니는 중이다. 텔레파시나 세뇌 전파를 막을 수 있는 알루미늄 호일 모자를 쓰고 이 글을 계속 읽기 바란다.

환경 변수 저장

대부분의 UNIX 사용자들은 선호하는 쉘 환경 시간을 계속 다시 작성하기 위해 .bashrc(Bash 쉘용) 및 .zshrc(Z 쉘용)와 같은 쉘 시작 파일에 수많은 설정을 계속 쌓고 있다. 시작 파일을 통해 별명을 작성하고 쉘 옵션을 설정하고 함수를 작성하고 환경 변수를 설정할 수 있다. 필수적인 환경 변수로는 HOME(홈 디렉토리를 지시함), PATH(애플리케이션을 검색할 디렉토리를 열거함) 및 MANPATH(매뉴얼 페이지를 검색하는 디렉토리를 나열함)가 포함된다. 쉘에 어떤 환경 변수가 설정되어 있는지 보려면 printenv를 입력한다. 사용 가능한 환경 변수의 전체 목록은 쉘의 매뉴얼 페이지를 참조한다.

쉘과 마찬가지로, 환경 변수를 통해 다른 많은 UNIX 애플리케이션을 사용자 정의할 수 있다. 예를 들어, Java™ 서브시스템에서 Java 런타임의 루트를 가리키려면 JAVA_HOME을 정의해야 한다. 이와 유사하게, AWS(Amazon Web Services) 유틸리티 패키지에서 유효한 개인용 키 신임 정보를 가진 파일을 가리키려면 AWS_CREDENTIAL_FILE을 사용해야 한다. 개별 애플리케이션에서는 환경 변수도 제공한다. 트릭은 변수를 검색하는 것이다. 다행히도, 이 작업에는 중단 및 입력 과정이 필요하지 않다. 그 대신, 유틸리티 매뉴얼 페이지를 참조하여 "환경 변수"라는 제목으로 따로 나와 있는 섹션을 살펴본다.

예를 들어, 호출기 유틸리티 less에서는 다음과 같이 유용한 환경 변수를 많이 정의한다.

?환경 변수 LESS는 명령행 옵션을 저장하여 호출기를 호출할 때마다 입력 작업량을 줄여준다. 예를 들어, 로그 파일을 많이 읽는 경우 쉘 시작 파일에 다음을 입력한다.

 

 

double square-root (export LESS='--RAW-CONTROL-CHARACTERS --squeeze-lines --ignore-case'const double);

 

이 옵션을 사용하면 각각 제어 문자(보통 구문 색상)를 해석하고 단일 행에 대한 공백 행의 실행 횟수를 줄이고 문자열이 일치하는 경우 대/소문자 구분을 무시할 수 있다. 코드 작업을 하는 경우 다음 옵션을 사용해보자.

 

 

export LESS='--LINE-NUMBERS --quit-if-one-screen --quit-on-intr'

 

?LESSKEY라는 이름의 환경 설정은 키 바인딩 파일을 가리킨다. 키 바인딩을 사용하여 다른 호출기 또는 편집기의 동작에 맞도록 less의 동작을 사용자 정의할 수 있다.
?쉘과 마찬가지로, less를 사용하여 호출 간의 히스토리를 유지 관리할 수 있다. persist 명령 파일을 가리키고 레코드에 대한 최대 명령 개수를 설정하려면 각각 LESSHISTFILE과 LESSHISTSIZE를 설정한다.

환경 변수를 사용하는 또 하나의 좋은 예는 GCC(GNU Compiler Collection)에서 찾아볼 수 있다. GCC는 다양한 환경 변수를 정의하여 작동을 사용자 정의한다. LIBRARY_PATH는 이름에서 알 수 있듯이 링크 대상 라이브러리를 검색하기 위한 디렉토리 목록이다. COMPILER_PATH는 쉘의 PATH와 비슷하지만, 이 환경 변수는 컴파일 프로세스 중에 사용되는 서브프로그램을 찾기 위해 GCC에서 내부적으로 사용된다.

단일 플랫폼에 대한 코드를 쓰고 2진 파일을 빌드하는 경우에는 이런 환경 변수를 절대 사용할 수 없다. 하지만, 많은 수의 플랫폼에 대해 같은 코드를 교차 컴파일하는 경우 그런 변수들은 각 플랫폼에 대해 다양한 헤더와 라이브러리에 액세스하는 데 필수적이다. 한 종류의 시스템에 대해 하나의 값 콜렉션으로 변수를 설정하고 다른 시스템에 대해 다른 콜렉션으로 값을 설정할 수 있다.

사실, GCC에서 큐를 받을 수 있다. 애플리케이션당 많은 환경 변수 세트를 유지 관리하고 수행해야 할 작업에 따라 한 풀에서 다른 풀로 전환한다. 한 가지 접근 방식은 각 프로젝트 디렉토리에 환경 초기화 파일을 보관하고 필요에 따라 source하는 것이다. 예를 들어, 수많은 Ruby 개발자가 이런 해결책을 통해 Ruby 버전 간에 전환함으로써, PATH, GEM_HOME 및 GEM_PATH 환경 변수를 필요에 따라 변경하여 한 버전에서 다른 버전으로 바꾼다.

dot 파일 개요

환경 변수와 마찬가지로, 많은 Linux? 및 UNIX 애플리케이션에서는 사용자 정의를 위해 dot 파일―이름이 마침표로 시작하는 작은 파일―을 제공한다. 하지만, 소수의 플래그나 상대적으로 소량의 정보를 캡처하는 환경 변수와는 달리, dot 파일은 자체의 고유한 구문 규칙과 경우에 따라서는 자체 프로그래밍 언어까지 가지고 있어, 훨씬 더 광범위하고 복잡하게 구성될 수 있다. (UNIX의 전통에 따라) 점(.)으로 시작하는 파일 이름은 표준 디렉토리 목록에 나타나지 않기 때문에, dot 파일은 옵션과 설정을 보관하기에 편리한 곳이다. (소위 이런 숨겨진 파일을 보려면 ls -a를 사용한다.) dot 파일은 특별한 이름을 제외하면 일반 텍스트 파일이다.

dot 파일은 보통 홈 디렉토리에 있지만, 일부 유틸리티에서는 현재 작업 디렉토리에서도 dot 파일을 찾는다. 애플리케이션에서 둘 이상의 dot 파일을 지원하는 경우, 프로그램에서는 일반적으로 우선 순위 규칙을 적용하여 파일 간의 우선 순위를 정한다. 일반적으로, "로컬" dot 파일― 현재 작업 디렉토리에 있는 dot 파일―의 우선 순위가 가장 높고, 그 다음으로 홈 디렉토리에 있는 dot 파일이 높으며, 나머지는 시스템 전체에 적용되는 구성에 따라 결정된다. 이런 파일들이 없거나 하나 있거나 모두 있을 수 있고, 애플리케이션에 따라 파일을 상호 독점적 또는 점진적인 것으로 다룬다. 앞의 사례에서는 앞선 체인에서 찾은 첫 번째 dot 파일로 결정된다. 그 다음 사례에서는 구성이 계단식으로 이루어지거나 최종 결과로 조정될 수 있다.

간단한 dot 파일의 한 예는 $HOME/.lesskey에 있는 less의 키 바인딩 파일이다. 파일에 있는 각각의 행은 아래의 스니펫과 닮은 형태의 쌍(키 입력과 명령의 쌍)이다.

 

 

\r forw-line

\n forw-line

e forw-line

j forw-line

^E forw-line

^N forw-line

k back-line

y back-line

^Y back-line

 

다른 극단적인 예로서 fetchmail을 생각해보자. 이 유틸리티는 여러 개의 원격 소스에서 이메일을 선택하여 로컬 위치로 메시지를 전달한다. 이 유틸리티의 작동은 $HOME/.fetchmailrc를 통해서만 제어된다. (이 유틸리티의 다양한 옵션에 관해서는 매뉴얼 페이지를 참조한다.) cron, git, vi 및 기타 많은 명령에서도 dot 파일을 인식한다. dot 파일에서 구성하는 항목에 대한 자세한 내용 역시 해당 애플리케이션의 매뉴얼 페이지를 참조한다. 어떤 dot 파일들은 crontab와 같은 별개의 매뉴얼 페이지가 있을 만큼 그 기능이 풍부하고 다양하다.

쉬 . . . SSH에 관한 비밀은...

SSH(Secure Shell)는 ―안전하게 원격 시스템에 로그인하고 파일을 복사하고 방화벽을 통해 터널링하는 데 사용하기 위해 다양한 기능을 갖춘 서브시스템이다. SSH는 서브시스템이므로, 작동을 사용자 정의하고 효율적으로 수행하기 위한 수많은 옵션을 제공한다. 사실, SSH에서는 모든 데이터를 포함하기 위해 $HOME/.ssh라는 이름의 전체 "dot 디렉토리"가 제공된다. (다른 사용자의 액세스를 방지하려면 .ssh 디렉토리가 600 모드여야 한다. 600 이외의 모드는 올바른 작동에 방해가 된다.) 특히, $HOME/.ssh/config 파일을 통해 시스템 이름, 호스트별 액세스 제어 등을 포함한 수많은 바로 가기를 정의할 수 있다.

다음은 특정 호스트에 대한 SSH를 사용자 정의하기 위해 $HOME/.ssh/config에서 찾을 수 있는 전형적인 블록이다.

 

 

Host worker

HostName worker.example.com

IdentityFile ~/.ssh/id_rsa_worker

User joeuser

 

~/.ssh/config에 있는 각각의 블록에서는 하나 이상의 호스트를 구성한다. 개별 블록은 공백 행으로 구분한다. 이 블록에서는 Host, HostName, IdentityFile 및 User의 네 가지 옵션을 사용한다. Host 옵션을 사용하면 HostName으로 지정되는 시스템의 별명을 설정할 수 있다. 예를 들어, 별명을 사용하면 ssh worker.example.com 대신 ssh worker로 입력할 수 있다. 또한, IdentityFile 및 User 옵션을 사용하면 worker에 로그인하는 방법을 정할 수 있다. IdentityFile 옵션은 호스트와 함께 사용하기 위한 개인용 키를 가리키고, User 옵션을 사용하면 로그인 ID가 제공된다. 따라서 이 블록은 다음 명령과 같은 것이다.

 

 

ssh joeuser@worker.example.com -i ~/.ssh/id_rsa_worker

 

강력하지만 잘 알려져 있지 않은 옵션이 바로 ControlMaster이다. 이 옵션을 설정하면 같은 호스트에 대해 여러 개의 SSH 세션이 단 하나의 연결을 공유한다. 첫 번째 연결이 설정된 후에는 후속 연결에 신임 정보가 필요하지 않으므로, 같은 시스템에 연결할 때마다 비밀번호를 입력해야 하는 번거로움이 없다. ControlMaster는 매우 편리한 옵션이므로, 모든 시스템에서 이 옵션을 사용하고 싶을 것이다. 다음과 같이 호스트 와일드카드 *로 손쉽게 설정할 수 있다.

 

 

Host *

ControlMaster auto

ControlPath ~/.ssh/master-%r@%h:%p

 

짐작할 수 있겠지만, Host * 태그로 표시된 블록은 구성 파일에서 명시적으로 이름이 지정되어 있지 않더라도 모든 호스트에 적용된다. ControlMaster auto는 기존 연결을 다시 사용하려고 시도하지만, 공유 연결을 찾을 수 없는 경우 새로 연결할 것이다. ControlPath는 공유를 위한 제어 소켓을 지속하는 파일을 가리킨다. %r은 원격 로그인 사용자 이름으로 바뀌고, %h는 대상 호스트 이름으로 바뀌고, %p는 연결에 사용되는 포트를 대신한다. (%l을 사용하여 로컬 호스트 이름으로 바꿀 수도 있다.) 위 스펙에서는 파일 이름이 다음과 유사한 제어 소켓이 생성된다.

 

 

master-joeuser@worker.example.com:22

 

원격 호스트에 대한 모든 연결이 이루어지면 각각의 제어 소켓이 제거된다. 언제든지 어떤 시스템에 연결되어 있는지 알고 싶으면 ls ~/.ssh를 입력하고 제어 소켓의 호스트 이름 부분(%h)을 보면 된다.

SSH 구성 파일은 매우 방대하여 자체 매뉴얼 페이지도 있다. 가능한 옵션을 모두 보려면 man ssh_config를 입력한다. 그리고 여기서는 영리하게 활용할 수 있는 SSH 트릭이 있다. 즉, SSH를 통해 로컬 시스템에서 원격 시스템으로 터널링할 수 있다. 사용할 명령행은 다음과 같다.

 

 

$ ssh example.com -L 5000:localhost:3306

 

이 명령은 "example.com을 통해 연결하고 로컬 시스템의 포트 5000과 'localhost'라는 이름의 시스템에 있는 포트 3306[MySQL 서버 포트] 사이에 터널을 설정하라"는 의미이다. localhost는 터널이 설정되면서 example.com에서 해석되기 때문에, localhost가 example.com이다. 아웃바운드 터널 ―정식 명칭은 로컬 전달(local forward)―이 설정된 상태에서, 로컬 클라이언트는 포트 5000에 연결하여 example.com에서 작동 중인 MySQL 서버와 통신할 수 있다.

터널링의 일반적인 양식은 다음과 같다.

 

 

$ ssh proxyhost localport:targethost:targetport

 

여기서 proxyhost는 SSH를 통해 액세스할 수 있고 targethost에 (SSH를 통해서가 아니라) 네트워크로 연결되는 시스템이다. localport는 로컬 시스템에 대한 권한이 없는 포트(1024를 초과하여 사용되지 않는 모든 포트)이고, targetport는 사용자가 연결하려는 서비스의 포트이다.

이전 명령을 실행하면 시스템에서 외부 세계로 터널링할 수 있다. SSH를 사용하여 내부로 터널링하거나 외부 세계에서 로컬 시스템에 연결할 수도 있다. 다음은 인바운드 터널의 일반적인 양식이다.

 

 

$ ssh user@proxyhost -R proxyport:targethosttargetport

 

인바운드 터널―정식 명칭은 원격 전달(remote forward)―을 설정하면 proxyhost 및 targethost의 역할이 뒤바뀌어, 로컬 시스템이 대상이 되고 원격 시스템이 프록시가 된다. user는 프록시에서의 로그인 ID다. 이 명령의 구체적인 예제는 다음과 같다.

 

 

$ ssh joe@example.com -R 8080:localhost:80

 

이 명령은 "example.com에 joe로 연결하고 원격 포트 8080을 로컬 포트 80에 연결하라"는 의미이다. example.com에서 사용자가 이 명령을 실행하면 Joe의 시스템에 터널이 제공된다. 원격 사용자는 8080에 연결하여 Joe의 시스템에 있는 웹 서버에 도달할 수 있다.

각각 로컬 및 원격 전달을 위한 -L 및 -R 외에도, SSH는 원격 시스템에서 HTTP 프록시를 만들기 위한 -D를 제공한다. 알맞은 구문은 SSH 매뉴얼 페이지를 참조한다.

히스토리를 이용해 다시 쓰기

쉘 프롬프트에서 많은 시간을 작업하는 경우 쉘 히스토리를 기록하면 시간을 절약하고 입력 작업량을 줄일 수 있다. 그러나 히스토리를 수정하지 않은 상태로 두면 히스토리를 사용할 때 약간 성가신 부분이 있다. 히스토리에서는 중복 명령이 기록되고 여러 쉘 인스턴스에서 서로의 히스토리에 나쁜 영향을 줄 수 있다. 두 가지 복잡한 문제 모두 쉽게 극복된다. 다음과 같이 .bashrc에 두 행을 추가한다.

 

 

export HISTCONTROL=ignoreboth

shopt -s histappend

 

첫 행은 쉘 히스토리에서 연속적으로 중복된 명령을 제거하는 역할을 한다. 순서에 상관없이 중복된 명령을 모두 제거하려면 ignoreboth를 erasedups로 변경한다. 둘째 행은 쉘 종료 시 히스토리 파일에 쉘의 히스토리를 추가하는 역할을 한다. 기본적으로, Bash 히스토리 파일은 ~/~/.bash_history(dot 파일임)로 이름이 지정된다. HISTFILE(환경 변수)을 설정하여 위치를 변경할 수 있다. 100,000개의 항목이 있는 히스토리 파일에 셀의 최근 10,000개 명령을 저장하려면 쉘 시작 파일에 export HISTSIZE=10000 HISTFILESIZE=100000을 추가한다. 쉘의 히스토리를 보려면 어떤 프롬프트에든 history를 입력하면 된다.

명령 히스토리를 저장하더라도 다시 불러올 수 없다면 거의 쓸모가 없다. ! 쉘 또는 bang 연산자의 목적이 바로 그것이다.

?!! ("bang bang")으로 마지막 명령을 완전히 반복할 수 있다.
?!:0은 이전 명령의 이름이다.
?!^은 이전 명령의 첫 인수이다. !$로 끝나는 !:2, !:3 등은 이전 명령의 두 번째, 세 번째 등의 인수이며, 결국 마지막 인수까지 표시할 수 있다. ?!*는 명령 이름을 제외한 마지막 명령의 모든 인수를 의미한다.
?!n은 히스토리에서 n이라는 번호가 매겨진 명령을 반복하는 역할을 한다.
?!handle로 handle에서 문자열로 시작하는 마지막 명령을 반복할 수 있다. 예를 들어, !ca를 사용하여 cat README와 같이 ca 문자로 시작한 마지막 명령을 반복할 수 있다.
?!?handle로 handle에서 문자열을 포함한 마지막 명령을 반복할 수 있다. 예를 들어, !?READ는 cat README와도 일치한다.
?^original^substitution을 사용하여 original의 첫 번째 항목을 substitution으로 바꿀 수 있다. 예를 들어, 이전의 명령이 cat README였다면 ^README^license.txt 명령을 실행하는 경우 cat license.txt라는 새 명령이 생성된다.
?!:gs/original/substitution을 사용하면 original이 나타날 때마다 모두 substitution으로 바뀐다. (!:gs는 "global substitution"을 의미한다.)
?!-2는 두 번째 명령이고, !-3은 최근 명령 중 세 번째 명령이라는 식이다.
히스토리 표현식을 결합하여 두 번째 명령의 명령 이름 뒤에 -R, 이전 명령의 첫 번째 인수, 세 번째 최근 명령의 두 번째 인수를 붙여 확장되는 !-2:0 -R !^ !-3:2와 같은 조합을 만들 수도 있다. 이처럼 비밀스러운 명령을 더 쉽게 읽을 수 있도록, 입력할 때 히스토리 참조를 확장할 수 있다. 어떤 프롬프트에서나 bind Space:magic-space 명령을 입력하거나 시작 파일에 이 명령을 추가하여 히스토리 대체를 인라인 상태로 확장하는 magic-space 함수에 스페이스 키를 바인딩한다.

Expand-o-Matic

이처럼 많은 코드를 인터넷에서 구할 수 있으므로, 매일 수십 개의 파일을 다운로드할 수도 있을 것이다. 그리고 그런 모든 파일들은 아마 다르게 패키징될 것이다.―각각 다른 유틸리티로 압축되지만, 경우에 따라 ZIP 파일, RAR 파일 및 수많은 TAR 파일로 패키징된다. 각각의 패키지 형식을 압축 해제하고 확장하는 방법을 일일이 기억하기 어려울 수 있다. 그렇다면, 그 모든 작업을 단일 명령에 캡처하지 못할 이유도 없다. 이 함수는 많은 샘플 dot 파일에서 널리 사용할 수 있다.

 

 

ex () {

if [ -f $1 ] ; then

case $1 in

*.tar.bz2) tar xjf $1 ;;

*.tar.gz) tar xzf $1 ;;

*.bz2) bunzip2 $1 ;;

*.rar) rar x $1 ;;

*.gz) gunzip $1 ;;

*.tar) tar xf $1 ;;

*.tbz2) tar xjf $1 ;;

*.tgz) tar xzf $1 ;;

*.zip) unzip $1 ;;

*.Z) uncompress $1 ;;

*.7z) 7z x $1 ;;

*) echo "'$1' cannot be extracted via extract()" ;;

esac

else

echo "'$1' is not a valid file"

fi

}

 

이 ex 함수는 11가지 파일 형식으로 확장되고 다른 패키지 유형을 다루는 경우 확장 가능하다. 이 함수가 정의된 후에는,―예컨대 쉘 시작 파일에서―간단히 ex somefile을 입력하면 되며, 여기서 somefile은 명명된 확장자 중 하나로 끝난다.

 

 

$ ls

source

$ tar czf source.tgz source

$ ls -1

source

source.tgz

$ rm -rf source

$ ex source.tgz

$ ls -1

source

source.tgz

 

그런데 오늘 다운로드한 것을 잘못된 위치에 둔 경우에도 find를 실행하여 검색할 수 있다.

 

 

$ find ~ -type f -mtime 0

 

-type f 명령으로는 일반 파일을 찾을 수 있고, 당일 자정 이후로 작성된 파일을 찾으려면 -mtime 0 명령을 사용한다.

훨씬 더 많은 비밀

아직도 전문가들만이 간직한 비밀이 많이 남아 있다. 웹에서 "shell auto-complete"를 검색하면 명령을 입력할 때 상황에 맞게 명령을 확장해주는 기능인 자동 완성 기능에 대해 더 자세히 살펴볼 수 있다. 또한, "shell prompts"를 검색하면 쉘 프롬프트를 사용자 정의하는 방법을 확인할 수 있다. 이것을 다채롭게 만들 수 있다. 즉, 현재 작업 디렉토리나 Git 분기를 표시하거나―다량의 히스토리를 불러오는 경우 편리하게 참조할 수 있는 히스토리 번호를 표시할 수도 있다. 작업 예를 보려면 Github에서 "dot files"를 검색한다. 많은 전문가들이 Github에 자신의 쉘 구성을 공개하고 있다.

실례지만, 이제 내 가발과 브론저 크림을 찾으러 가야겠다. 그루초 막스(미국의 희극 배우, 1890-1977)와 닮게/P>

Posted by redkite
, |

최근에 달린 댓글

최근에 받은 트랙백

글 보관함