여러분의 CS 교육에서 누락된 학기 - 셸

이 포스팅은 MIT 공개 강의를 바탕으로 작성되었습니다. https://missing.csail.mit.edu/


2021년 7월 1일

오랜만에 새 블로그 시리즈를 시작하게 되었습니다. 이번 시리즈에서는 MIT 공개 강의인 "여러분의 CS 교육에서 누락된 학기"를 수강하면서 배운 내용을 정리해보려고 합니다.

우리는 GUI에 익숙해져 있습니다. 분명 현재 상태와 조작 결과를 그래픽을 사용하여 직관적으로 볼 수 있다는 것은 큰 장점입니다. 그러나 GUI 상에서 우리는 오직 만들어져 있는 명령만을 컴퓨터에게 내릴 수 있습니다.

반면 을 사용하면 GUI로는 내릴 수 없는 다양하고 구체적인 명령을 컴퓨터에게 내릴 수 있게 됩니다. 늘 반복하는 작업을 자동화할 수도 있고 파일 권한을 바꾸는 것과 같은 명령도 내릴 수 있게 됩니다.

저의 실습 환경은 다음과 같습니다.

  • OS: MacOs
  • Shell: zsh
  • Terminal: iTerm2

셸 기초 사용법

셸 인터페이스

터미널을 켜면 기본적인 셸 인터페이스를 볼 수 있습니다.

Last login: Fri Jun 25 17:32:27 on ttys000

hyunochoi in ~ >

저의 환경에서는

  • 마지막 로그인 정보(최초 실행 시)
  • 유저네임(hyunochoi)
  • 현재 작업 디렉토리 정보(~)

를 표시해줍니다.

이러한 인터페이스는 셸마다 다를 수 있고, 사용자가 원하는 대로 꾸밀 수도 있습니다.🎨

셸 명령 내리기

GUI에서는 클릭으로 명령을 내렸다면, 에서는 명령어를 통해 컴퓨터에게 명령을 내리게 됩니다. 가장 간단한 것으로는 특정 프로그램을 실행하라는 명령을 내릴 수 있습니다.

hyunochoi in ~  > date
2021년 6월 28일 월요일 17시 25분 08초 KST

예시로 date라는 프로그램을 실행해보았습니다. 이 프로그램은 기본적으로 현재 시각을 출력해서 보여주는 기능을 가지고 있습니다.

hyunochoi in ~  > echo hello
hello

또다른 예시인 echo 프로그램은 전달받은 인자를 출력하는 기능을 갖고 있습니다. 여기서는 "hello"라는 문자열을 echo에게 인자로 전달하였습니다.

띄어쓰기와 인자

셸은 띄어쓰기를 기준으로 명령을 분할합니다. 가장 앞에 있는 단어를 실행할 프로그램으로 해석하고, 그 뒤에 띄어쓰기로 구분되어 있는 단어들을 인자로 해석합니다.

만약 방금 전의 예시에서 띄어쓰기가 포함된 문자열(예를 들면 "hello world")을 하나의 인자로 전달하고 싶다면 어떻게 해야할까요?

  1. '" 로 문자열을 둘러싸면 됩니다.
  2. 혹은, 공백 문자 앞에 \(탈출문자)를 붙여 공백이 갖는 분할의 의미를 없앨수도 있습니다.
echo 'hello world'
echo "hello world"
echo hello\ world

이 세 가지 명령어는 모두 같은 의미입니다.

셸이 프로그램을 찾는 법

우리가 평소 프로그램을 실행할 때는 프로그램의 실행파일을 더블클릭합니다(윈도우라면 .exe 파일) 그렇다면 셸에게 프로그램을 실행하라는 명령을 내리면 셸은 그 프로그램을 어떻게 찾는 것일까요?

아무 파일이나 만들어놓고 그 파일을 다른 디렉토리에서 경로를 주지 않고 실행할 수는 없습니다. 셸한테 프로그램을 실행하라고 명령할 때 우리는 경로를 주지 않았는데 (예를 들어 /bin/bash) 셸은 그 프로그램을 어떻게 찾아서 실행할까요?

셸은 프로그램 실행 명령을 받으면 프로그램의 위치가 적혀있는 일종의 '목록'을 훑어봅니다. 이 목록 역할을 하는 것이 바로 $PATH라는 환경 변수입니다.

