본문 바로가기
정보보안/이론

[KITRI] Day12. Disk quota 와 간단한 셸 스크립팅

by 민-Zero 2020. 5. 11.

quota 실습

quota에 대한 테스트를 해보기 위해 /home 과 /test를 sdb1과 sdc1 마운트 하고 user1~5 계정을 생성하자.

1. /etc/fstab에 파일시스템을 usrquota, grpquota 옵션을 적용하여 마운트한다. 

default옆에 usrquota를 추가하고 재마운트하여 적용되도록 하자.

그럼 마운트 상태를 확인하면 rw와 함께 usrquota가 적용된것을 확인할 수 있다.


2. quota DB를 생성한다. 이때 사용하는 명령어는 quotacheck가 있다.

quotacheck 명령어 
quotacheck -옵션 경로 : 특정 quota가 적용된 디렉토리만을 검사
해당 명령어는 검사 명령어지만 생성하는 과정까지 포함된다.

옵션(quotacheck, quotaon, edquota 비슷하게 적용된다)
-a : quota가 적용된 모든 디렉토리를 검사
-u : usrquota만 검사
-g : grpquota만 검사
-m : 재마운트를 생략한다
-v : 상태를 보여준다.
-p : 처리 결과를 출력한다.

quotacheck -mua : 재마운트하지 않고 검사하여 quota db생성

 

quota를 적용할 /home 디렉토리에만 quotacheck를 수행하여 quota db인 aquota.user가 생성된 것을 확인할 수 있다.

3. quota 동작 활성화 및 비활성화
quotaon -a : quota가 적용된 모든 디렉토리들을 활성
quotaon 경로 : 특정 quota가 적용된 디렉토리만을 활성
quotaoff -a , quotaoff 경로 : quota 비활성


활성/비활성은 활성시에는 사용자들의 사용량을 추적하면서 DB를 갱신한다. 따라서 비활성은 용량의 제한을 두지 않게 되는것이다.  혹시 quota가 동작하지 않는다면 활성화를 수행해 보면 되며 이미 활성화 되어 있을시 quotaon을 사용하면 이미 동작중이라는 에러를 보여주며 동작하지 않을떄 quotaoff를 입력해도 마찬가지로 에러를 보여준다.

4. 사용자나 그룹별 사용량을 제한한다.

원하는 디렉토리에 디스크를 마운트하고 quota를 적용하였으므로 이제 용량을 제한하면 quota의 목적을 이루게 된다.모든 파일시스템의 quota를 일괄로 편집 가능하다.

 

edquota 명령어

edquota -u 사용자 : 해당 사용자의 quota 편집하는 명령어

edquota -u user1을 입력하면 해당 사용자의 quota 설정을 확인할 수 있다. 이때 각 용어의 뜻은 아래와 같다.
edquota 로 db진입시 볼수 있는 용어 설명
Filesystem : 파일 시스템, 수정X 시스템에서 관리하는곳이다.
blocks : 현재 사용량(kbyte), 수정X 시스템에서 관리하는곳이다.
soft : 경고 사용량
hard : 절대 사용량
idnodes : 현재 파일수, 수정X 시스템에서 관리하는곳이다.
soft : 경고 파일수
hard : 절대 파일수

 

사용량의 soft에 500000 hard에 800000으로 설정한뒤 저장한뒤 편집을 끝내면

repquota /home 명령을 통해 설정한 내용이 quota에 적용되었음을 확인할 수 있다. 이 명령어는 해당 디렉토리에 설정된 quotaDB 정보를 확인할 수 있다.

해당 설정이 적용된다면 user1은 정의된 50000kbyte의 용량만 사용할 수 있게 된다.

일반사용자가 자신에게 적용된 할당량을 확인하고 싶다면 quota만 입력하면 된다.


quota를 사용하다 보면 현재 디렉토리의 총 용량이 얼마나 사용중인지 확인해야 할 경우가 생긴다. 이때 df 명령어를 통해 디스크들의 사용량을 확인 했다면 이번에는 각 디렉토리가 사용중인 용량을 확인해야 하는 경우 du 명령어를 사용하면 된다.

