3 minute read

bash 기초

shell 이란

  • Application을 실행시키는 도구
  • 물론 shell도 애플리케이션의 일종
  • OS의 커널에 직접 접근할 수 없기 때문에 명령어 해석기인 셸이 필요
  • Shell에서 내리는 명령어는 해석된 뒤에 자식 프로세스로 만들어져 실행된다. 실행된 프로세스는 시스템(커널)이 관리하게 된다.

    [no-alignment]

shell 의 역사

  • Bourne shell : /bin/sh
  • C shell : /bin/csh
  • Korn shell : /bin/ksh
  • bash : /bin/bash
  • Zsh : /bin/zsh
  • 본셸
    • /bin/sh
    • 스티븐 본이 작성 , 1977 , POSIX shell
    • 유닉스는 본셸을 꼭 갖고 있어야함
  • 씨셸
    • /bin/csh
    • 빌조이, BSD UNIX
    • C 언어와 비슷한 문법으로 인해 C shell 로명명
    • 호환성 문제 발생
  • 콘셸

    • /bin/ksh
    • 벨랩. 데이비드 콘
    • csh, tcsh 기능 포함
    • vi prompt mode 지원
  • 배시셸
    • /bin/bash
    • Korn 벤치 마킹
    • GNU/Linux , Mac OSX 계열에서 기본 셸로 사용 Mac OSX는 2019 부터 zsh 사용
  • 지셸
    • 커스터 마이징 다양
    • 예쁘고 편리한 플러그인 추가가 쉽다.

특수문자 읽는 방법

[no-alignment]

prompt input mdoe

  • vi : set -o vi
  • emacs mode set -o emacs
  • bash 에서 명령어 한줄 한줄치는것 자체가 명령어가 담긴 텍스트 파일을 편집해서 저장하는것으로할 수 있다. 파일은 history에 저장된다고 할수 있겠다 한줄 한줄 치는것의 편집기는 emacs를 사용한다.
  • emacs edting mode 요즘은 clear말고 ^(ctrl)L을 한다고 하더라… [no-alignment]

  • vi edting mode
    • j,k : 명령어 히슽리 라인의 이동 아래로 1줄, 위로 1줄
    • #G : 히스토리에서 #번째 명령어 싫앵
    • TAB : command-completion 기능
    • = : 매칭된 파일 이름 출력
  • recall command line args
    • 상황을 떠올려 보자. 내가 curl <url1> <url2> ...을 했는데 이 <urln>만 다시 가져오고 싶다.
    • 그때 ![i]:n을 써보자
      • i 번째 히스토리 명령어의 n-th argument (i 생략시 previous command)
    • !:n-m : 이전 명령어의 n~m 인자리스트를 불러온다.
    • 더 쉬운 단축키로는 ALT +.을 누르자. 그러면 인자 하나씩 하나씩 불러온다.

shell vs sub-shell

  • 셸에서 실행되는 UNIX 명령어는 sub-shell이 생성되어 실행
    • 서브셸이란 fork-exe로 만들어지는 child-process 셸이다.
    • 외부 명령어 실행은 기본적으로 서브 셸을 생성하므로 process 생성의 overhead가 존재한다.
    • ls -al이라는 명령을 싫앻나다면 원래의 셀이 포크해서 자식 프로세스가 생기고 자식은 부모를 복제한다. 이를 서브 셸이라고 한다. 그러고 나서 ls를 실행하기 위해 exec명령을 실행한다. 실행이 끝나면 부모에게 exit code 를 반환한다.

    [no-alignment]

    • 다음 작업을 진행하기위해 자식의 프로세스의 exit code를 받아야한다. ( true : 0 , else : false)
      obo@obo-900X3L:~$ touch qwer
      obo@obo-900X3L:~$ rm qwer
      obo@obo-900X3L:~$ echo $?
      0
      obo@obo-900X3L:~$ rm qwer
      rm: cannot remove 'qwer': No such file or directory
      obo@obo-900X3L:~$ echo $?
      1
      obo@obo-900X3L:~$ 
    

rm --force 에 대한 오해

  • rm -rf
  • UNIX command, 특히 rm 과 같은 optional한 기능에 --force 옵션이 존재하는 것은 child process로 작동할 때 exit code를 조작하기 위함이다.
  • 즉 shell script 처리를 위해서 존재하는 기능들이다.
  • 예로 어떤 파일을 삭제하려는데, 예를 들어서 쓰레기 파일들을 프로세스가 다 종류된다음에 다 청소를해야하는데, 생성될수도 안될 수도 있다. 그래서, 무조건 리턴값을 무시한다. 삭제할 때 없어도 리턴값은 0이 나올것이다.

      obo@obo-900X3L:~$ rm -f qwer
      obo@obo-900X3L:~$ echo $?
      0
      obo@obo-900X3L:~$ 
    
    

