본문 바로가기
Development/Linux

쉘(shell)에 대하여

by dohk325 2018. 12. 20.
반응형

                                                                                                                                                         

                                                                                                                                                                                                                   

                                                                                                                                                         

                                                                                                                                                                                                             

                                                                                                                                                                                                          

쉘의 개념, bashrc의 개념: https://dohk.tistory.com/191

1. 커널
 
컴퓨터 과학에서 커널(kernel)은 운영 체제의 핵심 부분으로서, 운영 체제의 다른 부분 및 응용 프로그램 수행에 필요한 여러 가지 서비스를 제공한다. 핵심(核心)[1]이라고도 한다.
 
초창기의 컴퓨터에서 운영 체제 커널은 필수적인 것이 아니었다. 초기의 프로그램은 하드웨어 추상화나 운영 체제의 지원을 받지 않고도 컴퓨터만으로 불러들인 다음 실행될 수 있었으며, 이것은 초창기 컴퓨터들의 일반적인 운영 방식이었다. 다른 프로그램을 실행하기 위해서는 컴퓨터의 전원을 껐다가 켬으로써 다시 입력자료를 읽어들여야 하는 방식이었다. 이러한 과정이 반복되면서 사람들은 로더와 디버거 같은 작은 프로그램들이 상주해 있는 것이, 다른 프로그램으로 교체하거나 새로운 프로그램을 개발하는 데 유리하다는 사실을 알게 되었다. 이와 같은 로더, 디버거들이 초기 운영 체제 커널의 기초가 되었다.
 

 
2. 쉘
shell 은 운영체제의 커널과 사용자 사이를 이어주는 역할을 한다. 커널이란 운영체제의 일부로서 컴퓨터의 메모리에 항상 떠있는 하나의 프로그램이다. shell은 상용자의 명령어를 해석하고 운영체제가 알아들을 수 있게 지시해준다. 다시 운영체제는 shell 에게서 받은 지시를 해석하여 하드웨어를 위한 지시어로 바꾸어준다.
 
 
  • Bourne shell은 유닉스 쉘의 오리지날이라고 할 수 있다. 벨 연구소의 Steve Bourne가 제작자이며 모든 유닉스 시스템에서 사용할 수 있다. 그러나 다른쉘과 비교해 볼 때 미흡한 점이 많이 있는 데 가장 큰 단점은 상호대화식 방식을 취하고 있지 않다는 것이다.
  • C shell은 버클리 대학에서 만든 쉘이고 특징이 쉘 스크립트 언어가 프로그램밍 언어인 C와 비슷하다는 것이다.
  • Korn shell 은 벨 연구소의 David Korn에 의해 만들어졌으며 요즘 사용되는 유닉스 시스템의 표준쉘로 제공된다. 이것은 C 쉘과 TC쉘의 기능을 모두 제공하 고 있고 쉘 스크립트언어는 Bourne 쉘과 비슷하다.
 
Simply put, the shell is a program that takes commands from the keyboard and gives them to the operating system to perform. In the old days, it was the only user interface available on a Unix-like system such as Linux. Nowadays, we have graphical user interfaces (GUIs) in addition to command line interfaces (CLIs) such as the shell.
단순히 말해서, 쉘이란 키보드로 명령어를 입력하고 운영체제가 구동하도록 하는 프로그램입니다. 리눅스처럼 유닉스와 유사한 시스템에서는 오랜 기간, 유일하게 구동 가능한 사용자 환경이었습니다. 요즘은 쉘처럼 명령어를 직접 입력하는 방식을 포함한 사용자에게 편리한 그래픽 환경을 가지고 있습니다.
 
쉘(Shell)은 운영체제에서 사용자가 입력하는 명령을 읽고 해석하여 대신 실행해주는 프로그램이다. 여기서 쉘을 Unix나 리눅스에만 있는 것으로 생각한다면 오산이다. Windows 운영체제나 다른 운영체제에도 Shell은 필수적으로 존재한다.
 
운영체제는 로그인한 사용자가 없다면 하나의 쉘도 실행되지 않는 상태다.
On most Linux systems a program called bash (which stands for Bourne Again SHell, an enhanced version of the original Unix shell program, sh, written by Steve Bourne) acts as the shell program. Besides bash, there are other shell programs that can be installed in a Linux system. These include: ksh, tcsh and zsh.
대부분의 리눅스 시스템에는 bash(Bourne Again SHell - Steve Bourn에 의해 작성된 Unix의 기본 쉘 프로그램인 sh의 개량형)라고 불리우는 프로그램이 쉘프로그램으로서 작동합니다. bash뿐만아니라 Ksh, tcsh, zsh와 같은 다른 쉘 프로그램 역시 리눅스 시스템에 설치할수 있습니다.
 
사용자가 유닉스 시스템에 접속하면 바로 쉘 상태로 들어가게 됩니다.
간단한 명령인 ls 명령어를 실행시켜 보면, 바로 파일리스트가 출력될 것입니다. 이렇게 명령의 결과를 볼 수 있는 것은 그 짧은 시간에 쉘이 명령을 해석해서 커널을 거쳐 뿌려주는 것이죠. 쉘이 단지 명령 해석 역할만 하는 것은 아닙니다. 쉘을 잘 이용하면 시스템 사용을 편리하게 할 수 있습니다.
 
시스템이 부팅하면, init 프로그램이 돌면서 /etc/inittab 파일을 검색합니다. init은 getty 프로그램을 호출하여 터미널화면에 login 프롬프트를 뛰우죠. 사용자의 아이디를 입력한 후 패스워드를 입력하면, getty는 login을 호출하고, login은 /etc/passwd 파일에서 패스워드가 일치하는지를 검색합니다.
 
만일 패스워드가 틀리면 다시 login 프롬프트를 뛰우고, 패스워드가 일치하면 사용자의 홈디렉토리로 위치시키고 시작프로그램 제어를 맡습니다. 처음 시스템에 접속하여 인증을 받은 후 뜨는 프롬프트는 자신이 사용하는 쉘의 프롬프트이고, 위치는 자신의 홈 디렉토리입니다.
 
사용자가 로그인을 시도하면 운영체제는 ID와 패스워드를 받아들이는 로그인 프로그램을 실행하게 되고 사용자가 입력한 ID와 패스워드를 검증한 뒤 정상적인 사용자라면 쉘을 실행하여 사용자 세션을 쉘에게 넘겨준다.
 
쉘의 역할은 사용자가 입력한 명령을 해석하여 대신 실행해주는 것이다. 쉘의 내부 명령어라면 스스로 실행한 뒤 결과를 화면에 표시해주고 내부 명령어가 아니라면 PATH 환경변수에 지정된 경로에서 입력받은 명령과 같은 파일을 찾아 exec() 시스템콜을 호출하여 실행한 뒤 키보드와 마우스 등의 입력장치와 모니터에 해당하는 표준 출력장치의 제어권을 해당 프로그램에게 넘겨준 뒤 프로그램이 끝날 때 까지 대기하는 역할을 수행한다.
 
현재 자신이 사용하는 쉘이 무엇인지 알아보려면 다음 명령어를 입력하면 됩니다.
 
# echo $SHELL
 
 

 
3. 쉘의 종류
Unix나 Linux의 경우 ps 명령을 실행하면 보이는 프로세스 중에서 bash, sh, ksh, csh 등이 쉘 프로그램이고 Windows의 경우 작업관리자에서 볼 수 있는 explorer.exe 가 쉘이라고 보면 된다. Windows의 경우 Explorer.exe 이외에도 cmd.exe가 추가적인 쉘로 지원되는데 이는 원래 DOS 시절의 잔재로서 DOS 호환을 위해 지원된다고 생각하면 된다.
 
