본문 바로가기
Old Posts/Linux

[Linux] bash-completion 사용법 - Bash 명령어 자동완성 기능

by A6K 2022. 2. 1.

클러스터 혹은 서버를 관리하기 위해 Bash 스크립트를 이용해 관리 툴을 구현하는 경우가 많이 있다. 관리용 Bash 스크립트의 경우 여러가지 옵션과 인자들을 받는 경우가 많은데, 이런 옵션들을 자동완성시키는 기능이 있다면 매우 편리할 것이다.

예를 들어 git 명렁을 입력하고 한칸 띄고, [TAB] 키를 누르면 git에서 사용할 수 있는 명령의 리스트가 뜬다. 일부 글자를 입력하고 다시 [TAB]을 누르면 사용자가 입력한 글자에 해당하는 옵션을 추려서 다시 리스트로 보여주거나 자동완성시켜준다.

Bash에서는 ‘bash-completion’을 이용해 이런 명령어 자동완성 기능을 사용할 수 있다.


1. 설치

‘bash-completion’이 설치되어 있지 않으면 ‘_get_comp_words_by_ref:command not found’ 같은 에러를 만나게 될 수 있다.

데비안 계열 리눅스 -  (우분투)

$ sudo apt-get install bash-completion

레드헷 계열 리눅스 - CentOS

$ sudo yum install bash-completion

$ brew install bash-completion

2. 예제 1 - 자동완성 호출

예제 쉘 스크립트를 하나 작성하고, 자동완성 기능을 만들어보자.

bash-completion을 설치하면 '/etc/bash_completion.d' 디렉토리가 생성된다. 이곳에 자동완성에 필요한 스크립트들이 설치된다. 이곳에 test 파일을 하나 만들어보자.

#!/bin/bash
_test()
{
    echo 'auto completion test'
}
complete -F _test test

자동완성을 위한 파일이 설치되었다. '/etc/bash_completion.d' 디렉토리 아래에 있는 스크립트들은 대부분 이렇게 생겼다. 여기서 핵심은 'complete -F _test test' 라는 부분이다. 이 명령은 커맨드라인에서 'test'라는 명령어를 사용했을 때, [TAB] 키를 누르면 '_test' 함수를 실행시켜주는 것을 의미한다. test 명령의 존재 여부는 중요하지 않다.

시스템에 새로운 세션이 로그인을 하면, '/etc/profile.d/bash_completion.sh' 스크립트가 실행된다. '/etc/bash_completion.d' 디렉토리에 설치된 스크립트들은 이를 통해 다음번 로그인시 적용이 된다. 현재 세션에도 적용하고 싶으면, 'source  /etc/profile.d/bash_completion.sh'를 실행하면된다.

터미널에서 해보자.

[root@fd215695de61 ~]# cat /etc/bash_completion.d/test
#!/bin/bash
_test()
{
    echo 'auto completion test'
}
complete -F _test test
[root@fd215695de61 ~]# source /etc/profile.d/bash_completion.sh
[root@fd215695de61 ~]# 
[root@fd215695de61 ~]# test [TAB]

test 명령의 옵션을 입력할 때, [TAB] 키를 눌러 자동완성 기능을 호출해보면,

'_test' 함수가 호출되고 화면에 echo 명령으로 찍은 문자열이 찍혔다. bash_completion의 자동완성은 이런식으로 호출된다.

3. 예제 2 - 상세 자동완성

이번에는 좀 더 상세한 자동완성 기능을 구현해보자.

자동완성 기능을 구현할 때, 사용자가 입력한 인자에 따라서 다르게 동작하도록 작성할 수도 있다. 명령어에 인자를 여러개 받는 경우 첫번째 인자가 뭐냐에 따라 두번째 인자를 다르게 출력하고 싶은 경우가 있다.

 

커맨드 라인에서 [TAB] 키를 누르면 bash_completion이 동작해서 적당한 자동완성 혹은 선택가능한 입력을 화면에 출력해준다. 즉, 현재 사용자가 입력한 옵션을 bash_completion 스크립트에서 사용할 수 있어야 한다.

bash_completion에서는 $COMP_CWORD, $COMP_WORDS 변수를 통해 사용자가 입력한 옵션을 읽을 수 있다.이 변수는 C언어에서 main() 함수의 두 가지 인자와 비슷한 역할을 한다. $COMP_CWORDS 변수는 int argc, $COMP_WORDS 변수는 char *argv[]에 대응된다고 생각하면 된다. 즉, $COMP_CWORDS 변수는 현재 입력된 인자의 개수, $COMP_WORDS 변수는 입력된 명령행 인자들이 문자열 배열로 입력되어 전달된다.

$ test option1 arg[TAB]

test 명령의 첫 번째 옵션으로 'option1'을 입력하고 arg까지만 입력하고 [TAB] 키를 누르면 $COMP_CWORD 변수에는 1, $COMP_WORDS에는 "option1"이 담겨서 스크립트로 넘어온다.

이를 이용해서 다음과 같이 자동완성을 구현해볼 수 있다.

#!/bin/bash
_test()
{
    local cur

    COMPREPLY=()
    _get_comp_words_by_ref cur

    if [ $COMP_CWORD = 1 ]
    then
        COMPREPLY=( $( compgen -W 'option1 option2' -- "$cur" ) )
    elif [ $COMP_CWORD = 2 ]
    then
        if [ "${COMP_WORDS[1]}" = "option1" ]
        then
            COMPREPLY=( $( compgen -W 'arg1 arg3' -- "$cur" ) )
        elif [ "${COMP_WORDS[1]}" = "option2" ]
        then
            COMPREPLY=( $( compgen -W 'arg2 arg4' -- "$cur" ) )
        fi
    fi
    return 0
}

complete -F _test test

test 명령의 첫 번째 인자로는 'option1'과 'option2'를 사용할 수 있다. 만약 첫 번째 옵션으로 'option1'이 입력되었다면 두번째 옵션으로는 'arg1'과 'arg3'을 입력할 수 있고, 'option2'가 입력되었다면 'arg2'와 'arg4'를 사용할 수 있다.

스크립트에서 '_get_comp_words_by_ref' 함수는 자동완성할 단어를 받아온다. 즉, 

cur="${COMP_WORDS[COMP_CWORD]}"

를 수행한 것처럼 현재 사용자가 입력한 마지막 단어를 리턴해준다고 생각하면 된다.

여기서 받아온 cur 값은 compgen 명령의 인자로 건내진다. compgen 명령은 -W 옵션으로 선택할 수 있는 옵션들을 인자로 받는다. 그리고 -W 옵션에 있는 선택지 중 cur 값으로 완성할 수 있는 키워드 리스트를 반환한다. 이 리스트는 COMPREPLY 변수에 담겨지고, 자동완성 기능에서 사용된다.

댓글