경로를 지정해주지 않으면 모든 디렉토리의 내용이 출력된다.

따라서 내가 보고자 하는 디렉토리가 있을경우 해당 디렉토리를 명시해 주고 -s를 붙여 해당 디렉토리만 확인하면 된다. -s를 사용하고 경로를 입력하지 않을 경우 현재 위치한 디렉토리의 사용량을 보여준다.

 

du -옵션 경로 : 해당 명령어를 통해 확인할 수 있다. 
-s : 요약해서 해당 디렉토리의 용량만 확인
-h : 사용자가 보기 편한 단위로 보여줌

 

quota로 적용된 용량 제한의 적용을 확인하기 위해 대략 100Mb가 넘는 파일을 만들자. tar cf file1 /etc로 파일을 하나 생성한뒤 user1이 자신의 홈디렉토리에 복사해가져가자. 

 

그런 다음repquota를 다시 사용하면 사용량이 변경된것을 확인할 수 있다. 제한을 걸지 않아도 사용량은 repquota로 확인 가능하다. 

 

이제 일반 사용자 계정으로 file1을 사용자 홈디렉토리에 계속 복사해보자 그럼 soft용량을 넘어설때 경고 메세지가 출력되고 일반사용자가 계속 파일을 생성한 결과 디스크 할당량이 초과되었다고 하며 hard에 정해놓은 용량까지만 복사되고 복사 중간에 끊어버린 것을 file8의 용량을 통해 알 수 있다. 즉 quota가 설정되면 hard에 설정된 용량을 절대 넘어서지 못한다. 

 

이때 repquota에서 +- 를 확인할 수 있다. +는 용량을 넘어선것을 뜻하며 그 뒤에 -는 파일 갯수를 뜻한다. 파일 갯수에 대한 제한을 걸지 않았으므로 -로 유지되어 있으며 만약 제한을 걸었는데 넘어가면 +로 변경된다. 
그리고 grace가 새로 갱신된것을 볼수 있다. grace는 soft<= 현재 용량 <=hard을 얼마동안 사용할 수 있는지 유예기간을 정해주며 그안에 soft보다 작은 용량으로 줄여야한다. 

 

user1의 파일들을 전부 지우면 repquota에 grace time같은게 사라지며 다시 원상복귀 된것을 확인할 수 있다.

 

만약 grace타임이 넘어가면 none 이라는 값으로 변경되고


sdb1: write failed, user block quota exceeded too long. 라는 문구와 함께 hard에 설정한 용량을 넘지 않았음에도 작은 용량의 파일조차 생성할 수 없게 된다.

파일 개수 용량의 제한은 없기 때문에 생성은 되나 0byte의 파일만 생성된다. 용량을 줄이면 다시 정상적으로 생성할 수 있다.

 

grace time은 edquota -t 를 통해 설정할 수 있다.

 

지금 까지 설정한 디스크 사용량 제한이나 grace time등을 기본값으로 모든 사용자에게 적용하고자 한다면 edquota -p 옵션을 사용하여 대표로 설정한 계정의 설정값을 복사하여 모두에게 적용할 수 있다.

edquota -p user1 user2 user3 user4 user5 : (paste)명령어를 통해 user1의 설정을 2, 3, 4, 5라는 대상사용자에게도 적용하여 quota설정을 동일하게 맞출 수 있다.

 

지금 실습의 경우 user1 2 3 4 와 같이 규칙성 있는 아이디를 생성했기 때문에 모든 사용자에게 동일설정을 적용하는 것이 편했지만 실제의 경우 아이디에 규칙성이 없기 때문에 일일이 타이핑을 통해 입력하려고 하는 경우에는 굉장히 힘들어 지게 된다. 이때 awk명령어를 사용하여 아이디만 가져와 설정을 복사하면 된다.

awk 사용법
awk -F필드구분자 ` {print $필드수}` 파일명 : 필드구분자로 구분된 $필드를 출력한다
awk -F필드구분자 ` 조건{print $필드수}` 파일명 : 필드구분자로 구분하고, 조건을 만족하는 $필드를 출력한다
awk -F: ' $3 >= 500 { -print $1} ' /etc/passwd : /etc/passwd 파일을 : 로 구분하고 $3번쨰 필드가 500이상인 경우 $1번째 필드를 출력하라

 

