1. 로그로테이션

1) 개념

- 리눅스 시스템에서 로그 파일을 관리하고 유지하는 프로세스

- 로그 파일은 시간이 지남에 따라 매우 커질 수 있기 때문에 로그파일을 주기적으로 교체해줄 필요가 있다.

 

2) 로그로테이션

① 로그 파일 설정

② 로그로테이션 설정

③ logrotate 설정 파일 작성

④ 로그로테이션 주기 설정

⑤ 로그 파일 압축 및 백업

⑥ 새로운 빈 로그 파일 생성

⑦ 로그 파일 삭제

 

☆ 로그로테이션은 시스템 관리에서 중요한 작업 중 하나이며 로그 파일의 크기를 관리하고 시스템 성능을 최적화하는 데 도움이 된다.

 

 

2. logrotate 패키지를 사용해 상세한 로그 파일 관리방침 설정하기

1) 패키지 설치

$ sudo apt-get install logrotate

 

2) logrotate 서비스 동작 원리

$ cat /etc/cron.daily/logrotate

logrotate 설치 시 cron에서 매일 자정에 수행하는 작업을 모아두는 /etc/cron.daily 경로 아래에 logrotate 파일이 생성된다.

즉, logrotate는 cron 서비스에 의해 daily job으로 실행되고, 매일 자정에 rotate 조건을 검사하고 실행한다.

 

3) logrotate.conf에 등록된 기본 경로에 스크립트 등록

$ cat /etc/logrotate.conf

logrotate.conf에서 rotate 스크립트를 등록할 기본 경로 확인

위와 같이 /etc/logrotate.d 경로에 등록된 스크립트를 감지하도록 되어 있다.

include </your/additional/logrotate/path> 구문으로 기본 경로로 삼을 디렉토리를 추가할 수 있다.

→ 기본 경로에 등록된 rotate 스크립트는 매일 자정에 조건 검사 및 수행

 

4) logrotate 설정 파일 예시

# 로그 파일을 저장할 경로 및 설정 시작
/var/log/syslog {
    rotate 7                          # 최대 7개의 백업 파일을 유지합니다.
    size 30                           # 30k 초과시 순환합니다.
    daily                             # 매일 로그를 로테이션합니다.
    create 0600 root root             # rotation된 로그파일 생성
    missingok                         # 로그 파일이 없는 경우 경고 없이 진행합니다.
    notifempty                        # 로그 파일이 비어 있는 경우 로테이션을 스킵합니다.
    delaycompress                     # 이전 로그 파일을 압축하기 전에 1회 로그를 더 남깁니다.
    compress                          # 이전 로그 파일을 압축합니다.
    postrotate                        # 로테이션 후에 실행할 스크립트의 시작입니다.
    /usr/bin/killall -HUP syslog-ng   # syslog-ng 프로세스에 HUP 신호를 보냅니다.
    endscript                         # postrotate 스크립트의 끝입니다.
}
# 로그 파일 경로 및 설정 끝

/var/log/syslog 파일을 매일 로그로테이션하며, 최대 7개의 백업 파일을 유지한다.

missingok, notifempty, delaycompress, compress는 다양한 옵션을 설정하는 데 사용되고, postrotate와 endscript 사이의 부분은 로그로테이션 이후에 실행할 스크립트를 지정한다.

 

 

3. 일 단위보다 더 자주 logrotate를 실행하는 방법

임의의 커스텀 경로에 logrotate 스크립트를 등록하고 crontab에 등록해서 실행

→ cronjob의 실행 주기인 1분마다 rotate 수행 가능

# cron 주기에 따라 logrotate -vf <로테이트 파일명> 으로 커스텀 파일을 강제로 즉시 실행
*/10 * * * * deploy /usr/sbin/logrotate -s /home/username/logrotate/status -vf /your/custom/logrotate/file/path >> /your/custom/logrotate/path/logrotate_exec_log.log 2>&1

위와 같이 -s 옵션을 통해 logrotate 수행 status를 관리하는 파일 경로를 수동으로 지정해야 한다.

 

 

4. 실습하기

- 로그로테이트 : 기존의 로그 파일을 썰어주는 역할

- 먼저, 원본 로그파일이 저장된 경로를 적고 { }를 추가로 적어주어야 함

