쉘스크립트

기본 Shell 스크립트 작성

트리스탄1234 2022. 7. 5. 17:51
728x90
반응형

1. 한라인에서 명령어 여러개 수행하기

한개의 명령어 라인에서 여려개의 명령을 실행할때에는 명령어 사이에 세미콜론으로 분리하면 됩니다.

$ date ; who

Mon Sep 24 19:44:35 EST 2007

rich :0 2007-09-24 18:23 (console)

rich pts/1 2007-09-24 18:24

rich pts/0 2007-09-24 18:42

barbara pts/2 2007-09-24 19:30

katie pts/3 2007-09-24 19:39

$

2. 스크립트 파일 작성하기

스크립트 파일을 작성할때에 항상 첫째줄에는 사용할 Shell을 아래와 같이 정의를 해야 합니다.

$ touch test1

$gedit test1

#! /bin/bash

# this is test script file ==> #다음에 작성된 문자들은 주석 처리됩니다.

date

who

$

위와 같이 작성 후 해당 스크립트를 실행을 시켜 보면 아래와 같이 명령어를 찾을수 없다고 나옵니다.

$ test1

bash: test1: command not found

$

이 경우에는 현재의 Shell이 사용하는 PATH 변수에 현재 스크립트 파일이 위치하는 경로를 추가를 하던가. 또는 절대경로나 상대경로를 이용하여 파일의 위치를 알려줘야 합니다. PATH 변수에 현재의 경로를 추가 하고 나서 해당 시크립트 파일을 실행을 해보면 아래와 같이 "허가 거부" 메세지가 나타나는데 이는 umake값이 022로 설정이 되어서 owner에게 실행권한이 빠져 있어서 발생 합니다.

$ ./test1

bash: ./test1: 허가 거부

그럼 owner에게 실행권한을 추가 하고 실행해 보겠습니다.

$ chmod u+x test1

$ ./test1

Mon Sep 24 19:58:35 EST 2007

rich :0 2007-09-24 18:23 (console)

rich pts/1 2007-09-24 18:24

rich pts/0 2007-09-24 18:42

barbara pts/2 2007-09-24 19:30

katie pts/3 2007-09-24 19:39

$

이번에는 스크립트 파일에 echo명령을 사용하여 스크립트 수행시 메세지를 표시하게 해보겠습니다.

우선 문장을 스크립트 수행시 출력을 하게 하려면 그냥 echo명령을 사용하면 되지만 특수 기호가 문장에 들어간 경우에는 홑따옴표나 쌍따움표로 문장 묶어줘야지 원하는대로 표시가 됩니다.

아래 예제를 한번 봅시다. test1 파일을 아래와 같이 수정 후 실행해 보겠습니다.

$gedit test1

#! /bin/bash

echo "let's check date"

date

echo "누가 접속을 했는지 표시 합니다"

who

#

$ ./test1

let's check date

2021. 05. 30. (일) 20:00:38 KST

누가 접속을 했는지 표시 합니다

hyowon tty7 2021-05-29 10:36 (:0)

$

그러면 echo 명령 다음에 한 라인에 명령어 출력 결과를 표시를 하려면 어떻게 해야 될까요?

-n 옵션을 사용하면 됩니다. 그럼 아래와 같이 스크립트를 수정해 보겠습니다.

$gedit test1

#! /bin/bash

echo -n "let's check date"

date

echo "누가 접속을 했는지 표시 합니다"

who

#

스크립트를 실행을 시키면 아래와 같이 한 라인에 명령어의 출력결과가 나타납니다.

$ ./test1

let's check date2021. 05. 30. (일) 20:06:13 KST

누가 접속을 했는지 표시 합니다

hyowon tty7 2021-05-29 10:36 (:0)

$

3. 변수 사용하기

스크립에서는 리눅스에서 사용하는 환경 변수들을 사용하여 스크립트를 작성을 할 수가 있습니다.

먼저 현재 활성화된 변수들을 보려면 아래와 같이 set 명령을 사용하면 현재 사용중인 환경 변수들을 출력해 주빈다.

