[Linux 기초] Shell과 리눅스 환경변수
카테고리: Linux
태그: Linux
서브쉘 실행 방법
리눅스에서 서브쉘을 실행하는 방법에 대해 알아보자.
프로세스 목록코프로세싱
1. 프로세스 목록
( 명령어 목록 )
명령어 목록이 프로세스 목록으로 간주되려면 명령들을 괄호()로 둘러싸야 한다. 괄호를 더해서 명령 목록을 프로세스 목록으로 바꾸면 해당 명령어 목록은 서브쉘에서 실행된다.
root@ubuntu-server:~# ( sleep 2; echo $BASH_SUBSHELL; sleep 2 ) // $BASH_SUBSHELL : 하위 서브쉘을 뜻하는 리눅스 환경 변수
1
root@ubuntu-server:~#
이때 백그라운드(&) 모드에서 프로세스 목록을 사용하는 것은 CLI에서 서브쉘을 사용하는 창의적인 방법이 될 수 있다. 서브쉘 안에서 많은 양의 작업을 처리하면서도 터미널이 서브쉘의 입출력에 발목이 잡히지 않아도 된다.
root@ubuntu-server:~# ( sleep 2; echo $BASH_SUBSHELL; sleep 2 ) & [1] 14451 root@ubuntu-server:~# 1
2. 코프로세싱
코프로세싱(co-processing)은 두 가지 작업을 동시에 수행하는 것을 말한다. 코프로세싱은 백그라운드 모드에서 서브쉘을 생성하고 서브쉘에서 명령을 실행한다.
coproc <Process NAME> { sleep 10; }
root@ubuntu-server:~# coproc MY_JOB { sleep 10; }
[1] 14498
root@ubuntu-server:~# jobs
[1]+ Running coproc MY_JOB { sleep 10; } &
코프로세싱 이름을 MY_JOB 으로 설정했다. 주의할 점은 첫 번째 여는 중괄호와 실행시킬 명령어 사이에 빈 칸이 반드시 하나 있어야 하고 명령은 반드시 세미콜론으로 끝나야 한다. 세미콜론과 닫는 중괄호 사이에도 빈 칸이 반드시 하나 있어야 한다.
쉘 명령
쉘 내장 명령 및 비내장 명령(외부 명령)에 대해 알아보자.
외부 명령내장 명령
1. 외부 명령
- 외부 명령은 bash 쉘의 외부에 존재하는 프로그램이다. 이들 명령은 쉘 프로그램에 내장되어 있지 않다. 외부 명령은 보통 /bin, /usr/bin, /sbin 또는 /usr/sbin 에 있다.
- ps 명령은 외부 명령이다. which와 type 명령으로 ps 명령의 파일 이름을 찾을 수 있다.
- 외부 명령이 실행될 때마다 자식 프로세스가 생성된다. 이러한 동작을 포크(Fork)라고 한다. ps는 현재의 부모 프로세스는 물론 포크된 자식 프로세스까지 표시한다.
root@ubuntu-server:~# ps -f
UID PID PPID C STIME TTY TIME CMD
root 14523 14402 0 00:33 pts/0 00:00:00 sudo su -
root 14524 14523 0 00:33 pts/0 00:00:00 su -
root 14525 14524 7 00:33 pts/0 00:00:00 -su
root 14538 14525 0 00:33 pts/0 00:00:00 ps -f
2. 내장 명령
- 내장 명령들은 자식 프로세스를 실행시킬 필요가 없다는 점에서 외부 명령과는 다르다.
- 이들은 쉘과 함께 컴파일되므로 쉘의 여러 기능 가운데 일부를 이루고 있다.
- 이들을 실행시킬 때에는 어떠한 외부 프로그램 파일도 필요 없다.
몇몇 명령은 여러 가지 특성이 있다는 점에 유의하라. 예를 들어 echo와 pwd 명령은 내장 명령의 특성만이 아니라 외부 명령의 특성도 있다. 이러한 특성은 약간씩 다르다. type 명령에 -a 옵션을 사용하면 명령의 여러 가지 특성을 볼 수 있다.
root@ubuntu-server:~# type -a echo echo is a shell builtin echo is /bin/echo root@ubuntu-server:~# type -a pwd pwd is a shell builtin pwd is /bin/pwd
history
여러 터미널 세션이 열려있어 열린 각 세션마다
history -a명령을 사용하여 .bash_history 파일에 히스토리를 추가할 수 있다. 그러나 열려있는 다른 터미널 세션의 히스토리가 자동으로 업데이트 되지는 않는다. .bash_history 파일은 터미널 세션이 처음으로 시작되었을 때 읽기 전용이 되기 땜누이다. .bash_history 파일을 다시 읽어 들이고 세션의 히스토리를 업데이트하도록 강제하려면history -n명령을 사용한다. (다른 터미널에서 입력한 명령을 보기 위해서는 각 터미널에서history -a명령을 입력하고, 현재 터미널에서history -n옵션으로 업데이트 해야한다.)
환경 변수
bash 쉘에는 두 가지 환경 변수의 유형이 있다. 이를 알아보자.
전역 변수지역 변수
1. 전역 변수
전역 환경 변수는 쉘 세션 및 그로부터 파생된 자식 서브쉘에서 사용할 수 있다. 반면 지역 변수의 경우 이를 만든 쉘 에서만 사용할 수 있다.
root@ubuntu-server:~# my_variable="I am Global now"
root@ubuntu-server:~# export my_variable
root@ubuntu-server:~# bash
root@ubuntu-server:~# echo $MY_NAME
HOON
✏️전역 변수 설정하기
전역 환경 변수를 만들려면 먼저 지역 변수를 생성하고 이를 전역 환경으로 export 한다.
root@ubuntu-server:~# my_variable="I am Global now"
root@ubuntu-server:~# export my_variable
자식 쉘 안에서 전역 환경 변수를 변경해도 부모 쉘의 변수 값에는 영향을 주지 않는다. 또한 자식 쉘이 변수 my_variable 을 다시 정의하고 익스포트하더라도 부모 쉘의 my_variable 변수는 원래 값을 유지한다.
✂️환경 변수 제거하기
unset 명령을 사용하여 환경 변수를 제거할 수 있다. unset 명령에서 환경 변수를 참조할 때에는 달러 기호를 사용하지 않는다는 점을 유의하라.
root@ubuntu-server:~# my_variable="I am Global now"
root@ubuntu-server:~# export my_variable
root@ubuntu-server:~# echo $my_variable
I am Global now
root@ubuntu-server:~# unset my_variable
root@ubuntu-server:~# echo $my_variable
변수 값을 변경할 때와 마찬가지로 자식 쉘에서는 변수를 unset 할 수 없으며 변수는 부모 쉘에서 unset 되어야 한다.
2. 지역 변수
지역 환경 변수는 그 이름에서 알 수 있듯이 이 변수를 정의한 지역 프로세스에서만 볼 수 있다. 사실 리눅스 시스템은 기본적으로 표준 지역 환경 변수도 함께 정의하지만 사용자에게 필요한 지역 변수도 정의할 수 있다. 이러한 변수를 사용자 정의 지역 변수라고 한다.
root@ubuntu-server:~# my_variable="I am Global now"
set 명령은 특정 프로세스에 대한 모든 변수를 표시하며, 지역 및 전역 환경 변수와 사용자 정의 변수를 모두 포함한다.
root@ubuntu-server:~# set
...
my_variable='I am Global now'
...
env 또는 printenv 명령을 써서 표시되는 모든 전역 환경 변수는 set 명령의 출력에서도 표시된다.
env, printenv, set 명령의 차이는 미묘하다. set 명령은 전역 및 지역 환경 변수와 사용자 정의 변수 모두를 표시한다. 또한 알파벳순으로 정렬한다. env 및 printenv 명령은 변수를 정렬하지 않는다는 점에서 set과는 다르며 지역 환경 변수나 지역 사용자 정의 변수도 표시하지 않는다. 이러한 맥락에서 보면 env와 printenv 명령은 똑같은 명령을 표시한다. 그러나 env 명령은 printenv 명령에는 없는 추가 기능이 있기 때문에 좀 더 강력하다.
시스템 환경 변수
리눅스 시스템에 로그인하여 bash 쉘을 시작할 때 bash는 명령에 관한 여러 개의 파일을 검사한다. 이 파일을 시동 파일 또는 환경 파일이라고 한다. bash 쉘이 시작 단계에서 처리하는 시동 파일은 bash 쉘을 실행하기 위해서 사용하는 방법에 따라 달라진다.
bash 쉘은 세 가지 방법으로 실행된다.
로그인 쉘서브쉘을 생성함으로써 실행되는 대화형 쉘스크립트를 실행시키기 위한 비대화형 쉘
로그인 쉘
리눅스 시스템에 로그인하면 bash 쉘은 로그인 쉘로 실행된다. 로그인 쉘은 보통 다섯 개의 파일을 찾아서 이로부터 명령을 실행하려고 한다.
- /etc/profile
- $HOME/.bash_profile
- $HOME/.bashrc
- $HOME/.bash_login
- $HOME/.profile
/etc/profile 파일은 시스템에서 bash 쉘의 주요 기본 시동 파일이다. 로그인할 때 시스템의 모든 사용자는 이 시동 파일을 실행한다. 다른 네 개의 시동 파일은 각 사용자에 대하여 특정되어 있으며 개별 사용자의 요구에 따라 맞춤형으로 정의할 수 있다.
다음 목록에 나오는 순서에 따라 처음 발견되는 파일만이 실행되며 나머지는 무시된다.
- $HOME/.bash_profile
- $HOME/.bash_login
- $HOME/.profile
$HOME/.bashrc 파일이 이 목록에 없다는 점을 유의하라. 보통은 다른 파일들 중 한 곳 안에서 실행되기 떄문이다.
test 중인 환경에서는 $HOME/.profile 에 의해 실행된다
root@ubuntu-server:~# cat ~/.profile
# ~/.profile: executed by Bourne-compatible login shells.
if [ "$BASH" ]; then
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
fi
mesg n || true
대화형 쉘
- 시스템에 로그인하지 않고 bash 쉘을 시작하면(CLI 프롬프트에서 bash 라고만 입력하는 경우) 대화형 쉘이라고 하는 것이 시작된다. 대화형 쉘은 로그인 쉘 처럼 동작하지 않지만 명령을 입력하는 CLI 프롬프트를 제공한다.
- bash 쉘이 대화형 쉘로 실행되면 /etc/profile 파일을 처리하지 않는다. 대신 사용자의 HOME 디렉터리에 있는 .bashrc 파일만 확인한다.
- .bashrc 파일은 두 가지 작업을 수행한다. 먼저 /etc 디렉터리에 있는 공통 bashrc 파일을 확인한다. 다음으로는 사용자가 정의한 alias, 스크립트 함수를 입력할 수 있는 장소를 제공한다.
비대화형 쉘
- 비대화형 쉘은 쉘 스크립트 실행을 시작할 수 있는 쉘로 CLI 프롬프트가 없다.
- bash 쉘은 BASH_ENV 환경 변수를 제공하여 쉘이 비대화형 쉘로 실행될 때, 쉘은 실행시킬 시동 파일 이름을 이 환경 변수에서 찾도록 한다.
- 이름이 존재하면 쉘은 이 파일의 명령을 실행하며 보통 이 파일은 쉘 스크립트를 위한 변수의 모음을 포함하고 있다.
BASH_ENV 변수가 설정되지 않았다면 쉘 스크립트는 어떻게 이 환경 변수를 사용할 수 있을까? 일 부 쉘 스크립트의 실행 방법은 서브쉘, 혹은 자식 쉘을 실행하는 것이라는 점을 기억하자. 자식 쉘은 부모 쉘의 변수를 상속한다.
👍환경 변수를 영구적으로 만들기 위한 모범 사례
전역 환경 변수(Linux 시스템의 모든 사용자가 필요로 하는 변수)인 경우, /etc/profile 파일안에 새로운 변수를 넣거나 값을 바꾸고 싶을 수도 있겠지만 이는 잘못된 생각이다. 배포판이 업그레이드될 때 이 파일이 변경될 수 있으며 그렇게 되면 수정했던 모든 사용자 정의 변수 설정을 잃게 된다. 좀 더 나은 방법은 /etc/profile.d 디렉터리에 .sh로 끝나는 파일을 만드는 것이다. 이 파일에 새로 만들었거나 수정한 전역 환경 변수 설정을 모두 배치한다. 대부분의 배포한에서 개별 사용자의 영구적인 bash 쉘 변수를 저장하기 위한 좋은 장소는 $HOME/.bashrc 파일이다. 이는 모든 유형의 쉘 프로세스에 대해 적용된다. 하지만 BASH_ENV 변수가 설정되어 있다면 이 변수가 $HOME/.bashrc를 가리키지 않는 한 비대화형 쉘을 위한 사용자 변수를 어딘가 다른 곳에 저장해야 할 수도 있다는 점을 잊지 말자.
📖출처
리처드 블룸, 크리스틴 브레스, ⌜리눅스 커맨드라인 쉘 스크립트 바이블⌟, 스포트라잇북(2016)
👍 개인 공부 기록용 블로그입니다. 오류나 조언이 있으시면 언제든지 댓글 혹은 메일로 남겨주시면 감사하겠습니다! 😄
댓글남기기