systemctl

  • 시스템 가동 관련 정보들을 감시하는 서비스..
  • sysstat unit으로 테스트해보자.
  • 시작 : systemctl enable --now sysstat

Variables

변수 선언

  • [set] name=value
    • name 이라는 변수에 value 선언 또는 변경
    • =사이에 공백은 허용되지 않는다.

변수 expression

  • ${name}
    • {} 중괄호 생략 가능, 명확하게 변수명이 구별 가능한 경우에 생략

변수 removal

  • unset <name>

white space

  • 셸 프로그래밍 문법에서 공백의 역할
    • 공백은 셸 프로그래밍에서 특별한 역할을 하는경우가 있다.
      • 변수와 연산자를 구별하기 위한 역할
      • 셸 명령어 토큰 처리를 위한 구분 역할
      • 프로그래밍 언어의 블록 구분 = { } 의 역할
    • 공백을 임의로 생략하거나 넣으면 오류가 발생한다
  • 공백이 중요한 예

      obo@obo-900X3L:~$ var1="helloobo"
      obo@obo-900X3L:~$ echo $var1
      helloobo
      obo@obo-900X3L:~$ var1 = "happyOBO"
      var1: command not found
    

environment variable

  • 환경 변수
    • 셸 변수에 상속 속성을 설정 -> fork하는 경우 child process에 상속됨
  • 환경 변수 declaration
    • export <NAME>=<CONTENTS> 또는 declare -x <NAME>=<CONTENTS>
  • 환경 변수 expression
    • 일반 변수와 동일
  • built in env. var

    [no-alignment]

      obo@obo-900X3L:~$ env
      LC_PAPER=ko_KR.UTF-8
      XDG_SESSION_ID=10
      LC_ADDRESS=ko_KR.UTF-8
      LC_MONETARY=ko_KR.UTF-8
      TERM=xterm-256color
      SHELL=/bin/bash
      ROS_ROOT=/opt/ros/kinetic/share/ros
      SSH_CLIENT=127.0.0.1 33984 22
      ROS_PACKAGE_PATH=/opt/ros/kinetic/share
      ROS_MASTER_URI=http://localhost:11311
      LC_NUMERIC=ko_KR.UTF-8
      ROS_PYTHON_VERSION=2
      OLDPWD=/home/obo/42dot
      ...
      PKG_CONFIG_PATH=/opt/ros/kinetic/lib/pkgconfig:/opt/ros/kinetic/lib/x86_64-linux-gnu/pkgconfig
      LESSOPEN=| /usr/bin/lesspipe %s
      CMAKE_PREFIX_PATH=/opt/ros/kinetic
      XDG_RUNTIME_DIR=/run/user/1000
      LESSCLOSE=/usr/bin/lesspipe %s %s
      LC_TIME=ko_KR.UTF-8
      SCENARIO_RUNNER_ROOT=/home/obo/42dot/scenario_runner
      ROS_ETC_DIR=/opt/ros/kinetic/etc/ros
      LC_NAME=ko_KR.UTF-8_=/usr/bin/env    
    
  • 환경변수 PATH
    • 명령어를 탐색하는 기능
    • 사실은 ls를 실행할때 PATH라는곳에 디렉토리를 다 뒤지면서 /bin/에 있네? /bin/에서 ls를 실행한다.
      # ~/.bashrc
      export PATH=~/develpment/sdk/bin:$PATH
      ## 이렇게 선언하면 PATH 가 계속적으로 늘어나서 나중엔 엉망이 된다...!
    
    
    • 그러면 어떻게 하나..! pathmunge라는 셸 함수를 만들어서 사용한다.
      • 기존에 이 PATH가 있으면 추가하지 않고, 없으면 추가해준다..!
        if [ "$(type -t pathmunge)" != 'function' ]; then
            pathmunge () {
                [ ! -d "$1" ] && return 1
                case ":${PATH}:" in
                    *:"$1":*) # 있으면 pass
                        ;;
                    *) # 없으면 추가
                        if [ "$2" = "after" ] ; then
                            PATH=$PATH:$1
                        else
                            PATH=$1:$PATH
                        fi
                esac
            }
        fi
      
        pathmunge $HOME/devel/sdk/bin after
      

Categories:

Updated: