Bash 입문자를 위한 핵심 요약 정리 (Shell Script)
-https://blog.gaerae.com/2015/01/bash-hello-world.html

(이런 것도 있구나 싶을 정도만 이해하도록 간단한 설명과 예제로 작성됨)
첫 시작은 문자 출력하기(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 |
BASH | BASH 실행 파일 경로 |
BASH_ENV | 스크립트 실행시 BASH 시작 파일을 읽을 위치 변수 |
BASH_VERSION | 설치된 BASH 버전 |
BASH_VERSINFO | BASH_VERSINFO[0] ~BASH_VERSINFO[5] 배열로 상세정보 제공 |
MAIL | 메일 보관 경로 |
MAILCHECK | 메일 확인 시간 |
OSTYPE | 운영체제 종류 |
TERM | 로긴 터미널 타입 |
HOSTNAME | 호스트 이름 |
HOSTTYPE | 시스템 하드웨어 종류 |
MACHTYPE | 머신 종류(HOSTTYPE 과 같은 정보지만 조금더 상세하게 표시됨) |
LOGNAME | 로그인 이름 |
UID | 사용자 UID |
EUID | su 명령에서 사용하는 사용자의 유효 아이디 값(UID 와 EUID 값은 다를 수 있음) |
USER | 사용자의 이름 |
USERNAME | 사용자 이름 |
GROUPS | 사용자 그룹(/etc/passwd 값을 출력) |
HISTFILE | history 파일 경로 |
HISTFILESIZE | history 파일 크기 |
HISTSIZE | history 저장되는 개수 |
HISTCONTROL | 중복되는 명령에 대한 기록 유무 |
DISPLAY | X 디스플레이 이름 |
IFS | 입력 필드 구분자(기본값: - 빈칸) |
VISUAL | VISUAL 편집기 이름 |
EDITOR | 기본 편집기 이름 |
COLUMNS | 현재 터미널이나 윈도우 터미널의 컬럼 수 |
LINES | 터미널의 라인 수 |
LS_COLORS | ls 명령의 색상 관련 옵션 |
PS1 | 기본 프롬프트 변수(기본값: bash\$ ) |
PS2 | 보조 프롬프트 변수(기본값: > ), 명령을 "\"를 사용하여 명령 행을 연장시 사용됨 |
PS3 | 쉘 스크립트에서 select 사용시 프롬프트 변수(기본값: #? ) |
PS4 | 쉘 스크립트 디버깅 모드의 프롬프트 변수(기본값: + ) |
TMOUT | 0 이면 제한이 없으며 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 변수는 타입을 구분하지 않고 기본적으로 문자열이다. 단 문맥에 따라서 연산 처리한다.그런데 불완전한 형태의
declare
, typeset
타입 지정 명령을 지원한다.(두 명령은 동일함)참고: 코멘트에 있는 다른 문법 사용을 추천한다.
# 읽기 전용
# 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 file2 | file1 파일이 file2 파일보다 최신임 |
file1 -ot file2 | file1 파일이 file2 파일보다 예전것임 |
file1 -ef file2 | file1 파일과 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)
간단하게는echo
, exit
명령나 tee
명령어로 디버깅한다.다른 방법으로 실행 시 옵션을 주거나 코드에 한줄만 추가하면 해볼수 있다.
Bash 옵션(스크립트 실행 시) | set 옵션(스크립트 코드 삽입) | 설명 |
---|---|---|
bash -n | set -n , set -o noexec | 스크립트 실행없이 단순 문법 오류만 검사(찾지 못하는 문법 오류가 있을수 있음) |
bash -v | set -v , set -o verbose | 명령어 실행전 해당 명령어 출력(echo ) |
bash -x | set -x , set -o xtrace | 명령어 실행후 해당 명령어 출력(echo ) |
set -u , set -o nounset | 미선언된 변수 발견시 "unbound variable" 메시지 출력 |
마무리하며
- 여기서 인자(argument)와 매개변수(parameter)는 이름만 다를 뿐 의미는 같다.
- Bash는 공백에 민감하다.
- 변수 사용은 생각하지 말고
${변수}
이렇게 쓰자.
함께보기
'Server > Linux' 카테고리의 다른 글
PM2로 인스턴스 재시작시 서비스 자동으로 시작하기 (0) | 2018.10.12 |
---|---|
Bash 입문자를 위한 핵심 요약 정리2(주석,함수,변수,내장변수,연산자,파일비교,반복문,조건문) (0) | 2018.10.09 |
service 와 chkconfig (0) | 2018.10.04 |
[centos]특정한 nodejs버전 설치, redis설치 (0) | 2018.10.04 |
[centos]EPEL이란? (0) | 2018.10.04 |