1. Shell Script

→ 실행할 명령어를 미리 파일에 작성해두고 매크로처럼 실행

1) 셔뱅을 이용하는 방법

ex) du -h ~ | tall -n 1 : 홈 디렉토리의 파일 사용량 출력

위와 같은 명령어는 직접 타이핑하기 불편함 쉘 스크립트로 작성해두고 짧게 실행하는 것이 효율적

#!/bin/bash : 셔뱅

#! 뒤에 오는 파일/경로를 실행매개로 간주하고 명령을 내린다는 의미 → 어디에서 해당 파일을 실행하든 /bin/bash를 통해 실행

위와 같이 해당 파일에 실행 권한을 준 후 ./파일명을 통해 실행하면 위와 같이 동일한 결과가 출력되는 것을 확인할 수 있다.

 

2) source 명령어를 이용하는 방법

위와 같이 source 명령어를 이용해서도 쉘 스크립트 실행이 가능하고,

source를 사용하면 셔뱅을 적지 않아도 현재 실행한 쉘을 이용해 스크립트를 실행한다.

위와 같이 "."를 사용하여 source 명령어를 대체할 수 있지만 가독성 문제로 source를 사용하여 실행한다.

 

3) source와 ./ 실행의 차이점

위와 같이 vim 에디터를 이용해 test1.sh 파일을 생성하고, poiuqwer라는 사전에 지정된 적 없는 리눅스 명령어를 실행한다.

alias 명령어로 별명을 등록할 수 있고, 해당 명령을 실행하면 poiuqwer은 ls -alF로 대체된다.

또한, source 명령어로 해당 파일을 실행해보면 ls -alF 명령을 수행한 결과가 잘 출력되는 것을 확인할 수 있다.

하지만, 위와 같이 . 명령어를 사용하여 실행하면 command not found 오류가 발생하는 것을 확인할 수 있다.

. 명령어로 실행 시 새로운 쉘을 하나 더 순간적으로 열게 되는데 이 때 새로운 쉘에는 alias 설정이 되어 있지 않기 때문에 해당 명령을 수행하지 못한다.

 

4) 쉘스크립트의 배치

→ 파일 관리 용이성을 위해 쉘스크립트를 모아두어야 함

먼저, ~/bin 디렉토리를 생성하고 해당 경로로 모든 쉘 스크립트를 옮긴다.

어떤 경로에서든 파일명만 적어도 실행되도록 만드는 것이 효율적이다. → 전역 경로 설정

검색 경로에 ~/bin을 추가하기 위해 ~/.profile 파일에 위와 같은 PATH를 추가해준다.

위 명령어를 실행하면 즉시 적용되고, 해당 작업을 수행한 계정은 어디서든 .sh 파일을 호출할 수 있다.

위와 같이 파일명만 입력해도 쉘스크립트에 작성해뒀던 명령어가 잘 실행되는 것을 확인할 수 있다.

 

5) 전역 경로 비활성화

shopt -u sourcepath 명령어를 사용하면 source 명령어 사용 시 해당 단축경로를 비활성화할 수 있다.

위와 같이 현재 경로에 test.sh 파일이 없기 때문에 source 명령어를 사용하여 실행하면 오류가 발생하는 것을 확인할 수 있다.

 

2. Shell Script 작성하기

1) 개행

- 실제 쉘 스크립트는 여러줄로 작성

- 여러 줄 명령어를 순차적으로 실행시킬 때 기본적으로 엔터키를 눌러 개행시키면 순차적으로 하나씩 실행

위와 같이 엔터로 개행시킨후 실행해보면 쉘스크립트에 작성했던 명령들이 잘 수행되는 것을 확인할 수 있다.

- 엔터키 개행 대신 ;로 대체 가능

위와 같이 ; 로 수정해도 같은 결과로 동작되는 것을 확인할 수 있다.

 

2) 개행 무시

\ (역슬래시)를 사용하여 여러줄을 한 줄에 쓴 것처럼 동작시킬 수있다.

위와 같이 개행이 있지만 echo "root" 명령을 한 결과가 출력되는 것을 확인할 수 있다.

 

3) 주석 : #

 

4) 변수 

변수명=저장할내역 : 변수 저장

$변수명 : 변수값 참조

기본적으로 위와 같이 변수를 저장하고 사용할 수 있다.

\$문자 : 일반문자 그대로 출력