- su 유저명 그룹명 형식으로 하나 더 적어주어야 함

<log file> { 
    # 주기
     [daily, weekly, monthly, yearly <cycle of rotates>]
    # 로테이트 횟수
     [rotate <number of rotates>]
    # 로테이트 실행 후 비어있는 로그 파일 생성
     [create <permission value> <owner> <own group>]
    # 로그 파일 크기가 설정 값 보다 크고 지정한 주기가 됐을때 로테이트 수행
     [minsize <1M, 100k>]
    # 로그 파일 크기가 설정 값 보다 크거나 지정한 주기가 지났을때 로테이트 수행
    [maxsize <1M, 100k>]
    # 주기에 관계 없이 로테이트를 수행하는 로그 파일 크기
    [size <1M, 100k>]
    # 로테이트를 통해 새로 생성되는 파일에 날짜를 덧붙혀서 생성하는지 여부
     [dateext]
    # 로테이트를 통해 생성되는 파일을 압축하는지 여부
     [compress]
    # 설정을 참고할 로그로테이트 파일 위치
     [include /etc/logrotate.d]
    # 로그 파일이 존재하지 않는 경우 메시지 출력 (기본 값)
     [nomissingok]
    # 로그 파일이 존재하지 않아도 오류로 처리하지 않음
     [missingok]
    # 로테이트 시 기존 로그 파일 복사 후 제거 후 빈 파일로 생성
     [copytruncate]
    # 로그 썰기 전후 처리작업 
		 [prerotate]
				# prerotate 로직 작성
		 [endscript]
		 [postrotate]
				# postrotate 로직 작성
		 [endscript]
}

※ 위와 같이 다양한 옵션이 있다.

이제 위 두 파일을 생성해준다.

rotate_result.log는 로그로테이트 시 pre, post script에 의해 콘솔에 찍힐 값을 담을 파일이다.

logrotate_status는 프로세스 상태를 저장해주는  파일로 데몬에 의해 관리하지 않는 경우 필요하다.

# 로그로테이트를 logrotate 데몬 프로세스가 관리하는 기본 경로가 아닌 곳에서 실행할 경우
# s 옵션으로 프로세스 스테이터스 경로를 별도로 지정해야 함
# f 옵션은 rotate 강제 실행, -v 옵션은 verbose 로 실행 내용을 콘솔에 출력

/usr/sbin/logrotate -s /home/username/logrotate/status -vf /your/logrotate/file/path > /your/rotate/job/checking/file.log 2>&1

실행해보면 위와 같이 lock이 걸려 있어서 로그로테이트를 할 수 없다고 나온다. 

이를 해결하기 위해서 추가적인 조작이 필요하다.

logrotate_status 파일의 권한을 600으로 만들어 현재 로그인 중인 유저만 참조할 수 있게 해야 한다.

위와 같이 로그를 썰어주는 것을 확인할 수 있고, 원래 로그 파일 뒤에 .1이라는 확장자가 붙는다.

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

로깅 실습  (0) 2024.02.22
jshell을 활용해서 어플리케이션 로깅 체험하기  (0) 2024.02.22
크론탭 메일전송  (0) 2024.02.21
크론잡과 크론탭  (0) 2024.02.21
Shell Script 실습  (0) 2024.02.20
  • 로그를 수납하는 서버를 따로 두겠습니다. 인스턴스 두 개를 더 만들어주세요.
  • 하나는 수납용 서버, 이제 우리가 수업에 활용한 서버 + 방금 생성한 서버가 로그를 발송하는 서버가 됩니다.
  • 양 서버에서 크론탭에서 어플리케이션 및 서버 자원에 대해 주기적으로 로그를 찍어주는 크론잡을 등록해주세요.
  • 예를들어 로그를 분마다 찍는다면 n시간에 1번 그간 쌓인 로그파일의 이름을 전송하는 시점.log로 변경한 다음, 로그 수납 서버로 전송하고, 원본 서버에 있던 로그는 지우는 크론잡을 작성해주세요. 이 때, 발송서버가 2개이므로, 각 발송된 로그파일은 어떤 서버에서 발송했는지 확인할 수 있도록 해 주세요.
  • 위 과정을 완성하셨다면 해당 작업에 대해 노션이나 블로그 포스팅을 남겨주세요.
  • 위 과정이 완료되었다면 어떤 도메인의 인프라를 활용할지도 설계하고 운영 시나리오를 작성해주세요.

