Linux에서 history 명령을 사용하는 방법

리눅스 셸 환경에서는 사용자가 실행한 명령어들이 기록으로 저장됩니다. 이러한 기록을 조회하고 재사용함으로써 작업 효율성을 극대화할 수 있습니다. 리눅스 history 명령어와 그 활용법을 숙지하면 생산성을 크게 향상시킬 수 있습니다.

기록 관리의 중요성

과거를 기억하지 못하는 사람은 과거를 반복할 수 밖에 없다는 조지 산타야나의 유명한 말처럼, 리눅스 환경에서도 명령어 기록을 제대로 관리하지 못하면 효율적인 작업이 어렵습니다. 이전 명령어를 쉽게 확인하고 재사용할 수 있도록 해주는 history 명령어는 이러한 문제점을 해결하는 데 매우 유용합니다. 이 기능은 단순한 게으름이나 시간 절약을 넘어 효율성과 정확성을 높이는 데 기여합니다. 특히 길고 복잡한 명령어의 경우, 오류 없이 다시 입력하기 어렵기 때문에 history 명령어의 중요성은 더욱 커집니다. history 명령어를 통해 명령어 오타나 실수로 인한 문제를 방지할 수 있습니다.

리눅스 명령어 대부분이 그렇듯, history 명령어 역시 단순해 보이지만 다양한 기능을 제공합니다. history 명령어를 능숙하게 활용하는 방법을 배우는 것은 리눅스 명령어 라인 사용 경험을 크게 향상시키는 지름길입니다. 반복적으로 위쪽 화살표 키를 누르는 것보다 훨씬 효율적인 방법으로 이전 명령을 재사용할 수 있습니다.

history 명령어 기본 사용법

history 명령어는 가장 기본적인 형태로 이름만 입력하여 사용할 수 있습니다.

history

명령어를 실행하면 터미널 창에 이전에 사용한 명령어 목록이 표시됩니다.

명령어는 번호가 매겨져 있으며, 가장 최근에 사용한 명령어(가장 높은 번호)가 목록의 맨 아래에 표시됩니다.

특정 개수의 명령어만 보고 싶다면, history 명령어 뒤에 숫자를 입력하면 됩니다. 예를 들어, 최근 10개의 명령어만 보려면 다음과 같이 입력합니다.

history 10

history 명령어의 결과를 tail 명령어와 함께 파이프하여 동일한 결과를 얻을 수도 있습니다. 다음 명령어를 실행하면 됩니다.

history | tail -n 10

명령어 재사용

history 목록에서 명령어를 재사용하려면 느낌표(!)와 함께 명령어 번호를 입력하면 됩니다. 예를 들어, 명령어 번호 37번을 재실행하려면 다음과 같이 입력합니다.

!37

가장 최근에 실행한 명령어를 재실행하려면 느낌표 두 개를 입력하면 됩니다.

!!

이는 명령어를 실행한 후 sudo 권한이 필요하다는 것을 깨달았을 때 유용합니다. `sudo !!` 명령어를 입력하면 바로 이전에 실행한 명령어를 sudo 권한으로 재실행할 수 있습니다.

다음 예시에서는 sudo 권한이 필요한 명령어를 실행했습니다. 전체 명령어를 다시 입력하는 대신 `sudo !!`를 사용하여 명령어 실행을 완료할 수 있습니다.

mv ./my_script.sh /usr/local/bin/
sudo !!

history 목록에서 특정 번호의 명령어를 재실행하거나, `!!`를 사용하여 가장 최근에 실행한 명령어를 다시 실행할 수 있습니다. 그렇다면, 목록에서 다섯 번째나 여덟 번째 명령어를 다시 실행하려면 어떻게 해야 할까요?

이전 명령어의 번호 앞에 느낌표와 하이픈(-)을 붙여서 실행할 수 있습니다. 예를 들어, 13번째 이전 명령어를 다시 실행하려면 다음과 같이 입력합니다.

!-13

문자열을 이용한 명령어 검색