\\$문자 : 백슬래시 문자(변수값) 출력

\\\$문자 : 백슬래시 일반문자 출력

 

5) quote : 따옴표

홑따옴표 : 변수값 포매팅 X

쌍따옴표 : 변수값 포매팅 O

위와 같이 홑따옴표는 일반 문자를 그대로 출력하고, 쌍따옴표는 해당 이름의 변수값이 출력되는 것을 확인할 수 있다.

만약 변수값 대입이 아닌 $name을 출력하고 싶다면 마찬가지로 \ (역슬래쉬)를 붙여주면 된다.

 

6) 명령어 치환

특정 명령어를 수행한 결과를 파일 이름 등으로 사용하고 싶은 경우 $(명령어) 로 이용 가능

위와 같이 $(명령어)를 이용해 변수를 생성하고 파일 생성 명령어 touch를 이용하는 쉘스크립트를 작성했다.

쉘스크립트를 실행해보면 위와 같이 touch $filename 명령이 잘 수행된 것을 확인할 수 있다.

 

7) 파라미터 전달

쉘 스크립트에서는 파라미터의 위치에 따라 $번호에 해당하는 변수에 대입된다. ($0부터 시작)

위와 같은 쉘스크립트를 작성해주고

위 파일을 실행해보면 위와 같이 파라미터 위치에 따라 0부터 순서대로 해당 변수에 대입되는 것을 확인할 수 있다.

위와 같이 전달된 인자의 개수가 몇 개인지는 $#를 사용하여 조회할 수 있다.

 

8) 제어문

① if문

- if [ 명령어 ]; then ~ else ~ fi

위와 같이 첫번째 파라미터 값이 bin이면 OK를, 아니면 NO를 출력하는 조건문을 작성했다.

※ if [ 명령어 ]; 입력 시 대괄호 안에 공백을 주의해야 한다.

※ 세미콜론이 있다면 then과 조건식이 같이 놓일 수 있지만 생략했다면 다음줄로 내려야 한다.

위와 같이 출력 결과가 잘 수행되는 것을 확인할 수 있다.

 

- 명령어의 종료 상태

$?를 사용하여 직전에 실행한 명령어의 상태를 조회할 수 있다.

기본적으로 명령어는 정상 종료 시 0을 가지지만, 에러 발생 시 0이 아닌 다른 번호를 가진다.

 

- if와 종료 상태

조건식을 작성하는 [ ] 역시 명령어이기 때문에 해당 조건식이 참이면 0, 거짓이면 0 이외의 숫자를 반환한다.

조건문 사용 시 반드시 [ ] 를 사용해야 하는 것은 아니고 위와 같이 참과 거짓을 판단할 수 있는 명령어라면 [ ] 없이도 사용이 가능하다.

 

- test 명령어로 [ ] 대신하기

위와 같은 조건문이 있을 때 [ ]를 test 명령어로 대체할 수 있다.

이처럼 [ ]를 사용했을 때와 같은 결과를 출력하는 것을 볼 수 있지만 [ ]가 가독성이 더 좋으므로 test 명령어를 잘 사용하지는 않는다.

 

- 문자열 비교

= 같다
!= 다르다
-n null이 아니다
-z null이다

위 스크립트에서는 첫 파라미터(filename)가 null이라면 default.dat을, 값이 있으면 filename을 출력해준다.

위와 같이 결과가 잘 출력되는 것을 확인할 수 있다.

 

- 정수 비교

-eq 같다
-ne 다르다
-lt 작다
-gt 크다
-le 작거나 같다
-ge 크거나 같다

위와 같이 기본적으로 max 변수에는 첫번째 파라미터 값이 들어 있고, -lt로 두 값을 비교하여 두번째 파라미터 값이 더크다면 max를 두 번째 파라미터로 넣어주는 조건문을 작성했다.

위와 같이 조건에 따라 결과가 잘 수행되는 것을 확인할 수 있다.

 

- 파일 비교

-e 파일 존재
-d 파일 존재하고, 디렉터리임
-h / -L 파일 존재하고, 심볼릭링크임
-f 파일 존재하고, 일반파일임
-r 파일 존재하고, 읽기 권한이 있음
-w 파일 존재하고, 쓰기 권한이 있음
-x 파일 존재하고, 실행 권한이 있음
file1 -nt file2 file1이 file2보다 최근에 변경됨
file1 -ot file2 file2가 file1보다 최근에 변경됨

 