네트워크 설정

$ docker network 대역폭 설정

$ docker run 할 때 고정ip 지정해서 실행하기

먼저, 위와 같이 172.30 대역을 사용하는 lognet이라는 네트워크 

로그 파일을 수집해주는 savelog와 서버 자원을 주기적으로 찍어주는 로그 파일을 전송할 서버 2개를 생성해주었다.

# apt-get update
# apt-get install iputils-ping
# apt-get install net-tools

같은 내부망 안에서 서로 통신이 되고 있는 것을 확인할 수 있다.

# service ssh start
# apt-get install openssh-server

전송하고받을 컨테이너에서 netstat -ntl로 확인해보면 위와 같이 ssh (22번) 포트가 잘 열려있는 것을 볼 수 있다.

위와 같이 scp 명령어로 파일을 전송할 수 있고, Permission Denied 오류가 뜨는 경우 파일이나 경로의 권한 설정이 제대로 되어있는지 확인해야 한다.

 

서버 설정 

$ docker run -it --net=네트워크명 --name=서버명 ubuntu:22.04 bash

# apt-get update

# apt-get install cron

# apt-get install file

# apt-get install nano 

# apt-get install sudo

# adduser 유저명

# service cron start

위와 같이 job1 컨테이너에서 memlog.sh 파일을 수정한 후 실행하면 전송받을 컨테이너의 비밀번호를 입력하라는 문구가 나오고, 비밀번호 확인이 되면 파일이 전송된다.

savelog 컨테이너로 가서 확인해보면 파일이 잘 받아진 것을 볼 수 있고, 명령어가 수행된 내용도 잘 저장된 것을 확인할 수 있다.

 

쉘스크립트 작성

① job1.mem.sh

먼저, 저장할 로그파일의 경로를 설정해주는 log_file 변수를 만들었다.

또한, free 명령어를 이용하여 메모리 사용량을 가져오고, 로그 파일에 기록하는 스크립트를 작성했다.

 

② job1-send.sh

log_file : 메모리 사용량이 저장되는 로그파일의 절대 경로

remote_server : 전송할 savelog 서버의 주소와 파일을 저장할 경로

current_time : 현재시간

remote_file : 전송하는 시점의 시간으로 로그파일명 변경

해당 로그 파일이 어떤 서버에서 보내는 것인지 구분하기 위해 sed 명령어를 이용하여 파일의 첫 번째 줄에 위와 같은 문구를 추가했다. -i 옵션은 파일을 직접 수정하라는 의미이다. 1s(파일의 첫(s) 줄의 시작(^)에 /내용\울 추가하라는 의미이다.

scp 명령어를 이용하여 해당 파일을 복사하여 이동시킨 후 rm 명령어로 삭제한다.

실행권한을 준 후 실행시켜보면 위와 같이 잘 전송되는 것을 확인할 수 있다.

savelog 서버에서 확인해보면 위와 같이 잘 이동된 것을 확인할 수 있다.

 

 

크론탭 등록

크론탭에는 위와 같이 등록할 수 있다.

job1-mem.sh는 1분마다 실행되어 메모리 사용량을 1분마다 로그파일에 찍어준다.

job1-send.sh는 1시간(매시간 정각)마다 실행되어 전송 시점의 시간을 파일명으로 하는 로그파일을 savelog 서버에 보내주고 해당 파일을 삭제하게 된다.

위와 같이 job1-mem.sh 스크립트로 인해 생성된 job1-mem.log 파일을 확인해보면 1분마다 메모리 사용량이 저장되고 있는 것을 확인할 수 있다.

 

 

※ 리눅스 로깅은 보통 서버 자원이나 프로세스의 개수 등을 감시하다가 개수가 튀거나 자원이 부족해지는 상황을 모니터링하는 것이 일반적이다. 자원 관련이 아니라면 어플리케이션을 리눅스 위에서 돌리다 해당 어플리케이션이 뱉어내는 오류를 로깅하는 것이 1차적인 목적이다.

오류와 오류가 아닌 메시지를 모두 뱉어내는 자바 어플리케이션을 간단하게 만들고, 웹어플리케이션을 얹는 상황의 로깅 방법을 확인한다.

 

1. 리눅스에 자바 설치

$ sudo apt-get install openjdk-17-jdk  # 자바 설치
$ java -version                        # 자바 버전 확인
$ nano run_on_shell_j                  # 자바 프로그램 작성

먼저, 위 명령어로 리눅스에 자바를 설치한 후 run_on_shell_j라는 파일에 아래와 같은 코드를 작성했다.

loglog를 출력해주는 클래스 파일을 만들었고, 해당 파일을 실행해보면 위와 같이 잘 출력되는 것을 확인할 수 있다.

위 구문은 일반구문이므로 로그파일에 기록 시 그냥 기록된다. 

 

 

2. 어플리케이션에서 남겨준 에러로그를 리눅스에서 받아서 처리하기

 

1) 자바스크립트 기준