이 결과를 사용하여 awk 명령을 홑따옴표 ` 로 감싸서 edquota -p 에 사용하면 규칙없는 사용자 id 모두에 동일하게 적용할 수 있다.
edquota -p user1 `awk -F: ' $3 >= 500 { print $1 } ' /etc/passwd` 

 

셸 스크립팅

bash 셸 기능
alias, History 기능, 연산 기능, job control 기능, 자동 이름 완성 기능, 프롬프트 제어 기능, 명령 편집 기능

 

환경변수

셸은 여러 가지 환경 변수 값을 갖는다. 설정된 환경 변수는 echo $환경변수이름 형식으로 명령을 실행하면 확인할 수 있다.

HOME : 현재 사용자의 홈 디렉터리
LANG: 기본 지원되는 언어
TERM : 로그인 터미널 타입
USER : 현재 사용자의 이름
COLUMNS : 현재 터미널으 ㅣ컬럼수
PS1 : 1차 명령 프롬프트 변수
BASH : bash 셸의 경로
HISTFILE : 히스토리 파일의 경로
HOSTNAME : 호스트의 이름
등이 있다.

env 또는 printenv 라는 명령어를 통해 모든 환경변수를 확인할 수 있다.


환경변수 선언

환경변수에는 2가지 종류가 있다. 지역 변수(Local variable) (셸(shell) 변수) 전역 변수(Global variable), (환경(environment) 변수) 가 존재한다. 

 

각 변수들의 선언방법은 지역변수의 경우 원하는 변수명에 대입연산자 =을 사용하면 되고 전역변수의 경우 export라는 명령어를 따로 붙여 주어야 한다. 

ABC="Local Variable"   : 지역 변수 선언
export XYZ="Global Variable" : 전역 변수 선언

 

두 변수의 차이는 서브 셸을 열어보면 확인할 수 있다. 서브 셸은 처음 접속할때 사용한 계정에 설정되어 있는 기본 셸대신 새롭게 셸을 사용할 경우 로그인셸 밑에 생성되는 셸을 뜻한다.

로그인셀    서브 셸    서브 셸 
login -> bash -> ksh -> tcsh 
Local 
pstree로 확인하면 볼 수 있다. 

 

서브 셸을 생성할 경우 pstree에서 로그인 셸인 bash셸 밑에 새롭게 ksh라는 셸이 생긴것을 확인할 수 있다.

 

/bin/ksh 로 셸을 서브 셸로 바꾼뒤 ABC 와 XYZ 를 echo를 통해 확인하면 ABC는 출력이 안되지만 XYZ는 확인이 가능하다.
즉, 두 변수의 차이는 지역 변수는 특정 shell에서만 사용되고, 다른 shell에서는 사용이 불가능하다. 전역 변수는 모든 shell에서 사용되고 다른 shell에서도 사용이 가능하다.

전역변수 또는 지역변수를 확인할때 set을 사용할 경우 지역, 전역변수 모두 확인 가능하지만 환경변수를 확인할때 사용헀던 env라는 명령어는 전역변수만 확인 가능하다.
set(지역변수, 전역변수 둘다 확인 가능)  env(전역변수 만 확인가능)

 

작성한 변수를 지울때에는 unset 명령어를 통해 지역변수 전역변수 모두 지울 수 있다.

또한 전역변수를 생성할때 사용했던 export라는 명령어를 지역변수에 사용하게 되면 해당 지역변수는 전역변수로 변경될 수 있다. 

unset 변수명 : 변수 제거 명령어, 전역 지역 모두에서 지워진다.
export 변수명 : 지역 변수를 전역변수에 추가하는 명령어
export -n 변수명 : 전역 변수에서 해당 변수 제거

 

 

셸 스크립트 파일 생성

셸 스크립트(shell script)는 이나 명령 줄 인터프리터에서 돌아가도록 작성되었거나 한 운영 체제를 위해 쓰인 스크립트이다. 단순한 도메인 고유 언어로 여기기도 한다. 그럼 스크립트 파일이 무엇인지 알아야 한다.

스크립트란 일반적으로 interpret 방식으로 동작하는 컴파일되지 않은 프로그램이며 라인 한줄한줄 읽고 해석해서 실행하는 과정을 반복하도록 만들어진 프로그래밍 언어로 작성된 파일을 뜻한다.

 

간단하게 셸 스크립트를 작성하는 방법을 정리하면 아래와 같다.

#!/bin/bash : 특별한 형태의 주석(#!)으로 bash를 사용하겠다는 의미로 첫행에 꼭 써야한다.
echo "사용자이름: " $USER  : 여려가지 동작을 수행할 구현부분
exit 0 : 종료코드를 반환

이렇게 총 3부분으로 나뉘게 된다.

스크립트의 경우 한꺼번에 작성된 코드를 한줄한줄 차례로 읽어 실행하는 실행파일 이기 때문에 실행 권한이 없다면 따로 sh 스크립트파일명 또는 bash 스크립트파일명 과 같은 형태로 명령어를 사용해야한다. 위의 경우 실행권한을 주었기 때문에 경로와 파일명으로만 실행할 수 있는 것이다.


만약 명령어처럼 어디서든 해당 파일명을 통해 작성한 명령을 수행하고 싶다면 환경변수 PATH에 등록된 디렉토리에 넣어 셸에서 바로 읽을 수 있도록 해야한다.

/bin과 같은 디렉토리에 넣지 않고도 name.sh 로 해당 스크립트 파일을 실행하고 싶다면 PATH 환경변수에 값을 추가해 주어야한다.

PATH=$PATH:/test 와 같이 경로를 추가해 주어야 한다. $PATH로 PATH에 저장된 값을 불러오는 이유는 그냥 /test로 저장할 경우 변수의 값은 덮어쓰기가 되기 때문에 환경변수에 지정된 값이 /test만 남게되기 때문이다.

 

변수

셸 스크립트에서 변수는 4가지의 특징을 가진다.

① 셸 스크립트에서는 변수를 사용하기 전에 미리 선언하지 않으며, 처음 변수에 값이 할당되면 자동으로 변수가 생성된다
② 변수에 넣는 모든 값은 문자열로 취급한다
③ 변수 이름은 대소문자를 구분한다
④ 변수를 대입할때 = 좌우에는 공백이 없어야한다

test = hello 띄어쓰기로 인해 =을 명령어로 인식해 에러가 발생한다.
test=hello
test=Yes sir  띄어 쓰기로 인해 sir이라는 명령어를 찾기때문에 에러가 발생한다

test=Yes\ sir 과 같이 공백을 이스케이프문자 처리하면 에러가 발생하지 않는다 
test="Yes sir"
test=7+5

 

만약 $를 출력하고 싶다면 echo "\$ABC" 와 같이 사용하면 된다. \를 사용하는 것이 헷갈리면 '' 작은따옴표를 사용하면 편하다

 

큰따옴표로 묶으면 문자열 처리가 되지만 `(홑따옴표)로 묶으면 명령어 처리가 되어 해당 명령어의 결과가 변수에 저장된다.
DATE="date"   "date" 문자열로 변수에 저장
DATE=`date`   date를 명령어로 인식하고 실행결과를 변수에 저장

 

