본 글은 bash 매뉴얼 번역본을 통해 minishell을 구현하는데에 있어서 필요할 것 같은 부분들만 내용을 짜집기한 글 입니다.
간단하게 설명하면 명령을 실행하는 매크로 처리기이다.
매크로 처리기란 텍스트와 심볼을 전개하여 더 큰 표현식을 만드는 장치
토큰: 셸에서 하나의 단위로 인식되는 연속된 문자들. 단어이거나 연산자.
메타문자: 따옴표를 제거했을 때 단어로 분리되는 문자들. 메타 문자는 스페이스, 탭, 개행이나 다음 중 하나입니다 |, &, ;, (, ), <, >
연산자: 제어 연산자나 리다이렉션 연산자
단어: 셸에서 하나의 단위로 처리되는 연속된 문자들. 단어는 따옴표가 제거된 메타문자를 포함하지 않을 수도 있습니다.
\
를 사용하더라도 '
출력 불가능$
, `, \
는 예외 (이력 전개 기능이 켜져있다면 !
도 포함)이력전개 기능 (Bash History Facilities)
set 빌트인에 -o history 옵션을 켜짐으로 설정했을 때, 이전에 입력한 명령어 리스트인 명령어 이력에 접근할 수 있도록 한다
복잡한 셸 명령어는 단순 명령어를 다양한 방식으로 조합하여 구성됩니다. 파이프라인을 사용해 한 명령어의 출력을 다음 명령어의 입력으로 사용하거나, 루프나 조건부 구조를 사용하거나, 다른 방식으로 그룹화할 수 있습니다.
파이프라인이란 제어 연산자의 하나인 '|', '|&'를 사용하여 나눠지는 하나 이상의 명령어 나열을 의미합니다.
파이프라인의 각 명령어의 출력은 파이프를 통해 다음 명령어의 입력으로 연결됩니다. 각 명령어는 직전 명령의 출력을 읽습니다. 명령어에 의해서 어떤 리다이렉션이 지정되기 전에만 이루어집니다.('|&'는 예외)
파이프라인의 종료 스테이터스는 pipefail 옵션을 켠 상태가 아니라면 파이프라인의 마지막 명령어의 종료 스테이터스입니다.
특수 문자를 사용하는 매개변수.
변수가 설정되면 unset 빌트인 명령어로만 제거할 수 있습니다.
최근에 실행된 명령어, 함수, 스크립트 자식의 종료 상태를 0과 1로 나타냄
리다이렉션을 이용해 파일 핸들을 복제, 열기, 닫기, 다른 파일에 대한 참조 만들기 그리고 명령어가 읽고 쓸 파일을 변경할 수 있습니다.
또한 리다이렉션은 현재 셸 실행 환경의 파일 핸들을 변경하기 위해서 사용할 수 있습니다. 다음의 리다이렉션 연산자는 앞에 두거나, 뒤에 두거나, 단순한 명령이라면 임의의 위치에 둘 수 있습니다.
리디렉션은 나타나는 순서대로 왼쪽에서 오른쪽으로 처리됩니다.
리다이렉션 연산자의 첫글자가
'<'라면, 리다이렉션은 표준 출력(파일 디스크립터 0)을 참조하며,
'>'라면 리다이렉션은 표준 출력(파일 디스크립터 1)을 참조합니다.
입력 리다이렉션은 word 를 전개하여 얻은 이름을 사용하는 파일을 열고, 파일 디스크립터 n으로부터 읽을 수 있도록 합니다. n이 지정되지 않았다면 표준 입력(파일 디스크립터 0)을 사용합니다.
[n]<word
출력 리다이렉션은 word 를 전개하여 얻은 이름을 사용하는 파일을 열고, 파일 디스크립터 n이 쓸 수 있도록 합니다.
n이 지정되지 않았다면 표준 출력(파일 디스크립터 1)을 사용합니다.
대상 파일이 존재하지 않는다면 만듭니다. 만약 파일이 존재하는 경우 파일의 내용물을 지우고 빈 파일로 만듭니다. (덮어쓰기)
[n]>[|]word
word를 전개하여 얻은 파일을 열고, 파일 디스크립터 n이 추가로 쓸 수 있도록 합니다. (이어쓰기)
n이 지정되지 않았다면 표준 출력(파일 디스크립터 1)을 사용합니다. 대상 파일이 존재하지 않는다면 만듭니다.
[n]>>word
셸에게 현재 소스로부터 (뒤따라오는 공백 문자가 없이) word를 포함하는 줄이 나타날 때까지를 입력으로 읽도록 지시합니다.
읽어들인 모든 줄은 표준 입력(파일 디스크립터 n이 지정되어 있다면 n)인 것처럼 취급됩니다.
[n]<<[-]word
here-document
delimiter
단순 명령어를 실행할 때, 셸은 다음의 전개, 할당, 리다이렉션을 왼쪽에서 오른쪽으로 순차실행합니다.
단순 명령어를 실행할 때, 셸은 다음의 전개, 할당, 리다이렉션을 왼쪽에서 오른쪽으로 순차실행합니다.
전개한 결과에 명령어가 존재하지 않을 경우, 변수 대입은 현재의 셸 환경에 적용됩니다. 그렇지 않으면 변수는 실행된 명령어의 환경에 추가되며, 현재의 셸 환경에는 영향을 주지 않습니다. 읽기 전용 변수에 대입을 시도한 경우, 명령어에서는 에러가 발생하며 0 이외의 스테이터스와 함께 종료됩니다.
명령어가 존재하지 않는 경우, 리다이렉션은 실행되지만 현재의 셸 환경에는 영향을 주지 않습니다. 리다이렉션 에러는 명령어가 0 이외의 스테이터스로 종료시킵니다.
전개 후에도 명령어가 남아있다면 다음 처리로 넘어가며, 남아있지 않다면 명령어 실행이 종료됩니다. 전개에 명령어 치환이 포함되어 있는 경우, 명령어의 종료 스테이터스는 마지막에 실행된 명령어 치환의 종료 스테이터스가 됩니다.
명령어가 단어로 분리된 이후, 그 결과가 단순 명령어와 인수 리스트라면 다음 동작을 수행합니다.
프로그램이 호출될 때, 환경이라고 불리는 문자열의 배열이 주어집니다. 이는 이름-값 쌍의 리스트로, name=value
의 형식입니다.
셸은 호출시에 자신의 환경을 스캔하고 발견한 이름마다 매개변수를 생성한 뒤, 자식 프로세스로 익스포트할 매개변수를 자동으로 표시해둡니다. 실행된 명령어는 환경을 상속합니다.
환경의 매개변수의 값이 수정되면 새 값은 이전 값을 대체하고 환경의 일부가 됩니다. 실행된 명령어에 상속된 환경은 셸의 초기 환경을 구성하며, 이는 unset
과 export -n
명령어를 통해 삭제할 수 있으며, export
, declare -x
를 통해 추가할 수 있습니다.
단순 명령어의 환경이나 함수는 Shell Parameters에서 설명된 것처럼 매개변수 대입을 앞에 두어서 일시적으로 변경할 수 있습니다. 이 대입식은 해당 명령어의 환경에만 영향을 미칩니다.
실행된 명령어의 종료 스테이터스는 waitpid 시스템 콜이나 이와 동등한 함수에 의해서 반환되는 값입니다.
종료 스테이터스는 0과 255사이의 값입니다만, 아래에서 설명하는 것처럼 셸은 125보다 큰 값을 특별한 의미로 사용합니다. 셸 빌트인 명령어와 복합 명령어의 종료 스테이터스는 이 범위로 제한됩니다.
셸에서는 종료 스테이터스 0으로 종료한 명령어는 실행 성공입니다. 0이 아닌 종료 스테이터스는 실패를 의미합니다.
set
빌트인에 -o history
옵션을 켜짐으로 설정했을 때, 셸은 이전에 입력한 명령어 리스트인 명령어 이력에 접근할 수 있도록 합니다.
HISTSIZE
셸 변수의 값은 이력 리스트에 저장할 명령어의 개수를 지정합니다. 마지막 $HISTSIZE
명령어의 텍스트(기본값은 500)가 저장됩니다. 셸은 매개변수나 변수를 전개하기 전에 각 명령어를 이력 리스트에 저장합니다.
셸이 시작할 때, HISTFILE
변수(기본값은 ~/.bash_history
)로 지정된 파일로 이력을 초기화합니다.
HISTFILE
의 값에 지정된 파일은 필요에 따라서 저장하고 있는 이력이 HISTFILESIZE
변수의 값에 지정된 줄 수 이하가 되도록 여분을 잘라냅니다.
이력 기능이 활성화된 상태에서 셸을 종료할 때, 마지막 $HISTSIZE
개의 줄이 이력 리스트로부터 $HISTFILE
로 지정한 파일에 복사됩니다.
histappend
셸 옵션이 켜져있다면, 이력 파일의 마지막에 추가되며, 옵션이 꺼져 있다면 이력 파일 전체를 덮어씁니다.
HISTFILE
이 설정되어 있지 않거나 이력 파일에 쓰기 권한이 없을 때, 이력은 저장되지 않습니다.
이력을 저장한 후, 이력 파일은 $HISTFILESIZE
개의 줄보다 많은 줄을 포함하지 않도록 여분을 잘라냅니다. HISTFILESIZE
가 설정되어 있지 않거나 또는 널, 숫자가 아닌 값, 0보다 작은 값이 설정되어 있다면, 이력 파일을 잘라내는 동작은 실행되지 않습니다.
셸은 어떤 명령어를 이력 리스트에 저장할지 제어할 수 있습니다. HISTCONTROL
과 HISTIGNORE
변수를 설정하면 셸은 입력된 명령어의 일부만 저장합니다.