echo $PATH 명령을 통해 저장되어 있는 환경 변수 목록을 볼 수 있습니다.

hyunochoi in ~  > echo $PATH
/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin

각 경로들은 :로 구분되어 있습니다. 셸이 경로 없이 프로그램명을 받으면 이 목록을 뒤져 실행할 프로그램이 어디에 있는지 찾습니다.

만약 어떤 프로그램이 있는 디렉토리를 찾고 싶다면 $PATH 목록을 뒤져볼 필요는 없습니다. which 프로그램에 찾고 싶은 프로그램명을 인자로 주면 해당 프로그램이 있는 디렉토리를 출력해줍니다.

hyunochoi in ~  > which date
/bin/date

이전 예시에서 사용한 date 프로그램의 위치는 /bin/date인 것을 확인할 수 있습니다.

$PATH에 등록된 프로그램만 실행할 수 있는 것은 아닙니다. 실행하고자하는 프로그램명 앞에 경로를 적어주면 $PATH를 거치지 않고 프로그램을 실행할 수 있습니다.

hyunochoi in /bin  > /bin/date
2021년 6월 28일 월요일 17시 44분 04초 KST

프로그램의 실행 결과는 똑같지만 여기서의 date 프로그램은 $PATH를 거치지 않고 실행되었습니다.

셸에서 디렉토리 탐색하기

기본적인 탐색

리눅스 계열 시스템에서 /로 시작하는 경로를 절대 경로, ./../로 시작하는 경로를 상대 경로라고 합니다.

상대경로에서 점 하나인 .는 현재 디렉토리, 점 두 개인 ..는 상위 디렉토리를 의미합니다.

셸에서 현재 작업 디렉토리를 보기 위해서는 pwd, 디렉토리를 이동하기 위해서는 cd 명령어를 사용합니다.

기본적인 리눅스 명령어에 대한 설명은 이 포스팅을 참고해주세요. https://han.gl/5vYGN

hyunochoi in ~/Desktop  > pwd
/Users/hyunochoi/Desktop
hyunochoi in ~/Desktop  > cd programming/test
hyunochoi in ~/Desktop/programming/test  > pwd
/Users/hyunochoi/Desktop/programming/test
hyunochoi in ~/Desktop/programming/test  > cd ../../
hyunochoi in ~/Desktop  > cd ./programming
hyunochoi in ~/Desktop/programming  > cd ..
hyunochoi in ~/Desktop  >

절대 경로, 상대 경로 및 cdpwd 명령어를 사용하여 위와 같이 디렉토리를 자유롭게 탐색할 수 있습니다. 이제 디렉토리를 탐색하는 연습을 했으니, 현재 디렉토리 안에 어떤 파일과 디렉토리들이 있는지를 볼 차례입니다.

ls 및 리눅스 파일 권한

ls 명령어는 현재 작업 디렉토리 상에 있는 파일과 디렉토리의 리스트를 보여줍니다.

hyunochoi in /  > ls
Applications	Volumes		etc		sbin
Library		bin		home		tmp
System		cores		opt		usr
Users		dev		private		var

ls 명령어를 실행한 결과입니다. 여기에 더해, ls 명령어에 -l 옵션을 주면 파일이나 디렉토리에 관한 자세한 정보를 함께 출력해줍니다.

hyunochoi in ~/Desktop/programming  > ls -l
drwxr-xr-x@ 2 hyunochoi  staff  64  6 28 18:40 test

~/Desktop/programming 디렉토리에는 test라는 파일이 하나 있고, test 파일의 자세한 정보가 출력되어 있습니다. 이 문자열은 아래 그림과 같은 규칙으로 이루어져 있습니다.

출처: https://linuxhandbook.com

눈여겨 볼 것은 "Permission"에 해당하는 부분입니다. Permission은 총 세 가지 문자 rwx로 표현됩니다. 각각의 문자는 다음과 같은 뜻을 지닙니다.

  • r: 읽기 권한
  • w: 쓰기 권한
  • x: 실행 권한

문자 없이 -로 표시된 부분은 해당 권한이 없음을 의미합니다.

Permission은 총 9자리로 이루어져 있습니다. 앞의 세 자리는 User Owner의 권한, 중간 세 자리는 Group Owner, 마지막은 Other에 해당하는 권한을 나타냅니다.

출처: https://linuxhandbook.com

