Skip to content

Latest commit

 

History

History
222 lines (134 loc) · 9.28 KB

Bash Reference Manual.md

File metadata and controls

222 lines (134 loc) · 9.28 KB

IEEE Std 1003.1

셸의 소개

  1. 입력 문자열을 인용 규칙을 준수하며 metacharacter 기준으로 단어 및 연산자, 즉 토큰으로 분해한다.
  2. 토큰을 Simple / Compound Command로 파싱한다.
  3. 셸 확장을 수행한다. 환경 변수 확장이 일어난다.
  4. 리디렉션을 수행하고 아규먼트 리스트에서 리디렉션 관련 연산자 및 피연산자를 제거한다.
  5. 명령을 실행한다.
  6. 명령이 종료되는 것을 대기한 후 exit status를 저장한다.

이때 metacharacter에는 space, tab, newline, |, <, >가 있다.

인용 규칙

quoting이라 함은 홑따옴표나 쌍따옴표로 문자열의 특정 부분을 감싸는 것이다. 이때 metacharacter는 특별한 의미를 상실하게 되며 토큰으로 쪼개지지 않게 된다.

홑따옴표 인용

2개의 홑따옴표 사이에 온 문자들은 그 내용이 그대로 전달된다. 홑따옴표 쌍 사이에 홑따옴표 쌍이 겹쳐 있는 경우는 인정하지 않는다. 그러한 경우 2개의 겹치지 않은 쌍으로 해석한다.

쌍따옴표 인용

이는 홑따옴표 인용과 동일하나 $은 여전히 환경 변수를 확장한다는 의미를 가진다.

Simple Command

Simple Command는 <space>로 구분되고 <newline>으로 끝나는 단어들이다.

이때 첫 단어는 실행 파일의 이름이고 나머지는 매개 변수의 값이다. 이 명령의 exit status를 waitpid()로 회수해야 한다.

Pipeline

|로 연결된 simple command들이다. 각 simple command는 각자의 프로세스에서 실행되어야 한다.

마지막 simple command의 exit status가 pipeline의 status가 된다.

파라미터

파라미터는 값을 담을 수 있는 어떤 것이다. 이때 값은 무언가의 이름일 수도 있고, 숫자 또는 특수문자일 수 있다.

변수는 이름이 붙은 파라미터이다. 하나의 값을 가지며 0개 이상의 속성을 가진다.

무언가에 값을 지정하면 파라미터가 생겨난다. 값 자체는 없어도 (NULL) 무관하며, 빈 파라미터가 생성된다. 이는 unset 명령을 통해 없앨 수 있다.

파라미터에 지정되는 값은 저장되기 전 모두 셸 확장을 거친다.

특별한 파라미터

$?은 마지막으로 수행된 명령의 exit status를 담고 있다.

셸 확장

셸 확장이 일어나기 위해서는 기본적으로 다음과 같은 문법을 따라 문자열이 등장해야 한다. ${parameter}

이때 parameter가 한자릿수 이상의 숫자거나 (위치 파라미터) parameter 뒤에 문자가 올 시 {}가 필요하다.

리디렉션

here-document

here-document의 기본 문법은 다음과 같다.

<< word
	here-document
delimeter

이때 word에 대해서 파라미터 확장은 일어나지 않는다. 다만 따옴표가 남아있을 시 이들은 제거된다.

delimeter는 앞 뒤에 공백 없이 word와 완전히 일치할 경우 인정된다.

word에 따옴표가 있을 시 here-document 내용은 확장되지 않는다. 반대의 경우 확장이 일어난다.

Simple Command 실행

Simple Command를 실행하려면 확장, 리디렉션을 수행해야 한다. 커맨드는 왼쪽에서 오른쪽으로 토큰을 읽으며 차례대로 실행한다. 자세한 방법은 다음과 같다.

  1. 리디렉션 관련 단어일 경우 추후 처리할 수 있게 저장해 놓는다.
  2. 위에 해당하지 않는 단어는 확장을 거친다. 결과가 1개 이상 단어일 시 첫 단어가 명령 이름, 나머지는 매개변수다.

리디렉션만 하는 명령어는 셸 환경 변수를 조작할 수 있다. 그렇지 않고 다른 행동까지 포함하는 명령어에서 지정된 변수는 해당 명령에서만 사용 가능하다.

이것은 전자는 본래 프로세스에서 실행되는 명령이지만 후자는 fork()된 새 프로세스에서 실행되기 때문이다.

실행 파일 탐색 및 실행

  1. 명령어에 슬래시가 없을 시 실행 파일의 실제 위치를 찾으려 시도한다.
  2. 빌트인 명령어의 이름과 일치할 시 이를 실행한다.
  3. 일치하지 않는데 슬래시가 없을 시 $PATH에서 그 실행 파일이 있는 디렉토리를 찾으려 한다. 없을 시 코드 127 반환
  4. 실행 파일을 찾았거나 이름에 슬래시가 있을 시 별도의 환경에서 실행한다. 이때 아규먼트 0번은 파일의 이름, 나머지는 simple command의 나머지 단어들을 순서대로 입력한다.
  5. 파일을 실행할수 없고, 파일이 디렉토리가 아닐 시, 셸 스크립트로 간주하여 실행한다.
  6. 명령이 실행되는 것을 기다리고 종료 코드를 회수한다.