hyowon@hyowon-800G5M-800G5W:~$ set
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=()
BASH_ARGV=()
BASH_CMDS=()
BASH_COMPLETION_COMPAT_DIR=/etc/bash_completion.d
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="4" [1]="3" [2]="48" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")
BASH_VERSION='4.3.48(1)-release'
CLUTTER_IM_MODULE=xim
COLUMNS=80
COMPIZ_BIN_PATH=/usr/bin/
COMPIZ_CONFIG_PROFILE=ubuntu
DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-bfMwnwWEoh
DEFAULTS_PATH=/usr/share/gconf/ubuntu.default.path
DESKTOP_SESSION=ubuntu
DIRSTACK=()
DISPLAY=:0
EUID=1000
GDMSESSION=ubuntu
GDM_LANG=ko
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
GNOME_KEYRING_CONTROL=
GNOME_KEYRING_PID=
GPG_AGENT_INFO=/home/hyowon/.gnupg/S.gpg-agent:0:1
GROUPS=()
GTK2_MODULES=overlay-scrollbar
GTK_IM_MODULE=fcitx
GTK_MODULES=gail:atk-bridge:unity-gtk-module
HISTCONTROL=ignoreboth
HISTFILE=/home/hyowon/.bash_history
HISTFILESIZE=2000
HISTSIZE=1000
HOME=/home/hyowon
HOSTNAME=hyowon-800G5M-800G5W
HOSTTYPE=x86_64
IFS=$' \t\n'
IM_CONFIG_PHASE=1
INSTANCE=
JOB=unity-settings-daemon
LANG=ko_KR.UTF-8
LANGUAGE=ko
LESSCLOSE='/usr/bin/lesspipe %s %s'
LESSOPEN='| /usr/bin/lesspipe %s'
LINES=24
LOGNAME=hyowon

변수가 너무 많아 일부만 표시를 했습니다.

그럼 위의 변수 중 일부를 활용하여 스크립트를 작성해 보겠습니다.

$gedit test1

#! /bin/bash

echo -n "let's check date"

date

echo "누가 접속을 했는지 표시 합니다"

who

echo "로그인한 사용자는: $USER"

echo "사용자의 아이디는: $UID:"

echo "사용자의 HOME디록토리는: $HOME"

#

이 스크립트를 실행시켜 보겠습니다.

$ ./test1

let's check date2021. 05. 30. (일) 20:20:01 KST

누가 접속을 했는지 표시 합니다

hyowon tty7 2021-05-29 10:36 (:0)

로그인한 사용자는: hyowon

사용자의 아이디는: 1000:

사용자의 HOME디록토리는: /home/hyowon

$

사용자 변수 사용하기

리눅스에서는 사용자가 필요로 하는 변수를 선언할수 있습니다. 변수는 최대 20글자까지 문자와 숫자 또는 언더스코어(_)를 이용하여 변수 생성이 가능합니다. 사용자 변수는 대소문자를 구분 합니다. 따라서 Value1과 VALUE1은 다른 변수가 됩니다. 변수 선언을 할때에는 프로그래밍 언어와 다르게 Type을 선언할 필요는 없습니다.

변수 생성 예제는 아래를 참고 하세요.

var1=10

var2=-57

var3=testing

var4="still more testing" ==> 문자열을 저장할때에는 쌍따옴표나 싱글 따옴표로 문장을 묶어 줘야 됩니다.

$touch test3

$gedit test3

#! /bin/bash

#변수 테스트 하기.

days=5

guest="katie"

echo "$guest checked in $days days ago"

guest="Jessica"

echo "$guest checked in $days days ago"

#

위의 스크립트에서 보듯이 변수를 사용할때에는 항상 '$변수명'으로 사용하여야 합니다. 그리고 만약 $를 문자로 처리를 하고 싶은경우엔는 \$와 같이 $앞에 백슬러시를 붙여 주면 $를 문자로 처리 하게 됩니다.