이제 Permission 부분을 해석하는 규칙과 함께 앞의 예시를 다시 보겠습니다.

hyunochoi in ~/Desktop/programming  > ls -l
drwxr-xr-x@ 2 hyunochoi  staff  64  6 28 18:40 test

이 파일의 Permission 부분은 rwxr-xr-x인 것을 볼 수 있습니다. 사용자별로 허락된 권한을 표로 정리하면 다음과 같을 것입니다.

사용자문자열권한
User Ownerrwx읽기, 쓰기, 실행
Group Ownerr-x읽기, 실행
Otherr-x읽기, 실행

입출력 변경, 프로그램 연결하기

입출력 변경

지금까지 실행한 프로그램은 모두 입력과 출력 방식이 정해져있었습니다. date를 입력하면 터미널 창에 현재 시각이 출력되고, echo 프로그램에 인자를 주기 위해서는 echo 뒤에 공백을 넣고 문자열을 적여줘야 했습니다.

그러나 기본 입출력만을 통해 프로그램을 사용해야 하는 것은 아닙니다. <, >를 사용해서 프로그램의 입출력 방식을 직접 바꿀 수 있습니다.

hyunochoi in ~/Desktop  > date > date.txt
hyunochoi in ~/Desktop  > cat date.txt
2021년 6월 30일 수요일 01시 12분 03초 KST

date 프로그램의 출력 스트림을 같은 터미널 창이 아니라 date.txt라는 텍스트 파일로 바꿨습니다. date.txt 파일의 내용을 확인해보면 date의 실행결과가 잘 담겨있는 것을 볼 수 있습니다(cat은 파일에 적힌 텍스트를 보여주는 프로그램입니다.).

hyunochoi in ~/Desktop  > cat < date.txt > date2.txt
hyunochoi in ~/Desktop  > cat date2.txt
2021년 6월 30일 수요일 01시 14분 59초 KST

이번에는 cat 프로그램의 입력과 출력 스트림을 모두 바꿨습니다. cat은 파일명을 인자로 받는 대신 date.txt 파일을 입력으로 직접 받고, 출력을 다시 date2.txt 파일에 저장합니다.

프로그램 연결하기(파이프)

때로는 한 프로그램의 출력을 다른 프로그램이 입력으로 받아 출력을 만들고, 그 출력을 다른 프로그램이 다시 입력으로 받아 출력을 만드는, 일종의 데이터가 흐르는 파이프를 만들고 싶을 때가 있습니다.

| 연산자를 사용하면 연산자 앞에 있는 명령어의 출력을 연산자 뒤에 있는 명령어의 입력으로 바로 전달할 수 있습니다.

hyunochoi in ~/Desktop  > cat test.txt
hello world!
world
hello
hyunochoi in ~/Desktop  > cat test.txt | grep world
hello world!
world
  • cat은 파일명을 인자로 받아 파일 내용을 출력합니다.
  • grep은 파일과 정규표현식을 인자로 받아 파일 내용 중 정규표현식과 매치되는 내용을 출력합니다.

이 두 프로그램을 |을 사용해 파이프로 연결할 수 있습니다. 데이터의 흐름은 다음과 같이 진행됩니다.

  1. cat은 파일 입력을 받습니다.
  2. cat은 파일 내용을 출력으로 내보냅니다.
  3. grepcat의 출력을 입력으로 받습니다.
  4. grep은 인자로 받은 정규표현식과 매치되는 단어를 출력으로 내보냅니다.

물론 grep은 파일 입력을 인자로 받을 수 있으므로 위의 예시가 가지는 의미는 없지만, 파이프에서 데이터가 어떤 식으로 흐르는지 확인할 수 있습니다.

grep 명령어의 자세한 사용법은 해당 링크를 참고해주세요. https://phoenixnap.com/kb/grep-command-linux-unix-examples

챕터 1을 마치며

챕터 1에서는 다음 내용을 공부했습니다.

  1. 기본적인 셸 사용법 및 리눅스 명령어
  2. $PATH 환경변수
  3. 셸에서 디렉토리 탐색하기
  4. 리눅스 시스템 파일 권한
  5. 프로그램 입출력 변경
  6. 파이프 구성하기

다음 포스팅에서는 챕터 1의 내용에 해당하는 연습문제를 리뷰하도록 하겠습니다.


<참고한 사이트>

좋은 웹페이지 즐겨찾기