명령이 실행되는 환경

프로그램이 실행될 때 프로그램이 열어 놓은 파일이나 현재 디렉토리 등을 프로그램의 환경이라고 한다. 빌트인이 아닌 simple command가 실행될 시 다음 환경 요소들을 그대로 복제한 새 환경에서 실행된다.

  1. 열린 파일 (fd table)
  2. 현재 디렉토리 (CWD)
  3. 파일 생성 모드 마스크 (umask)
  4. export 속성이 켜져 있는 변수 및 커맨드 실행 시 export된 변수

subshell이란 원본 셸의 복사본이다. 명령 탐색을 통해 실행된 명령, 파이프라인 내에서 실행된 빌트인 명령은 subshell에서 실행된다.

환경이란?

환경은 "이름=값"의 쌍으로 구성된 문자열이다. C 언어에서는 getenvchar** envp 변수를 통해 접근할 수 있다. 셸이 실행 시 찾아낸 모든 이름들에 대해 export 속성을 켠 채로 파라미터를 생성한다.

커맨드를 실행할 시 기본적으로 환경은 유지된다. 외부 명령을 실행하기 전 $_ 변수를 해당 명령의 절대경로 (full pathname)으로 설정해야한다.

Exit Status

Exit Status는 0 이상 256 미만 값을 가진다. 이 중 125를 초과하는 값은 셸이 특별한 의미로 사용한다.

  • 0: 성공
  • 128 + N: 치명적 신호 N번에 의해 종료됨
  • 127: 커맨드를 찾지 못함
  • 126: 커맨드를 찾았지만 실행할 수 없음
  • 양수: 명령 이름을 찾거나 리디섹션을 하던 중 오류 발생

마지막으로 실행된 명령의 Exit status는 $?에 저장된다.

시그널

  • Interactive 모드에서는 SIGTERM을 무시한다.
  • SIGINT는 새 프롬프트를 띄우거나 빌트인 명령을 중지시키는 등 적절히 처리한다.
  • 항상 SIGQUIT는 무시한다.
  • SIGHUP을 받을 시 셸이 종료된다.
  • 빌트인이 아닌 명령은 부모 셸에서 시그널 핸들러를 상속받는다.

명령이 실행되는 중 생성된 키보드 시그널은 셸에게도 전달된다. 이것은 셸과 셸이 생성한 명령 프로세스는 같은 프로세스 그룹에 속해있기 때문이다. SIGINT를 받았다면 명령이 끝나기를 기다린 후 새 프롬프트를 띄우면 된다.

  • Ctrl+CSIGINT
  • Ctrl+\SIGQUIT
  • Ctrl+DEOF 전달

스크립트

셸을 실행할 시 첫 아규먼트로 파일 이름을 넣으면 해당 파일을 읽어 실행하게 된다. 이때 $0은 파일의 이름, $1$N은 나머지 아규먼트가 된다.

셸이 명령 이름 탐색을 수행할 때 이름이 일치하고 실행 비트(chmod)가 켜진 스크립트 파일을 찾을 시 실행하려고 시도하게 된다. 즉 셸에 ./script arguments 라고 입력하는 것은 minishell ./script argument 와 같다.

스크립트의 첫 줄에 #!가 있을 시 Shebang 절차에 의거 해당 파일을 해석할 프로그램을 찾아 넘긴다.

빌트인 명령

echo

echo [-n] [args …]

args들을 <space>로 구분하고 <newline>을 끝으로 출력한다. 이때 -n 옵션이 켜졌을 경우 끝에 <newline>을 출력하지 않는다.

exit status는 쓰기 오류가 없는 한 0이다.

cd

cd [dir]

dir로 현재 디렉터리 (Current Working Directory)를 바꾼다. dir가 제공되지 않을 시 $HOME의 값으로 변경한다.

..는 상위 디렉터리, -$OLDPWD의 값으로 변경한다. -를 사용했다면 STDOUT에 새 pwd의 절대경로를 출력한다.

cd가 성공했다면 $PWD에 새 pwd를, $OLDPWD에 이전 pwd를 저장한다.

exit status는 성공시 0, 실패시 0이 아닌 값이다.

pwd

pwd

현재 디렉토리를 STDOUT에 출력한다. exit status는 성공시 0, 실패할 경우 0이 아닌 값이다.

export

export [name[=value] ...]

name이 제공되지 않을 시 현재 export된 모든 변수를 표시한다. name이 제공될 시 해당 변수의 export 속성을 켠다. =value가 제공될 시 해당 name에 값을 할당한다.

올바르지 않은 옵션을 입력하거나 올바르지 않은 name이 입력될 시 0이 아닌 값을, 그렇지 않을 경우 0을 반환한다.

export 출력 형식

declare -x NAME="VALUE"

unset

unset [name ...]

name를 변수에서 삭제한다. 제거에 성공시 0, 실패할 시 0이 아닌 값을 반환한다.

env

env

환경 변수의 목록을 출력한다.

성공시 0, 실패시 양수를 반환한다.

exit

exit [n]

n을 exit status로 셸을 종료한다. n이 제공되지 않을 시 마지막 실행된 명령의 status가 반환된다.