리눅스 혹은 유닉스 시스템에 원격 접속을 위해서 터미널로 연결을 하면
간혹 백스페이스 키가 오동작 할 때가 있습니다. H,? 문자가 찍히는 현상이지요.
어제 팀원 중 한 분이 물어보길래 현상에 대해 설명하고 해결 방법을 알려줬는데
제대로 이해를 못하는 눈치라서 나름 문서로 정리를 해봤습니다.
예전에 정리한 문서가 있었는데 다시 보니 저 조차도 헷갈려서 다시 구글링으로 정리했습니다.
현대식 키보드에 붙어 있는 Backspace와 Delete 키의 역할은 분명합니다.
Backspace == 이전 글자 지움
Delete == 다음 글자 지움
그러나 리눅스 콘솔의 전신인 vt100, vt220 터미널에서는 좀 다르게 동작합니다.
설명을 드리기 전에 용어의 개념 정리가 필요한데
Ctrl+H로 입력.. 아스키 코드 08, BS 문자입니다. 터미널 기호는 ^H
백스페이스키.. 아스키 코드 127, DEL 문자입니다. 터미널 기호는 ^? (rubout 이라고도 합니다)
vt100 시절에는 한 글자를 삭제하기 위해 BS + DEL 키 조합을 사용했습니다.
아주 오래 전 천공카드 시절로 거슬러 올라가서..
잘 아시는 것처럼 그 때는 종이카드에 구멍을 뚫어 데이터를 기록하고 프로그래밍 했습니다.
7비트 천공카드라면 한 라인에 7개의 구멍이 있고 한개의 라인이 각각의 문자로 인식하게 됩니다.
아스키 문자 값을 천공기계에 전송하여 한땀한땀 구멍을 뚫다가 만약 오타가 발생했다면?
기계의 헤드를 이전으로 움직여 구멍을 다시 마킹해야 합니다.
즉 7개 비트 값을 모두 천공하여 '삭제' 라는 문자로 만들어 버리는 겁니다. (그래서 127값)
그 과정을 보면, 먼저 BS 코드를 보내서 천공기의 헤드를 이전 위치로 이동 하고
다시 DEL 코드를 보내 7개 비트를 천공, 즉 '삭제' 된 문자로 만들어 버립니다.
메인프레임 시절 VT의 사실상 표준인 vt100 에서도 똑같이 구현됩니다.
번잡하지만 BS키로 이전 위치로 이동하여 DEL 키로 문자를 삭제하는 방식인데
vt100 키보드의 우측 상단에 Backspace키가 있지만 현대와 같은 "이전문자 삭제" 가 아닌
커서위치를 이전으로 이동 기능입니다. BS, 즉 이전으로 이동 후 다시 Delete키를 눌러서 현재 위치의 글자를 삭제합니다.
※ 고증이 잘못되어 본문을 다시 수정했습니다. 위 내용이 맞습니다.
VT100 VT220
Control-h ^H ^H
Backspace ^H ^?
Delete ^? ^[[3~
vt220에서는 현대와 같은 방식으로 바뀌었고 이를 계승한 리눅스 터미널에서는 좀 더 유연합니다.
ssh, telnet으로 원격 접속 했을 때 stty erase 값으로 삭제기능을 할 문자를 지정할 수 있습니다.
stty 명령어는 단말과 터미널 서버 사이의 통신 방법을 정의하는데 그중에 하나가 erase 입니다.
예를 들어 erase 값이 ^? 이면 키보드의 백스페이스키로 한 글자 삭제가 된다는 뜻입니다.
vt100단말에서는 Ctrl+h(혹은 Backspace) 와 Delete 키를 연달아 눌러야 글자가 지워졌지만
현대적인 터미널 환경에서는 둘 중에 하나만 눌러도 이전 글자 삭제가 됩니다.
이제 ctrl+h 와 ^? 중에 어떤 것을 백스페이스 기능(이전 문자 삭제)으로 사용할지 선택해야 합니다.
# 현재 연결된 서버 라인 상태 값
stty -a
# 삭제 문자를 어떤 걸로 받을지 설정 (둘 중 선택)
stty erase ^?
stty erase ^H
stty -a 명령을 실행하면 현재 세션의 erase 값을 보실 수 있습니다.
윈도용 터미널 클라이언트로 putty, xshell 정도가 유명하고
이 프로그램들은 접속 설정에서 백스페이스를 어떤 값으로 보낼지 설정할 수 있습니다.
Ctrl+h, ^? 두개 중에 설정 가능하고 이 값이랑 서버의 stty erase 값이 일치해야만 백스페이스 기능이 올바르게 동작합니다.
가령, 유닉스 서버에 원격 접속하여 백스페이스를 눌렀는데 ^H^H^H^H 문자가 계속 찍힌다면
stty ersae 값은 ^? 으로 되어 있고 터미널 클라이언트에서는 백스페이스 값을 ^H 으로 보내고 있는겁니다.
만약에 백스페이스를 입력 했을 때 ^?^?^?^? 문자가 찍힌다면 위와 반대의 경우라고 할 수 있겠네요.
짐작 하셨겠지만 터미널 클라이언트와 stty erase (또는 터미널의 terminfo) 값을 똑같이 맞춰주면 문제는 해결됩니다.
백스페이스의 아스키 값이 127이니 일반적으로 ^? 으로 통일하는게 일관성이 있습니다.
그리고 아무 설정도 하지 않고 erase 문자도 ^? 로 맞췄는데 ctrl+h 가 백스페이스 키로 동작할 때가 있습니다.
vt220 혹은 linux콘솔에서는 ctrl+h이 터미널 제어문자가 아닌 프로그램 독립적으로 설정이 가능한데
bash에서 bind 설정이 \C-h: backward-delete-char 으로 되어 있다면 백스페이스 키로 동작합니다.
emacs나 vim에서도 개별적으로 설정이 가능하고요.
bash의 C-h 설정은 초기화 파일에 아래 코드를 추가하면 됩니다.
bind '"\C-h": backward-delete-char'
xorg 환경에서 xterm을 사용하는 경우에도 BS, DEL값을 설정해야 합니다.
vt100에뮬레이터 특성상 BS, DEL키를 비슷하게 에뮬레이트 하는데 현대의 설정으로 맞춰야만 탈이 없습니다.
홈 디렉토리의 .Xresources 파일에 아래 설정을 추가합니다.
XTerm*backarrowKeyIsErase: false
XTerm*ptyInitialErase: true
XTerm*deleteIsDEL: false
XTerm*ttyModes: erase ^?
XTerm*vt100.backarrowKey: false
XTerm*vt100.Translations: #override \
<Key>BackSpace: string(0x7f)\n\
<Key>Delete: string(0x1b) string("[3~")\n\
<Key>Home: string(0x1b) string("[1~")\n\
<Key>End: string(0x1b) string("[4~")
이 정도면 BS, DEL의 혼란은 더 이상 없으실거라 생각하고요.
혹시 내용에 잘못 된 부분이 있으면 지적 부탁드립니다.
e. 내용 보충합니다.
putty나 xshell 설정에서 터미널 종류에 따라 백스페이스 코드를 미리 맞춰주면 혼란을 줄일 수 있습니다.
타입이 linux 일때는 ^? 값으로 지정하면 되고 그외 vt100, vt220, xterm 일때는 ^H로 하시면 됩니다.
아래 사이트에서 터미널 타입 별로 미리 정의된 kbs 값을 체크하실 수 있습니다.
ÇØ´çÁõ»óÀÌ ºó¹øÈ÷ ¹ß»ýÇߴµ¥ ´Ù½Ã Á¤µ¶ÇÏ°í³ª¼ Á¤¸®ÇغÁ¾ß °Ú³×¿ä