수업 개요 + 셸(SHELL)

이 수업에 관하여

컴퓨터 과학을 공부하는 사람으로서, 우리는 컴퓨터가 반복적인 일을 처리하는데 능숙하다는 것을 알고 있습니다. 하지만 우리는 종종 효율적인 반복 처리가 프로그램 상에서만 아니라 컴퓨터 사용 자체에도 적용할 수 있다는 것을 간과합니다. 우리는 컴퓨터 자체와 관련된 문제를 해결할 때 더 생산적이고 복잡한 문제를 해결할 수 있는 다양한 도구들을 가지고 있습니다. 그러나 많은 사람들이 이 도구들을 활용할 줄 모르고, 주입식 교육을 통한 명령어들과 인터넷에서 복붙(복사 후 붙여넣기)만 활용하고 있습니다.

우리는 이 수업을 통해 여러분들 들어봤을 법한 도구를 활용하는 방법을 가르치고, 쓸만한 도구들을 소개하고, 당신이 스스로 더 많은 도구를 탐구하고(무언가를 만들거나!) 관심을 가지길 바랍니다. 이 지식들은 통상적인 컴퓨터 공학 수업에서는 다루지 않을 내용일 것입니다.

강의 구조

수업은 11개의 1시간 강의로 이루어져 있습니다. 각 강의는 특정 주제에 대해 집중적으로 다룹니다. 강의는 대체로 독립적이지만 수업을 진행하면서 이전 강의 내용에 익숙하다고 가정할 예정입니다. 온라인 강의 노트가 있지만 영상 속에서 다루는 콘텐츠가 더 많을 것입니다. (예 : 메모에 없을 수도 있는 데모)

11개의 1시간 강의에 대한 많은 것들을 다루려고 하기 때문에 강의는 상당히 빽빽합니다. 각 강의에는 강의의 핵심을 파악하는 일련의 연습이 포함되어 있습니다. 이 연습은 강의 내용을 본인의 페이스로 배울 수 있게합니다. 온라인으로 수업에 참석하고 있다면, missing-semester@mit.edu에 질문을 보내세요

시간이 제한되어 있기 때문에 모든 세부 사항을 다룰 수 없습니다. 그래도 가급적 여러분들이 관심있을 도구와 주제를 다루려고 합니다. 하지만 특별히 좋아하는 것이 있다면, 주저하지 말고 우리에게 제안해주세요!

주제 1: 셸(The Shell)

셸(Shell)은 무엇인가?

요즘 컴퓨터에는 명령을 제공하기 위한 다양한 인터페이스가 있습니다. 화려한 그래픽 사용자 인터페이스, 음성 인터페이스 및 AR / VR 등 어디에나 있습니다. 이들은 80%의 사용 사례에 매우 적합하지만, 종종 그들이할 수 있는 것에 근본적으로 제한됩니다. 당신은 거기에 없는 버튼을 누르거나 프로그래밍되지 않은 음성 명령을 내릴 수 없습니다. 컴퓨터가 제공하는 도구를 최대한 활용하려면 구식 방식인 텍스트 인터페이스를 사용해야합니다. 그것이 셸(Shell)입니다.

당신이 접근 가능한 거의 모든 플랫폼에는 한 형태로 셸이 있고, 그 중 다수의 플랫폼에는 선택적일 수 있는 몇 개의 셸이 있습니다. 세부 사항이 다양할 수 있지만 핵심은 거의 동일합니다. 프로그램을 실행하고 입력을 제공하며 반 구조화된 방식으로 출력을 검사할 수 있습니다.

이 강의에서는 bash라고 불리는 셸로 수업을 진행할 것입니다. 이것은 가장 널리 사용되는 셸 중 하나이며, 구문은 다른 많은 셸에서 볼 수 있는 것과 유사합니다. 셸 프롬프트(prompt) (명령을 입력 할 수있는 곳)를 열려면 먼저 터미널(terminal) 이 필요합니다. 여러분들의 컴퓨터에는 기본적으로 설치가 돼있거나, 없어도 설치가 매우 쉬울 것입니다.

셸을 사용하는 방법

터미널(terminal)을 키게 되면 다음과 같은 프롬프트(prompt) 를 볼 수 있을 것입니다.

missing:~$ 

이것은 셸의 기본 텍스트 인터페이스입니다. 이것은 당신이 지금 missing이란 기계에 있고 당신의 “현재의 작업 디렉토리”또는 당신이 현재 어디에 있는지, 또는 ~(홈 디렉토리)를 표시합다. $는 당신이 루트 사용자가 아니라는 것을 알려줍니다 (나중에 더 자세히). 이 프롬프트에서 명령을 입력할 수 있으며,이 명령은 셸에 의해 해석됩니다. 가장 기본적인 명령은 프로그램을 실행하는 것입니다.