- 일반 로그 : console.log()

- 에러 로그 : console.err()

 

2) 자바 기준

- 일반 로그 : System.out.println() 혹은 log.info()

- 에러 로그 : System.err.println() 혹은 log.error()

 

위와 같이 코드 수정 후 catlogerr.log를 찍어보면 일반 로그인 loglog만 출력되는 것을 확인할 수 있다.

앞에서 배웠듯 유형 1, 유형 2로 분류되기 때문에 System.err.println()의 내역은 저장되지 않는 것이다.

이처럼 2>&1을 이용하여 저장하면 errerr도 문제없이 출력되는 것을 확인할 수 있다.

 

 

3. 로깅이 제대로 되고 있는지 좀 더 쉽게 확인하기

※ 해당 로깅 내역이 제대로 돌아가는지를 체크하기 위해 실제 현업에서는 크론탭을 2개씩 작성한다.

- 실행여부만 체크해주는 크론탭

- 실제 어플리케이션을 실행해주는 크론탭

 

💡 실습하기

더보기

1. 어플리케이션 호출 + 로깅 로직을 크론탭에 등록해서 주기적으로 어플리케이션 체크를 하게 해 주세요

2. 해당 크론탭이 돌았는지를 검증하는 크론잡도 같이 등록해주세요

 

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

로그로테이트를 통한 로그파일 관리  (0) 2024.02.23
로깅 실습  (0) 2024.02.22
크론탭 메일전송  (0) 2024.02.21
크론잡과 크론탭  (0) 2024.02.21
Shell Script 실습  (0) 2024.02.20

루트계정에서 진행

apt-get install mailutils

Configuration : Internet Site

System mail name 

 

mail 명령의 대표적인 옵션

-s : 메일 제목

-r : 발신자 주소

-c : 참조 목록

-b : 숨은 차모

-a : 첨부 파일

크론탭에 위와 같이 등록해주면 30분마다 메일이 발송된다.

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

로깅 실습  (0) 2024.02.22
jshell을 활용해서 어플리케이션 로깅 체험하기  (0) 2024.02.22
크론잡과 크론탭  (0) 2024.02.21
Shell Script 실습  (0) 2024.02.20
Shell Script  (0) 2024.01.17

1. 크론잡과 크론탭이란?

- 리눅스 시스템에서 crontab을 사용하여 작업을 예약할 수 있다.

- crontab : 시스템에 주기적으로 실행되는 작업을 설정하는 데 사용되는 유닉스 기반의 시간 기반 작업 스케줄러

- 일반적으로 스크립트, 명령 또는 프로그램을 지정된 시간에 실행하도록 예약하는 데 사용

 

루트 계정에서 다음 명령을 이용하여 환경설정을 진행한다.

# apt-get install cron
# apt-get install sudo

 

crontab -e 를 해주면 위와 같이 크론탭 파일이 열리고, 해당 파일을 수정하여 스케줄링화된 작업을 등록할 수 있다.

또한, crontab -l로 크론잡 목록을 조회할 수 있다. 아직 등록된 것이 없기 때문에 위와 같이 출력된다.

# sudo service cron start
# sudo systemctl start cron

위 명령어를 이용하여 최초에는 크론 데몬을 실행해줘야 한다.

 

 

2. 잡 등록해보기

* * * * * command_to_execute