- 연산자 결합

-a and 연산
-o or 연산
! not 연산

연산자 결합 역시 ( )를 이용하여 우선순위를 다르게 지정할 수도 있다.

 

- &&와 ||를 활용한 명령어 순차평가

&& 왼쪽이 참이어야 오른쪽을 실행
|| 왼쪽이 거짓일 때 오른쪽을 실행

위와 같이 && 연산자를 이용하여 iftest.sh 파일이 존재하기 때문에 ifex.sh의 내용을 잘 출력하는 것을 볼 수 있다.

위와 같이 || 연산자를 이용하여 ifor.sh 파일이 존재하지 않기 때문에 ifor.sh 파일을 잘 생성해주는 것을 볼 수 있다.

 

② for문

- for 변수 in 리스트 ~ do ~ done

위와 같이 반복문을 작성할 수 있고 name이라는 변수에 값을 차례로 넣어 출력하는 것을 확인할 수 있다.

head : 맨 위부터, tail : 맨 뒤부터

위와 같이 경로에 따라서는 와일드카드를 사용할 수도 있고, 현재 경로의 모든 .sh 파일의 내용을 세번째 줄까지 출력해주는 것을 확인할 수 있다.

 

- seq 1 5 : 1~5 출력

for을 쓰지 않고 seq을 이용하여 더 간단하게 반복문을 사용할 수 있다.

위와 같이 seq을 이용하여 현재 경로에 5개의 파일을 생성하라는 코드를 작성할 수 있다.

실행 후 확인해보면 위와 같이 5개의 파일이 잘 생성된 것을 확인할 수 있다.

 

- 커맨드라인으로 보낸 인자 일괄처리

"$@"를 in 우변에 사용하면 받은 파라미터를 전부 반복문 타겟으로 잡는다.

위 코드는 paratest.sh를 실행하며 넘긴 모든 인자를 $@에 받아 처리해준다는 의미이다.

이와 같이 파라미터 값들이 다 넘겨지고 출력되는 것을 확인할 수 있다.

 

③ case문 : if문보다 강한 분기처리

case 문자열 in 패턴1) ~ ;; 패턴2) ~ ;; esac

case문을 사용하여 첫번째 파라미터 값이 start나 stop인 경우에만 checked가 출력되도록 하는 코드를 작성했다.

위와 같이 분기문이 잘 처리되어 결과가 출력되는 것을 확인할 수 있다.

 

④ while문 : 조건이 거짓이 될 때까지 반복

i 값이 10보다 작은 경우 계속 반복하는 while문을 작성했다.

실행해보면 위와 같이 반복문이 수행된 결과가 잘 출력되는 것을 확인할 수 있다.

 

⑤ until문 : while문과 반대로 조건이 거짓인 동안만 실행

위와 같이 until은 while과 사용법이 동일하게 수행된다.

 

⑥ C언어식 반복문

위와 같이 C언어식으로 반복문을 작성하는 것도 가능하다.

이 때 괄호는 겹쳐야 하고, 겹친 괄호 내에서는 변수에 $를 붙이지 않는다는 것을 주의해야 한다.

실행해보면 위와 같이 반복문이 잘 수행되는 것을 확인할 수 있다.

 

9) 셀 내부에서 함수 활용하기

function 함수명 (){
	실행문;
}

function 함수명 {
	실행문;
}

함수명(){
	실행문;
}

위의 세 가지 방식으로 쉘 내부에서 함수를 활용할 수 있다. 주로 세번째 방식을 사용한다.

date 결과와 디렉터리의 용량을 보여주는 du 명령어를 수행한 결과를 마지막 1줄만 출력하라는 homesize() 함수를 선언했고, 선언 후 homesize 함수를 호출해준다.

※ 쉘 함수는 반드시 호출구문 위쪽에 위치해야 한다.

위와 같이 수행 결과가 잘 출력되는 것을 확인할 수 있다.

또한, 종료코드는 return 상태코드 형식으로 전달하면 된다.

'네트워크캠퍼스 > LINUX' 카테고리의 다른 글

크론잡과 크론탭  (0) 2024.02.21
Shell Script 실습  (0) 2024.02.20
Devops와 SE를 위한 리눅스 커널 이야기  (0) 2024.01.17
프로세스  (0) 2024.01.16
텍스트에디터  (0) 2024.01.15

+ Recent posts