missing:~$ date
Fri 10 Jan 2020 11:49:31 AM EST
missing:~$ 

date라는 프로그램을 호출하면, 현재 날짜와 시간을 출력합니다. 그 후에 셸을 통해 다른 명령을 내릴 수 있습니다. 또한 명령과 인자(argument)를 함께 입력할 수도 있습니다.

missing:~$ echo hello
hello

이 경우엔 우리가 셸에게 echo라는 프로그램을 hello라는 인자와 호출하도록 명령한 것입니다. echo 프로그램은 단순하게 인자를 출력합니다. 셸은 명령을 띄어쓰기로 분할하여 첫 번째 단어로 표시된 프로그램을 실행하고, 각 후속 단어를 프로그램이 액세스할 수 있는 인수로 제공합니다. 만약 띄어쓰기나 특수문자를 인자에 포함시키고 싶다면 '"로 둘러싸거나(예 : "My Photos"), 혹은 띄어쓰기 앞에 \를 넣어 표기해줄 수 있습니다.(예 : My\ Photos)

하지만 어떻게 셸이 dateecho 프로그램을 찾을 수 있을까요? 셸은 파이썬이나 루비처럼 프로그래밍 환경이고, 그래서 변수, 조건부, 루프, 함수(다음 강의!)를 가지고 있습니다. 셸에서 명령을 실행한다는 것은, 실제로는 셸 인터프리터에다가 짧은 코드를 작성하는 것이라고 볼 수 있습니다. 셸이 명령을 실행하도록 요청되면 명령을 받을 때 프로그램을 검색해야하는 디렉토리를 나열하는 $PATH라는 환경 변수에 접근합니다.

missing:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
missing:~$ which echo
/bin/echo
missing:~$ /bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

echo 명령을 실행하면 셸은 echo라는 프로그램을 찾아서 실행해야된다는 것을 보고, $PATH:로 분리된 디렉토리 목록을 검색합니다. 만약 발견하고 실행가능하다면 실행합니다. which 프로그램을 사용하여 주어진 프로그램 이름에 대해 실행되는 파일을 찾을 수 있습니다. 우리는 또한 우리가 실행하고자 하는 파일에 대한 경로를 제공함으로써 $PATH를 완전히 우회할 수 있습니다.

셸에서 이동하기

셸의 경로는 구분 문자로 구분돼있습니다. Linux 및 macOS는 /로, Windows에서는 \로 구분합니다. Linux와 macOS에서는 /가 파일 시스템의 ‘루트(root)’지만, Windows는 각 디스크 파티션에 대한 루트가 있습니다.(예: C:\) 이 수업 및 대부분의 수업들은 여러분들이 Linux 파일 시스템을 사용한다고 가정하고 진행합니다. /로 시작하는 경로들은 절대(absolute) 경로라고 부릅니다. 다른 경로들은 상대(relative) 경로라고 부릅니다. 상대 경로는 최근 작업 디렉토리에 상대적입니다. 최근 작업 디렉토리는 pwd로 볼 수 있고, cd로 디렉토리를 이동할 수 있습니다. 경로 표시에서 .는 현재 디렉토리를, ..는 상위 디렉토리(parent directory)를 뜻합니다.

missing:~$ pwd
/home/missing
missing:~$ cd /home
missing:/home$ pwd
/home
missing:/home$ cd ..
missing:/$ pwd
/
missing:/$ cd ./home
missing:/home$ pwd
/home
missing:/home$ cd missing
missing:~$ pwd
/home/missing
missing:~$ ../../bin/echo hello
hello

우리의 셸이 현재 작업 디렉토리가 어디인지 알려준다는 것을 명심하세요. 당신은 여러 종류의 유용한 정보를 보여주는 당신만의 프롬프트를 구성할 수 있습니다. 이것에 대한 내용은 나중 강의에서 다루겠습니다.

기본적으로 프로그램을 실행하면 현재 디렉토리에서 작동합니다. 예를 들어, 일반적으로 어디선가 파일을 검색한 후에 파일을 만들면, 그 장소에 파일이 만들어집니다.

주어진 디렉토리에 어떤 것들이 있는지 보기 위해서는 ls명령을 사용합니다.

missing:~$ ls
missing:~$ cd ..
missing:/home$ ls
missing
missing:/home$ cd ..
missing:/$ ls
bin
boot
dev
etc
home
...

디렉토리가 첫 번째 인수로 주어지지 않는 한, ls는 현재 디렉토리의 내용을 출력할 것입니다. 대부분의 명령은 행동을 수정하기 위해 시작되는 플래그와 옵션(값이 있는 플래그)을 쓸 수 있습니다. 보통 -h 또는 --help 플래그(/? Windows에서)는 사용 가능한 플래그와 옵션을 알려주는 도움말 텍스트를 인쇄한다. 예를 들어, ls --help는 우리에게 다음과 같은 의미가 있습니다.

  -l                         use a long listing format