- 분(0~59), 시간(0~23), 일(1~31), 월(1~12), 요일(0-7, 0과 7은 일요일을 나타냄) ex) 0 3 * * * 은 매일 새벽 3시를 의미

- 해당 별표 지점에 */주기를 적어도 된다. ex) */10 * * * * 코드 : 10분마다

>>는 append의 의미를 가지기에 매 분마다 date의 결과를 화면에 찍어줄 것이다.

※ 로깅 등을 할 때 명령어나 실행구문은 되도록 절대경로로 작성하는 것이 바람직하다.

이와 같이 cron.log 파일이 생성되고 매 분마다 date 결과를 찍어주는 것을 볼 수 있다.

$ sudo service cron start

크론잡은 기본적으로 아무 조치를 취하지 않아도 자동으로 실행되지만, 실행되지 않는다면 위와 같이 강제로 시작시킬 수도 있다.

 

💡 실습하기

더보기

매 분마다 특정 문장을 로그에 남겨주는 cronjob 등록하기

시간 정보와 특정 문장을 같이 남도록 등록하기

ex) Wed Feb 21 05:02:01 UTC 2024 : hello cronjob!!!

위와 같이 "$()"를 이용하여 한 줄에 출력하도록 하는 것이 가능하다.

위와 같이 cronjob을 등록할 수 있다.

조회해보면 crontest.log가 잘 생성된 것을 볼 수 있고, 앞서 등록한대로 매 분마다 로그가 잘 남겨지는 것을 확인할 수 있다.

 

 

3. 로깅 본격적으로 해 보기

먼저, 위와 같이 error_out.sh 파일을 생성하고 실행 시 에러가 발생할 구문을 작성해주었다.

chmod로 권한을 준 후 실행해보면 j라는 옵션은 없으므로 위와 같이 오류 메시지가 출력된다.

리다이렉션을 이용하여 err.log에 찍은 후 err.log 파일을 cat으로 확인해보면 아무 내용이 출력되지 않는다.

리다이렉션은 추가적인 옵션이 없다면 정상적인 상황에서 발생하는 메세지만 저장해주고, 오류에 의해 발생하는 메세지를 정상적인 상황에서 발생하는 메세지로 변환해주는 옵션을 추가해야 한다.

해당 내용이 2>&1이고, 이 옵션을 추가하여 err.log에 찍고 조회해보면 위와 같이 오류 메시지가 잘 출력되는 것을 볼 수 있다.

1 : 정상적인 상황에서 발생하는 메시지

2 : 오류에 의해 발생하는 메시지 

2>&1 : 2에 해당하는 메시지를 1 유형으로 변환해주는 옵션

이번에는 정상문장 ls -al과 오류유발문장 ls -j를 같이 적어보았다.

실행 권한을 준 후 실행해보면 위와 같이 정상 결과값과 오류 메시지가 출력된다.

2>&1을 포함하지 않고 로그파일을 만든 후 조회해보면 정상 결과만 출력되는것을 확인할 수 있다.

2>&1을 포함하면 오류메시지까지 모두 저장되어 출력되는 것을 확인할 수 있다.

 

💡 실습하기

더보기

1. 아래 양식에 맞춰 주기적으로 시간과 메시지를 남겨주는 로깅을 해 보자

    yyyy-MM-dd hh:mm:ss - 메시지

2. top을 활용하면 현재 pc 자원에 대한 정보가 나온다.

     yyyy-MM-dd hh:mm:ss - %Cpu(s)... 형식으로 매 10초마다 자원량을 기록하는 쉘 스크립트를 만들어 로깅해보자

 

 

4. 시스템에서 주로 사용하는 명령어와 로깅 항목

- uname : 시스템 및 커널정보 확인, -r(커널 릴리즈 정보), -p(프로세스 정보), -a(전부)

- grep : 조회 내용에서 특정 단어가 포함된 줄 조회, -i(대소문자 무시), -v(제외하고 확인), -E(정규표현식)

- sar : cpu, 메모리, 소켓 i/o 등의 정보 확인

 

1) CPU 사용량 로깅

#!/bin/bash

# 현재 CPU 사용량을 top 명령어로 가져와서 로그 파일에 기록
top -b -n1 | grep "Cpu(s)" >> cpu_usage.log

 

2) 메모리 사용량 로깅

#!/bin/bash

