Bash 익히기(http://pyrasis.com/book/DockerForTheReallyImpatient/Chapter04)

Docker가 리눅스 기반이기 때문에 이미지를 생성할 때 Bash(Bourne-again shell)를 주로 사용합니다. 그래서 이미지를 생성하기 전에 자주 사용하는 Bash 문법을 간단히 알아보겠습니다.

문법설명
>출력 리다이렉션. 명령 실행의 표준 출력(stdout)을 파일로 저장합니다. 유닉스계열 운영체제는 장치도 파일로 처리하기 때문에 명령 실행 결과를 특정 장치로 보낼 수도 있습니다.
$ echo "hello" > ./hello.txt
$ echo "hello" > /dev/null
<입력 리다이렉션. 파일의 내용을 읽어 명령의 표준 입력(stdin)으로 사용합니다.
$ cat < ./hello.txt
>>명령 실행의 표준 출력(stdout)을 파일에 추가합니다. >는 이미 있는 파일에 내용을 덮어쓰지만 >>는 파일 뒷부분에 내용을 추가합니다.
$ echo "world" >> ./hello.txt
2>명령 실행의 표준 에러(stderr)를 파일로 저장합니다.
2>>명령 실행의 표준 에러(stderr)를 파일에 추가합니다.
&>표준 출력과 표준 에러를 모두 파일로 저장합니다.
1>&2표준 출력을 표준 에러로 보냅니다. echo 명령으로 문자열을 표준 출력으로 출력했지만 표준 에러로 보냈기 때문에 변수에는 문자열이 들어가지 않습니다.
$ hello=$(echo "Hello World" 1>&2)
$ echo $hello
 
2>&1표준 에러를 표준 출력으로 보냅니다. abcd라는 명령은 없으므로 에러가 발생하지만 에러를 표준 출력으로 보낸 뒤 다시 /dev/null로 보냈기 때문에 아무것도 출력되지 않습니다.
$ abcd > /dev/null 2>&1
|파이프. 명령 실행의 표준 출력을 다른 명령의 표준 입력으로 보냅니다. 즉 첫 번째 명령의 출력 값을 두 번째 명령에서 처리합니다.
$ ls -al | grep .txt
$Bash의 변수입니다. 값을 저장할 때는 $를 붙이지 않고, 변수를 가져다 쓸 때만 $를 붙입니다.
$ hello="Hello World"
$ echo $hello
Hello World
$()명령 실행 결과를 변수화합니다. 명령 실행 결과를 변수에 저장하거나 다른 명령의 매개 변수로 넘겨줄 때 사용합니다. 또는 문자열안에 명령의 실행 결과를 넣을 때 사용합니다.
$ sudo docker rm $(docker ps -aq)
$ echo $(date)
Tue Sep 9 21:24:30 KST 2014
` `$()과 마찬가지로 명령 실행 결과를 변수화합니다.
$ sudo docker rm `docker ps -aq`
$ echo `date`
Tue Sep 9 21:24:30 KST 2014
&&한 줄에서 명령을 여러 개 실행합니다. 단 앞에 있는 명령이 에러 없이 실행되어야 뒤에 오는 명령이 실행됩니다.
$ make && make install
;한 줄에서 명령을 여러 개 실행합니다. 앞에 있는 명령이 실패를 해도 뒤에 오는 명령이 실행됩니다.
$ false; echo "Hello"
Hello
' '문자열입니다. ' '안에 들어있는 변수는 처리되지 않고 변수명 그대로 사용됩니다. 또한 ` `와 $()도 처리되지 않고 그대로 사용됩니다.
$ echo '$USER'
$USER
$USER가 그대로 출력됩니다.
" "문자열입니다. 명령에 문자열 매개변수를 입력하거나 변수에 저장할 때 주로 사용합니다. ' '와는 달리 " "안에 변수가 들어있으면 변수의 내용으로 바뀝니다. 또한 ` `와 $()도 실행 결과 값이 사용됩니다.
$ echo "Hello World"
Hello World
$ echo "$USER"
pyrasis
$ echo "Host name is $(hostname)"
Host name is ubuntu
$ echo "Time: `date`"
Time: Tue Sep  9 21:28:10 KST 2014
" ' ' "" "안에 ' '가 들어갈 수 있습니다. 명령 안에서 다시 명령을 실행하고 매개 변수를 지정할 때 사용합니다.
$ bash -c "/bin/echo Hello 'World'"
Hello World
\"
\$hello
' '안에서 "를 사용할 때는 \"처럼 앞에 \를 붙여줍니다.
$ bash -c "/bin/echo '{ \"user\": \"$USER\" }'"
{ "user": "pyrasis" }
" "안에서 ", $, ` 등의 특수문자를 그대로 사용하려면 앞에 \를 붙여줍니다.
$ echo "\$hello \" \`"
$hello " `
${}변수 치환(substitution)입니다. " " 문자열 안에서 변수를 출력할 때 주로 사용합니다. ${} 대신 $만 사용해도 됩니다.
$ str="World"
$ echo "Hello ${str}"
Hello World
스크립트에서 변수의 기본 값을 설정할 때도 사용합니다. 다음은 HELLO 변수가 있으면 그대로 사용하고 변수가 없으면 기본 값으로 설정한 abcd를 대입합니다.
$ HELLO=
$ HELLO=${HELLO-"abcd"}
$ echo $HELLO
값이 NULL인 HELLO 변수가 이미 있기 때문에 기본 값을 대입하지 않습니다. 다음은 변수에 값이 있으면 그대로 사용하고, 값이 NULL이면 기본 값으로 설정한 abcd를 대입합니다.
$ WORLD=
$ WORLD=${WORLD:-"abcd"}
$ echo $WORLD
abcd
변수에 값이 NULL이므로 기본 값을 대입합니다.
\한 줄로된 명령을 여러 줄로 표현할 때 사용합니다.
$ sudo docker run -d --name hello busybox:latest
$ sudo docker run \
    -d \
    --name hello \
    busybox:latest
{1..10}연속된 숫자를 표현합니다. {시작 숫자..끝 숫자} 형식입니다.
$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
{문자열1,문자열2}{}안에 문자열을 여러 개 지정하여 명령 실행 횟수를 줄입니다. 다음은 hello.txt, world.txt 두 파일을 한번에 hello-dir 디렉터리 아래에 복사합니다.
$ cp ./{hello.txt,world.txt} hello-dir/
ifif 조건문입니다. 변수와 변수끼리 또는 문자열과 비교할 때 사용합니다.
if [ $a -eq $b ]; then
  echo $a
fi
숫자 비교
  • -eq: 같다
  • -ne: 같지 않다
  • -gt: 초과
  • -ge: 이상
  • -lt: 미만
  • -le: 이하
문자열 비교
  • =, ==: 같다
  • !=: 같지 않다
  • -z: 문자열이 NULL일 때
  • -n: 문자열이 NULL이 아닐 때
forfor 반복문입니다. 변수안에 있는 값을 반복하거나 범위를 지정하여 반복할 수 있습니다.
for i in $(ls)
do
  echo $i
done

for (( i=0; i < 10; i++ ))
do
  echo $i
done

NUM=(1 2 3)
for i in ${NUM[@]}
do
  echo $i
done
whilewhile 반복문입니다.
while :
do
  echo "Hello World";
  sleep 1;
done
<<<문자열을 명령(프로세스)의 표준 입력으로 보냅니다.
$ cat <<< "User name is $USER"
User name is pyrasis
<<EOF
EOF
여러 줄의 문자열을 명령(프로세스)의 표준 입력으로 보냅니다.
cat > ./hello.txt <<EOF
Hello World
Host name is $(hostname)
User name is $(USER)
EOF
cat은 파일이나 표준 입력의 내용을 출력하는 명령입니다. cat의 표준 출력을 ./hello.txt로 저장하고, <<EOF로 문자열을 cat의 표준 입력으로 보냅니다. 이렇게 하면 문자열 3줄이 ./hello.txt 파일에 저장됩니다.
export설정한 값을 환경 변수로 만듭니다. export <변수>=<값> 형식입니다.
$ export HELLO=world
printf지정한 형식대로 값을 출력합니다. 파이프와 연동하여 명령(프로세스)에 값을 입력하는 효과를 낼 수 있습니다.
$ printf 80\\nexampleuser\\ny | example-config
Port: 80
User: exampleuser
Save Configuration (y/n): y
예를 들어 example-config는 Port, User, Save Configuration을 사용자에게 입력을 받습니다. printf로 미리 값을 설정하여 파이프로 example-config에 넘겨주면 사용자가 입력하지 않아도 자동으로 값이 입력됩니다. 줄바꿈(개행)은 \\n으로 표현합니다.
sed텍스트 파일에서 문자열을 변경합니다. hello.txt 파일의 내용 중에서 hello라는 문자열을 찾아서 world 문자열로 바꾸려면 다음과 같이 실행합니다.
$ sed -i "s/hello/world/g" hello.txt
sed -i "s/<찾을 문자열><바꿀 문자열>/g" <파일명> 형식입니다. /와 같은 특수 문자는 앞에 \를 붙여 \/로 입력합니다.
#주석입니다. 스크립트에 설명을 추가하거나, 명령이 실행되지 않도록 합니다.
# echo "Hello World"

표 4-1 Bash 기본 문법

Bash 입문자를 위한 핵심 요약 정리 (Shell Script)

-https://blog.gaerae.com/2015/01/bash-hello-world.html

Bash 입문자를 위한 기본적인 문법과 알고 있으면 좋은 것들만 정리했다.
(이런 것도 있구나 싶을 정도만 이해하도록 간단한 설명과 예제로 작성됨)

첫 시작은 문자 출력하기(Hello World)

고전적이지만 "hello world" 단순 출력부터 시작해보자.
파일명은 hello.sh로 만들고 실행해보자. 단 두줄이면 끝이다.
(만일 실행이 안된다면 퍼미션을 변경해야되는데 뭔지 모르겠다면 일단 이렇게 해봐라.chmod 700 hello.sh)
참고: echo 문장을 출력하는데 자동으로 줄바꿈 됨
참고: printf C언어와 비슷함
#!/usr/bin/env bash
echo "hello world"
printf "hello world"
printf "%s %s" hello world

주석(Comments)

# 기호로 시작하면 주석이다. 

함수(Function)

형식은 다른 언어와 차이는 없다. 그러나 function는 생략해도 된다.
함수 명을 쓰면 함수가 호출이 되는데 주의할 것은 호출 코드가 함수 코드보다 반드시 뒤에 있어야 된다. 함수 코드 보다 앞에서 호출 시 오류가 발생한다.
string_test() {
    echo "string test"
}

function string_test2() {
    echo "string test 2"
    echo "인자값: ${@}"
}
string_test
string_test2

# 함수에 인자값 전달하기(공백의로 뛰어서 2개의 인자값을 넘김)
string_test2 "hello" "world"

변수(Variable)

변수 사용시에는 "=" 기호 앞뒤로 공백이 없이 입력하면 대입연산자가 된다.
그리고 선언된 변수는 기본적으로 전역 변수(global variable)다. 단 함수 안에서만 지역 변수(local variable)를 사용할 수 있는데 사용할려면 변수 명 앞에 local을 붙여주면 된다.
그런데 전역 변수는 현재 실행된 스크립트 파일에서만 유효하다. 자식 스크립트에서는 사용 할 수 없는 변수다.
변수 명 앞에 export을 붙여주면 환경 변수(environment variable)로 설정되어 자식 스크립트에서 사용 가능하다.
환경 변수 사용시 예약 변수(reserved variable)에 주의하자.(참고로 환경 변수는 .bash_profile에서 정의한다.)
# 전역 변수 지정
string="hello world"
echo ${string}

# 지역 변수 테스트 함수
string_test() {
    # 전역 변수와 동일하게 사용함. 만약 local 뺀다면 전역 변수에 덮어씌어지게 됨
    local string="local"
    echo ${string}
}
# 지역 변수 테스트 함수 호출
string_test
# 지역 변수 테스트 함수에서 동일한 변수 명을 사용했지만 값이 변경되지 않음
echo ${string}

# 환경 변수 선언
export hello_world="hello world..."
# 자식 스크립트 호출은 스크립트 경로을 쓰면된다.
/home/export_test.sh

#환경 변수를 테스트하기 위해 export_test.sh 파일을 만들고 선언한 변수를 확인해본다.
echo ${hello_world}

예약 변수(Reserved Variable)

문자설명
HOME사용자의 홈 디렉토리
PATH실행 파일을 찾을 경로
LANG프로그램 사용시 기본 지원되는 언어
PWD사용자의 현재 작업중인 디렉토리
FUNCNAME현재 함수 이름
SECONDS스크립트가 실행된 초 단위 시간
SHLVL쉘 레벨(중첩된 깊이를 나타냄)
SHELL로그인해서 사용하는 쉘
PPID부모 프로세스의 PID
BASHBASH 실행 파일 경로
BASH_ENV스크립트 실행시 BASH 시작 파일을 읽을 위치 변수
BASH_VERSION설치된 BASH 버전
BASH_VERSINFOBASH_VERSINFO[0]~BASH_VERSINFO[5]배열로 상세정보 제공
MAIL메일 보관 경로
MAILCHECK메일 확인 시간
OSTYPE운영체제 종류
TERM로긴 터미널 타입
HOSTNAME호스트 이름
HOSTTYPE시스템 하드웨어 종류
MACHTYPE머신 종류(HOSTTYPE과 같은 정보지만 조금더 상세하게 표시됨)
LOGNAME로그인 이름
UID사용자 UID
EUIDsu 명령에서 사용하는 사용자의 유효 아이디 값(UID와 EUID 값은 다를 수 있음)
USER사용자의 이름
USERNAME사용자 이름
GROUPS사용자 그룹(/etc/passwd 값을 출력)
HISTFILEhistory 파일 경로
HISTFILESIZEhistory 파일 크기
HISTSIZEhistory 저장되는 개수
HISTCONTROL중복되는 명령에 대한 기록 유무
DISPLAYX 디스플레이 이름
IFS입력 필드 구분자(기본값:   - 빈칸)
VISUALVISUAL 편집기 이름
EDITOR기본 편집기 이름
COLUMNS현재 터미널이나 윈도우 터미널의 컬럼 수
LINES터미널의 라인 수
LS_COLORSls 명령의 색상 관련 옵션
PS1기본 프롬프트 변수(기본값: bash\$)
PS2보조 프롬프트 변수(기본값: >), 명령을 "\"를 사용하여 명령 행을 연장시 사용됨
PS3쉘 스크립트에서 select 사용시 프롬프트 변수(기본값: #?)
PS4쉘 스크립트 디버깅 모드의 프롬프트 변수(기본값: +)
TMOUT0이면 제한이 없으며 time시간 지정시 지정한 시간 이후 로그아웃

위치 매개 변수(Positional Parameters)

문자설명
$0실행된 스크립트 이름
$1$1 $2 $3...${10}인자 순서대로 번호가 부여된다. 10번째부터는 "{}"감싸줘야 함
$*전체 인자 값
$@전체 인자 값($* 동일하지만 쌍따옴표로 변수를 감싸면 다른 결과 나옴)
$#매개 변수의 총 개수

특수 매개 변수(Special Parameters)

문자설명
$$현재 스크립트의 PID
$?최근에 실행된 명령어, 함수, 스크립트 자식의 종료 상태
$!최근에 실행한 백그라운드(비동기) 명령의 PID
$-현재 옵션 플래그
$_지난 명령의 마지막 인자로 설정된 특수 변수

매개 변수 확장(Parameter Expansion)

아래 예를 테스트하기 위한 변수: string="abc-efg-123-abc"
문자설명
${변수}$변수와 동일하지만 {} 사용해야만 동작하는 것들이 있음(예: echo ${string})
${변수:위치}위치 다음부터 문자열 추출(예: echo ${string:4})
${변수:위치:길이}위치 다음부터 지정한 길이 만큼의 문자열 추출(예: echo ${string:4:3})
${변수:-단어}변수 미선언 혹은 NULL일때 기본값 지정, 위치 매개 변수는 사용 불가(예: echo ${string:-HELLO})
${변수-단어}변수 미선언시만 기본값 지정, 위치 매개 변수는 사용 불가(예: echo ${string-HELLO})
${변수:=단어}변수 미선언 혹은 NULL일때 기본값 지정, 위치 매개 변수 사용 가능(예: echo ${string:=HELLO})
${변수=단어}변수 미선언시만 기본값 지정, 위치 매개 변수 사용 가능(예: echo ${string=HELLO})
${변수:?단어}변수 미선언 혹은 NULL일때 단어 출력 후 스크립트 종료,(예: echo ${string:?HELLO})
${변수?단어}변수 미선언시만 단어 출력 후 스크립트 종료(예: echo ${string?HELLO})
${변수:+단어}변수 선언시만 단어 사용(예: echo ${string:+HELLO})
${변수+단어}변수 선언 혹은 NULL일때 단어 사용(예: echo ${string+HELLO})
${#변수}문자열 길이(예: echo ${#string})
${변수#단어}변수의 앞부분부터 짧게 일치한 단어 삭제(예: echo ${string#a*b})
${변수##단어}변수의 앞부분부터 길게 일치한 단어 삭제(예: echo ${string##a*b})
${변수%단어}변수의 뒷부분부터 짧게 일치한 단어 삭제(예: echo ${string%b*c})
${변수%%단어}변수의 뒷부분부터 길게 일치한 단어 삭제(예: echo ${string%%b*c})
${변수/찾는단어/변경단어}처음 일치한 단어를 변경(예: echo ${string/abc/HELLO})
${변수//찾는단어/변경단어}일치하는 모든 단어를 변경(예: echo ${string//abc/HELLO})
${변수/#찾는단어/변경단어}앞부분이 일치하면 변경(예: echo ${string/#abc/HELLO})
${변수/%찾는단어/변경단어}뒷부분이 일치하면 변경(예: echo ${string/%abc/HELLO})
${!단어*}, ${!단어@}선언된 변수중에서 단어가 포함된 변수 명 추출(예: echo ${!string*}echo ${!string@})

배열(Array Variable)

배열 변수 사용은 반드시 괄호를 사용해야 한다.(예: ${array[1]})
참고: 1차원 배열만 지원함
# 배열의 크기 지정없이 배열 변수로 선언
# 참고: 'declare -a' 명령으로 선언하지 않아도 배열 변수 사용 가능함
declare -a array

# 4개의 배열 값 지정
array=("hello" "test" "array" "world")

# 기존 배열에 1개의 배열 값 추가(순차적으로 입력할 필요 없음)
array[4]="variable"

# 기존 배열 전체에 1개의 배열 값을 추가하여 배열 저장(배열 복사 시 사용)
array=(${array[@]} "string")

# 위에서 지정한 배열 출력
echo "hello world 출력: ${array[0]} ${array[3]}"
echo "배열 전체 출력: ${array[@]}"
echo "배열 전체 개수 출력: ${#array[@]}"

printf "배열 출력: %s\n" ${array[@]}

# 배열 특정 요소만 지우기
unset array[4]
echo "배열 전체 출력: ${array[@]}"

# 배열 전체 지우기
unset array
echo "배열 전체 출력: ${array[@]}"

변수 타입 지정(Variables Revisited)

Bash 변수는 타입을 구분하지 않고 기본적으로 문자열이다. 단 문맥에 따라서 연산 처리한다. 
그런데 불완전한 형태의 declaretypeset 타입 지정 명령을 지원한다.(두 명령은 동일함)
참고: 코멘트에 있는 다른 문법 사용을 추천한다.
# 읽기 전용
# readonly string_variable="hello world" 문법과 동일 함
declare -r string_variable

# 정수
# number_variable=10 문법과 동일 함
declare -i number_variable=10

# 배열
# array_variable=() 문법과 동일 함
declare -a array_variable

# 환경 변수
# export export_variable="hello world" 문법과 동일 함
declare -x export_variable="hello world"

# 현재 스크립트의 전체 함수 출력
declare -f

# 현재 스크립트에서 지정한 함수만 출력
declare -f 함수이름

논리 연산자(Logical Operators)

문자설명
&&-a논리 AND
||-o논리 OR

산술 연산자(Arithmetic Operators)

문자설명
+더하기
-빼기
*곱하기
/나누기
++누승(exponentiation)
%modulo 나 mod (정수 나누기에서 나머지 값)
+=상수값 만큼 증가(plus-equal)
-=상수값 만큼 감소(minus-equal)
*=상수값을 곱함(times-equal)
/=상수값으로 나눔(slash-equal)
%=상수값으로 나눈 나머지 값(mod-equal)

비트 연산자(Bitwise Operators)

문자설명
<<비트 왼쪽 쉬프트(쉬프트 한 번당 2를 곱하는 것과 동일함)
<<=left-shift-equal
>>비트 오른쪽 쉬프트(쉬프트 한 번당 2로 나눔)
>>=right-shift-equal(<<=와 반대)
&비트 and
&=비트 and-equal
|비트 OR
|=비트 OR-equa
~비트 negate
!비트 NOT
^비트 XOR
^=비트 XOR-equa

기타 연산자(Miscellaneous Operators)

문자설명
,콤마 연산자(comma operator), 2개 이상의 산술 연산을 묶어줌

정수 비교(Integer Comparison)

문자설명
-eq같음
-ne같지 않음
>-gt더 큼(> 이중 소괄호에서 사용 가능)
>=-ge더크거나 같음(>= 이중 소괄호에서 사용 가능)
<-lt더 작음(< 이중 소괄호에서 사용 가능)
<=-le더 작거나 같음(<= 이중 소괄호에서 사용 가능)

문자열 비교(String Comparison)

문자설명
===같음
!=같지 않음
<ASCII 알파벳 순서에 더 작음
>ASCII 알파벳 순서에서 더 큼
-z문자열이 NULL, 길이가 0인 경우
-n문자열이 NULL이 아님
${변수}문자열이 NULL이 아님

파일 비교(File test operators)

문자설명
-e파일이 존재
-f파일이 존재하고 일반 파일인 경우(디렉토리 혹은 장치파일이 아닌 경우)
-s파일이 존재하고 0보다 큰 경우
-d파일이 존재하고 디렉토리인 경우
-b파일이 존재하고 블록장치 파일인 경우
-c파일이 존재하고 캐릭터 장치 파일인 경우
-p파일이 존재하고 FIFO인 경우
-h파일이 존재하고 한 개 이상의 심볼릭 링크가 설정된 경우
-L파일이 존재하고 한 개 이상의 심볼릭 링크가 설정된 경우
-S파일이 소켓 디바이스인 경우
-t파일이 디스크립터가 터미널 디바이스와 연관이 있음
-r파일이 존재하고 읽기 가능한 경우
-w파일이 존재하고 쓰기가 가능한 경우
-x파일이 존재하고 실행 가능한 경우
-g파일이 존재하고 SetGID가 설정된 경우
-u파일이 존재하고 SetUID가 설정된 경우
-k파일이 존재하고 스티키 비트(Sticky bit)가 설정된 경우
-O자신이 소유자임
-G그룹 아이디가 자신과 같음
-N마지막으로 읽힌 후에 변경 됐음
file1 -nt file2file1 파일이 file2 파일보다 최신임
file1 -ot file2file1 파일이 file2 파일보다 예전것임
file1 -ef file2file1 파일과 file2 파일이 같은 파일을 하드 링크하고 있음
!조건이 안 맞으면 참(예: ! -e file)

반복문(for, while, until)

반목문 작성 시 아래 명령어(흐름제어)을 알아두면 좋다.
반복문을 빠져 나갈때: break
현재 반복문이나 조건을 건너 뛸때: continue
# 지정된 범위 안에서 반복문 필요 시 좋음
for string in "hello" "world" "..."; do;
    echo ${string};
done

# 수행 조건이 true 일때 실행됨 (실행 횟수 지정이 필요하지 않은 반복문 필요 시 좋음)
count=0
while [ ${count} -le 5 ]; do
    echo ${count}
    count=$(( ${count}+1 ))
done

# 수행 조건이 false 일때 실행됨 (실행 횟수 지정이 필요하지 않은 반복문 필요 시 좋음)
count2=10
until [ ${count2} -le 5 ]; do
    echo ${count2}
    count2=$(( ${count2}-1 ))
done

조건문(if...elif...else...fi)

조건문 작성 시 주의해야될 부분은 실행 문장이 없으면 오류 발생함
string1="hello"
string2="world"
if [ ${string1} == ${string2} ]; then
    # 실행 문장이 없으면 오류 발생함
    # 아래 echo 문장을 주석처리하면 확인 가능함
    echo "hello world"
elif [ ${string1} == ${string3} ]; then
    echo "hello world 2"
else
    echo "hello world 3"
fi

# AND
if [ ${string1} == ${string2} ] && [ ${string3} == ${string4} ]
..생략

# OR
if [ ${string1} == ${string2} ] || [ ${string3} == ${string4} ]
..생략

# 다중 조건
if [[ ${string1} == ${string2} || ${string3} == ${string4} ]] && [ ${string5} == ${string6} ]
..생략

선택문(case)

정규식을 지원하며 | 기호로 다중 값을 입력 가능하며 조건의 문장 끝에는 ;; 기호로 끝을 표시한다.
참고: 대문자와 소문자는 다른 문자다.
# case문 테스트를 위한 반복문
for string in "HELLO" "WORLD" "hello" "world" "s" "start" "end" "etc"; do

    # case문 시작
    case ${string} in
        hello|HELLO)
            echo "${string}: hello 일때"
            ;;
        wo*)
            echo "${string}: wo로 시작하는 단어 일때"
            ;;
        s|start)
            echo "${string}: s 혹은 start 일때"
            ;;
        e|end)
            echo "${string}: s 혹은 start 일때"
            ;;
        *)
            echo "${string}: 기타"
            ;;
    esac
    # //case문 끝

done

디버깅(Debugging)

간단하게는 echoexit 명령나 tee 명령어로 디버깅한다.
다른 방법으로 실행 시 옵션을 주거나 코드에 한줄만 추가하면 해볼수 있다.
Bash 옵션(스크립트 실행 시)set 옵션(스크립트 코드 삽입)설명
bash -nset -nset -o noexec스크립트 실행없이 단순 문법 오류만 검사(찾지 못하는 문법 오류가 있을수 있음)
bash -vset -vset -o verbose명령어 실행전 해당 명령어 출력(echo)
bash -xset -xset -o xtrace명령어 실행후 해당 명령어 출력(echo)
set -uset -o nounset미선언된 변수 발견시 "unbound variable" 메시지 출력

마무리하며

  • 여기서 인자(argument)와 매개변수(parameter)는 이름만 다를 뿐 의미는 같다.
  • Bash는 공백에 민감하다.
  • 변수 사용은 생각하지 말고 ${변수} 이렇게 쓰자.

함께보기


리눅스는 서버로 많이 사용되므로 부팅시 서비스용 데몬들은 자동으로 구동되어야 관리가 편리하며 데몬 미구동으로 인한 서비스 제공 불능 상황을 방지할 수 있다. 서비스를 자동으로 구동하기 위해서는 먼저 리눅스의 부팅 과정에 대해서 알아야 하므로 간략하게 살펴 보도록 하자.

CentOS 의 부팅 절차

사용자가 CentOS 가 설치된 서버의 전원을 올리고 부팅을 하면 다음과 같은 절차를 거쳐서 부팅된다.

 
부팅 절차

사용자 입장에서 중요한 부분은 /sbin/init 단계부터이다. init 은 부팅시 linux kernel 이 처음 실행하는 프로세스로 이후의 모든 프로세스는 init 이 생성하게 하며 그래서 init 을 모든 프로세스들의 아버지라고도 한다.

init 프로세스가 수행 동작은 크게 BSD 계열과 SysV 계열로 나눠져 있고 이에 따라 동작 방식이 약간 다르다.

CentOS 의 init 은 SysV 계열의 init 이므로 /etc/inittab 파일을 참고하여 부팅시 실행할 run level 을 결정하게 된다. 런 레벨의 종류 및 의미는 다음과 같다.

런 레벨
의미
0시스템 중단(Halt)
1텍스트 기반의 단일 사용자 모드(single user mode)
2사용되지 않음(사용자가 지정 가능)
3텍스트 기반의 다중 사용자 모드
4사용되지 않음(사용자가 지정 가능)
5 X 윈도 기반의 다중 사용자 모드(로그인도 X 윈도에서 이뤄짐)
6시스템 리부팅
런 레벨 의미

 

우리는 X 윈도를 제외하고 설치했으므로 /etc/inittab 파일을 열어보면 다음과 같이 설정되어 있을 것이다.

id:3:initdefault:

위 설정은 init 프로세스 구동시 기본 run level을 3으로 실행하게 된다. run level 에 맞게 실행되는 프로세스의 목록은 /etc/rc.d/rcX.d 에 있으며 X 는 run level 숫자이다. 3 일 경우 /etc/rc.d/rc3.d 아래에 있는 명령어중 S* 로 시작되는 명령어를 순서대로 모두 실행하며 시스템 종료나 재부팅시는 K* 로 시작하는 명령어를 모두 실행하게 된다. 다음은 ls -l /etc/rc.d/rc3.d/S* 명령 실행의 결과이다.

런 레벨 3일 경우 구동 명령어

웹 서버, DBMS 서버등 어떤 프로그램은 시스템 부팅시 자동으로 같이 구동되어야 할 필요가 있다. 이런 프로그램들은 런레벨 3과 5와 같은 다중 사용자 모드로 부팅할 경우 모두 실행해야 하므로 /etc/rc.d/rc3.d 와  /etc/rc.d/rc5.d 에 모두 등록이 되어 있다. (실제로는 init.d 에 실제 구동 스크립트가 위치하여 rc3.d와 rc5.d 는 init.d 에 대한 심볼릭 링크로 처리되어 있다.)

/etc/inittab 파일을 잘못 편집하면 부팅이 안 되거나 단일 사용자 모드로 부팅될 수 있으므로 주의해야 한다.

 

chkconfig

https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/5/html/Installation_Guide/s2-boot-init-shutdown-sysv-util.html

run level 에 맞게 자동 실행할 서비스 프로그램을 직접 편집해서 설정하기는 번거롭고 실수할 여지가 많은 일이다.

chkconfig 는 간단한 유틸리티로 특정 run level 에서 실행할 프로그램을 등록/설정/변경할 수 있다. 옵션없이 실행하면 전체 등록된 서비스 프로그램의 목록 및 어떤 run level 에서 실행하는지 여부를 출력해 준다.

--list 옵션 뒤에 서비스명을 입력하면 해당 서비스의 run level 설정을 볼 수 있다.  ssh 같은 경우 중요한 서비스이므로 단일 사용자 모드외에는 모두 실행하도록 등록이 되어 있다.

chkconfig --list sshd   sshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off

 

chkconfig 는 on과 off 옵션을 제공하는데 해당 서비스 서버를 부팅과 동시에 구동하고 싶으면 on 옵션을, 부팅시 자동 구동되지 않게 하려면 off 옵션으로 설정할 수 있다.

다음 명령어는 netfs 서비스를 자동 시작하지 않는다.

chkconfig --list


netfs netfs 0:off 1:off 2:on 3:on 4:on 5:on 6:off

chkconfig netfs off

chkconfig --list netfs

netfs 0:off 1:off 2:off 3:off 4:off 5:off 6:off

 

이제 on 옵션을 주고 실행하면 부팅시 자동으로 구동되게 설정이 변경된다.

chkconfig netfs on  

chkconfig --list netfs

netfs 0:off 1:off 2:on 3:on 4:on 5:on 6:off

apache httpd 나 ftpd 등의 서비스 프로그램 설치시 실수로 chkconfig on 명령을 실행하지 않을 경우 부팅시 서비스가 자동으로 구동 되지 않을수 있으므로 서비스 프로그램을 설치했다면 chkconfig 명령어로 자동 실행되게 설정하자

service

service는 /etc/init.d 에 있는 Sys V init script 를 실행/중지/재실행 하는 유틸리티이다. 부팅시 실행되는 네트워크 설정이나 iptables 방화벽 설정, sshd, httpd 등의 서비스 프로그램등을 재시작 할 수 있다.

사용은 service 서비스명 옵션 형식으로 사용하면 되며 옵션은 다음과 같다.

 

  • --status-all
    모든 서비스의 상태를 출력한다. 이 옵션은 모든 서비스를 대상으로 하므로 서비스명을 주지 않아도 된다.
  • start 
    service httpd start 처럼 서비스명을 주고 실행해야 하며 지정된 서비스를 시작하는 명령이다. 서비스가 이미 구동되어 있으면 아무 동작도 하지 않는다. 정상 구동되지 않으면 에러 메시지가 표시되므로 로그 파일등을 확인해서 조치해야 한다.
  • stop
    service httpd stop 처럼 서비스명을 주고 실행해야 하며 지정된 서비스를 종료하는 명령이다. 서비스가 구동되지 않았는데 stop 명령을 했거나 또는 정상적으로 종료되지 않았다면 에러 메시지가 출력된다.
  • restart
    service httpd restart 처럼 서비스명을 주고 실행해야 하며 지정된 서비스를 종료후 시작하는 명령이다. stop/start 를 실행한 것과 동일하며 서비스의 설정 파일을 변경해서 반영시킬 경우 편리하게 사용할 수 있다. 

 

활용

service 와 chkconfig 명령어는 리눅스에서 구동되는 서비스 프로그램을 등록/삭제하고 실행/종료/상태 확인을 위해 꼭 알아야 하는 프로그램이다. 앞으로 설치하게 되는 MySQL DBMS 서버나 postfix 이메일 서버, apache httpd 웹서버등은 모두 service 명령어를 통해  관리하게 되며 서비스마다 동일한 옵션을 제공하므로 사용법을 알면 새로운 서비스가 추가되더라도 동일한 방법으로 관리할 수 있다.



CentOS5/6

$ sudo yum install nodejs, npm, redis $curl --silent --location https://rpm.nodesource.com/setup_6.x | sudo bash - $sudo yum install -y nodejs

curl로 6.x라고 적혀잇는데, 이에따라 6.x버전의 nodejs를 인스톨한다



CentOS5/6

$ sudo yum install --enablerepo=epel gperftools // $ yum info --enablerepo=epel redis Version : 3.0.7 $ sudo yum install redis --enablerepo=epel

이때 centos의 버전에 따라 기본 패키지에 들어있는 모듈도 있고 없는 모듈도 있는데 



自動起動スクリプトがインストールされるので、実行して正常起動することを確認します

Redisサーバ起動
$ sudo service redis start
redis-server を起動中:                                     [  OK  ]
プロセス確認
$ ps -ef | grep redis
redis 10995 1 0 21:57 ? 00:00:00 /usr/bin/redis-server 127.0.0.1:6379

Redis に接続してバージョンを確認します








아래는 츠바키 상으로 부터 받은 소프트웨어 설치 테쥰

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

_/ AI Hubのセットアップメモ

_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/


■ Node.js のインストール

$ curl --silent --location https://rpm.nodesource.com/setup_10.x | sudo bash -

$ sudo yum -y install nodejs

$ node -v

v10.9.0



■ Redis のインストール

$ sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

$ sudo yum install -y redis

$ redis-server --version

Redis server v=3.2.12 sha=00000000:0 malloc=jemalloc-3.6.0 bits=64 build=3dc3425a3049d2ef

$ sudo systemctl start redis

$ redis-cli ping

PONG

$ sudo systemctl enable redis




■ MySQL のインストール

$ sudo yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm -y

$ sudo yum-config-manager --disable mysql80-community

$ sudo yum-config-manager --enable mysql57-community

$ yum info mysql-community-server

$ sudo yum install mysql-community-server -y

$ mysqld --version

mysqld  Ver 5.7.23 for Linux on x86_64 (MySQL Community Server (GPL))


$ sudo systemctl start mysqld

[ec2-user@ip-10-2-1-79 ~]$ sudo systemctl enable mysqld

[ec2-user@ip-10-2-1-79 ~]$ systemctl status mysqld

● mysqld.service - MySQL Server

   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)

   Active: active (running) since Thu 2018-08-23 02:53:33 UTC; 11s ago

     Docs: man:mysqld(8)

           http://dev.mysql.com/doc/refman/en/using-systemd.html

 Main PID: 6030 (mysqld)

   CGroup: /system.slice/mysqld.service

           mq6030 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid


Aug 23 02:53:28 ip-10-2-1-79.ap-northeast-1.compute.internal systemd[1]: Starting MySQL Server...

Aug 23 02:53:33 ip-10-2-1-79.ap-northeast-1.compute.internal systemd[1]: Started MySQL Server.




$ cat /var/log/mysqld.log | grep password

2018-08-23T02:53:29.909619Z 1 [Note] A temporary password is generated for root@localhost: twZC.j6#)vgp



mysql> show global variables like 'character%';

+--------------------------+----------------------------+

| Variable_name            | Value                      |

+--------------------------+----------------------------+

| character_set_client     | latin1                     |

| character_set_connection | latin1                     |

| character_set_database   | latin1                     |

| character_set_filesystem | binary                     |

| character_set_results    | latin1                     |

| character_set_server     | latin1                     |

| character_set_system     | utf8                       |

| character_sets_dir       | /usr/share/mysql/charsets/ |

+--------------------------+----------------------------+

8 rows in set (0.00 sec)


mysql> sudo vi /etc/my.cnf

    -> ^C

mysql> exit

Bye

[ec2-user@ip-10-2-1-79 ~]$ sudo vi /etc/my.cnf

[ec2-user@ip-10-2-1-79 ~]$ sudo cp -p /etc/my.cnf /etc/my.cnf.default

[ec2-user@ip-10-2-1-79 ~]$ sudo vi /etc/my.cnf

[ec2-user@ip-10-2-1-79 ~]$ sudo systemctl restart mysqld

[ec2-user@ip-10-2-1-79 ~]$ mysql -u root -p

Enter password:

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 2

Server version: 5.7.23 MySQL Community Server (GPL)


Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.


Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.


Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.


mysql> show global variables like 'character%';

+--------------------------+----------------------------+

| Variable_name            | Value                      |

+--------------------------+----------------------------+

| character_set_client     | utf8mb4                    |

| character_set_connection | utf8mb4                    |

| character_set_database   | utf8mb4                    |

| character_set_filesystem | binary                     |

| character_set_results    | utf8mb4                    |

| character_set_server     | utf8mb4                    |

| character_set_system     | utf8                       |

| character_sets_dir       | /usr/share/mysql/charsets/ |

+--------------------------+----------------------------+

8 rows in set (0.00 sec)

CentOS に EPEL リポジトリを追加する

EPEL リポジトリとは

EPEL リポジトリとは、CentOS 標準のリポジトリでは提供されていないパッケージを、yum コマンドでインストールすることを可能にするリポジトリのことです。

EPEL は、エンタープライズ向けのリポジトリなので、サードパーティー製リポジトリの中では信頼性の高いものになっています。

EPEL 以外のサードパーティ製リポジトリには、Remi、RPMForge があります。特徴としては、Remi は最新バージョンのパッケージを入手可能、RPMForge は大量のパッケージを入手可能と言われているようです。

実際には、用途やパッケージの依存関係を考慮して各リポジトリを活用することになります。

個人的には、EPEL > Remi > RPMForge の優先度で、できるだけ EPEL まででとどめたいと考えています。

EPEL のインストール

CentOS 6 の 64 ビット版に EPEL をインストールするには、以下のコマンドを実行します。

このままだと、yum コマンドを実行する度に EPEL も使用することになってしまうので、EPEL を無効にして、必要時だけ使用するように下記コマンドで設定を変更します。

epel-release のアップデートを行います。

今後、EPEL リポジトリを利用する際には、以下のように EPEL リポジトリを使用することを指示してコマンド実行します。


'Server > Linux' 카테고리의 다른 글

service 와 chkconfig  (0) 2018.10.04
[centos]특정한 nodejs버전 설치, redis설치  (0) 2018.10.04
cmd로 private ip 취득  (0) 2018.09.07
cmd로 public IP 취득하기  (0) 2018.09.07
Red Hat Linux 와 CentOS  (0) 2018.09.06

ipコマンドでIPアドレスを表示する

以下のコマンドを実行します。

ip a

すると、ネットワークデバイスごとにアドレス情報が表示されます。以下は出力例です。実際の出力に色はつきませんが、分かりやすいように色分けしてあります。

$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever

2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:00:5e:00:53:01 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.2/32 scope global dynamic ens4
       valid_lft 80568sec preferred_lft 80568sec
    inet6 fe80::1/64 scope link 
       valid_lft forever preferred_lft forever

上記のうち、赤文字の部分がデバイス「ens4」のIPアドレス(IPv4アドレス)です。複数のネットワークデバイスが搭載されている場合は、デバイスごとに表示されます。デバイス名は環境によって異なり、「eth0」や「eth1」であったり、「ens1」や「enp2s0」といったものであったりします。
なお、灰色の部分はデバイス名「lo」で「localhost」、つまり使用しているコンピューター自身を指すデバイスです。通常は「127.0.0.1」が割り当てられています。

もし出力が長くて画面に収まらないなら、以下のようにlessにパイプするといいでしょう。

ip a | less

このコマンド、すこし出力が多くて見にくいですよね。IPv6に関する情報が必要ないなら、以下のように実行してIPv4の情報だけを表示させることができます。

ip -4 a

以下のように、少しスッキリします。

$ ip -4 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever

2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc fq_codel state UP group default qlen 1000
    inet 10.0.0.2/32 scope global dynamic ens4
       valid_lft 80568sec preferred_lft 80568sec

デバイスを限定することもできます。以下は「ens4」の情報だけを指定する例です。

$ ip -4 a show ens4
2: ens4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc fq_codel state UP group default qlen 1000
    inet 10.0.0.2/32 scope global dynamic ens4
       valid_lft 80568sec preferred_lft 80568sec

少し複雑になりますが、出力をパイプでgrepコマンドに送って、IPアドレス部分だけを取り出すこともできます。

$ ip -4 a | grep -oP '(?<=inet\s)\d+(\.\d+){3}'
127.0.0.1
10.0.0.2
$ ip -4 a show ens4 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'
10.0.0.2

hostnameコマンドでIPアドレスを表示する

hostnameコマンドは、その名の通りホスト名を表示するコマンドですが、以下のように「-I」オプションをつけて実行すれば、設定されているIPアドレスをすべて出力します。ただし、ループバックアドレスは表示されません。

$ hostname -I
192.168.1.15 192.168.111.12

networkctlコマンドでIPアドレスを表示する

networkctlコマンドがインストールされているなら、次のように「networkctl status」コマンドで、ネットワークインタフェースに割り当てられたIPアドレスや、ゲートウェイアドレスが確認できます。

$ networkctl status
●        State: routable
       Address: 192.168.1.201 on enp3s0
                2001:db8::1 on enp3s0
                fe80::1 on enp3s0
       Gateway: 192.168.1.1 (Cisco Systems, Inc) on enp3s0
                fe80::fe (Cisco Systems, Inc) on enp3s0

ifconfigコマンドでIPアドレスを表示する

ifconfig」コマンドの実行例も紹介しておきましょう。何年も前からipコマンドへの移行が推奨されており、いずれは使えなくなるかもしれません。しかし長年にわたりLinuxでIPアドレスを表示したり設定したりする定番のコマンドだったため、今も多くのユーザーが使っています。

$ ifconfig 
eth0      Link encap:イーサネット  ハードウェアアドレス 08:00:27:64:d7:10  
          inetアドレス:192.168.1.15  ブロードキャスト:192.168.1.255  マスク:255.255.255.0
          inet6アドレス: fe80::c67d:4ff9:b277:98b2/64 範囲:リンク
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:6378 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:6779 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:1000 
          RXバイト:927393 (927.3 KB)  TXバイト:743171 (743.1 KB)

lo        Link encap:ローカルループバック  
          inetアドレス:127.0.0.1  マスク:255.0.0.0
          inet6アドレス: ::1/128 範囲:ホスト
          UP LOOPBACK RUNNING  MTU:65536  メトリック:1
          RXパケット:5171 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:5171 エラー:0 損失:0 オーバラン:0 キャリア:0
          衝突(Collisions):0 TXキュー長:1 
          RXバイト:456561 (456.5 KB)  TXバイト:456561 (456.5 KB)


'Server > Linux' 카테고리의 다른 글

[centos]특정한 nodejs버전 설치, redis설치  (0) 2018.10.04
[centos]EPEL이란?  (0) 2018.10.04
cmd로 public IP 취득하기  (0) 2018.09.07
Red Hat Linux 와 CentOS  (0) 2018.09.06
chkconfigまとめ  (0) 2018.08.16

先日、SSHサーバーを踏み台にしてWebアクセスする記事を書きました。


その時、アクセス元のグローバルアドレスなどを確認できるページを作ってリンクしたのですが、「そういえばコマンドラインからグローバルアドレスを取得できたほうが便利だな」と思って、調べてみました。

やはり、ありました。以下のコマンドです。

curl ifconfig.io

このコマンドを実行することで、http://ifconfig.ioから返されたグローバルアドレスが出力されます。

以下のように、HTTPSで取得することもできます。

curl https://ifconfig.io

これで、わざわざブラウザを開かなくてもグローバルアドレスが取れますね。aliasを作成しておくと便利そうです。

なお、ブラウザでifconfig.ioにアクセスすると、使い方を書いたページが表示されます。IPアドレス以外にも、以下のような情報を取得できます。

アクセス元ホスト名

curl ifconfig.io/host

国コード

curl ifconfig.io/country_code

User-Agent

curl ifconfig.io/ua

アクセス元ポート番号

curl ifconfig.io/port

Accept Language

curl ifconfig.io/lang

Accept Encoding

curl ifconfig.io/encoding

Accept MIME Types

curl ifconfig.io/mime

X-Forwarded-For

curl ifconfig.io/forwarded

すべての情報をGo言語のMapで出力

curl ifconfig.io/all

すべての情報をJSON形式で出力

curl ifconfig.io/all.json

うまく自作のプログラムに組み込んだりしても面白そうですね。

なお、ifconfig.ioのソースコードはGitHubで公開されています。なので、自分のLinuxサーバーで動かすことも可能でしょう。

'Server > Linux' 카테고리의 다른 글

[centos]EPEL이란?  (0) 2018.10.04
cmd로 private ip 취득  (0) 2018.09.07
Red Hat Linux 와 CentOS  (0) 2018.09.06
chkconfigまとめ  (0) 2018.08.16
[linux]데몬(daemon) 이란?  (0) 2018.06.15

Red Hat Enterprise Linux(RHEL)

RHEL 은 Red Hat 사가 개발하는 상업용 리눅스 배포판으로 Intel 과 AMD 의 x86과 x86-64 아키텍처가 주요 플랫폼이며 추가로 IBM POWER 와 IBM System Z & S/390 아키텍처도 지원하고 있다. 버전 5까지 Intel의 Itanium 플랫폼도 지원했으나 6 부터 제외가 되었다.

소스는 공개되지만 매년 기술 지원에 대해 비용을 지불해야 사용할 수 있는 서브스크립션(subscription) 라이선스이며 구매한 고객들은 문제 발생시 기술 지원과 OS 나 SW 의 패치와 업그레이드를 받을 수 있다.

주요 목표는 기업 환경에 맞게 안정성과 성능, 보안성을 최우선 목적으로 하고 있으며 이에 따라 철저하게 검증된 기능과 패키지만 배포본에 포함시키고 있다.

하지만 안정성 중시에 따라 내장된 패키지가 오래된 버전인 경우가 많아서 새로운 개발 도구나 프레임워크등을 사용하려면 기반 도구부터 패키지까지 별도로 설치와 업그레이드를 해 주어야 하는 경우도 많다.

예로 이 책에서 설명하는 gitlab 이나 redmine 같은 ruby on rails 기반의 솔루션을 사용하려면 기본 탑재된 패키지로는 불가능하므로 별도로 설치하는 과정을 거쳐야 한다.


RHEL 은 특정 버전의 페도라(Fedora) 리눅스 배포판을 기반으로 하여 검증되고 안정화된 코드를 채택하여 개발된다.  또 기반이 된 페도라의 이후 버전에 추가된 기능이라도 중요하거나 유용하다면 해당 기능들을 RHEL로 역이식(backport)하기도 한다.

2010년 출시되어 현재 주로 쓰이고 있는 버전 6의 RHEL 은 Linux kernel 2.6과 fedora 12 를 기반으로 하여 13, 14등에 추가된 기능들을 역이식하여 개발되었다. 13년 12월 Beta 버전을 발표한 RHEL 7 은 Linux kernel 3.10 과 Fedora 19 를 기반으로 개발되고 있다.

RHEL의 안정성은 유명하여 Oracle 사의 Linux 배포본인 Oracle Linux도 RHEL 을 기반으로 하고 있으며 아마존 웹서비스에 사용되는 Amazon Linux AMI 및 라우터등의 다양한 어플라이언스에서도 사용되고 있다.

그외에 유럽 입자 물리 연구소(CERN)와 미국의 페르미 국립 가속기 연구소(FermiLab) 에서 과학자들의 연구/개발에 사용하기 위해 개발한 Scientific Linux 도 RHEL 기반의 유명한 배포판이다.


Fedora 리눅스

레드햇이 후원하고 개발 공동체에 의해 진행되는 Linux 배포판으로 새로운 기술과 SW 를 실험하고 선도하는 것을 주요 목적으로 하고 있다. Fedora 개발자는 Open Source SW 를 수정하면 변경한 내용을 페도라 배포본에만 적용하지 않고 원 개발자에게 보내(upstream 패치) 다른 리눅스 배포본 공동체에도 반영되게 하는것을 선호한다. fedora 의 주요 특징중 하나는 보안을 중요시하고 이에 많은 투자를 한다는 점으로 fedora는 SELinux 가 가장 먼저 적용된 OS 이기도 하다.

fedora 위에서 SELinux 의 다양한 정책과 관련 유틸리티가 개발되고 있으며 안정성이 검증되면 RHEL 에 재이식되기도 한다. 예로 Ruby와 Python 의 Application Server 인 Phusion Passenger 가 SELinux 하에서 제대로 동작하지 않자 이를 수정한 policy 가 RHEL 6.4 에 이식되어 배포되기도 한다.

레드햇의 다른 제품들도 Fedora 와 RHEL 의 관계처럼 오픈소스 커뮤니티를 지원하고 이를 활용하여 기능을 개발하고 안정화되면 상용 제품에 반영하는 개발 절차를 밟고 있다. 이는 유명한 웹어플리케이션 서버인 JBoss Community 와  JBoss Enterprise, 기업용 리눅스 관리 솔루션인 Satellite 와 Space Walk 에서도 찾아 볼 수 있다.

업스트림(Upstream) 패치

수정한 오픈소스 소프트웨어를 원 저자나 개발팀에게 보내서  메인 개발 소스에 반영시키는 작업을 의미한다. 예로 아파치 웹서버를 사용중인데 버그를 발견후 소스를 내려받아서 수정하고 내부에서만 사용하고 있다고 가정하자. 이 경우 아파치 웹서버 개발팀에 수정된 내용이 전달되지 않았으므로 아파치 웹서버가 업그레이드 되어도 동일한 버그가 존재할 소지가 높고 수정자는 업그레이드때마다 동일한 소스 패치 작업을 반복해야 한다. 수정 부분을 원 개발팀에 전달하여 메인 소스에 반영하는 업스트림 패치가 이루어졌다면 이런 반복 패치 작업을 할 필요가 없어지며 지구상의 또 다른 누군가가 동일한 시행 착오를 겪지 않아도 된다.


CentOS

CentOS는 Community Enterprise Operating System 의 약자로 Red Hat 이 공개한 RHEL의 Source 를 가져와서 Red Hat 의 브랜드와 로고를 제거하고 컴파일하여 만드는 배포본이다. RHEL 의 소스를 거의 수정없이 사용하므로 RHEL 과 OS 버전, Kernel 버전, 패키지 구성이 똑같고 바이너리가 100%로 호환된다. 무료로 사용 가능하며 문제 발생시 커뮤니티를 통해 지원된다. RHEL 사용시 가장 중요한 기능중 하나인 Yum 저장소도 제공되고 있으며 우리나라에서도 포탈사이트나 IDC 서비스를 제공하는 회사등을 통해 mirror 서비스가 제공되고 있다.

특히 Web Server 로 인기가 높으며 업무의 중요도에 따라 RHEL 과 혼용하여 사용할 수도 있다. 예로 Web Server 는 CentOS, WAS 와 DBMS는 RHEL 의 조합으로도 사용 가능하다. 단점으로는 버그나 보안 패치가 RHEL 보다 늦게 나오며 문제 발생시 자체적으로 해결해야 하는 점이다.

배포판별 비교표


RHEL을 기업이 선호하는 이유

OS 는 서비스와 솔루션을 구동하기 위한 중요한 요소이므로 기업에서는 OS 를 선택할때 여러 가지 척도로 제품을 선정하고 있다. 특히 중요한 척도들은 다음과 같다.

  1. OS 를 설치하려는 장비가 해당 OS를  잘 지원하는가
  2. 사용하려는 소프트웨어나 솔루션이 해당 OS에서 잘 구동되는가
  3. 원활한 기술 지원이 제공되는가
  4. 제품이 지속적으로 업데이트되고 있고 버그나 보안 문제점에 대해 패치가 신속하게 이루어지는가
  5. 검증된 성능 및 안정성 
  6. 사용자가 많이 있고 관련 정보를 획득하기 용이한가

왜 여러가지 배포본중에 RHEL 을 기업에서 선호하는지 위 조건에 맞춰서 살펴보자.


레드햇 하드웨어 인증

리눅스를 데스크탑으로 사용하고자 할 경우 중요하게 살펴봐야 할 부분은 사용하고 있는 하드웨어가 리눅스에서 잘 동작하는지 여부이다.

사용자의 하드웨어가 리눅스용 장치 드라이버가 없어서 사용을 못 할 수도 있고 또 드라이버가 있지만 제조사의 지원이 윈도에 비하면 미비하여 해당 제품을 사용하는데 문제가 발생할 수 있다.

PC용 하드웨어 제조사는 해당 제품을 윈도에서 사용하는 고객이 많으므로 장치 드라이버나 지원을 윈도를 최우선으로 하는 경향이 있다.

레드햇에서는 IBM이나 HP, Dell 등 인텔의 x86 CPU 기반의 서버 제조사들이 제작하는 서버 제품에 대해 RHEL 이 잘 설치되고 구동되는지 하드웨어 인증을 수행하고 이를 데이타 베이스화하여 제공하고 있다.

이로서 데스크탑으로 사용할 때와는 다르게 인증받은 서버 장비를 구입한다면 장치 드라이버 문제없이 설치와 구동에 대해 보장받고 안정적으로 업무에 사용할 수 있다. 레드햇 인증을 받은 장비의 목록은 http://www.redhat.com/rhel/compatibility/hardware/ 에서 확인할 수 있다.


풍부한 어플리케이션

오라클 DBMS, IBM DB2, MySQL, MariaDB, PostgreSQL 등 대부분의 DBMS 가 RHEL 에서 잘 동작하며 IBM websphere, JBoss, tomcat, jetty 등의 WAS 도 RHEL을 지원하고 있다.

그외 SAP, SAS등 기업에서 많이 사용되는 소프트웨어들은 거의 다 RHEL 을 잘 지원하고 있다.

RHEL의 패키지 정책이 보수적이라 패키지가 잘 업데이트되지 않는 단점도 있지만 기업내에서 리눅스를 서비스용 서버로 사용한다면 버그 패치/보안 패치등을 적용하는 작업외에는 서비스용 서버는 큰 변경이 없으므로 큰 단점이 아닐수 있다.


안정적인 기술 지원

subscription을 구매하면 레드햇 고객 포탈(https://access.redhat.com/home) 에서 방대하고 양질의 기술 문서와 Know-how 에 접근할 수 있으며 문제 발생시 Web 과 전화를 통해 기술 지원을 받을 수 있다.

RHEL 은 버전 5부터 10년의 프로덕션 단계의 지원을 하고 있으며 이후 3년간 연장 단계 지원을 제공하고 있다. RHEL의 수정이나 패치는 레드햇 고객 포탈이나 기타 공인 사이트에서 이루어 지며  에라타 권고라고 하는 개별 업데이트를 통해 제공된다.

수정된 패키지는 기존 런타임 환경과 바이너리 호환성을 갖기 위해 노력하고 있다.

단계별 지원 내역은 다음 표와 같다.


프로덕션 단계1(약 5년 6개월)
프로덕션 단계2(약 1년)
프로덕션 단계3(약 3년 6개월)
연장 라이프 단계(약 3년)
Red Hat Customer Portal을 통해 이전에 출시된 콘텐츠에 액세스(ティック)(ティック)(ティック)(ティック)
Red Hat Customer Portal을 통한 자가 지원(ティック)(ティック)(ティック)(ティック)
기술 지원무제한무제한무제한기존 설치에 한해 지원
RHSA(비동기 보안 에라타)(ティック)(ティック)(ティック)(エラー)
비동기 버그 픽스 Errata(RHBA)(ティック)(ティック)(ティック)(エラー)
업데이트 릴리스(ティック)(ティック)(ティック)(エラー)
개정된 하드웨어 지원기본소스 변경이 많지 않을 경우에 한해 지원가상화 사용가상화 사용
소프트웨어 기능 개선(ティック)(エラー)(エラー)(エラー)
업데이트된 설치 이미지(ティック)(ティック)(ティック)(エラー)
단계별 기술 지원표

위와 같이 긴 제품 수명 주기를 갖고 지원을 하고 있으므로 OS 의 해당 버전 단종이나 기술 지원 만료로 구동하는 솔루션이나 서비스에 문제가 생길수 있는 우려가 적다. ( RHEL 3, 4는 7년을 지원한다.)

RHEL 기술지원 연대표

또 국내의 많은 리눅스 기술지원 업체와 별도 계약을 통해 장애나 문제 발생시 외부 전문가들의 현장 방문 지원도 받을 수 있다.


검증된 성능과 안정성

많은 솔루션이 리눅스위에서 최적의 성능을 발휘하고 있으며 주식 거래 같은 미션 크리티컬한 업무도 안정적이고 지속적으로 제공할 수 있을 정도로 성능과 안정성이 검증되어 있다. 


지속적인 업데이트 및 보안 패치

레드햇은 주기적으로 마이너 버전을 출시하면서 기능을 개선하고 있으며 기존 패키지도 개별로 업데이트를 제공하고 있다.

인터넷을 통한 공격이 늘어나면서 보안성은 핵심적인 평가 지표중에 하나이다. RHEL 은 보안을 고려하여 설계/개발되었고 linux 커널 기반의 보안 강화 기능인 SELinux 의 개발을 주도적으로 지원하였으며 이를 RHEL 에 적용하여 SELinux 와 완벽한 통합을 자랑한다.

RHEL 의 보안 대응팀은 신규 보안취약점(CVE - Common Vulnerabilities and Exposure) 발표되면 발빠르게 대응하여 신속하게 패치를 발표하고 있으며 가끔은 원 저자보다 보안 취약점을 빨리 수정하고 업스트림 패치를 보내는 경우도 있다.


폭넓은 사용자층과 정보

사용자가 많으므로 관련 정보 얻기가 쉬우며 검색 엔진과 블로그등을 통해 많은 정보와 지식을 얻을 수 있다.  


fedora 도 훌륭한 배포본이지만 위과 같은 이유로 안정성이 우선인 기업환경에서는 RHEL을 선호할 수 밖에 없다. 

fedora 를 설치하고 사용하면서 버그 리포팅을 하는 것은 Linux 공동체에 기여하는 좋은 방법이지만 이는 Desktop 이나 개인적인 컴퓨팅 환경에 사용하고 기업에서 Linux 를 서버로 도입한다면 RHEL 이나 이의 파생 배포본을 기반으로 진행하는 방안을 권장한다.


Ref


'Server > Linux' 카테고리의 다른 글

cmd로 private ip 취득  (0) 2018.09.07
cmd로 public IP 취득하기  (0) 2018.09.07
chkconfigまとめ  (0) 2018.08.16
[linux]데몬(daemon) 이란?  (0) 2018.06.15
[linux]리눅스의 소유권과 허가권  (0) 2018.06.06

+ Recent posts