Shell Script
사용OS: Ubuntu 22.04
본 내용은 '이것이 리눅스 우분투다' 를 참고하여 제작하였습니다.
스크립트 작성 시 고려사항
1. 명확한 작업순서 정의필요
2. 관련 커맨드 확인
3. 궁극적으로 원하는 목표가 무엇인지? ★
* ex) 목표 : 딸깍 한번으로 웹 페이지 구축해보자~
개요
- 셀이나 명령 줄 인터프리터에서 돌아가도록 작성
- 한 운영 체제를 위해 쓰인 스크립트
- 일반 기능으로는 파일 이용, 프로그램 실행, 문자열 출력 등이 존재
환경 변수
- 쉘은 여러가지 환경 변수값을 가짐
- 프로세스가 컴퓨터에서 동작하는 방식에 영향을 미치는 동적인 값들의 모임
[표 1] bash의 주요한 환경 변수
환경 변수 | 설명 | 환경 변수 | 설명 |
HOME | 현재 사용자의 홈 디렉터리 | PATH | 실행 파일을 찾는 디렉터리 경로 |
LANG | 기본 지원되는 언어 | PWD | 사용자의 현재 작업 디렉터리 |
TERM | 로그인 터미널 타입 | SHELL | 로그인해서 사용하는 쉘 |
USER | 현재 사용자의 이름 | DISPLAY | X 디스플레이 이름 |
COLUMNS | 현재 터미널의 컬럼 수 | LINES | 현재 터미널 라인 수 |
PS1 | 1차 명령 프롬포트 변수 | PS2 | 2차 명령 프롬프트(대게는 '>') |
BASH | bash 쉘의 경로 | BASH_VERSION | bash 버전 |
HISTRILE | 히스토리 파일의 경로 | HISTSIZE | 히스토리 파일에 저장되는 개수 |
HOSTNAME | 호스트의 이름 | USERNAME | 현재 사용자 이름 |
LOGNAME | 로그인 이름 | LS_COLORS | ls 명령의 확장자 색상 옵션 |
메일을 보관하는 경로 | OSTYPE | 운영체제 타입 |
[참조] 이것이 우분투 리눅스다 교재
실습 1 ( 기본 )
1. 터미널을 접속해서 ~ 디렉터리로 이동 후 쉘 스크립트를 테스트 할 환경을 만들어준다.
touch 명령어로 sh_test.d를 만들어보자 그 이후 cd 명령으로 sh_test.d 로 이동
2. name_01.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
(필자는 vim을 사용하였으며, vim을 사용할 때 i (들여쓰기)를 입력해 작성을 시작한 후 작성이 끝나면 esc를 눌러 :wq 명령어로 저장 후 나간다.)
3. sh name_01.sh 명령어로 쉘 스크립트를 실행한다.
실습 2 - 1 ( 변수 )
필요한 값을 계속 변경해 저장한다는 개념. 쉘 스크립트 구조는 변경할 필요가 없는데 설정해야 하는 값이 상황에 따라 다르면 변수에 필요한 값을 계속 바꿔가는 방법으로 프로그래밍 가능
1. var_01.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
2. sh var_01.sh 명령어로 쉘 스크립트를 실행한다.
실습 2 - 2 ( 숫자 계산 )
변수에 넣은 값은 모두 문자열로 취급. +,-,*,/ 등의 연산을 사용하려면 expr 키워드를 사용해야함
1. numcalc_01.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
2. sh numcalc_01.sh 명령어로 쉘 스크립트를 실행한다.
실습 2 - 3 ( 파라미터 변수 )
*파라미터 변수는 $0, $1, $2 등의 형태를 가짐. 즉, 명령어에 포함된 모든 단어를 각자 $변수 형식으로 지정
1. paravar_01.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
2. sh paravar_01.sh 명령어로 쉘 스크립트를 실행한다.
실습 3 - 1 ( 기본 if문 )
대부분의 프로그래밍 언어에서 지원하는 if문 작성
1. if_01.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
2. sh if_01.sh 명령어로 쉘 스크립트를 실행한다.
실습 3 - 2 ( if~else 문 )
참인 경우와 거짓인 경우를 구분해서 실행한다.
1. if_02.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
2. sh if_02.sh 명령어로 쉘 스크립트를 실행한다.
실습 3 - 3 ( 조건문에 들어가는 비교 연산자 )
[표 2] 문자열 비교 연산자
문자열 비교 | 결과 |
"문자열1" = "문자열2" | 두 문자열이 같으면 참 |
"문자열1" != "문자열2" | 두 문자열이 같지 않으면 참 |
-n "문자열" | 문자열이 NULL(빈 문자열)이 아니면 참 |
-z "문자열" | 문자열이 NULL(빈 문자열)이면 참 |
[표 3] 산술 연산자
산술 비교 | 결과 |
수식1 -eq 수식2 | 두 수식(또는 변수)이 같으면 참 |
수식1 -ne 수식2 | 두 수식(또는 변수)이 같지 않으면 참 |
수식1 -gt 수식2 | 수식 1이 크면 참 |
수식1 -ge 수식2 | 수식 1이 크거나 같으면 참 |
수식1 -lt 수식2 | 수식 1이 작으면 참 |
수식1 -le 수식2 | 수식1이 작거나 같으면 참 |
!수식 | 수식이 거짓이면 참 |
1. if_03.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
2. sh if_03.sh 명령어로 쉘 스크립트를 실행한다.
실습 3 - 4 ( 파일과 관련된 조건 )
if문에서 파일을 처리하는 조건이 존재하는데, 아래의 표는 파일과 관련된 조건에 대한 표이다.
[표 4] 파일과 관련된 조건
파일 조건 | 결과 |
-d 파일이름 | 파일이 디렉터리면 참 |
-e 파일이름 | 파일이 존재하면 참 |
-f 파일이름 | 파일이 일반 파일이면 참 |
-g 파일이름 | 파일에 set-group-id가 설정되면 참 |
-r 파일이름 | 파일이 읽기 가능이면 참 |
-s 파일이름 | 파일 크기가 0이 아니면 참 |
-u 파일이름 | 파일에 set-user-id가 설정되면 참 |
-w 파일이름 | 파일이 쓰기 가능 상태면 참 |
-x 파일이름 | 파일이 실행 가능 상태면 참 |
1. if_04.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
<주석>
2행: fname 변수에 cron 서버 실행 파일인 /lib/systemd/system/con.service를 저장
3행: fname 변수에 저장된 /lib/systemd/system/con.service 파일이 일반 파일이면 참이므로 5행을 실행하고, 그렇지 않으면 7행을 실행
5행: fname에 들어 있는 파일의 앞에 5줄을 출력한다.
2. sh if_04.sh 명령어로 쉘 스크립트를 실행한다.
실습 4 (case~esac문)
if~else문은 조건이 많아지게 되면 구문이 복잡해지는 단점 존재. 이와 같은 단점을 보완하여 case~esac문은 복잡한 구문에 효과적으로 사용할 수 있는 분기문이다.
1. case_01.sh, case_02.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
<주석>
3행: 선택할 사계절의 파라미터 안내 문자열 출력
4행: case 문의 시작과 첫 번째 파라미터 $1 지정
5행: 조건 1에 주어진 파라미터는 Spring
6행: 조건1에 해당할 때 출력문장이며 주의할 점은 세미클론(;;) 2개 선언
13행: *)는 앞에 주어진 모든 조건에 해당되지 않을 경우
17행: case 문 종료
2. sh case_01.sh, case_02.sh 명령어로 쉘 스크립트를 실행한다.
실습 5 ( AND, OR 관계 연산자 )
if~else문과 case~esac문에서 주어진 조건을 하나 또는 여러 개를 선언하여 분기문 수행. if~else문에서는 하나의 조건만을 사용했지만 분기문에서의 조건은 두 개 이상을 설정하여 프로그램을 작성한다.
1. ifandor.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
2. sh ifandor.sh 명령어로 쉘 스크립트를 실행한다.
Search Name : 이 뜬다면 /lib/systemd/system/udev.service 를 입력해보자!
실습 6 - 1 for문 ( 반복문 )
반복문: 누적되는 합을 구하거나 수행할 명령을 반복적으로 수행할 수 있도록 조건으로 제어
1. for_02.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다. (순차적으로 증가하면서 반복 : seq)
seq 명령어는 sequence의 약어로 반복문을 수행할 첫 번째 값과 마지막 값을 선언하여 반복구간을 정의할 때 사용. seq 명령을 사용할 때는 반드시 `(backtick)로 묶어줘야함.
<주석>
3행: 반복문을 수행할 때 횟수를 카운트 할 변수를 선언하고 0의 값으로 초기화
4행: seq 명령 구간은 반드시 역따옴표로 묶어줘야 함
6행: 숫자 계산을 위한 expr 명령 구간은 반드시 역따옴표로 묶어줘야 함
7행: 출력 형식지정자 %02d를 선언하여 0을 포함한 숫자 2자리씩 출력되도록 자릿수 지정
2. sh for_02.sh 명령어로 쉘 스크립트를 실행한다.
실습 6 - 2 while문 ( 반복문 )
1. while_ex.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
키보드로 입력받은 비밀번호가 일치할 때까지 while 문으로 반복해서 수행하는 쉘 스크립트
<주석>
4행: 키보드로 입력받은 비밀번호를 pw 변수에 저장
5행: $pw != "980520"으로 조건문을 설정하여 키보드로 980520이 입력될 때까지 무한 반복 수행
6행: while문의 구문 시작, 비밀번호 980520이 입력될 때까지 7행~9행 반복 수행
9행: 다시 입력하는 비밀번호를 pw 변수에 저장 -> 5행의 조건문에서 다시 판별
10행: while문의 구문 종료
12행: 정확한 비밀번호가 입력되었을 때 입력한 비밀번호를 출력
2. sh while_ex.sh 명령어로 쉘 스크립트를 실행한다.
실습 6 - 3 until문 ( 반복문 )
until문은 주어진 조건식이 항상 거짓일 경우에만 명령을 수행
1. until_ex.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
<주석>
5행: until [ $cnt -gt 30] 에서 cnt의 값이 30보다 크다는 것을 의미하는 조건문은 거짓이 되지만 until문은 조건문이 거짓일 때 반복을 수행하는 특징
7행: until문이 반복 수행되면서 누적되는 합계를 산출
8행: until문이 수행될 때마다 누적되는 합계를 출력
9행: 5배수의 합을 구하기 위해 반복문이 수행될 때마다 카운트 변수의 크기를 5씩 증가
11행: 5행에서 선언한 조건식이 참이 되는 순간 반복 수행을 멈추고 1~30까지 5배수의 누적합계를 출력
2. sh until_ex.sh 명령어로 쉘 스크립트를 실행한다.
실습 7 while문 ( 분기문 )
분기문: 명령을 수행하는 과정에서 특정 위치로 이동하거나 반복문을 탈출할 때 사용하는 명령문 (break, countinue, exit, return 문)
1. bcer.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
<주석>
5행: while 문에서 조건을 [ 1 ]로 선언하면 무조건 참이므로 무한 반복 수행
9행: case 구문 시작. 조건은 키보드로 입력한 알파벳이 저장된 $choice 변수를 지정
11행: 알파벳 B 또는 b를 입력받았을 때 수행할 명령, 두 명령을 구분은 가운데 세미클론(;) 사용. 명령어 끝은 2개 사용
13행: 알파벳 C 또는 c를 입력받았을 때 수행할 명령
15행: 알파벳 E 또는 e를 입력받았을 때 수행할 명령
16행: 앞에서 주어진 조건 이외의 알파벳 입력은 * 문에 해당
알파벳 대/소문자 관계없이 b, c, e 이외의 알파벳을 입력받았을 때의 조건
17행: 알파벳 b, c, e 이외의 알파벳을 입력받았을 때 출력할 메시지
18행: continue문을 사용하여 반복문의 처음인 조건식으로 다시 돌아감
19행: case구문 종료
20행: while반복문 종료
2. sh bcer.sh 명령어로 쉘 스크립트를 실행한다.
실습 8 - 1 함수와 파라미터
1. userfun_01.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
<주석>
3행: 함수의 이름을 myfun( )으로 사용자 함수 정의
4행: myfun ( ) 함수 시작 구간
5행: myfun ( ) 함수에서 수행할 명령문
8행: 사용자 정의 함수 myfun ( ) 호출
2. sh userfun_01.sh 명령어로 쉘 스크립트를 실행한다.
실습 8 - 2 함수의 파라미터
키보드로 입력받은 숫자를 사용자 정의 함수를 사용하여 연산할 때는 파라미터(Parameter)를 사용해야함. 함수를 호출할 때도 함수 이름 뒤에 파라미터를 붙여서 '함수 이름 $1, $2, ... ' 와 같은 형태로 호출해야함
1. userfun_02.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
<주석>
3행: add ( ) 사용자 함수 정의
5행: 2개의 파라미터로 덧셈 연산 후 결과값을 total 변수에 대입
7행: 키보드로 입력받은 2개의 정수와 덧셈 연산결과 출력
11행: 첫 번째 정수값을 입력받아 num1 변수에 저장
13행: 두 번째 정수값을 입력받아 num2 변수에 저장
14행: 2개의 파라미터와 함께 사용자 정의 함수 add 호출
2. sh userfun_02.sh 명령어로 쉘 스크립트를 실행한다.
기타 알아두면 좋은 내용들
문자열을 명령문으로 인식 : eval
- eval은 프로그램에서 문자열로 처리한 부분을 명령문으로 인식할 때 사용
- eval 선언해 문자열을 명령문으로 인식하는 프로그램 작성 예시
1. eval.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
<주석>
3행: 문자열 "ls /tmp"를 변수 filename에 대입
5행: "ls /tmp" 문자열이 대입된 변수 $filename 출력
7행: eval 명령으로 ls /tmp 문자열을 명령문으로 인식하여 수행
2. sh eval.sh 명령어로 쉘 스크립트를 실행한다.
명령어 형식 지정
- 우분투에서 사용하는 명령어를 파라미터로 세팅하여 사용하려면 set 명령과 $(명령어) 형식을 함께 지정하여 사용
- 오늘 날짜와 시각 중 요일만 출력하고자 할 때 예시
3. set_date.sh 파일을 만들어 아래와 같이 작성 후 저장하고 나간다.
<주석>
3행: 오늘의 날짜와 요일, 시각을 출력하기 위해 $(date) 명령어 지정
4행: 명령어 형식지정을 위한 set $(date) 선언
5행: set $(date) 형식지정에서 네 번째 요소인 요일을 출력하기 위해 $4를 선언
4. sh set_date.sh 명령어로 쉘 스크립트를 실행한다.
이렇게 Shell Script에 대하여 기초적인 부분을 실습해보았다. 이후 주요정보통신기반시설 취약점 분석 및 평가 기준에 맞도록 스크립트를 만들어 직접 만든 서버에 취약점 진단을 목표로 공부를 해보았다.
'Server > Ubuntu' 카테고리의 다른 글
[Server] Web Server란? (0) | 2024.05.30 |
---|---|
[Server] Web Server 구축 (2) | 2024.05.29 |
[Server] Mail Server 구축 (0) | 2024.04.25 |
[Server] FTP Server 구축 (0) | 2024.04.24 |
[Server] Telnet Server 구축 (0) | 2024.04.24 |