# 현재 메모리 사용량을 free 명령어로 가져와서 로그 파일에 기록
free -m | grep "Mem:" >> memory_usage.log

 

3. 디스크 공간 로깅

#!/bin/bash

# 현재 디스크 사용량을 df 명령어로 가져와서 로그 파일에 기록
df -h >> disk_space_usage.log

 

4. 네트워크 트래픽 로깅

#!/bin/bash

# 현재 네트워크 인터페이스의 트래픽을 가져와서 로그 파일에 기록
ifstat -n >> network_traffic.log

 

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

jshell을 활용해서 어플리케이션 로깅 체험하기  (0) 2024.02.22
크론탭 메일전송  (0) 2024.02.21
Shell Script 실습  (0) 2024.02.20
Shell Script  (0) 2024.01.17
Devops와 SE를 위한 리눅스 커널 이야기  (0) 2024.01.17

1. 환경설정

$ docker run -d --name=shellprac ubuntu:22.04
$ docker exec -it shellprac bash

위 명령어를 통해 도커 컨테이너 환경에서 실습을 진행했다.

# apt-get update
# apt-get install file

먼저, 쉘스크립트 내에 작성된 명령어를 확인하기 위해서 file을 설치해준 후 진행한다.

위 명령어로 /usr/bin/* 경로인 모든 파일 중 shell script를 검색하면 위와 같이 쉘스크립트로 작성된 명령어들을 확인할 수 있다.

루트계정으로 명령을 내리지 않기 위해 jihyun 계정을 추가하여 실습을 진행했다.

위와 같이 sandbox 폴더를 생성한 후 실습을 진행했다.

 

※ 쉘 스크립트를 사용하면 좋은 경우

① 중규모 시스템에서 자동화하기

② 성능보다 자동화 자체에 방점을 두기

 

 

2. 일기장 작성 실습

root # apt-get install nano -y
jihyun $ nano diary.sh

루트 계정에서 nano 에디터를 설치한 후 다시 돌아와 diary.sh에 아래와 같은 스크립트를 작성했다.

먼저, ${HOME}/diary라는 경로를 directory 변수에 저장한다. (※ 할당 연산자 사용 시 띄어쓰기 금지)

directory 변수에 적힌 경로에 폴더가 존재하지 않는다면 mkdir 명령으로 폴더를 생성해준다.

nano 에디터를 이용하여 연-월-일.txt 형식으로 당일 서버시간 기준 날짜로 일기 파일을 생성해준다.

위와 같이 실행 권한을 부여한 후 조회해보면 diary.sh가 잘 생성된 것을 확인할 수 있다.

diary.sh를 실행해주면 자동으로 home 폴더 하위에 diary 폴더를 만들고, 만약 없다면 연-월-일.txt라는 파일을 nano 에디터로 실행해준다.

또한, 파일에 위와 같은 문구를 작성해주고 다시 diary.sh를 실행해보면 이미 diary 폴더가 존재하므로 새로 만들지는 않고, 아까 작성 완료한 내용이 기입된 채로 파일이 열리는 것을 확인할 수 있다.

 

일기장 쉘스크립트를 개선하기 위해 diary.sh 코드를 아래와 같이 수정했다.

먼저, directory 폴더 하위에 diaryfile이라는 명칭으로 연-월-일.txt를 저장하는 변수명을 하나 더 만들어주었따.

diaryfile이 존재하지 않는다면 > 기호를 이용하여 해당 파일을 만들되 연월일을 집어넣은 채로 파일을 생성한 후 열어준다.

기존의 일기장 파일을 삭제한 후 다시 실행해보면 위와 같이 날짜가 적힌 채로 열리는 것을 확인할 수 있다.

 

 

3. 재귀호출을 이용한 폴더 내부 조회하기

 

먼저, nano를 이용하여 tree.sh 파일을 생성하고 아래와 같은 코드를 작성한다.

list_recursive() 함수는 파라미터를 하나 받아서 filepath라는 지역변수에 저장을 하고, 해당 filepath 변수에 든 값을 echo로 화면에 출력한다.

if문을 이용해 해당 파일경로가 존재한다면 file 경로에 존재한다는 메세지를 echo로 날리고 종료한다.

파라미터로 받은 파일이나 경로가 존재하지 않는 경우는 아무 일도 하지 않고, 존재한다면 존재한다는 확인 후에 종료된다.

위와 같이 실행 권한을 준 후 실행해보면 홈 디렉토리 경로는 존재하므로 존재한다는 문구가 출력되고, sandbo라는 경로는 존재하지 않으므로 아무 일도 하지 않는 것을 확인할 수 있다.

 

 

4. 재귀호출 자기자신 호출하기

단순히 해당 경로가 존재하는 것 뿐만 아니라 폴더와 같이 트리형으로 작성된 계층을 순회하도록 하기 위해 아래와 같이 코드를 수정했다.

특정 경로를 받아서 존재한다면 ls를 이용하여 해당 폴더경로 내부의 파일을 fname이라는 반복문 변수에 대입하여 해당 폴더 내부의 fname을 하나하나 출력해준다.

이렇게 하여 특정 경로 하위에 있는 파일들을 모두 출력할 수 있다.

저장 후 실행해보면 위와 같이 홈 디렉토리에 존재하는 파일명들을 출력해주는 것을 확인할 수 있다.

하위 경로를 모두 훑고 다니면서 최종적인 결과를 얻어내기 위해 위와 같이 코드를 수정했다.

특정한 파일경로 존재 시 해당 파일경로를 토대로 다시 list_recursive를 호출한다.

재귀호출을 통해 fname의 하위경로를 호출하지만, -d 옵션이 첫 if문에 걸려 있으므로 폴더가 아니면 따로 추가 재귀가 돌지 않는다.

즉, 폴더인 경우만 재귀호출, 아닌 경우는 파일만 조회해주고 탈출하는 구문이다.

위와 같이 현재 경로 하위에 있는 모든 폴더 및 파일을 다 순회하며 조회하는 것을 확인할 수 있다.

 

 

5. 순회 시 들여쓰기로 계층 표시

들여쓰기를 통해 더욱 가독성 높은 조회를 하기 위해 코드를 아래와 같이 수정했다.

위와 같이 들여쓰기 변수 indent를 생성한다.

처음에는 ""와 같은 빈 문자열을 받지만 내부적으로는 들여쓰기가 들어가도록 파라미터를 전달시킬 수 있다.

filepath##*/은 전방 최장 매치로 패턴에 일치하는 부분을 제거한다. 즉, */에 해당하는 상위 폴더를 나타내는 / 문자를 제거하는 역할을 한다.