그럼 잘동작 하는지 한번 실행 시켜 보겠습니다.

$ chmod u+x test3 ==> 소유자에게 실행권한을 부여 합니다.

$ ./test3

katie checked in 5 days ago

Jessica checked in 5 days ago

백틱 사용하기

스크립트 안에서 리눅스 명령어를 실행 시키고 그 결과 값을 변수에 저장하고 싶을 경우에 백틱(`)을 사용하여 명령어를 묶어 주면 명령어 수행결과를 변수에 저장할 수 있습니다.

$touch test4

$gedit test4

#! /bin/bash

#백틱 사용 예제

testing=`date`

echo "the date and time are:" $testing

#

그럼 사용자에게 실행권한을 부여하고 실행해 보겠습니다.

$chmod u+x test4

$./test4

the date and time are: 2021. 06. 01. (화) 17:37:11 KST

예제로 명령어 실행결과를 저장하고 파일명을 날짜로 지정하는 예제를 만들어 보겠습니다.

#! /bin/bash

# /usr/bin 밑에 파일들을 출력하고 날짜 이름으로 로그파일 만들기

today=`date +%y%m%d' ==> 날짜 형식을 년/월/일 각 2자리로 만들어 today 변수에 저장합니다.

ls /usr/bin -al > log.$today ==> ls 명령어로 파일들의 목록을 출력하고 log.날짜 파일로 리다이렉트 합니다.

#

그럼 실행 결과를 한번 볼까요

$ ./test5

$ ls -al log.*

-rw-rw-r-- 1 hyowon hyowon 144842 6월 1 17:47 log.210601

4. 입출력 리다이렉트

명령어 출력 결과를 모니터가 아닌 파일이나 다른 스크립트의 입력으로 넣는다던지. 입출력의 방향을 바꿀수 있는 연산자를 리눅스는 제공 합니다. 하나 하나씩 공부해 봅시다.

출력 리다이렉트

명령어 출력 결과를 파일로 저장할때 구문은 아래와 같습니다.

command > outputfile

꺽쇠 한개 >는 새로운 파일을 만들때 사용을 하고 기존에 존재 하는 파일에 추가로 내용을 입력 할때에는 >>를 사용하면 됩니다. 그럼 예를 들어 date 명령의 실행 결과를 test6파일에 저장하려면 아래와 같이 명령을 입력 하면

됩니다.

$ date > test6

$ ls -l t*

-rw-rw-r-- 1 root root 10 5월 29 14:12 test.txt

-rwxrw-r-- 1 hyowon hyowon 229 5월 30 20:19 test1

-rw-rw-r-- 1 hyowon hyowon 0 4월 7 17:51 test12.sh

-rwxrw-r-- 1 hyowon hyowon 157 6월 1 17:21 test3

-rwxrw-r-- 1 hyowon hyowon 91 6월 1 17:37 test4

-rwxrw-r-- 1 hyowon hyowon 151 6월 1 17:47 test5

-rw-rw-r-- 1 hyowon hyowon 33 6월 1 18:11 test6

$ cat test6

2021. 06. 01. (화) 18:11:24 KST

그럼 이제 test6 파일에 who 명령어 결과를 추가로 넣어 보도록 하겠습니다.

$who >> test6

$ cat test6

2021. 06. 01. (화) 18:11:24 KST

hyowon tty7 2021-05-29 10:36 (:0)

입력 리다이렉트

입력 리다이렉트는 출력 리다이렉트와는 반대로 파일을 명령어의 입력으로 넣을 경우 사용을 합니다.

사용 방법은 아래와 같습니다.

command < inputfile

그럼 wc명령어를 사용하여 입력 리다이렉트를 해보도록 하겠습니다. 우선 wc명령은 파일의 몇개 라인이 있는지, 몇개 단어가 있는지, 그리고 몇바이트 인지를 표시해 줍니다.

$ wc < test6

2 11 77

인라인 입력 리다이 릭트

인라인 입력 리다이렉트는 << 기호를 사용을 하고 << 다음에 입력의 마지막을 표시하는 텍스트를 입력을 해주어야 합니다. 이 방법은 한개의 명령어에 입력할 데이터가 여러개일때 사용하고, 사용형식은 command << marker(명령어 종료 문자) 형식으로 사용합니다. wc를 이용하여 간단한 테스트를 해보도록 하겠습니다.

hyowon@hyowon-800G5M-800G5W:~$ wc << END

> test string 1

> test string 2

> test string 3

> END

3 9 42

END 단어를 만나자 명령어는 종료되고 결과값으로 3개 라인, 9개 단어. 42바이트를 출력해 줍니다.

5. PIPE 명령어

파이프 명령은 하나의 명령어 출력을 다른 명령어의 입력으로 전달할때 사용이 됩니다. 기 방법은

command | command 형식으로 사용을 하면 됩니다.

예를 들어 /etc/passwd의 내용들을 알파벳 순서를 출력을 하게 하려면 아래와 같이 사용하면 됩니다.

$ cat /etc/paswd | sort

_apt:x:105:65534::/nonexistent:/bin/false

avahi-autoipd:x:110:119:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false

avahi:x:111:120:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false

backup:x:34:34:backup:/var/backups:/usr/sbin/nologin

bin:x:2:2:bin:/bin:/usr/sbin/nologin

colord:x:113:123:colord colour management daemon,,,:/var/lib/colord:/bin/false

daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

dnsmasq:x:112:65534:dnsmasq,,,:/var/lib/misc:/bin/false

games:x:5:60:games:/usr/games:/usr/sbin/nologin

gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin

guest-3moqme:x:997:997:손님:/tmp/guest-3moqme:/bin/bash

만약 여기서 출력 결과를 파일로 저장을 하고 싶다면 출력 리다이렉트를 사용하여 아래와 같이 사용하면 됩니다.

$cat /etc/passwd | sort > passwd.txt

6. 수학 연산

expr 명령어 사용하기

리눅스 쉘에서 수학연산을 하는 방법은 2가지가 있습니다. 하나는 expr 명령을 사용을 하는 것이고 나머지 하나는 브라겟을 사용하는 방법입니다. 우선 expr명령어 사용방법 부터 살펴 보도록 하겠습니다.

사용방법은 간단 합니다 'expr 숫자 연산자 숫자' 형식으로 사용이 됩니다. 다만 *나 기타 다른 의미가 있는 연산자들을 사용 하기 위해서는 앞에 백슬러쉬를 붙여 줘야 합니다.

~$ expr 5 + 3

8

$ expr 5 - 3

2

$ expr 5 * 2

expr: 문법 오류

$ expr 5 \* 2

10

expr은 논리 연산도 가능한데, 아래표를 참고 하시기 바랍니다.

그럼 스크립트에서 사용해 보도록 하겠습니다.

$touch test7

#! /bin/bash

# expr 명령어 스트립트에서 사용하기

var1=10

var2=20

var3=`expr $var2 / $var1`

echo The result is $var3

#

그럼 실행시켜 봅시다.

$./test7

The result is 2

결과가 정상적으로 나오는군요.. 하지만 expr명령어는

브라겟 사용하기

expr명령어 이외에도 수학 연산을 할수 있는 방법은 브라켓을 사용하는 방법 입니다. 사용 형식은 아래와 같습니다.

브라켓 앞에 $기호를 붙여서 브라켓안의 결과값을 변수화를 해서 저장 하는 방법입니다.

$ var1=$[1 + 5]

그럼 스크립트에서 한번 사용해 보도록 하겠습니다.

$touch test8

$chmod u+x test8

#! /bin/bash

var1=50

var2=30

var=20

var4=$[var1 * ($var2 - $var3)]

echo the result is $var4

#

그럼 실행시켜 보도록 하겠습니다.

$ ./test8

the result is 500

부동 소숫점 연산

리눅스 에서는 expr이나 브라켓을 사용을 해도 부동 소숫점의 연산을 처리할수 없는 한계가 있습니다.

이를 사용하기 위해 bc(bash caculate)를 사용하여 연산을 합니다. 그럼 우선 명령어 라인에서 사용하는 방법을 알아 보도록 하겠습니다.

$ bc

bc 1.06.95

Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.

This is free software with ABSOLUTELY NO WARRANTY.

For details type `warranty'.

4 * 5

20

4.1 * 10.1

41.4

3.342 * (3 + 5)

26.736

quit

$

bc 연산의 결과값을 소수점 몇자리까지 표시 할것인지 설정을 할수 있습니다. 이 방법은 아래와 같이 scale 변수값을 지정하는 방법 입니다. 아래 예를 보겠습니다.

$ bc -q (-q는 환영베너 삭제하는 옵션 입니다)

3.44 / 5

0

scale=4

3.44 / 5

.6880

quit

$

그럼 스크립트에서 bc를 사용해 보겠습니다. 우선 사용방법은 아래와 같습니다.

variable=`echo "options; expression" | bc`

전체는 백틱으로 감싸고 옵션부분에서 변수를 정의를 할수 있고, 변수가 여러개 일때에는 변수 사이를 세미콜론으로 분리를 시켜 하용하고, 방정식 부분을 기술하면 됩니다. 그럼 예제를 들어 실행해 보도록 하겠습니다.

$touch test8

#! /bin/bash

var1=20

var2=3.14159

var3=`echo "scale=4; $var1 * $var2" | bc`

var4=`echo "scale=4; $var3 * $var2" | bc`

echo The result is $var4

#

실행시키면

$ ./test9

The result is 197.39175

방정식이 여러개일때에는 인라인 리다이렉트로 아래와 같이 사용을 하면 조금 편리 합니다.

#! /bin/bash

var1=10.46

var2=43.67

var3=33.2

var4=71

var5=`bc << EOF

scale = 4

a1 = ( $var1 * $var2)

b1 = ($var3 * $var4)

a1 + b1

EOF

`

echo The final answer for this mess is $var5

#

$ ./test10

The final answer for this mess is 2813.9882

$

exit code 사용하기

리눅스는 명령어 실행결과를 exit 변수에 실행결과 값을 숫자로 저장을 합니다. 협약된 exit code는 아래표와 같고 스크립트에서는 이 exit코드를 사용하여 여러가지 동작을 하는 스크립틀를 만들 수 있어서 많은 스크립트에서 사용하고 있습니다. 명렁어가 성공적으로 실행이 되면 exit code는 0으로, 그리고 없는 명령을 실행했을때는 127번으로 리턴을 합니다. 이 코드값을 확인할때에는 echo $?를 사용하여 확인이 가능합니다.

$ date

Sat Sep 29 10:01:30 EDT 2007

$ echo $?

0

$

$ asdfg

-bash: asdfg: command not found

$ echo $?

127

$

스크립트에서 사용자가 원하는 값으로 exit code값을 저장을 할 수도 있습니다. 아래 예제를 봅시다.

이럴때 exit 명령어 뒤에 리턴값을 지정해 주면 됩니다.

$touch test11

#!/bin/bash

# testing the exit status

var1=10

var2=30

var3=$[ $var1 * var2 ]

echo The value is $var3

exit $var3

$

$ ./test11

The value is 300

$ echo $?

44

$

여기서 exit code가 44인 이유는 쉘스크립트는 exit코드의 범위(0 ~ 255)를 넘는 경우 256으로 나눈 나머지 값을 exit code로 돌려 줍니다.

자 그럼 오늘은 여기까지.... 쉘 스크립트 전문가가 되는 그날까지 화이팅!!!!

728x90
반응형

'쉘스크립트' 카테고리의 다른 글

세부 구조적인 Shell 명령어  (1) 2022.07.06
구조화된 명령어들  (1) 2022.07.06
리눅스 파일 퍼미션  (1) 2022.07.05
환경 변수  (1) 2022.07.04
Bash Shell 명령어들  (0) 2022.07.04