missing:~$ ls -l /home
drwxr-xr-x 1 missing  users  4096 Jun 15  2019 missing

이것은 각 파일이나 디렉토리 현재에 대한 더 많은 정보를 제공합니다. 첫째, 줄의 시작 부분에 있는 dmissing이 디렉토리임을 나타냅니다. 그런 다음 세 개의 문자 (rwx)의 세 그룹이 따라옵니다. 이들은 파일 소유자 (missing), 소유 그룹 (users), 다른 모든 사람들이 관련 항목에 대해 각각 권한을 가지고 있는지를 나타냅니다. -는 그 자리의 권한이 없다는 것을 나타냅니다. 위의 경우 소유자만 missing 디렉토리 (즉, 파일 추가 / 제거)를 수정(w) 할 수 있습니다. 디렉토리를 입력하려면 사용자가 해당 디렉토리 (및 부모 디렉토리)에 대한 “검색”( “execute”의 약자인 x로 표현 됨) 권한을 가져야합니다. 콘텐츠를 나열하려면 사용자가 디렉토리에 대한 읽기(r) 권한이 있어야 합니다. 파일의 경우도 마찬가지입니다./bin의 거의 모든 파일에는 마지막 그룹인 “다른 모든 사람”에 대한 x 권한 세트가 있어 모든 사람이 해당 프로그램을 실행할 수 있습니다.

다른 자주 쓰이면서도 꼭 알아야 하는 프로그램으로는 mv(이름 변경, 파일 이동)와 cp(파일 복사) 그리고 mkdir(새 디렉토리 만들기)가 있습니다.

어떤 프로그램의 인자, 입력, 출력 또는 일반적으로 어떻게 작동하는지에 대한 더 많은 정보를 원한다면 man(manual의 약자) 프로그램을 실행해보세요. 그것은 하나의 인자로 프로그램 이름을 사용하고 해당 프로그램의 매뉴얼 페이지를 보여줍니다. q를 누르면 종료합니다.

missing:~$ man ls

프로그램 연결하기

셸에서의 프로그램은 입력 스트립과 출력 스트림을 보유하고 있습니다. 프로그램이 입력을 읽을 때는 입력 스트림에서 읽고, 출력할 때는 출력 스트림으로 출력합니다. 일반적으로 프로그램의 입력과 출력은 모두 당신의 터미널에서 진행합니다. 즉, 키보드로 입력을 하고, 화면으로 출력합니다. 하지만 이 스트립을 변경할 수가 있습니다.

가장 간단한 형태로 경로를 재설정하는 방법은 < 파일> 파일입니다. 이것은 여러분들이 입력과 출력 스트림을 각각 변경할 수 있게 합니다.

missing:~$ echo hello > hello.txt
missing:~$ cat hello.txt
hello
missing:~$ cat < hello.txt
hello
missing:~$ cat < hello.txt > hello2.txt
missing:~$ cat hello2.txt
hello

>>를 통해서 파일에 추가를 할 수도 있습니다. 이런 종류의 입출력 경로 재설정이 가장 유용하게 쓰이는 곳은 ‘파이프’를 구성할 때입니다. | 연산자는 프로그램들 간의 체인을 만들어줄 때 활용합니다.

missing:~$ ls -l / | tail -n1
drwxr-xr-x 1 root  root  4096 Jun 20  2019 var
missing:~$ curl --head --silent google.com | grep --ignore-case content-length | cut --delimiter=' ' -f2
219

데이터 랭글링(data wrangling)에 관한 강의에서 파이프를 어떻게 활용할 것인지에 대해 더 자세히 살펴볼 것입니다.

다재다능하고 강력한 도구

대부분의 유닉스 시스템에서는 ‘루트’ 사용자란 것이 있습니다.(위에서 언급 됐습니다!) 루트 사용자는 모든 액세스 제한을 초과하고 (거의) 모든 시스템의 파일을 만들고 읽고 업데이트하고 삭제 할 수 있습니다. 하지만 실수로 무언가를 망가뜨리기에는 너무 쉽기 때문에 루트 사용자로 시스템에 로그인하지 않을 것입니다. 대신 sudo(super-user-do의 줄임말) 명령을 사용할 예정입니다. 어떤 커맨드의 권한이 거부되면 보통 루트 권한이 필요합니다. 이럴때 sudo 사용하면 권한 문제를 무시할 수 있습니다!

예를 들면, /sys에 있는 sysfs 시스템 파일을 변경하려면 루트 권한이 필요합니다. sysfs를 사용하며 별도의 툴 없이도 몇몇 커널 매개변수를 특저 파일을 이용해 쉽게 재구성할 수 있습니다 . sysfs는 Windows 또는 macOS에 존재하지 않습니다.

