목표
Bash Shell Script를 사용할 일이 있어서 급하게 Review하고자 한다.
여기나오는 내용은 educative Shell for programer와 Mastering Linux Shell Scripting에 있는 내용을 정리하였다.
https://github.com/PacktPublishing/Mastering-Linux-Shell-Scripting-Second-Edition
기초
Default Shell 찾기
~$ ps $$
PID TTY STAT TIME COMMAND
10374 pts/0 Ss 0:00 -bash
$ echo $SHELL
/bin/bash
Shell 종류
- Bash Shell : Bourne shell, 가장 기초 쉘
- Ksh shell : Korn shell, bash shell과 호환 됨
- Csh : C언어로 만들어진 쉘
Shell 변경하기
$ chsh -s /bin/bash
Command Line 단축키
단축키 | 행동 |
Ctrl + C | 현 실행 중인 Task를 종료한다 |
Ctrl + L | 화면을 clear 한다 |
Ctrl + w | 커서의 마지막 한문장을 삭제한다 $ aaa bbb ddd
에서 bbb 앞에서 단축키를 입력하면 aaa가 사라진다 $ bbb ddd
|
tab | 자동완성 |
Ctrl + R | 내가 앞서 사용했던 history에서 찾는 단어와 유사성이 있는 실행문을 찾아 준다 (reverse-i-search)`kaf': docker-compose -f docker-compose-kafka-triplet.yml down
|
Ctrl + U | 한라인을 모두 삭제 한다 |
Variables Type
Shell variables
쉘이 정상적인 작동을 하게끔 사전 정의된 Local Variable이다.
쉘이 시작하면서 로드하게 된다.
$shell_var
Local Variables
하나의 쉡 내부에서만 작동하는 Variable. 다른 쉘에 영향을 주지 않는다.
사용자가 해당 쉘에서만 순간적으로 사용하게 하기 위해 사용된다.
$ MY_VALUE=hello
$ echo $MY_VALUE
hello
Environment Variable
모든 쉘에서 접근 가능한 varialbe이다.
Bash 에서는 export 를 사용해서 정의하게 된다. 대표적으로 PATH 가 있다.
$ cat .profile
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
기타
$USER |
$ echo $USER
theyoung
|
$HOSTNAME |
$ echo $HOSTNAME
theyoung-MS-7D77
|
$$ |
$ echo $$
10374
현 스크립트 ID |
$0 |
$ echo $0
-bash
현 실행중인 스크립트의 이름 |
$1~9 |
스크립트 실행시 입력된 아규먼트
|
Variable setup 방법
$ VAR_NAME=HELLO
$ echo "my name is $VAR_NAME !"
my name is HELLO !
$ echo "my name is ${VAR_NAME} !"
my name is HELLO !
주의 해야할 것은 Uppercase는 일반적으로 Environment Variable로 많이 사용한다
$ 또는 ${} 를 이용해서 value를 확인할 수 있다.
Space가 필요하다면 " " 를 해줘야 한다
Shell Scripting
Hello world
#!/bin/bash
echo "Hello World"
exit 0
/script$ vi hello.sh
/script$ chmod +x hello.sh
/script$ ./hello.sh
Hello World
- #!/bin/bash : 쉬뱅, '#' 심볼 이후에 스크립트가 시작됨을 system에게 알려줌
- echo : standard 아웃풋
- exit 0 : 종료, 0이외의 값은 오류를 뜻함
/script$ echo $?
0
마지막 스크립트 실행의 결과가 0임을 나타냄
- command1 || command2 : command1이 실패할 경우 command 2가 실행됨. 그외 실행 안됨
#!/bin/bash
echo "Hello New World"
exit 0
위와 같은 shell이 있을 경우
./hello.sh || ./hello2.sh
Hello World
앞에 있는 쉘만 실행 한다.
만약에 앞쉘을 1로 바꾸면
~/script$ ./hello.sh || ./hello2.sh
Hello World
Hello New World
command2가 실행 된것을 확인 할 수 있다.
Arguments
#!/bin/bash
echo "Hello New World $1, count $#, all the arguments $*"
exit 0
/script$ ./hello2.sh ar1 ar2 ar3 ar4
Hello New World ar1, count 4, all the arguments ar1 ar2 ar3 ar4
- $숫자 : 아규먼트 값
- $# : 아규먼트 카운트
- $* : 모든 아규먼트
Defined Variables
#!/bin/bash
name="superman"
job="hero"
echo "Hello New World $1, count $#, all the arguments $*"
echo "name ${name}, job ${job}"
exit 0
~/script$ ./hello2.sh
Hello New World , count 0, all the arguments
name superman, job hero
space를 중간에 넣지 말것!!
ex) name = "superman"
List Variables
#!/bin/bash
name="superman"
job="hero"
list=(1 2 3 4 5)
echo "Hello New World $1, count $#, all the arguments $*"
echo "name ${name}, job ${job}"
echo "${list[*]}"
unset list[0]
echo "${list[*]}"
exit 0
~/script$ ./hello2.sh
Hello New World , count 0, all the arguments
name superman, job hero
1 2 3 4 5
2 3 4 5
- unset은 리스트의 특정 index를 삭제함
Environment variables
printenv로 환경변수 값을 확인할 수 있음
~/script$ printenv
SHELL=/bin/bash
LANGUAGE=ko:en
[omitted]
SSH_TTY=/dev/pts/2
LC_NUMERIC=ko_KR.UTF-8
_=/usr/bin/printenv
OLDPWD=/home/theyoung
export (변수 scope)
각 스크립트간 로컬 variable은 공유되지 않음.
export활용해서 공유 가능함
단, 실행 스크립트내에서 다른 스크립트를 호출한 경우에 한함
참고로 hello2.sh에서 name정의 부분은 삭제 하였다.
#!/bin/bash
echo "Hello World"
name="spider man"
export name
./hello2.sh
~/script$ ./hello.sh
Hello World
Hello New World , count 0, all the arguments
name spider man, job hero
1 2 3 4 5
2 3 4 5
아주 혹시라도 hello2.sh에 name 정의 부분을 안 삭제 한다고 해도 원래 hello.sh의 name은 해당 프로세스 내에서 수정되지는 않는다.
bash command 실행
#!/bin/bash
cur_dir=`pwd`
echo $cur_dir
iam=$(whoami)
echo $iam
스크립트 내에서 command를 실행하는 방법은 2가지가 있다
- ` 백틱
- $() : 중괄호
/script$ ./command.sh
/script
theyoung
Debugmode script 실행
/script$ bash -x ./command.sh
++ pwd
+ cur_dir=/home/theyoung/script
+ echo /home/theyoung/script
/home/theyoung/script
++ whoami
+ iam=theyoung
+ echo theyoung
theyoung
사용자 입력 read
#!/bin/bash
echo -n "Your name : "
read
echo "My name is $REPLY"
~/script$ ./read.sh
Your name : steven
My name is steven
$REPLY 를 통해서 입력 결과를 표시함
command line 을 통한 입력
/script$ read -p "Your name is " name
Your name is steven
/script$ echo $name
steven
read 명령어를 통해서 name 변수에 이름이 입력 된것을 확인 가능함
#!/bin/bash
echo -n "Your name : "
read
echo "My name is $REPLY"
read -p "Your ages : " age
echo "My ages is $age"
/script$ ./read.sh
Your name : steven
My name is steven
Your ages : 43
My ages is 43
read -n1 을 아규먼트로 넣을 경우 1회의 키만 받는 다는 의미임
read -sn1 에 s를 넣을 경우 입력값이 보이지 않게 됨
while-case
#!/bin/bash
while [ -n "$1" ]
do
case "$1" in
-f) echo "--first option selected";;
-s) echo "--second option selected";;
-t) echo "--third option selected";;
*) echo "no option selected";;
esac
shift
done
while [ 비교문 ]
do
done
비교문에서 "-n"은 not empty string이라는 의미이다
case 비교대상 in
*)
esac
in 아래에 비교 대상을 직접적으로 )로 표시 하면 된다.
shift는 arguments를 하나씩 좌측으로 shipt해서 pop하게 된다.
for 순환
#!/bin/bash
num=1
for param in $@
do
echo "#$num: $param"
num=$(( $num + 1 ))
done
for variable in range
do
done
으로 이루어짐 여기서 $@는 모든 array라는 의미로 foreach 형태로 하나씩 space단위로 값을 빼어냄
num=은 variable을 재정의 하는 형태이고
$()를 통해서 command를 실행 시킴
그 내부에 ()가 하나더 있는데 'Numeric calculations'이라고 함
./for.sh a b c d e f g
#1: a
#2: b
#3: c
#4: d
#5: e
#6: f
#7: g
Condition Test
~/script$ test $PWD == $HOME
/script$ echo $?
1
test를 통해서 현재 있는 위치와 HOME의 path가 같은지를 확인했다.
0이외의 결과는 error임으로 위는 error를 뜻한다
#!/bin/bash
echo "Your basename is $(basename $0)"
test -z $1 || echo "Hello $1"
exit 0
test -z $1은 $1이 empty string일때 true가 된다.
만약 아무런 파라메터도 없으면 hello는 나오지 않는다.
~/script$ ./test.sh
Your basename is test.sh
~/script$ ./test.sh a
Your basename is test.sh
Hello a
test는 다음과 같이 활용 될 수 있다.
- test expression : expression이 참이냐 false냐
- test ! expression : 결과 반대
- test expression -a expression : and
- test expression -o expression : or
- test -n string : string에 값이 있는가?
- test -z string : string에 값이 없는가?
- test string = string : 두 string은 같은가?
- test 3 -gt 0 : 3은 0보다 큰가?
- test 3 -lt 0 : 3은 0보다 작은가?
- test 3 -eq 0 : 3은 0과 같은가?
- test 3 -nq 0 : 3은 0과 같지 않은가
String을 shell script내에서 test condition으로 사용할 경우 반듯이 ""를 해야한다
if [ "mother" = "Mother" ]
~/script$ test $USER = root
~/script$ echo $?
1
~/script$ test ! $USER = root
~/script$ echo $?
0
~/script$ test -n iam
~/script$ echo $?
0
~/script$ test -z iam
~/script$ echo $?
1
~/script$ test 3 -gt 0
~/script$ echo $?
0
~/script$ test 3 -lt 0
~/script$ echo $?
1
~/script$ test 3 -eq 0
~/script$ echo $?
1
- test -d 디렉토리 : 디렉토리 인가?
- test -x 실행파일 : 실행가능한가?
- test -f 파일 : 파일이 맞는가?
- test -r 파일 : 읽을 수 있는가?
$ test -d script/
~$ echo $?
0
~$ test -x script/
~$ echo $?
0
~$ test -f script/
~$ echo $?
1
복합 컨디션
- test a = b || test b = b : a와b의 string이 같거나 b와 b의 스트링이 같으면 true이다
~/script$ test a = b || test b = c
~/script$ echo $?
1
~/script$ test a = b || test b = b
~/script$ echo $?
0
if condition
#!/bin/bash
if [ $# -lt 1 ];then
echo "no param"
fi
echo "all params : $*"
exit 0
입력된 파라메터가 1보다 작은지 확인하는 코드
if 컨디션 ; then
if
으로 구성된다
~/script$ ./if.sh a b c
all params : a b c
~/script$ ./if.sh
no param
all params :
else를 추가할 수 있다
if 컨디션 ; then
else
if
#!/bin/bash
if [ $# -lt 1 ];then
echo "no param"
else
echo "all params : $*"
fi
exit 0
~/script$ ./if.sh
no param
~/script$ ./if.sh abc
all params : abc
복합 컨디션은 아래와 같다
#!/bin/bash
if [ $# -lt 1 ] || [ -n "abc" ];then
echo "no param"
else
echo "all params : $*"
fi
exit 0
위의 경우는 무조건 no param이 나오게 된다
-n "abc"는 항상 참이기 때문이다.
~/script$ vi if.sh
~/script$ ./if.sh a b c d
no param
Script example
Ping
#!/bin/bash
read -p "server address : " serveraddr
ping -c 3 $serveraddr 2>1 > /dev/null || echo "Server Dead"
ping에서 -c는 retry의 횟수이다. 2>1은 standard 아웃풋을 모두 /dev/null로 보냄으로써 화면에 표시하지 않겠다는 의미이다.
마지막으로 ping의 결과가 0이 아닌 결과로 error로 판단되면 Server Dead가 표시된다.
~/script$ ./ping.sh
server address : 1.2.3.4
Server Dead
파일 내용 읽기
#!/bin/bash
while read line
do
echo $line
done
/script$ ./readfile.sh < ping.sh
#!/bin/bash
read -p "server address : " serveraddr
ping -c 3 $serveraddr 2>1 > /dev/null || echo "Server Dead"
'Software활용' 카테고리의 다른 글
openssl 명령어 모음 (0) | 2023.09.01 |
---|---|
Window 10 pro 다중 원격 접속하기 (Hex edit) (0) | 2023.08.09 |
mac에서 java version 변경하기 (0) | 2022.08.22 |
linux에서 json Pretty Print 하기 (jq 명령어) (0) | 2022.08.11 |
Slack backup 파일 Discord로 이동하기 (Slackord 사용법) (0) | 2022.08.01 |