실행해보면 위와 같이 들여쓰기가 들어간 채로 잘 출력되는 것을 확인할 수 있다.

 

 

6. 이름에 띄어쓰기가 들어간 파일 추가 처리

현재 작성 구문은 띄어쓰기가 되면 하나의 파일명으로 인식하지 않고, 위와 같이 띄어쓰기 갯수만큼 쪼개진 파일명으로 인식한다.

이는 ls 명령이 띄어쓰기를 파일 구분자로 삼고 있기 때문이다.

내부 필드를 구분할 수 있도록 IFS라는 환경 변수를 조작하여 공백을 내부 문자 구분 기준에서 없애버리는 방식으로 해결할 수 이싿.

위와 같이 IFS에 줄바꿈을 등록하면 더 이상 띄어쓰기를 구분자로 삼지 않는다.

다만, IFS를 바꿔둔 채로 두면 다음 로직에 영향을 줄 수 있기 때문에 모든 호출이 끝나면 IFS 값을 원래 값으로 돌려놓는 조치가 필요하다. 

위와 같이 공백도 구분자가 아닌 하나의 파일로 인식되는 것을 확인할 수 있다.

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

크론탭 메일전송  (0) 2024.02.21
크론잡과 크론탭  (0) 2024.02.21
Shell Script  (0) 2024.01.17
Devops와 SE를 위한 리눅스 커널 이야기  (0) 2024.01.17
프로세스  (0) 2024.01.16

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

1. 시스템 구성정보 확인하기

uname 커널 버전 관련 정보 조회
dmesg 디버깅 메세지 체크
dmidecode bios, system, processor
dmidecode memory
df 디스크 파티션 타입 정보 조회
smartctl 디스크의 물리적 정보 조회
lspci 네트워크 정보 조회
ethtool 네트워크 카드의 세팅 정보 조회

 

 