예를 들어서, 노트북 화면 밝기를 brightness라는 프로그램으로 호출해봅시다.

/sys/class/backlight

파일에 값을 기록하면 화면 밝기를 변경할 수 있습니다. 여러분들은 아래와 같이 시도해볼 수 있을 것입니다.

$ sudo find -L /sys/class/backlight -maxdepth 2 -name '*brightness*'
/sys/class/backlight/thinkpad_screen/brightness
$ cd /sys/class/backlight/thinkpad_screen
$ sudo echo 3 > brightness
An error occurred while redirecting file 'brightness'
open: Permission denied

이상하게도 에러가 나타났습니다! sudo 명령어를 썼는데 왜 이런걸까요? 먼저 중요한 사실을 짚고 넘어가겠습니다. |,>,<같은 명령어는 개별 프로그램 아니라 셸이 직접 실행하는 기능입니다. 예를들어 echo같은 프로그램들은 입출력이 |로 연결되고 있다는 사실을 전혀 모릅니다. 이들은 그저 정해진 입력을 받고 정해진 출력을 할 뿐입니다. 위의 경우 셸은 sudo 권한으로 echo를 실행했지만 사용자 권한으로 >을 실행해서 파일을 작성하려고 했기 때문에 문제가 생긴 것입니다. 따라서, 같은 명령어를 사용하면 문제가 해결됩니다.

$ echo 3 | sudo tee brightness

tee 프로그램은 /sys파일을 읽고 실행하고 루트에서 실행됩니다. 루트로 실행되기 때문에 모든 권한이 해결됩니다. 당신은 /sys에서 다양하고 재밌는 것들을 제어할 수 있습니다. 예를 들어 다양한 시스템 LED의 상태 (경로가 다를 수 있음)를 제어할 수도 있죠.

$ echo 1 | sudo tee /sys/class/leds/input6::scrolllock/brightness

다음에는…

이 시점에서 당신은 기본적인 것을 달성할 수 있을만큼 충분히 셸 사용법을 배웠습니다. 원하는 파일을 찾고 대부분의 프로그램의 기본 기능을 사용하려면 주변을 돌아 다니며 이동해야 합니다. 다음 강의에서는 셸과 많은 편리한 명령 프로그램을 사용하여 더 복잡한 작업을 수행하고 자동화하는 방법에 대해 이야기할 것입니다.

연습 문제

  1. /tmpmissing이라는 새로운 경로를 만들어 보세요 .
  2. touch라는 프로그램을 관찰해보세요. man 프로그램이 도움이 될겁니다.
  3. touch를 이용해서 semester라는 파일을 missing 안에 만들어 보세요.
  4. 아래 주어진 것을 그 파일에 써보세요. 단, 한번에 한줄씩
    #!/bin/sh
    curl --head --silent https://missing.csail.mit.edu
    

    첫번째 줄을 작동시키는게 꽤 까다로울 것입니다. #으로 시작하는 것은 코멘트(comment)고, !는 큰 따옴표(")로 둘러쌓인 문자열 내에서도 특별한 의미를 가집니다. 배시(Bash)는 작은 따옴표' 문자열과 큰따옴표를 구분합니다. 이것은 매우 헷갈리는 케이스입니다. Bash 인용 관련 메뉴얼 페이지에 더 자세한 정보가 설명돼있습니다.

  5. 파일을 실행해보세요. 예를 들어, (./semester)라는 경로를 셸에 입력해보세요. 이것이 왜 작동하지 않는지 ls를 이용해 파악해보세요. (힌트: 파일의 비트 권한을 확인해보세요.)
  6. sh 인터프리터로 시작해 명령을 실행하고, semester 파일에 첫 인자로 주세요. (즉 sh semester 이렇게!). ./semester는 안되는데, 앞에 거는 왜 실행이 될까요?
  7. chmod 프로그램을 살펴보세요. (man chmod를 사용해보세요.)
  8. chmod를 활용해 sh semester 대신에 ./semester을 사용 가능하게 해보세요. sh을 이용해 이 파일을 해석해야 한다는 것을 셸이 어떻게 알까요? 이 페이지에서 셔뱅(shebang)에 대해서 더 알아보세요.
  9. |>를 사용해 semester별 “last modified” 날짜 출력을 홈 디렉토리에 last-modified.txt라는 파일에 작성하세요.
  10. 노트북 배터리의 전원 레벨 또는 데스크탑 컴퓨터의 CPU 온도를 /sys에서 읽는 명령을 작성하십시오. 참고: 만약 macOS 사용자라면, 당신의 OS는 sysfs가 없기 때문에, 이 예제를 건너뛸 수 있습니다.

이 페이지를 수정.

CC BY-NC-SA에 따라 라이센스를 부여합니다.