숫자 계산

+, -, /, * 의 연산을 사용하려면 expr 키워드를 사용하면 된다.

 

numcalc.sh 파일을 위와 같이 생성하고 연산에 대해 확인하면 expr을 사용하지 않은 num2의 경우 문자열 처리가되어 숫자 계산이 수행되지 않았지만 num3의 경우 100+200의 결과인 300이 출력되는것을 확인할 수 있다.

num4의 경우 ()* 가 연산식이 아닌 다른 제어문자로 처리되는 것을 방지하기 위해 이스케이프 처리를하고 expr을 통해 연산식으로 계샨 하는 것을 확인할 수 있다. 풀이하면 (100+200)/10*2 의 계산 결과가 담기게 된다.

 

파라미터 변수

파라미터 변수는 $0 $1 등의 형태를 갖는다. 이는 실행하는 명령의 부분 하나하나를 변수로 지정한다는 의미다.
예를 들어 dnf -y install gftp 명령을 실행한다고하면 파라미터 변수는 다음과 같이 지정할 수 있다.

dnf -y install gftp
$0 $1 $2 $3

명령부분에 매개변수로 값들을 스크립트로 넘길 수 있는것을 확인할 수 있다.

 

if 문

if문의 기본 모양은 아래와 같다.


if [ 조건 ]
then
명령어1
명령어2
fi
then 이라는 문구로 수행할 명령어가 시작되며 fi로 해당 조건문이 끝남을 알린다. 이때 주의할 점은 [ 조건 ] 사이의 각 단어에는 모두 공백이 있어야 한다. 