위의 화면이 쉘이 실행중인 화면이다. 위의 화면에선 id 라는 명령어와 ps 라는 명령어 2개가 실행되었고 그 실행결과가 표시되었다. 그리고 각 명령이 실행된 뒤 다시 프롬프트 (#)이 표시되어 다음 명령을 기다리는 화면이다. 이렇게 입력과 실행을 반복하는 형태의 쉘을 대화형 쉘이라고 한다.
 
ps 명령이 실행된 결과를 보게되면 bash 라는 프로세스가 보이는데 bash가 바로 쉘이다. 프롬프트인 #이나 $를 화면에 보여주고 명령의 입력을 기다리는 역할을 수행한다. 서버에서 사용자 계정을 생성하게 되면 사용자가 로그인할 때 어떤 쉘을 실행시켜주어야 하는지를 지정하도록 되어 있다.bash는 리눅스에서 지원되는 기본 쉘로서 사용자 계정을 생성할 때 쉘을 특별히 지정하지 않으면 기본적으로 지정되는 기본 쉘이다.
 
쉘을 공부함에 있어 가장 중요한 것중 하나가 환경변수의 이해다. 쉘은 여러가지 환경변수를 사용하는데 이 환경변수는 사용자가 임의로 본인의 의지에 따라 값의 변경이 가능하다. 하지만 미리 정의된 환경변수의 이름을 변경해서는 안된다.(변경할 수도 없지만..) 환경변수는 쉘의 종류에 다라 설정하는 방법과 확인하는 방법이 다르다. 리눅스의 기본 쉘인 bash (본어게인쉘)에서는 아래와 같이 env 명령으로 확인할 수 있다. (csh의 경우 set 명령)
 
쉘은 사용자와 운영체제의 사이에 위치하는 프로그램이다. 사용자가 입력한 명령어를 신속하게 찾고 운영체제와 사용자 그리고 사용자가 실행한 다른 프로그램과의 소통을 위해 사용하는 것이 환경변수다.
 
이 환경변수들은 사용자가 읽을 수만 있는 것과 변경이 가능한 것이 있다. 그 중에서 가장 대표적인 환경변수는 PATH가 있다.
 
환경변수 PATH는 사용자가 명령을 입력하였을 경우 쉘은 내부 명령어 인지 확인하고 아닐 경우 해당 명령은 외부명령어 즉 실행파일인 것으로 간주한다. 만약 사용자가 /usr/bin/df 와 같이 Full Path를 입력하였다면  /usr/bin 디렉토리에 있는 df란 명령을 바로 실행할 수 있으나 사용자가 df 라고만 입력하였다면 쉘은 df라는 명령어가 어느 디렉토리에 있는지 알 수 없다. 이때 쉘이 df 라는 명령어를 어디에서 찾을 수 있는지를 정의해주는 환경변수가 바로 PATH 다. 위의 화면에서 보면 PATH 환경변수는 다음과 같다. ( echo 명령으로 특정 환경변수만 조회할 수 있다.)
 
[root@CentOS_100 ~]# echo $PATH
 
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
 
PATH 환경변수에는  : (콜론)을 구분자로 하여 여러개의 디렉토리가 나열되어 있는 것을 볼 수 있다. 쉘은 df 라는 명령이 입력되면 해당 명령어의 위치를 찾기 위해 가장 먼저 /usr/kerberos/sbin 디렉토리에 df 가 있는지 확인한다. 만약 없다면 다음에 있는 /usr/kerberos/bin 에서 찾고 거기에도 없다면 /usr/local/sbin 에서 찾게 된다. 이렇게 순서대로 PATH 변수 내의 디렉토리에서 명령을 찾다가 df 라는 명령어가 발견되면 그 파일을 실행시켜주는 것이다.
 
만약 PATH 환경변수에 지정된 경로에 해당 명령어가 없다면 명령어를 찾을 수 없다는 메시지를 뿌리며 에러를 리턴해준다. (따라서 프로그램이 있는 full PATH를 직접 입력해주어야 한다고 생각이 든다.)
 
모든 환경변수는 의미를 갖고 있으며 사용법과 환경변수를 참조하는 프로그램도 다양하다. 그리고 환경변수의 값이 잘못되어 있으면 오작동을 하는 경우도 많다. 특히 날짜와 시간을 사용하는 프로그램의 경우 환경변수 TZ (time zone), 펑션키를 사용하는 프로그램의 경우 TERM (Terminal) 환경변수, 한글을 사용하는 프로그램의 경우 LANG (Language) 환경변수 등은 잘못 설정될 경우 문제가 발생하는 경우가 많다.
 

 
  • 쉘 환경변수의 설정
쉘의 환경변수는 로그인 할 때 설정된다. 사용자 환경은 프로파일에서 설정되는데 프로파일은 글로벌 프로파일과 계정 프로파일 두가지가 있다. 그리고 이 프로파일의 파일위치와 이름은 운영체제와 쉘의 종류에 따라 조금씩 다르다.
 
sh, ksh 은 /etc/profile 과 사용자 홈디렉토리의 .profile 이다.
 
리눅스의 bash는 /etc/profile과 /etc/bashrc 두개의 파일과 사용자 홈디렉토리의 .bashrc 가 환경변수가 설정될 수 있는 파일이다.
 
csh 은 /etc/csh.login (Unix 종류와 버전에 따라 다르나 대체로 login 이라는 이름이 붙음. 내용을 보면 확인 가능함)과 사용자 홈디렉토리의 .cshrc 이다.
 
이 프로파일의 내용을 보면 환경변수를 설정할 수 있는 방법을 짐작할 수 있다. 미리 정의된 환경변수 이외에도 사용자 환경변수를 추가하여 사용할 수 있다. 이 파일에 환경변수를 추가하고 다시 로그인한 뒤 env 명령을 실행하면 추가한 새로운 환경변수가 표시되는 것을 확인할 수 있다.
 
쉘에 대해 서술하자면 너무도 분량이 많아진다. 하지만 중요한 것은 쉘의 원리를 이해하는 것이 중요하다. 모든 지식이 그렇듯 단편적인 커맨드나 변수 이름만 딸랑 암기하는 것은 운영체제를 이해하는데 전혀 도움이 안되고 그런 지식은 죽은 지식이다. 쉘과 쉘의 환경변수가 어떤 역할을 하는지를 개념부터 이해하는 것이 중요하다. 쉘을 이해하였다면 쉘의 인터프리터 방식의 언어인 쉘스크립트에 대해 공부하는 것이 순서다.
컴파일 언어와 인터프리터 언어

 
4. 쉘 스크립트
쉘 스크립트의 기본 개념은 실행 순서에 나와있는 명령의 목록입니다. 좋은 쉘 스크립트는 단계를 설명, 파운드 기호 # 앞에 의견을해야합니다.
쉘 스크립트를 만들 때에는 제일 첫 줄에 어떤 쉘을 쓸지를 명시해주어야 한다. 현재 위의 쉘스크립트는 Bourne 쉘에 의해 실행되어야하는 시스템임을 말한다.
 
쉘 스크립트를 이해하려면 먼저 스크립트(Script)가 무엇인지 이해해야 한다. 스크립트란 일반적으로 인터프리트(interpret) 방식으로 동작하는 컴파일되지 않은 프로그램이라고 이해하면 된다.
 
쉘 스크립트, 펄 스크립트, 자바 스크립트 등등등.... 스크립트라는 단어 앞에 여러가지 수식어(?)가 붙는다. 이 수식어는 바로 스크립트를 읽어 실행해주는 인터프리트 엔진을 말한다고 이해하면 된다. 즉 쉘스크립트는 운영체제의 쉘 즉 bash, ksh, csh 등이 읽어 실행해주는 스크립트 언어
 
각각의 스크립트 언어들은 문법이 모두 다르기 때문에 호환되지 않는다.
 
다음은 C언어와 쉘스크립트로 된 똑같은 기능을 하는 프로그램이다.
 
 
두 프로그램 모두 실행하면 화면에 "hello~ c~"와 "hello~ script~" 한줄을 출력하는 프로그램이다.  하지만 두 프로그램이 파일로 저장된 뒤 실행되기 까지는 여러 차이점이 있다. 그 차이점을 알아보면 다음과 같다.
 
C언어로 작성된 프로그램은 컴파일(Compile)하여 기계어로 변환된 목적파일(Object File)로 만들어준 뒤 링크(Link)과정을 거치고 실행퍼미션(x)을 주어야만 실행이 가능하지만 쉘스크립트로 작성된 파일은 이러한 과정이 필요없고 실행퍼미션만 주면 된다.(스크립트로 작성됬으니까 그런 것)
C언어로 작성된 프로그램은 기계어로 변환되었기 때문에 커널에 의해 실행되지만 쉘 스크립트는 쉘(bash, sh, ksh) 이 한줄씩 읽어 실행한다.
C언어로 작성된 프로그램은 정식 프로세스로 생성되지만 쉘 스크립트로 작성된 프로그램은 이름은 보이지만 정식 프로세스는 아니다.
 
 
 
hello.c 의 컴파일은 hello.c를 작성한 뒤 다음의 명령을 통해 수행하면 된다.
 
#  gcc -o hello hello.c
 
이 명령을 수행하면 실행파일 hello 가 생성된다.
 
 
 
 
 

 
5. 터미널
It's a program called a terminal emulator. This is a program that opens a window and lets you interact with the shell. There are a bunch of different terminal emulators you can use. Most Linux distributions supply several, such as: gnome-terminal, konsole, xterm, rxvt, kvt, nxterm, and eterm.
이것은 터미널 에뮬레이터라 불리우는 프로그램입니다. 이 프로그램은 윈도우상에서 쉘에 명령어를 보내고 결과를 받아볼수 있는 프로그램입니다. 터미널 에뮬레이터에는 많은 다른 종류가 있습니다. 대부분의 리눅스 배포판은 gnome-terminal, konsole, xterm. rxvt, kvt nxterm, eterm등 그중 몇가지를 제공해줍니다.  
 
 

 
 
6. #!/bain/bash
쉘 스크립트의 가장 첫 라인에  #!/bain/bash 를 쓰는 이유는, 내가 사용 하려는 명령어 해석기가 bash 쉘 임을 미리 알려주는 것입니다.
 
일반적으로 스크립트에서 #는 주석기호이지만, 첫라인의 #!/bin/bash 에서의 #은 주석기호가 아닙니다.
 
스크립트의 가장 첫라인에 있는 #! 은 스크립트의 제일 앞에서 이 파일이 어떤 명령어 해석기의 명령어 집합인지를 시스템에게 알려주는 역할을 합니다.
 
#! 은 두 바이트의 "매직넘버"("magic number")로서, 실행 가능한 쉘 스크립트라는 것을 나타내는 특별한 표시자입니다.
 
#! 바로 뒤에 나오는 것은 경로명으로, 스크립트에 들어있는 명령어들을 해석할 프로그램의 위치를 나타내는데 그 프로그램이 쉘인지, 프로그램 언어인지, 유틸리티인지를 나타냅니다.
 
이 명령어 해석기가 주석은 무시하면서 스크립트의 첫 번째 줄부터 명령어들을 실행시킵니다.
 
"#!" 뒤에 나오는 경로는 정확히 Full PATH를 기록 해야 합니다.

만약 PATH를 잘못 적게 되면, 스크립트를 돌렸을 때 거의 대부분 "Command not found"라는 에러 메세지만 보게 될 것입니다.

 

반응형