Memory
Disk(디스크) : Kernal, Utility(bash, Is)
커널 : 커널은 부팅될때 가장 먼저 운영채제가 메모리에 올라가도록 한다(로딩함). 내 컴퓨터가 꺼질떄까지 존재함
Utility(bash, Is) : On demand 한 특징을 지님. 즉, 실행시간에 캐쉬 같은것을 무시하면 로딩된다. 즉 utility 란 프로그램임
shell : utility 의 일종이다. 사용자로부터 입력된 명령을 읽고, 그 입력된 명령들을 interpret 해서 다른 utility 를 실행할 수 있도록 커널에 요청하는 역항을 수행한다.
=> 다른 uitlity 를 관리하기 위한 utility 라 할 수있다.
bash shell : 리눅스에서 대부분 사용. shell 프로그램은 On demand 하다.
=> shell 에서 $ ./a.out 과 같은 명령을 입력하면, 이 shell 프로그램이 fork 를 한다. 즉, 디스크에 있는 a.out 실행파일을 메모리에 올린다.
test.c 와 같은 실행파일을 컴파일 및 실행하면, 아래와 같이 디스크 상에 바이너리 형태의 실행파일(a.out)이 생성됨
그러고 나서 shell 에서 $ ./a.out 과 같은 명령을 입력하면, 이 shell 프로그램이 fork 를 한다. 즉, 디스크에 있는 a.out 실행파일을 메모리에 올린다.
사용자로부터 입력받은 명령어를 interpret 하는 특별한 utility
interpret 후에 커널에게 다른 utility 를 실행할 수 있도록 요청한다.
종류 : Bourne Shell, C Shell, Korn Shell, Bourne again Shell
=> Bourne Shell : 최초의 shell
Bourne again Shell : GNU 프로젝트에서 Brain Fox 라는 사람이 만듦. 대부분의 기능을 포함하고 있고, ubuntu 나 페도리와 같은 다양한 리눅스 환경에서의 디폴트 shell 이다.
쉘 명령어
$ whoamdi : 계정 정보 나옴
$ bash --version : 버전정보
$ cat /etc/shells : 현재 사용 가능한 (유효한) login shell 듷을 보여줌
$ echo $SHELL : 현재 사용중인 shell 을 보여줌
앞으로 3주차 수업동안 리눅스 쉘에서 수행가능한 다양한 명령어들과, 이런 명령어들의 묶음을 텍스트 파일로써 쉘 프로그램을 만들 것이다!
쉘뿐만 아니라 많은 리눅스 utility 프로그램들은 수행에 필요한 정보(ex. 현재작업위치(Current Working Directory)) 들을 변수로써 정의해 놓았다.
즉, 프로그램이 동작하는 방식에 영향을 미치는 값들의 모임
EX) "$ ./a.out" 와 같이 실행시키면,
$ => 이 쉘 프로그램이 부모 process 가 되며,
./a.out => 이 쉘 프로그램이 자식 process 가 되는것인데,
부모 process 의 쉘 프로그램 중에서 환경변수만 카피해서 전달이된다. 즉, 환경변수들은 자식 process 들에게 상속된다! (카피된다)
=> 즉, 부모 proecess 의 환경변수를 수정하게 되면, 부모 process 에게는 영향을 주지 않아도 또 다른 자식 process 에게는 영향을 준다.
쉘 명령어
- $변수명 = 값 : 새로운 쉘 변수 생성 및 값 할당
- echo $변수명 : 쉘 변수에 저장된 값 출력
- set : 쉘 변수 목록을 확인 (모든 쉘 변수들의 변수명과 값을 출력)
- unset 변수명 : 쉘 변수 삭제
- 명령어1 | 명령어2 : 앞에있는 명령어의 표준출력을 다음 명령어의 표준입력으로 전달하는 기법
- (ex. set / grep 변수명 : set을 grep 이라는 명령의 표준입력을 전달하는것이다. 이때 grep 이란 입력받은 파일 또는 입력에서 문자열을 찾는 명령어. 즉 set 에서 변수명에 해당하는 변수를 찾는다 )
- grep : 입력받은 파일 또는 입력에서 문자열을 찾는 명령어
- more : 리눅스에서 파일 내용을 확인하는 명령어들 중에 하나로, 파일을 읽어 화면에 화면 단위로 끊어서 출력하는 명령어
- set more : 출력되는 쉘 변수들의 정보들을 화면 단위로 끊어서 보여줌 (엔터치면 다음 화면 단위로 넘어감)
- type 명령어 : 어디에 위치해 있는 utility 인지 확인(경로 출력)
(type more : utility 인 more 의 경로출력, type grep : grep 의 경로출력)
=> * 주의점
1) 빈공간(space) 를 잘못할시에 에러발생.
2) 대소문자를 구분함
3) 변수명 맨앞에는 알파벳이나 언더스코어("_") 만 올 수 있다.
environment 변수(환경변수) : 부모 process 로부터 상속받은(카피된) 변수
쉘변수는 현재 process(시점) 에서만 영향을 미치는 변수인 반면,
환경변수는 그 자식들에게 영향을 준다는 특징(상속)이 있다.
- export 변수명 = 값 : 환경변수 생성
- export -n 환경변수명 : 환경변수를 일반변수로 변환
- env (또는 printenv) : 환경변수 목록을 확인 (모든 쉘 환경변수들의 변수명과 값을 출력)
- printenv : env 와 동일한 명령어
( <-> set이 모든 쉘변수 목록 출력이라면, env는 쉘 환경변수 목록만 출력)- pstree : proecss의 상관관계(부모-자식 관계)를 트리 형태로 출력해주는 명령어로써, 관계를 트리 형태로 출력해주므로 계층 관계를 한 눈에 파악할 수 있다.
- exit : 현재 쉘에서 나오는 것
이떄 sub-shell 에다 일반변수 no1 는 전달이(카피가) 되지 않고, 환경변수 no2만 전달된다.
- export -n 환경변수명 : 환경변수를 일반변수로 변환
예제
위 그림예제에서 p 는 parent process, c 는 child process 를 의미
export -n no2 에서 환경변수 no2 는 일반변수로 변하게 되었다.
맨 마지막 child process 에서 echo no2 를 해보면 no2 가 환경변수가 아니라서, 즉 child process 에 no2 라는 변수가 존재하지 않으므로 조회가 안된다!
- env | grep no : 환경변수(env) 목록에서 no 라는 문자열 확인
- printenv | grep no : 환경변수 목록을 확인 ( = env | grep no 와 동일한 명령)
- env | wc -l : 라인(한 줄) 단위로 환경변수의 개수를 확인 (=> wc : word count, l : line)
- printenv | wc -l : env | wc-l 과 동일함
- pstree | grep bash
종류
- PATH : 현재 경로(디렉토리) // ex. PATH = /usr/local/sbin:/usr/ ~~
- HOME : Home Directory // ex. HOME = /home/fos
- PWD : Current Work Directory // ex. PWD = /home/students/common
- BASH : 현재 사용중인 쉘 이름 // ex. BASH = /bin/bash
- OSTYPE : OS 타입(종류) // ex. OSTYPE = Linux
ls : 현재경로에 있는 파일들
cd : 경로변경
pwd : 현재경로
PATH
cf) 기존의 PATH 에 할당된 디렉토리에 추가적인 디렉토리 정보를 추가하고 싶은 경우
- 형태 : PATH = $PATH":추가경로"
ex. PATH = $PATH":/home/you/bin"
기존 PATH가 PATH = /home/fos/bin:home/fos/.local/bin:/usr/ ~ /games:/snap/bin 이였다면,
새롭게 지정된 PATH 는
PATH = /home/fos/bin:home/fos/.local/bin:/usr/ ~ /games:/snap/bin/home/you/bin 이 된다.
HOME
cd 명령어 : 아무 인자없이 딸랑 cd만 적으면 HOME 디렉토리로 넘어감
cf) 내장된 HOME directory 를 변경하고 싶은경우
형태: $ HOME = 새롭게 지정할 경로(디렉토리)
리눅스에서 명령어를 입력시에 바로 실행되는 것이 아니다.
Bash 쉘이 먼저 command line (명령어) 를 스캔한다.
이떄 스캔시에 특별한 원소들(ex. 키워드, meta char)이 있는지 찾아보고 interpret 한 결고를 새로운 문자열 (command lone) 으로 변환한다.
=> 이러한 과정을 expanded(확장) 또는 substituted(치환) 라고 부른다.
생성 및 출력하고자 하는 문자열들의 일정한 패턴을 가지고 문자열들을 생성하는 확장작업
여러 expansion 과 substitutions 중에서 가장 먼저 일어나는 작업
prefix(접두사) 와 suffix(접미사) 을 이용해서 문자열들을 조합해서 확장할 수 있는 기능을 제공
주의) 단일 확장인 경우, 공백이 있는 경우에는 확장이 일어나지 않는다.
점 2개 ".." 를 사용해서도 사용가능 및 문자열이 생성된다. => 점 2개의 양끝에 있는 숫자는 start point 와 end point 가 된다.
ex) echo b{ed, olt, ar}s => 3개의 문자열 beds, bolts, 그리고 bars 가 생성 및 print 된다.
echo {5..12} 와 같이 start point = 5, end point = 12를 할당해서 5 ~ 12 사이의 숫자로 구성된 문자열 생성 및 출력가능
echo {5..k} 와 같이 숫자와 문자를 혼용 불가능
괄호 {} 가 여러개 있을 때 순서대로 문자열 생성 및 출력 처리후 그 다음 문자열 생성 및 출력 하는 과정으로 이루어짐
=> 즉, 위 예제에서는 A~Z 까지 문자 생성후에 a~z 까지 문자를 생성한다.
brace expansion 은 항상 확장이나 치환이 가장 먼저 일어난다는 것에 유의하자!
2번쨰 줄에 "$ echo {1,2} $ A" 에서 $ A 은 변수 치환(parameter expansion) 으로, 변수 치환보다 brace expansion, 즉 확장이 먼저 일어나서 "1 $ A" 와 "2 $ A" 라는 문자열이 먼저 생성되고
그 후에 변수 치환($ A 가 foo 로 치환)이 일어나서 1foo 와 2foo 라는 문자열을 얻을 수 있다.
(cf. 변수치환은 아래에서 설명!)
이에 따라 4번째줄 $ echo $ A{1,2} 를 보면 brace expansion 이 먼저 일어남에 따라
$ A1 과 $ A2 라는 문자열이 생성되고 변수치환이 일어나서 문자열에 foo1 과 foo2 가 생성 되는데, foo1 과 foo2 라는 변수는 존재하지 않으므로 null 이 출력되는 것이다.
touch 로 아래와 같이 txt 파일 생성가능
~ : HOME 변수를 치환한 변수
~+ : PWD 변수를 치환한 변수 (Current Working Directory 를 출력)
~- : OLDPWD 변수를 치환한 변수 (Previous Working Directory, 즉 바로 직전의 작업 디렉토리를 출력)
예제
디렉토리 구조를 보면 oss 라는 디렉토리가 가 상위에 있고, 그의 아래 디렉토리로 bin, prj 라는 디렉토가 있는 상태.
또 HOME 디렉토리 = oss 인 상태이다.
- 형태1 : $변수명
- 형태2 : ${변수명}
$ 뒤에 변수명을 주게되면, 이 변수에 해당하는 값으로 그 값이 치환되서 다른 command 에게 전달된다.
=> 쉽게말해, 해당 변수에 대한 값으로 치환되는 것
예제
HOME 변수에 저장된 값은 /home/inha/oss/pr 이다.
parameter expansion 이 발생해서 $HOME 을 하면 /home/inha/oss/pr 으로 치환 및 출력된다.
USER 변수, HOSTNAME 변수에 저장된 값은 inha, ubuntu 이다.
parameter expansion 이 발생해서 ${USER} 와 ${HOSTNAME} 은 각각 inha 와 ubuntu 로 치환된다.
- 형태1 : ${변수명:-할당할 값}
=> 의미 : 이러한 "변수명" 을 가진 값으로 치환해주세요. 단, 값이 없거나(unset) null 이 할당되어 있는 경우에는 "할당할 값" 이러한 값으로 디폴트 값을 넣어주세요!
- 형태2 : ${변수명-할당할 값}
=> unset 일때만 디퐅트 값 넣어주세요! 라는것 (null 이 할당되어 있는 경우는 디폴트 값을 넣지 않음)
OSS 변수에 값 null 이 할당된 상황이다.
$ echo ${OSS-1000} => null 이 할당된 경우는 디폴트 값을 넣지 않고 변수에 저장된 값 그대로 null 을 출력한다.
형태1 : $(명령어)
형태2: '명령어'
예제
whoami 명령어 : 사용자 계정을 알려줌(출력)
=> 이 명령어를 사용하고 나온 결과값이 inha 이다.
hostname 명령어 : 현재 호스트 이름을 알려줌(출력)
=> 이 명령어를 사용하고 나온 결과값이 ubuntu 이다.
중첩된 구조를 사용해야 하는 경우 '' 를 쓰지말고, $ 를 쓰자!
=> $ echo $(echo $(ls)) : $(ls) 가 먼저 command substitution 이 실행되고,
그 결과값을 기반으로 $(결과값) 을 실행해서 최종 결과값인 Test.txt 로 치환된다.
%Y%m%d 는 출력형식을 지정하는 것
형태1 : $((산술식))
형태2 : $[산술식]
그래서 이럴때 산수 연산을 하고 싶를때 arithmetic expression 을 사용하는 것이다.
지금껏 배운 연산중 3가지는 아래와 같다.
=> 이 3개의 연산은 모두 동시에 일어나되, 왼쪽에서 오른쪽 방향으로 연산이 수행된다.
$ echo $x $((x++)) $x
=> parameter expansion 과 command expansion 이 동시에 일어났는데,
연산이 왼쪽에서 오른쪽으로 수행된다.
즉 $x 가 수행되고, $((x++)) 가 수행되고, 마지막으로 $x 가 순서대로 수행된다.
- : 0개 이상의 문자들과 매칭되는 파일이름들에 대한 문자열로 확장되는 것 (현재 존재하는 working directory 안에서)
- ex)
- $ ls * : 현재 working directory 에 있는 파일 이름들에 대한 문자열을 출력
- $ ls a * : a 로 시작하는 파일이름 문자열을 보여줌(출력)
- ls * .c : .c 로 끝나는 모든 파일이름 문자열을 출력
- ? : 모든 단일문자(문자 하나) 와 매칭되는 파일이름들에 대한 문자열로 확장하는 것
- ex)
- $ ls ? : 어떤 단일문자가 와도 좋으나, 딱 하나의 문자로 구성된 파일이름을 문자열로 출력
- $ ls fo? : 파일이름이 앞에는 fo 이고, 그 뒤에 단일문자가 아무거나 와도되는 파일이름들로 구성된 문자열로 출력 (ex. 파일이름 : fo1, foo)
- [...] : 괄호 [] 안에 둘러싸인 모든 문자중 아무 단일문자를 가지는 파일 이름들에 대한 문자열을 출력
- $ ls [abc]* : a,b,c 중에 아무거나 맨 처음 시작문자로 가지는 파일이름들 출력 (ex. 파일이름 : aws_file, b_file)
touch 명령어 ㅣ 파일 생성
ls test?.py => filename expansion 은 존재하는 파일들에 대해서만 확장되는 거싱다. 즉, 확장자 .py 를 가지는 파일이 없다면 확장되지 않음
- 파일이름 확장(filename expansion) 은 brace expansion 이후에 발생한다는 것을 명심하자!
( brace expansion 이 확장과 치환에서 가장 먼저 일어난다고 앞서 배웠었다! )
예제
ls test?.[c-o] : file expansion => test 로 시작하고 + c 에서 o 까지 해당하는 모든 문자에 해당하는 파일이름을 출력
ls test?.{c..o} : brace expansion => 가장 먼저 brace 가 된다. 즉
test?.c 와 test?.d 와 같이 만들어놓고 이 중에서 와일드카드를 감안하여 존재하는 파일이름과 매칭된다.
ex. 공백문자, tab, 개행문자 등등
meta character 들의 특수한 기능을 없애기 위해 사용된다.
따옴표 종류: " ' " '
기본적으로 quotes 는 문자처리가 되서, single quotes (작은 따옴표 쌍) 을 하던 double quotes (큰 따옴표 쌍) 을 하던간에 그냥 단순하게 처리된다.
아래를 보면 그냥 문자처리 됨을 알 수 있다
그러면 언제 quotes 를 쓰는가?
아래를 보면 공백문자가 단어 사이마다 존재해서 hello 와 world 가 서로 다른 인자로써 ls 에게 전달이 된다. 즉, 각각이 서로 다른 파일로 보고 에러가 발생한다.
이럴때 따옴표로 묶어주면 하나의 인자로 ls 에 전달이 가능해진다!
아래 예제도 같은 원리로, * 가 와일드카드로 인식되지 않게 하고 싶다면 이럴때도
따옴표로 묶어주면 된다!
작음 따옴표 쌍과 큰 따옴표 쌍이 meta characters 에 대해서 서로 다르게 동작한다.
Quoting(따옴표 처리)는 어떤 미리 정의된 특정 문자들(meta characters)의 특별한 기능을 없애고 그냥 평범한 문자로 바꿔버림
1) Escape character ( \ )
2) Single quote ('')
3) Double quote ("")
큰 따옴표 안에 담긴 대두분의 meta character 의 기능을 제거시킴
단, parameter expansion(변수 확장) 과 command substitution(명령어 치환) 은 예외임.
즉, 변수확장 과 명령어 치환은 기능이 제거되지 않고, meta character 들이 그대로 기능을 수행한다.
$ touch \ *
=> meta character 인 * 의 기능을 없앤다. 즉, * 라는 파일이름을 가진 파일을 생성함
$ touch "this is a $USER"
=> 큰 따옴표에 안에 들어있는 meta characte 인 $ 는 기능을 상싱하지 않기 떄문에,
변수 확장(parameter expansion) 기능이 그대로 수행된다!