리눅스 명령줄을 자주 사용한다면, 히스토리(history) 기능을 효과적으로 활용하는 것만으로도 작업 생산성이 크게 향상됩니다. 이 글에서 소개하는 15가지 예제를 익히고 나면 명령줄 작업이 한층 더 편리하고 즐거워질 것입니다.
1. HISTTIMEFORMAT으로 타임스탬프 표시하기
명령줄에서 history를 입력하면 일반적으로 명령 번호와 명령어만 표시됩니다. 감사(audit) 목적이라면 아래와 같이 명령어 실행 시각(타임스탬프)을 함께 표시하는 것이 유용합니다.
# export HISTTIMEFORMAT='%F %T ' # history | more 1 2008-08-05 19:02:39 service network restart 2 2008-08-05 19:02:39 exit 3 2008-08-05 19:02:39 id 4 2008-08-05 19:02:39 cat /etc/redhat-release
2. Ctrl+R로 히스토리 검색하기
아마도 가장 자주 사용하게 될 히스토리 기능입니다. 이미 실행했던 긴 명령어를 다시 입력해야 할 때, 키워드로 검색하여 전체를 다시 타이핑하지 않고도 동일한 명령어를 재실행할 수 있습니다. Ctrl+R을 누른 뒤 키워드를 입력하세요. 다음 예제에서는 red를 검색했고, 히스토리에서 'red'라는 단어가 포함된 이전 명령어 "cat /etc/redhat-release"가 표시되었습니다.
# [명령 프롬프트에서 Ctrl+R을 누르면 reverse-i-search 프롬프트가 나타납니다] (reverse-i-search)`red': cat /etc/redhat-release [참고: 원하는 명령어가 보이면 Enter를 누르세요. 히스토리에서 해당 명령어가 그대로 실행됩니다] # cat /etc/redhat-release Fedora release 9 (Sulphur)
때로는 명령어를 실행하기 전에 수정하고 싶은 경우가 있습니다. 예를 들어 httpd를 검색하면 히스토리에서 service httpd stop이 표시되는데, 이 상태에서 왼쪽 또는 오른쪽 화살표 키를 눌러 stop을 start로 변경한 후 다시 실행할 수 있습니다.
# [명령 프롬프트에서 Ctrl+R을 누르면 reverse-i-search 프롬프트가 나타납니다] (reverse-i-search)`httpd': service httpd stop [참고: 명령어가 보이면 왼쪽 또는 오른쪽 화살표 키를 누르세요. 실행 전에 명령어를 편집할 수 있습니다] # service httpd start
3. 직전 명령어를 빠르게 반복 실행하는 4가지 방법
여러 가지 이유로 직전 명령어를 반복해야 할 때가 있습니다. 마지막으로 실행한 명령어를 다시 실행하는 방법은 다음 4가지입니다.
- 위쪽 화살표 키로 이전 명령어를 불러온 후 Enter를 눌러 실행합니다.
- 명령줄에 !!를 입력하고 Enter를 누릅니다.
- 명령줄에 !-1을 입력하고 Enter를 누릅니다.
- Ctrl+P를 누르면 이전 명령어가 표시되며, Enter로 실행합니다.
4. 히스토리에서 특정 명령어 실행하기
다음 예제처럼 4번 명령어를 반복 실행하고 싶다면 !4라고 입력하면 됩니다.
# history | more 1 service network restart 2 exit 3 id 4 cat /etc/redhat-release # !4 cat /etc/redhat-release Fedora release 9 (Sulphur)
5. 특정 단어로 시작하는 이전 명령어 실행하기
재실행하고 싶은 명령어의 앞부분 몇 글자에 !를 붙여 입력하면 됩니다. 다음 예제에서 !ps를 입력하고 Enter를 누르자, ps로 시작하는 이전 명령어 'ps aux | grep yp'가 실행되었습니다.
# !ps ps aux | grep yp root 16947 0.0 0.1 36516 1264 ? Sl 13:10 0:00 ypbind root 17503 0.0 0.0 4124 740 pts/0 S+ 19:19 0:00 grep yp
6. HISTSIZE로 히스토리 저장 개수 조절하기
.bash_profile 파일에 다음 두 줄을 추가한 뒤 bash 셸에 다시 로그인하면 변경 사항이 적용됩니다. 이 예제에서는 최대 450개의 명령만 bash 히스토리에 저장됩니다.
# vi ~/.bash_profile HISTSIZE=450 HISTFILESIZE=450
7. HISTFILE로 히스토리 파일 이름 변경하기
기본적으로 히스토리는 ~/.bash_history 파일에 저장됩니다. .bash_profile에 다음 줄을 추가하고 bash 셸에 다시 로그인하면, 히스토리가 .bash_history 대신 .commandline_warrior 파일에 저장됩니다. 실용적인 용도를 찾기는 어렵지만, 서로 다른 터미널의 명령 이력을 각각 별도의 히스토리 파일로 구분해 추적하고 싶을 때 유용할 수 있습니다.
# vi ~/.bash_profile HISTFILE=/root/.commandline_warrior
혹시 히스토리 파일 이름을 변경할 만한 좋은 이유가 있다면 공유해 주세요. 이 기능을 어떻게 활용하는지 궁금합니다.
8. HISTCONTROL로 연속 중복 항목 제거하기
다음 예제에서 pwd를 세 번 입력했더니, history 실행 시 세 번 모두 기록되어 있는 것을 확인할 수 있습니다. 이런 연속 중복을 제거하려면 아래와 같이 HISTCONTROL을 ignoredups로 설정하면 됩니다.
# pwd # pwd # pwd # history | tail -4 44 pwd 45 pwd 46 pwd [위에서 pwd를 3번 실행했더니 히스토리에 pwd가 세 번 기록되었습니다] 47 history | tail -4 # export HISTCONTROL=ignoredups # pwd # pwd # pwd # history | tail -3 56 export HISTCONTROL=ignoredups 57 pwd [pwd를 3번 실행했지만 히스토리에는 pwd가 한 번만 기록되었습니다] 58 history | tail -4
9. HISTCONTROL로 히스토리 전체에서 중복 제거하기
앞서 살펴본 ignoredups는 연속된 명령어의 중복만 제거합니다. 히스토리 전체 범위에서 중복을 제거하려면 아래와 같이 HISTCONTROL을 erasedups로 설정하세요.
# export HISTCONTROL=erasedups # pwd # service httpd stop # history | tail -3 38 pwd 39 service httpd stop 40 history | tail -3 # ls -ltr # service httpd stop # history | tail -6 35 export HISTCONTROL=erasedups 36 pwd 37 history | tail -3 38 ls -ltr 39 service httpd stop [pwd 이후에 실행했던 이전 service httpd stop 기록이 삭제되었습니다] 40 history | tail -6
10. HISTCONTROL로 특정 명령어를 히스토리에 기록하지 않기
HISTCONTROL을 ignorespace로 설정한 상태에서 명령어 앞에 공백을 하나 입력하면, 해당 명령어는 히스토리에서 무시됩니다. 명령어를 히스토리에서 숨길 수 있다는 점에 많은 주니어 시스템 관리자들이 흥미를 느끼곤 합니다. ignorespace의 동작 방식을 이해해 두는 것은 좋지만, 모범 사례 관점에서는 히스토리에서 의도적으로 무언가를 숨기지 않는 것이 바람직합니다.
# export HISTCONTROL=ignorespace # ls -ltr # pwd # service httpd stop [service 앞에 공백이 있어 이 명령어는 히스토리에서 무시됩니다] # history | tail -3 67 ls -ltr 68 pwd 69 history | tail -3
11. -c 옵션으로 이전 히스토리 전체 삭제하기
이전 히스토리는 모두 지우면서도 앞으로의 히스토리 기록은 계속 유지하고 싶을 때가 있습니다.
# history -c
12. 히스토리 명령어의 인수 치환하기
히스토리를 검색할 때, 방금 검색한 명령어의 인수(파라미터)는 그대로 활용하면서 명령어만 바꿔서 실행하고 싶은 경우가 있습니다.
아래 예제에서 vi 명령어 옆의 !!:$는 직전 명령어의 인수를 현재 명령어로 가져옵니다.
# ls anaconda-ks.cfg anaconda-ks.cfg # vi !!:$ vi anaconda-ks.cfg
아래 예제에서 vi 명령어 옆의 !^는 직전 명령어(cp 명령어)의 첫 번째 인수를 현재 명령어(vi 명령어)로 가져옵니다.
# cp anaconda-ks.cfg anaconda-ks.cfg.bak anaconda-ks.cfg # vi !^ vi anaconda-ks.cfg
13. 특정 명령어의 특정 인수 치환하기
아래 예제에서 !cp:2는 히스토리에서 cp로 시작하는 이전 명령어를 찾아 두 번째 인수를 가져와 ls -l 명령어에 대입합니다.
# cp ~/longname.txt /really/a/very/long/path/long-filename.txt # ls -l !cp:2 ls -l /really/a/very/long/path/long-filename.txt
아래 예제에서 !cp:$는 cp로 시작하는 이전 명령어를 찾아 마지막 인수(위 예제에서는 두 번째 인수와 동일)를 ls -l 명령어에 대입합니다.
# ls -l !cp:$ ls -l /really/a/very/long/path/long-filename.txt
14. HISTSIZE=0으로 히스토리 기능 비활성화하기
히스토리 기능을 완전히 끄고 bash 셸이 입력한 명령어를 기억하지 않게 하려면, 아래와 같이 HISTSIZE를 0으로 설정하면 됩니다.
# export HISTSIZE=0 # history # [히스토리에 아무것도 표시되지 않습니다]
15. HISTIGNORE로 특정 명령어를 히스토리에서 제외하기
pwd나 ls 같은 기본 명령어들로 히스토리가 지저분해지는 것이 싫다면, HISTIGNORE를 사용해 무시할 명령어들을 지정할 수 있습니다. 주의할 점은 HISTIGNORE에 ls를 추가하면 ls만 무시되고 ls -l은 무시되지 않는다는 것입니다. 따라서 히스토리에서 제외하고 싶은 명령어를 정확히 지정해야 합니다.
# export HISTIGNORE="pwd:ls:ls -ltr:" # pwd # ls # ls -ltr # service httpd stop # history | tail -3 79 export HISTIGNORE="pwd:ls:ls -ltr:" 80 service httpd stop 81 history [히스토리에 pwd, ls, ls -ltr가 기록되지 않았습니다]
추천 도서
Ramesh Natarajan의 Bash 101 Hacks. 저는 대부분의 시간을 리눅스 환경에서 보내기 때문에 자연스럽게 Bash 명령줄과 셸 스크립팅의 열렬한 팬이 되었습니다. 15년 전 다양한 *nix 계열 시스템에서 작업할 때는 C 셸과 Korn 셸로 많은 코드를 작성했습니다. 이후 리눅스 시스템 관리자로 일하면서 가능한 거의 모든 작업을 Bash 셸 스크립팅으로 자동화했습니다. 이러한 경험을 바탕으로, Bash 명령줄과 셸 스크립팅에 관한 101가지 실용적인 예제를 담은 eBook 'Bash 101 Hacks'를 집필했습니다. Bash를 제대로 마스터하고 싶다면 이 책을 읽어보세요. Bash 명령줄과 셸 스크립팅을 완전히 내 것으로 만드는 데 큰 도움이 될 것입니다.
함께 읽으면 좋은 리눅스 아티클
다음은 도움이 될 만한 15가지 예제 시리즈 아티클입니다.
- Unix LS 명령어: 15가지 실용 예제
- Grep 완벽 정복 – Grep 명령어 15가지 실용 예제
- Linux Crontab: 15가지 Cron Job 예제
- 엄마, 찾았어요! — Linux Find 명령어 15가지 실용 예제