특정 문자열로 시작하는 가장 최근의 명령어를 재실행하려면, 느낌표 다음에 문자열을 입력하고 Enter 키를 누릅니다. 예를 들어, `sudo`로 시작하는 마지막 명령어를 다시 실행하려면 다음과 같이 입력합니다.

!sudo

주의할 점은, 만약 `sudo`로 시작하는 마지막 명령어가 사용자가 의도한 명령어가 아닐 경우 예기치 않은 명령어가 실행될 수 있다는 점입니다.

이러한 위험을 방지하기 위해 `:p` 수정자를 함께 사용할 수 있습니다. 다음 명령어를 실행해봅시다.

!sudo:p

이렇게 하면 명령어를 실행하는 대신 터미널 창에 명령어를 출력합니다. 사용자는 명령어를 실행하기 전에 미리 확인할 수 있습니다. 원하는 명령어가 맞다면 위쪽 화살표 키를 누른 다음 Enter 키를 눌러 명령어를 실행하면 됩니다.

특정 문자열을 포함하는 명령어를 검색하려면 느낌표와 물음표를 사용할 수 있습니다. 예를 들어, “aliases”라는 단어가 포함된 첫 번째 명령어를 검색하여 실행하려면 다음과 같이 입력합니다.

!?aliases

이렇게 하면 문자열이 명령어의 어느 위치에 나타나든 “aliases” 문자열을 포함하는 모든 명령어를 찾을 수 있습니다.

대화형 검색

대화형 검색을 사용하면 일치하는 명령어 목록을 탐색하지 않고도 원하는 명령어를 쉽게 찾아서 재사용할 수 있습니다.

Ctrl+r 키를 눌러 검색을 시작합니다.

