#90DaysOfDevOps - Automate tasks with bash scripts - Day 19
bash 스크립팅을 이용한 작업 자동화
오늘 사용할 shell은 bash이지만, 내일 ZSH에 대해 다룰 때 다른 shell도 다룰 예정입니다.
BASH - Bourne Again Shell
프로그래밍 언어처럼 shell 스크립팅에도 거의 일주일 동안의 섹션을 쓸 수 있습니다. bash는 다른 자동화 도구와 함께 작업하는 기능을 제공합니다.
여전히 많은 사람들이 복잡한 shell 스크립트를 만들어 무언가를 실행하게 하고, 비즈니스에서 가장 중요한 부분을 이 스크립트에 의존하고 있다고 합니다. 하지만 이런 이유로 shell/bash 스크립팅을 이해해야 한다고 말하는 것은 아닙니다. 자동화 도구와 함께 사용하고 ad-hoc(특별한) 작업을 위해 shell/bash 스크립팅을 배워야 합니다.
이 섹션에서 사용한 예로, 매주 월요일 아침에 리눅스 VM을 새로 생성하고, 해당 리눅스 기계에 필요한 모든 소프트웨어 스택을 추가하는 등의 작업을 할 수 있는 간단한 bash 스크립트로 VAGRANTFILE을 감쌀 수 있습니다.
면접에서 스크립팅 경험 관련 질문이 점점 더 많아지고 있다는 소식도 종종 듣고 있습니다.
시작하기
이 90일 동안 다루는 많은 것들과 마찬가지로, 진정한 배움은 경험을 통해 알게 됩니다. 실제로 경험을 통해 배우면 기억에 오래 남습니다.
우선, 텍스트 에디터가 필요합니다. Day 17에 가장 일반적인 텍스트 에디터 두 가지와 그것들을 어떻게 사용하는지에 대해 다뤘습니다.
첫 번째 shell 스크립트를 생성해봅시다.
touch 90DaysOfDevOps.sh
그다음 nano 90DaysOfDevOps.sh
를 입력하면 nano에서 새로운 빈 shell 스크립트가 열립니다. 여기서 원하는 텍스트 에디터를 선택할 수 있습니다.
모든 bash 스크립트의 첫 줄은 다음과 같아야 합니다: #!/usr/bin/bash
(bash 바이너리의 경로입니다.)
터미널에서 which bash
를 실행하여 이를 확인해야 합니다. Ubuntu를 사용하지 않는 경우 터미널에서는 whereis bash
도 시도해 볼 수 있습니다.
그러나 이미 생성된 shell 스크립트는 다른 경로들이 있을 수도 있습니다:
#!/bin/bash
#!/usr/bin/env bash
스크립트의 다음 줄에는 주석을 추가하여 스크립트의 목적이나 스크립트에 대한 정보를 제공합니다. #
을 사용하면 코드의 특정 줄에 주석을 달고 다가올 명령어가 무엇을 할 것인지 설명할 수 있습니다. 주석을 많이 남길수록 사용자 경험이 향상된다고 생각합니다. 특히 공유할 때 그렇습니다.
리눅스 섹션에서 설치한 figlet 프로그램을 사용하여 스크립트에서 asci 아트를 만들 때도 있습니다.
이 리눅스 섹션에서 앞서 다룬 모든 명령어들(Day 15)은 스크립트를 테스트하는 간단한 명령어로 사용할 수 있습니다.
스크립트에 간단한 코드 블록을 추가해 봅시다.
텍스트 에디터를 저장하고 종료한 후, ./90DaysOfDevOps.sh
를 실행하면 권한이 거부되었다는 메시지가 표시됩니다. ls -al
명령을 사용하여 이 파일의 권한을 확인할 수 있는데 이 파일에 실행 권한이 없음을 확인할 수 있습니다.
chmod +x 90DaysOfDevOps.sh
를 사용하여 이를 변경한 다음 x
인 것을 봤을 때 스크립트를 실행할 수 있음을 확인할 수 있습니다.
./90DaysOfDevOps.sh
를 사용하여 스크립트를 다시 실행할 수 있습니다. 스크립트를 실행한 후 새 디렉토리가 생성되고 해당 디렉토리로 이동한 다음 새 파일이 생성됩니다.
기본적인 것들이지만, 다른 도구를 호출하여 일상적인 작업을 쉽게 만들고 자동화하는 데 사용할 수 있다는 것을 알 수 있습니다.
변수, 조건문
이 섹션의 대부분은 Golang을 배울 때 다룬 것과 중복되지만, 여기에서 다시 살펴볼 가치가 있다고 생각합니다.
-
변수
변수를 사용하면 스크립트 내에서 반복되는 특정 용어를 한 번만 정의할 수 있습니다.
스크립트에 변수를 추가하려면 다음과 같이 새로운 줄에 입력하면 됩니다.
challenge="90DaysOfDevOps"
이렇게 하면 코드에서 $challenge
를 사용할 때 변수가 변경되면 전체에 반영됩니다.
이제 sh
스크립트를 실행하면 스크립트에 추가된 출력이 표시됩니다.
또한 다음과 같이 사용자 입력을 요청하여 변수를 설정할 수도 있습니다:
이렇게 하면 입력이 변수 $name
으로 정의됩니다. 이후에 이를 사용할 수 있습니다.
-
조건문
우리는 도전 과제에 참여한 사람과 그들이 완료한 날짜 수를 알아보고 싶을 수도 있습니다. 이를 if
, if-else
, else-if
조건문을 사용해 정의할 수 있습니다. 아래 스크립트에 이를 정의한 것을 확인할 수 있습니다.
#!/bin/bash
# ___ ___ ____ ___ __ ____ ___
# / _ \ / _ \| _ \ __ _ _ _ ___ / _ \ / _| _ \ _____ __/ _ \ _ __ ___
#| (_) | | | | | | |/ _` | | | / __| | | | |_| | | |/ _ \ \ / / | | | '_ \/ __|
# \__, | |_| | |_| | (_| | |_| \__ \ |_| | _| |_| | __/\ V /| |_| | |_) \__ \
# /_/ \___/|____/ \__,_|\__, |___/\___/|_| |____/ \___| \_/ \___/| .__/|___/
# |___/ |_|
#
# 이 스크립트는 bash 스크립팅을 시연하기 위한 것입니다!
# 정의할 변수
ChallengeName=#90DaysOfDevOps
TotalDays=90
# 사용자 입력
echo "Enter Your Name"
read name
echo "Welcome $name to $ChallengeName"
echo "How Many Days of the $ChallengeName challenge have you completed?"
read DaysCompleted
if [ $DaysCompleted -eq 90 ]
then
echo "You have finished, well done"
elif [ $DaysCompleted -lt 90 ]
then
echo "Keep going you are doing great"
else
echo "You have entered the wrong amount of days"
fi
다음 단계로 이동하기 위해 값을 비교하거나 확인하는 과정을 위에서 볼 수 있습니다. 여기서 주목할 만한 다양한 옵션이 있습니다.
eq
- 두 값이 같으면 TRUE 반환ne
- 두 값이 같지 않으면 TRUE 반환gt
- 첫 번째 값이 두 번째 값보다 크면 TRUE 반환ge
- 첫 번째 값이 두 번째 값보다 크거나 같으면 TRUE 반환lt
- 첫 번째 값이 두 번째 값보다 작으면 TRUE 반환le
- 첫 번째 값이 두 번째 값보다 작거나 같으면 TRUE 반환
파일 및 폴더에 대한 정보를 결정하기 위해 bash 스크립팅을 사용할 수도 있습니다. 이를 파일 조건이라고 합니다.
-d file
파일이 디렉토리인 경우 True-e file
파일이 존재하는 경우 True-f file
제공된 문자열이 파일인 경우 True-g file
파일에 그룹 ID가 설정된 경우 True-r file
파일이 읽을 수 있는 경우 True-s file
파일의 크기가 0이 아닌 경우 True
FILE="90DaysOfDevOps.txt"
if [ -f "$FILE" ]
then
echo "$FILE is a file"
else
echo "$FILE is not a file"
fi
디렉토리에 파일이 아직 있다면 첫 번째 echo를 반환해야 합니다. 그러나 파일을 제거하면 두 번째 echo를 반환하게 됩니다.
특정 항목을 시스템에서 검색할 때 시간을 절약하는 데 사용할 수 있는 방법을 확인하실 수 있습니다.
GitHub에서 놀라운 저장소를 발견했습니다. 많은 스크립트를 가진 것 같습니다. DevOps Bash Tools
예제
시나리오: 우리 회사는 "90DaysOfDevOps"라는 이름을 가지고 있으며, 이제 확장할 때가 왔습니다. 1인 팀에서 다음 몇 주 동안 더 많은 사람으로 늘리려고 합니다. 지금까지 나만이 온보딩 과정을 알고 있으므로, 이러한 작업 중 일부를 자동화하여 병목 현상을 줄이고자 합니다.
요구 사항:
- 사용자 이름이 커맨드 라인 인수로 전달될 수 있습니다.
- 커맨드 라인 인수의 이름으로 사용자가 생성됩니다.
- password가 커맨드 라인 인수로 전달될 수 있습니다.
- 사용자의 password가 설정됩니다.
- 계정 생성이 성공적으로 이루어졌음을 나타내는 메시지가 표시됩니다.
먼저 touch create_user.sh
를 사용하여 shell 스크립트를 생성합시다.
계속 진행하기 전에, chmod +x create_user.sh
를 사용하여 이를 실행 가능하게 만들어줍시다.
그런 다음 nano create_user.sh
를 사용하여 설정한 시나리오에 대한 스크립트 편집을 시작하겠습니다.
첫 번째 요구 사항인 "사용자 이름이 커맨드 라인 인수로 전달될 수 있습니다."는 다음과 같이 사용할 수 있습니다.
이를 실행하려면 ./create_user.sh Michael
을 사용하십시오. Michael 대신에 당신의 이름을 사용하세요.
다음으로 두 번째 요구 사항인 "커맨드 라인 인수의 이름으로 사용자가 생성됩니다."를 처리할 수 있습니다. 이는 useradd
명령어를 사용하여 수행할 수 있습니다. -m
옵션은 사용자 홈 디렉토리를 /home/username으로 생성하기 위한 것입니다.
#! /usr/bin/bash
# 사용자 이름이 커맨드 라인 인수로 전달될 수 있습니다.
echo "$1 user account being created."
# 커맨드 라인 인수의 이름으로 사용자가 생성됩니다.
sudo useradd -m "$1"
경고: 사용자 계정 이름을 제공하지 않으면 $1
변수가 채워지지 않아 오류가 발생합니다.
계정이 생성되었는지 확인하려면 awk -F: '{ print $1}' /etc/passwd
명령을 사용합니다.
다음 요구 사항은 "password가 커맨드 라인 인수로 전달될 수 있습니다."입니다. 먼저, 이는 실제 환경에서는 절대 사용하지 않는 것이 좋습니다. 이는 단지 연습을 위한 것이며, 이를 통해 요구 사항을 이해할 수 있습니다.
#! /usr/bin/bash
# 사용자 이름이 커맨드 라인 인수로 전달될 수 있습니다.
echo "$1 user account being created."
# 커맨드 라인 인수의 이름으로 사용자가 생성됩니다.
sudo useradd -m "$1"
# password가 커맨드 라인 인수로 전달될 수 있습니다.
sudo chpasswd <<< "$1":"$2"
두 개의 파라미터로 이 스크립트를 실행하려면 ./create_user.sh 90DaysOfDevOps password
를 사용하세요.
아래 이미지에서 스크립트를 실행하여 사용자와 password를 생성한 다음, 수동으로 해당 사용자로 전환하고 whoami
명령으로 확인했다는 것을 알 수 있습니다.
마지막 요구 사항은 "계정 생성이 성공적으로 이루어졌음을 나타내는 메시지가 표시됩니다."입니다. 우리는 이미 코드의 첫 번째 줄에 이를 포함하고 있으며, 위의 스크린샷에서 90DaysOfDevOps user account being created
라는 메시지가 표시되는 것을 볼 수 있습니다. 이는 $1
매개변수로 테스트할 때 남겨진 것입니다.
이제 이 스크립트를 사용하여 리눅스 시스템에 새 사용자를 빠르게 온보딩하고 설정할 수 있습니다. 하지만 기존 사용자 중 몇 명이 이 과정을 거쳐 다른 사람들에게 새 사용자 이름이나 password를 알려주는 대신 앞서 다룬 사용자 입력을 추가하여 변수를 수집할 수 있습니다.
#! /usr/bin/bash
echo "What is your intended username?"
read username
echo "What is your password"
read password
# 사용자 이름이 커맨드 라인 인수로 전달될 수 있습니다.
echo "$username user account being created."
# 커맨드 라인 인수의 이름으로 사용자가 생성됩니다.
sudo useradd -m $username
# password가 커맨드 라인 인수로 전달될 수 있습니다.
sudo chpasswd <<< $username:$password
단계를 더욱 인터랙티브하게 만들면
마무리하기 위해, 새 사용자 계정이 생성되었다는 성공적인 출력을 원할 수도 있습니다.
한 가지 눈에 띄는 점은 입력 시 비밀번호가 표시된다는 점인데, 코드 read -s password
에서의 -s
플래그를 사용하여 이를 숨길 수 있습니다.
실험 목적으로 생성한 사용자를 삭제하려면 sudo userdel test_user
를 사용할 수 있습니다.
한 번 더 강조하고 싶은 바는, 이것은 shell 스크립팅이 유연하게 활용될 수 있는 다양한 용도를 갖는다는 것을 강조하기 위해 만들어진 것이라는 것입니다.
매일, 매주, 매월 반복되는 작업이 어떤 것이 있는지 생각해보고, 그것을 어떻게 더 잘 자동화할 수 있을지 생각해보세요. 첫 번째 옵션은 주로 bash 스크립트를 사용하는 것이며, 그 이후에는 더 복잡한 영역으로 이동할 수 있습니다.
저는 제 로컬 머신에서 minikube를 사용하여 쿠버네티스 클러스터를 빠르게 생성하고 데이터 서비스 및 Kasten K10을 사용하여 데이터 관리에 대한 요구 사항과 필요성을 보여주기 위한 매우 간단한 bash 파일을 생성했습니다만, 아직 쿠버네티스를 다루지 않았기 때문에 여기서 다루는 것이 적절하지 않다고 생각합니다.
자료
- Bash in 100 seconds
- Bash script with practical examples - Full Course
- Client SSH GUI - Remmina
- The Beginner's guide to SSH
- Vim in 100 Seconds
- Vim tutorial
- Learn the Linux Fundamentals - Part 1
- Linux for hackers (don't worry you don't need to be a hacker!)
Day 20에서 봐요!