Shell
동작 방식
- 파일 또는 터미널로부터 입력을 받는다.
- 따옴표 규칙을 지키며 입력을 단어와 연산자로 쪼갠다. 이러한 토큰들은 메타문자로 구분된다.
- 토큰들을 간단하고 복합된 명령어로 파싱한다.
- 다양한 shell 확장을 진행한다.
- 필요한 리다이렉션들을 수행하고 해당 연산자와 피연산자들을 인자 리스트에서 제거한다.
- 명령을 실행한다.
- 선택적으로 명령이 끝나기를 기다렸다가 종료 상태를 수집한다.
Shell 확장 (Shell Expansions)
파일명 확장 (filename expansion)
- 기능
- 와일드카드 등의 문자가 경로나 파일로 확장된다.
예시
1 2
$ echo * Applications Code Desktop Documents Downloads Library Movies Music Pictures goinfre
- 기타
다음과 같은 옵션을 추가해 파일을 지칭할 수도 있다.
문자 클래스 매칭 문자 [:alnum:] 모든 알파벳과 숫자 [:alpha:] 모든 알파벳 [:digit:] 모든 숫자 [:lower:] 소문자 알파벳 [:upper:] 대문자 알파벳 예시
1 2 3 4 5
$ echo * Test2 Test4 test1 test3 $ echo [[:lower:]]* test1 test3
틸드 확장 (tilde expansion)
- 기능
- 틸드
~
문자를 유저 홈 디렉토리로 해석한다.
- 틸드
예시
1 2
$ echo ~ /Users/taehooki
산술 확장 (arithmetic expansion)
- 기능
- 계산기와 유사하게 사용할 수 있다. 정수 간의 연산만 가능하다.(zsh는 가능)
$((expression))
와 같이 사용한다.사용 가능한 연산자는 다음과 같다.
연산자 설명 + 덧셈 - 뺄셈 * 곱셈 / 나눗셈(소수가 아닌 몫만 구해진다) % 나머지 ** 거듭제곱
예시
1 2
$ echo $((6 * 7)) 42
1 2
$ echo $((6 / 5)) 1
중괄호 확장 (brace expansion)
- 기능
- 임의의 문자열을 생성한다.
- 패턴들은 콤마로 나뉘어진다.
..
과 같이 사용하면 범위를 표현할 수 있다.
예시
1 2
$ echo a{d,c,b}e ade ace abe
1 2 3 4 5 6 7
$ touch a{d,c,b}e $ ls -l total 0 -rw-r--r-- 1 taehooki 2022_seoul 0 Nov 21 15:46 abe -rw-r--r-- 1 taehooki 2022_seoul 0 Nov 21 15:46 ace -rw-r--r-- 1 taehooki 2022_seoul 0 Nov 21 15:46 ade
1 2
$ echo {a..z} a b c d e f g h i j k l m n o p q r s t u v w x y z
매개변수 확장 (shell parameter expansion)
- 기능
- 변수를 사용할 수 있다.
${parameter}
와 같이 사용한다.
예시
1 2
$ echo $USER taehooki
- 기타
변수를 정의하는 방법은 다음과 같다.
1
$ my_variable=42
1 2
$ echo $my_variable 42
명령어 치환 (command substitution)
- 기능
- 명령어의 출력이 명령어 자신을 대체할 수 있다.
- 예시
파일의 경로를 찾는 명령어인 which를 통해 brew의 위치를 찾으면 다음과 같이 출력된다.
1 2
$ which brew /Users/taehooki/.brew/bin/brew
이 때 해당 명령어를
$(command)
또는command
로 묶어 다음과 같이 사용하면 위 명령어의 결과가 해당 명령어를 대체하게 된다.1 2
$ ls -l $(which brew) -rwxr-xr-x 1 taehooki 2022_seoul 4565 Nov 18 16:03 /Users/taehooki/.brew/bin/brew
단어 분할 (word splitting)
- 설명
- 셸에서는 $IFS의 각 문자를 구분자로 취급하고 단어를 분할하는 데 사용한다.
- IFS (Internal Field Separator)
- 외부 프로그램을 실행할 때 입력되는 문자열을 나누는 기준이 되는 문자를 정의하는 환경 변수
- 기본값 : 공백, 탭, 개행문자
- IFS (Internal Field Separator)
- 셸에서는 $IFS의 각 문자를 구분자로 취급하고 단어를 분할하는 데 사용한다.
용어 정리
- POSIX
- Unix 기반의 오픈 시스템 표준
- builtin
- 파일 시스템 내의 실행가능한 프로그램 형태로 있지 않고, 셸 자체에 내장되어 있는 명령어
- control operator
- 제어 기능을 하는 토큰
- 개행문자 또는 다음 중 하나이다 :
||
,&&
,&
,;
,;;
,;&
,;;&
,|
,|&
,(
,)
.
- exit status
- 명령어에 의해 호출자에게 돌아온 값.
- 8비트로 제한되어 있으며 최대 값은 255.
- field
- 셸 확장들 중 하나의 결과로 나온 문자의 단위.
- 확장 이후에 실행될 때 , 필드들은 명령어 이름과 인자로 사용된다.
- job
- 파이프라인을 구성하는 프로세스들의 집합, 해당 프로세스에서 나온 같은 프로세스 그룹에 속하는 다른 프로세스들.
- job control
- 사용자가 프로세스의 실행을 선택적으로 중지하고 재개할 수 있는 메커니즘
- metacharacter
- 따옴표로 감싸져있지 않을 경우 단어를 분리시키는 문자
- 공백, 탭, 개행문자 또는 다음 중 한 문자이다
|
,&
,;
,(
,)
,<
,>
.
- operator
- control operator와 redirection operator가 있다.
- 연산자는 최소 한 개의 따옴표가 없는 metacharacter를 포함한다.
- process group
- 동일한 프로세스 그룹 ID를 가진 연관된 프로세스들의 집합
- process group ID
- 프로세스 그룹을 대표하는 고유한 식별자. 프로세스의 lifetime동안 사용한다.
- reserved word
- 셸에서 특별한 의미를 갖는 word. for, while 등이 있다.
- return status
- = exit status
- signal
- 프로세스가 커널에 의해 시스템 내에서 이벤트의 발생을 전달받는 메커니즘
- token
- 셀에서 하나의 유닛으로 취급받는 일련의 문자들
- word 또는 operator 중 하나이다.
- word
- 셀에서 하나의 유닛으로 취급받는 일련의 문자들
- 따옴표 없는 metacharacters는 제외한다.
파싱
리다이렉션
- 입력
>
: 표준 출력을 리다이렉션한다. 동일한 파일이 존재한다면 덮어 쓰여진다.>>
: 표준 출력을 리다이렉션한다. 동일한 파일이 존재한다면 뒷부분에 이어서 쓴다.
- 출력
<
: 표준 입력을 리다이렉션한다.<<
: here document. 뒤에 오는 구분자가 올 때까지 입력을 받는다.
환경 변수
- 의미
- 프로세스가 컴퓨터에 동작하는 방식에 영향을 미치는 동적인 값들의 모임
- 셸 변수(shell variable)와의 차이점
- 환경 변수는 global 하게 사용가능한 변수이다.
- 그에 반해 셸 변수는 현재의 셸에서만 사용가능한 변수이다.
- 명명 규칙
- 대문자, 소문자, 밑줄 문자(
_
)만이 올 수 있다.
- 대문자, 소문자, 밑줄 문자(
사용 예시
1 2 3
$ QUESTION=ANSWER $ echo $QUESTION ANSWER
- env, declare, export의 차이점
- env : 단일 명령에 대한 환경 변수를 설정할 수 있다.
- declare : 셸 변수를 설정한다.
- export : 셸 변수를 환경 변수로 만든다.
전역변수
- data 영역에 위치한다.(정적 변수와 동일)
- 별도의 초기화를 하지 않으면 0으로 초기화 된다.
터미널, 콘솔, 셸, 커널의 차이점
터미널 (terminal)
- 터미널을 실행했을 때 켜지는 사각형의 창
- 사용자로부터 명령어 형식의 입력을 받아서, 출력을 화면에 표시하는 역할
- 정보를 처리하는 것이 아님
콘솔 (console)
- 윈도우OS 상에서 터미널의 또 다른 이름
- 콘솔은 직접 실행시키는 것이 아니라 명령 프롬프트를 통해서 실행시킨다.
셸 (shell)
- 터미널 상에서 명령을 입력하고 엔터를 눌렀을 때 터미널이 명령어를 넘겨주는 곳
- 종단 사용자(end-user)와 커널 사이의 인터페이스
- 예시) TCSH, KSH, Seashell, Bash
커널 (kernel)
- OS의 제일 안쪽에 위치한 프로그램
- shell이 사용자의 명령을 커널의 언어로 변환하면, 커널은 OS 라이브러리와 디바이스 드라이버를 사용해 명령어를 실행시킨다.
과제 허용 함수
- readline
- 헤더
#include <readline/readline.h>
사용 예시
1 2 3 4 5 6 7 8 9 10 11 12 13
int main(void) { char *str; while (1) { str = readline("minishell$ "); if (strlen(str) == 0) continue ; printf("you typed : %s\n", str); free(str); } }
- 기타
- 컴파일 시
-lreadline
과 같이 include 옵션 지정
- 컴파일 시
- 헤더
- rl_on_new_line
- 함수 원형
int rl_on_new_line(void)
- 설명
- 업데이트 함수에게 새 줄로 이동했다는 것을 알려준다. 주로 개행을 출력한 이후에 사용한다.
- 함수 원형
- rl_replace_line
- 함수 원형
void rl_replace_line (const char *text, int clear_undo)
- 설명
- rl_line_buffer의 내용을 변경한다.
- 기타
컴파일 시 include path 지정
1
-lreadline -L${HOME}/.brew/opt/readline/lib -I${HOME}/.brew/opt/readline/include
- 유의사항
- stdio.h를 readline헤더보다 먼저 include 해야함
- 함수 원형
- rl_redisplay
- 함수 원형
void rl_redisplay(void)
- 설명
- rl_line_buffer를 프롬프트에 재출력해준다.
- 함수 원형
- add_history
- 함수 원형
add_history(const char *string)
- 설명
- string을 history list 맨 뒤에 위치시킨다.
- 함수 원형
- wait
- 헤더
#include <sys/wait.h>
- 함수 원형
pid_t wait(int *status)
- 인자
- status : 종료된 자식 프로세스의 상태가 저장됨
- 정상 종료된 경우 : 하위 8비트에는 0, 상위 8비트에는 종료시
exit()
에 들어있던 인수 - 비정상 종료된 경우 : 하위 8비트에는 종료시킨 시그널 번호, 상위 8비트에는 0
- 정상 종료된 경우 : 하위 8비트에는 0, 상위 8비트에는 종료시
- status : 종료된 자식 프로세스의 상태가 저장됨
- 헤더
- getcwd
- 헤더
#include <unistd.h>
- 함수 원형
char *getcwd(char *buf, size_t size);
- 설명
- 현재 디렉토리의
full path
를\0
로 끝나는 문자열로buf
에 저장
- 현재 디렉토리의
- 인자
buf
:full path
를 저장할 저장공간size
:buf
에 할당된 저장공간 크기
- 반환값
- 성공한 경우 : 경로명에 대한 포인터
- 실패한 경우 : NULL 포인터 반환. errno 설정.
- 기타
- buf가 NULL인 경우 자동으로 공간을 할당해준다.
- 헤더
- chdir
- 함수 원형
int chdir(const char *path)
- 설명
- 현재 작업 디렉토리를 변경한다.
- 인자
path
: 디렉토리의 경로명
- 반환값
- 성공 : 0 반환
- 실패 : -1 반환. errno 설정.
- 함수 원형
- stat
- 헤더
#include <sys/stat.h>
- 함수 원형
int stat(const char *path, struct stat *buf)
- 설명
- path가 가리키는 파일의 정보를 가져온다.
- 인자
path
: 상태를 알아볼 파일의 경로buf
: 상태를 저장할 stat 구조체
stat 구조체
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
struct stat { dev_t st_dev; /* ID of device containing file */ mode_t st_mode; /* Mode of file (see below) */ nlink_t st_nlink; /* Number of hard links */ ino_t st_ino; /* File serial number */ uid_t st_uid; /* User ID of the file */ gid_t st_gid; /* Group ID of the file */ dev_t st_rdev; /* Device ID */ struct timespec st_atimespec; /* time of last access */ struct timespec st_mtimespec; /* time of last data modification */ struct timespec st_ctimespec; /* time of last status change */ struct timespec st_birthtimespec; /* time of file creation(birth) */ off_t st_size; /* file size, in bytes */ blkcnt_t st_blocks; /* blocks allocated for file */ blksize_t st_blksize; /* optimal blocksize for I/O */ uint32_t st_flags; /* user defined flags for file */ uint32_t st_gen; /* file generation number */ int32_t st_lspare; /* RESERVED: DO NOT USE! */ int64_t st_qspare[2]; /* RESERVED: DO NOT USE! */ };
- 반환값
- 성공 : 0 반환
- 실패 : -1 반환. errno 설정.
- 헤더
- unlink
- 함수 원형
int unlink(const char *path);
- 설명
- 디렉토리 엔트리를 제거한다.
- 디렉토리 엔트리란?
- 디렉토리를 표현하는 데에 사용되는 자료구조
- 보통 파일 이름, 파일 속성 등 파일에 대한 다양한 정보가 저장됨.
- 유닉스 계열에서는 파일명과 아이노드 번호만 저장됨.
- 디렉토리 엔트리란?
- 이름이 path인 링크를 제거하고 해당 링크가 참조한 링크 카운트를 감소시킨다.
- 링크 카운트가 0이 되고 아무 프로세스도 파일을 열고 있지 않다면 해당 파일에 대한 리소스가 회수된다.
- 링크 카운트가 0이지만 누군가 파일을 열고 있다면 해당 파일이 닫힐 때까지 파일의 삭제가 미뤄진다.
- 디렉토리 엔트리를 제거한다.
- 함수 원형
- execve
- 함수 원형
int execve(const char *path, char *const argv[], char *const envp[]);
- 설명
- 파일을 실행한다.
- 호출한 프로세스를 새 프로세스로 변환한다.
- 인자
path
: 실행할 파일의 경로argv
: 인자 목록envp
: 환경 변수 목록
- 함수 원형
- dup
- 함수 원형
int dup(int fildes);
- 설명
- 존재하는 파일 디스크립터를 복제한다.
- 반환값
- 성공 : 새로운 파일 디스크립터
- 실패 : -1 반환. errno 설정.
- 함수 원형
Ref.
GNU shell expansions
Shell expansions
환경 변수 - 위키백과, 우리 모두의 백과사전
bash - Environment variable vs Shell variable, what’s the difference? - Ask Ubuntu
[LINUX] IFS
Here document - Wikipedia
[minishell] 사용 가능 함수 정리
디렉토리 엔트리 - 위키백과, 우리 모두의 백과사전
bash - What is the difference between set, env, declare and export when setting a variable in a Linux shell?
What is Terminal, Console, Shell and Kernel? - GeeksforGeeks
01.리눅스 기초 - 쉘(Shell)과 디렉토리 구조