if~else문
if [ 조건 ]
then
코드1
else
코드2
fi
코드 1은 조건이 참인 경우만 실행 코드 2는 조건이 거짓일 경우에 실행된다.

 

if문 안에 들어가있는 코드의 경우 해당 조건이 만족 하거나 만족하지 않을때 실행되지만 이외의 코드는 무조건 차례로 실행되기 때문에 어떤 상황에도 "프로그램을 종료합니다." 라는 문구는 출력되는 것을 확인할 수 있다.

 

조건문에 들어가는 비교 연산자

 

정수 비교 연산자

 연산자

의미 

표현 

-eq

같음

if [ $a -eq $b ]

-ne

(같지 않음)

if [ $a -ne $b ]

-gt

(보다 큼)

if [ $a -gt $b ]

-ge

(크거나 같음)

if [ $a -ge $b ]

-lt

(보다 작음)

if [ $a -lt $b ]

-le

(작거나 같음)

if [ $a -le $b ]

>

(보다 큼)

(($a > $b))

>=

(크거나 같음)

(($a >= $b))

<

(보다 작음)

(($a < $b))

<=

(작거나 같음)

(($a <= $b))

[ 문자열 비교 ]

 연산자

의미 

표현

=

(같음) 

if [ "$a" = "$b" ]

==

(같음)

if [ "$a" == "$b" ]

!= 

(같지 않음)

if [ "$a" != "$b" ]

-z

(문자열이 "null"임. 길이가 0)

if [ -z "$a" ]

! -z

(문자열이 "null"이 아님.)

if [ ! -z "$a" ]

-n

(문자열이 "null"이 아님.) 

if [ -n "$a" ]

>

(ASCII값이 보다 큼.)

if [[ "$a" > "$b" ]]

if [ "$a" \> "$b" ]

<

(ASCII값이 보다 작음.)

if [[ "$a" < "$b" ]]

if [ "$a" \< "$b" ]

 

복합 비교 연산자

 연산자

의미 

표현 

-a

(논리 and)

if [ $a -eq 0 -a $b -eq 1 ]

-o

(논리 or)

if [ $a -eq 0 -o $b -eq 1 ]

&&

(논리 and)

if [ $a -eq 0 ] && [ $b -eq 1 ]

if [[ $a -eq 0 && $b -eq 1 ]]

||

(논리 or)

if [ $a -eq 0 ] || [ $b -eq 1 ]

if [[ $a -eq 0 || $b -eq 1 ]]

 

파일 비교 연산자

 연산자

의미 

표현 

-d

Directory

if [ -d FILE ]

-f

File

if [ -f FILE ]

-e

Exist

if [ -e FILE ]

-r

Readable

if [ -r FILE ]

-w

Writable

if [ -w FILE ]

-x

Execuable

if [ -x FILE ]

-s

 

if [ -s FILE ]

-O

Same Owner

if [ -O FILE ]

-G

Same Group

if [ -G FILE ]

-nt

Newer Than

if [ FILE1 -nt FILE2 ]

-ot

Older Than

if [ FILE1 -ot FILE2 ]

 

비교 연산자를 사용할 경우 좀더 다양한 조건을 통해 원하는 코드를 실행할 수 있다.

 

댓글