2. top 명령어를 통해 프로세스 정보 조회하기

1) top 명령어

- top : 시스템 정보 확인 가능

- 구동된 시간, 로그인된 사용자 숫자, 실행 중인 프로세스의 개수, cpu, memory, swap 메모리의 사용량

- 우선순위, 조정 우선순위, 가상배정 메모리, 실제배정 메모리, 공통사용영역 등

 

2) VIRT, RES, SHR

- VIRT : VIRT + RES + SHR를 모두 포함한 영역, 각 Task에 할당된 메모리 전체

- RES : 할당된 메모리 중 실제로 사용되고 있는 물리 메모리의 양

- SHR : 다른 프로세스와 공유 중인 메모리의 양

 

 

3. 가상 메모리 배정과 memory commit

1) memory  commit : 메모리에 쓰기 작업이 들어가야 진짜 할당이 되도록 하는 것

- 메모리는 동적으로 배정

- 처음부터 할당 시 비효율적 → 최대 배분 상한선만 정해놓고 실제 쓰기 작업 시 진짜 할당 진행

 

2) 가상 메모리 배정의 이유

- fork() 프로세스 콜 : 현재 실행 중인 프로세스와 똑같은 프로세스를 하나 더 할당 → 실질적으로 사용하는 영역만 배정

- COW(Copy On Write) : 복사된 메모리 영역에 실제 쓰기 작업이 발생한 후에 실질적인 메모리 할당 시작

 

 

4. 프로세스의 상태 변화

- SHR의 S 항목 : 프로세스 상태 확인 가능

D 디스크 혹은 네트워크 I/O를 위해 대기하는 프로세스
R 실행 중인 프로세스
S 요청한 리소스를 즉시 사용할 수 있는 상태의 프로세스
T 프로세스의 시스템콜을 추적하고 있는 상태
Z 부모 프로세스가 죽으 자식 프로세스
Zombie 프로세스라고 함

 

 

5. 프로세스의 우선순위

→ PR과 NI 항목을 통해 조절

- NI(Nice value) : 우선순위 → 숫자가 낮을수록 높은 값

- Run Queue : 우선순위별로 프로세스 연결

- Run Queue 상태에서 NI를 호출해 PR을 올리면 호출 우선순위가 올라가 실행될 확률이 높아지는 형식

 

 

6. Load Average

1) Load Average

- R/D 상태인 프로세스의 1, 5, 15분마다의 평균 개수

- 얼마나 많은 프로세스가 실행중이거나 대기중인지 나타내는 수치

- 값이 높을수록 실행/대기중인 프로세스가 많음을 의미

- 하나의 코어에 2개의 프로세스 vs 두 개의 코어에 2개의 프로세스

   → load average값은 같으나 가용자원 측면에서는 다르게 인식

위와 같이 uptime 명령어를 이용하여 load average를 계산할 수 있다.

 

2) CPU Bound vs I/O Bound

→ 부하의 종류에 따라 처리하는 방법론이 달라지기 때문에 구분하는 것이 중요

- CPU Bound : CPU의 자원(ex.연산)을 많이 필요로 하는 프로세스

- I/O Bound : 많은 I/O 자원(ex.디스크 쓰기)을 필요로 하는 프로세스

 

3) vmstat : 부하 원인 확인 (r, b 값이 중요)

- r : 현재 실행되기를 기다리거나 실행되고 있는 프로세스의 개수 → r이 높으면 CPU Bound일 확률이 높음

- b : I/O를 위해 대기열에 있는 프로세스의 개수 → b가 높으면 I/O Bound일 확률이 높음

 

4) Load Average가시스템에 끼치는 영향

Load Average 값이 같다고 해도 실제 시스템에 미치는 영향은 부하의 원인에 따라 달라짐

→ CPU나 I/O 자원에 대한 경합 정도에 따라 실제롤 딜레이되는 시간이 다를 수 있음

 

5) OS 버전과 Load Average

커널 차이로 인해 버그건 아니면 실제로 건 차이가 발생할 수도 있음

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

Shell Script 실습  (0) 2024.02.20
Shell Script  (0) 2024.01.17
프로세스  (0) 2024.01.16
텍스트에디터  (0) 2024.01.15
파일시스템  (0) 2024.01.11

+ Recent posts