검색어를 입력하면 입력한 문자와 일치하는 첫 번째 명령어가 나타납니다. 입력한 문자는 백틱(`)과 아포스트로피(‘) 사이에 표시됩니다. 문자를 입력할 때마다 일치하는 명령어가 업데이트됩니다.

Ctrl+r 키를 누를 때마다 터미널 창에 나타나는 일치하는 다음 명령어를 역순으로 검색합니다.

Enter 키를 누르면 표시된 명령어가 실행됩니다.

명령어를 실행하기 전에 편집하려면 왼쪽 또는 오른쪽 화살표 키를 누릅니다.

그러면 명령어가 명령어 라인에 나타나고 편집할 수 있게 됩니다.

history 목록은 다른 리눅스 도구를 사용하여 검색할 수도 있습니다. 예를 들어 history의 출력을 grep으로 파이프하여 문자열 “aliases”를 포함하는 명령어를 검색할 수 있습니다. 다음 명령어를 실행하면 됩니다.

history | grep aliases

최근 명령어 수정

최근 명령어에 오타가 있을 경우, 캐럿(^) 기호를 사용하여 쉽게 수정할 수 있습니다. 이는 명령어를 잘못 입력했거나 다른 명령줄 옵션 또는 매개변수를 사용하여 명령어를 재실행하려는 경우에 유용합니다.

캐럿, 변경할 텍스트, 캐럿, 변경할 텍스트, 캐럿을 입력하고 Enter 키를 누릅니다. 예를 들어, 다음과 같은 명령어를 입력했으나 “sshd”를 “shhd”로 잘못 입력했다고 가정해 봅시다.

sudo systemctl start shhd

다음 명령어를 입력하면 쉽게 수정할 수 있습니다.

^shhd^sshd^

이제 명령어는 “shhd”를 “sshd”로 수정하여 실행됩니다.

기록 목록에서 명령어 삭제

-d(삭제) 옵션을 사용하면 history 목록에서 명령어를 삭제할 수 있습니다. 오타가 있는 명령어는 기록 목록에 남겨둘 필요가 없습니다.

grep을 사용하여 삭제할 명령어를 찾고, -d 옵션으로 해당 명령어의 번호를 전달하여 삭제한 다음, 다시 검색하여 삭제되었는지 확인할 수 있습니다.

history | grep shhd
history -d 83
history | grep shhd

-d 옵션에는 여러 개의 명령어를 함께 전달할 수도 있습니다. 22번부터 32번까지의 모든 목록 항목을 삭제하려면 다음 명령어를 입력합니다.

history -d 22 32

최근 5개의 명령어만 삭제하려면 다음과 같이 음수를 사용할 수 있습니다.

history -d -5

히스토리 파일 수동 업데이트

로그인하거나 터미널 세션을 열 때, history 목록은 히스토리 파일에서 읽어옵니다. Bash의 기본 히스토리 파일은 .bash_history입니다.

현재 터미널 창에서 변경한 내용은 터미널 창을 닫거나 로그아웃할 때만 기록 파일에 기록됩니다.

만약 다른 터미널 창을 열어서 이전에 입력한 명령어를 포함한 전체 history 목록에 접근하고 싶다면 어떻게 해야 할까요? -a(all) 옵션을 사용하면 두 번째 터미널 창을 열기 전에 첫 번째 터미널 창에서 이 작업을 수행할 수 있습니다.

다음과 같이 입력합니다.

history -a

이제 변경 사항이 히스토리 파일에 자동으로 기록됩니다.

history 목록에 대한 모든 변경 사항(예: 일부 이전 명령어를 삭제한 경우)을 history 파일에 즉시 기록하려면 -w(쓰기) 옵션을 사용할 수 있습니다.

history -w

기록 목록 지우기

history 목록에서 모든 명령어를 지우려면 -c(지우기) 옵션을 사용할 수 있습니다.

history -c

이러한 변경 사항을 history 파일에 적용하려면 -w 옵션을 함께 사용해야 합니다.

history -w

보안 및 히스토리 파일

만약 명령줄에 중요한 정보(예: 비밀번호)를 입력해야 하는 프로그램을 사용한다면, 이 정보 또한 기록 파일에 저장된다는 점을 기억해야 합니다. 특정 정보를 기록에 남기지 않으려면 다음 명령 구조를 사용하여 기록 목록에서 즉시 삭제할 수 있습니다.

special-app my-secret-password;history -d $(history 1)
history 5

이 구조는 세미콜론(;)으로 구분된 두 개의 명령어를 포함합니다. 자세히 살펴보겠습니다.

special-app: 사용 중인 프로그램의 이름입니다.
my-secret-password: 명령줄에서 애플리케이션에 제공해야 하는 비밀 암호입니다. 이것이 첫 번째 명령어의 끝입니다.
history -d: 두 번째 명령어에서 history의 -d(삭제) 옵션을 호출합니다. 삭제할 대상은 명령어의 다음 부분에 있습니다.
$(history 1): 이는 명령어 대체를 사용합니다. $()로 묶인 명령어 부분은 하위 셸에서 실행됩니다. 해당 실행 결과는 원래 명령어에 텍스트로 게시됩니다. history 1 명령어는 이전 명령어를 반환합니다. 따라서 두 번째 명령어를 `history -d “여기에 이전 명령어”`라고 생각할 수 있습니다.

history 5 명령어를 사용하여 비밀번호가 포함된 명령어가 기록 목록에서 제거되었는지 확인할 수 있습니다.

더 간단한 방법도 있습니다. Bash는 기본적으로 공백으로 시작하는 줄을 무시하므로, 줄 시작 부분에 공백을 포함시키기만 하면 됩니다.

 special-app another-password
history 5

이제 비밀번호가 포함된 명령어가 기록 목록에 추가되지 않습니다. 이 트릭이 작동하는 이유는 .bashrc 파일에 설정되어 있기 때문입니다.

.bashrc 파일

.bashrc 파일은 로그인하거나 터미널 창을 열 때마다 실행됩니다. 여기에는 history 명령어의 동작을 제어하는 몇 가지 값도 포함되어 있습니다. gedit 편집기를 사용하여 이 파일을 편집해 보겠습니다.

다음과 같이 입력합니다.

gedit .bashrc

파일 상단 근처에 다음 두 개의 항목이 있습니다.

HISTSIZE: 기록 목록에 저장할 수 있는 최대 명령어 개수입니다.
HISTFILESIZE: 히스토리 파일에 저장할 수 있는 최대 라인 수에 대한 제한입니다.

이 두 값은 다음과 같은 방식으로 상호 작용합니다.

로그인하거나 터미널 창 세션을 시작하면 history 목록은 .bash_history 파일에서 채워집니다.
터미널 창을 닫을 때 HISTSIZE에 설정된 최대 명령어 수는 .bash_history 파일에 저장됩니다.
histappend 셸 옵션이 활성화된 경우 명령어가 .bash_history에 추가됩니다. histappend가 설정되지 않은 경우 .bash_history를 덮어씁니다.
history 목록의 명령어를 .bash_history에 저장한 후, history 파일은 HISTFILESIZE 라인 이하로 잘립니다.

또한, 파일 상단 근처에 HISTCONTROL 값에 대한 항목이 있습니다.

이 값을 설정하여 다음 중 하나를 수행할 수 있습니다.

ignorespaces: 공백으로 시작하는 줄은 기록 목록에 추가되지 않습니다.
ignoredups: 중복된 명령어가 기록 파일에 추가되지 않습니다.
ignoreboth: 위의 두 가지를 모두 활성화합니다.

기록 목록에 추가하고 싶지 않은 특정 명령어를 나열할 수도 있습니다. 콜론(:)으로 구분하고 큰따옴표(“…”)로 묶습니다.

이 구조를 따라 .bashrc 파일에 줄을 추가하고 무시하려는 명령어로 대체합니다.

export HISTIGNORE="ls:history"

타임스탬프 사용

history 목록에 타임스탬프를 추가하려면 HISTTIMEFORMAT 설정을 사용할 수 있습니다. 이렇게 하려면 .bashrc 파일에 다음과 같은 줄을 추가하기만 하면 됩니다.

export HISTTIMEFORMAT="%c "

닫는 따옴표 앞에 공백이 있습니다. 이렇게 하면 타임스탬프가 명령 목록의 명령어와 겹치는 것을 방지할 수 있습니다.

이제 history 명령어를 실행하면 날짜 및 타임스탬프가 표시됩니다. 타임스탬프를 추가하기 전에 기록 목록에 있던 모든 명령어는 타임스탬프를 처음 받은 명령의 날짜와 시간으로 타임스탬프가 찍힙니다. 아래 예시에서는 118번 명령어가 처음 타임스탬프를 받은 명령어입니다.

타임스탬프가 너무 길다면 %c 외에 다른 토큰을 사용하여 간소화할 수 있습니다. 사용할 수 있는 다른 토큰은 다음과 같습니다.

%d:
%m:
%y:
%H:
%M:
%S:
%F: 전체 날짜 (년-월-일 형식)
%T: 시간 (시:분:초 형식)
%c: 전체 날짜 및 시간 스탬프 (일-월-일-년 및 시:분:초 형식)

몇 가지 다른 토큰을 실험하여 사용해 보겠습니다.

export HISTTIMEFORMAT="%d %m %T "

이제 출력은 일, 월 및 시간을 표시합니다.

만약 일과 월을 제거한다면 시간만 표시됩니다.

HISTTIMEFORMAT에 대한 모든 변경 사항은 전체 기록 목록에 적용됩니다. 이는 각 명령어에 대한 시간이 유닉스 에포크로부터의 초 수로 저장되기 때문에 가능합니다. HISTTIMEFORMAT 지시문은 초 수를 사람이 읽을 수 있는 스타일로 렌더링하는 데 사용되는 형식을 지정합니다.

export HISTTIMEFORMAT="%T "

이제 출력을 더욱 쉽게 관리할 수 있습니다.

history 명령어를 사용하여 감사를 수행할 수도 있습니다. 때로는 과거에 사용한 명령어를 검토하면 문제를 일으킨 원인을 식별하는 데 도움이 될 수 있습니다.

인생에서처럼, 리눅스에서도 history 명령어를 사용하여 좋은 시간을 되새기고 나쁜 상황에서 배울 수 있습니다.