파일 & 문자열 비교문
파일 비교문
-d file : 파일이 존재하고 디렉토리인지 검사
-e file : 파일이 존재하는지 검사
-f file : 파일이 존재하고 파일인지 검사
-r file : 파일이 존재하고 읽을 수 있는지 검사
-s file : 파일이 존재하고 비어 있지 않은지 검사
-x file : 파일이 존재하고 실행할 수 있는지 검사
문자열 비교문
-n str : str의 길이가 0보다 큰지 검사
-z str : str의 길이가 0인지 검사
한 줄 스크립트 #1
파일 용량 확인하기
ls -alh /var/log | sort -k 5 -r | awk '{print $9 " - " $5}'
한 줄 스크립트 #2
타 서버의 루트 파티션 용량 체크하기
ssh nfs-client@192.168.219.124 -p 9706 "df -h | grep \"/dev/sda*\""
한 줄 스크립트 #3
ssh 명령 전송
ssh nfs-client@192.168.219.124 -p 9706 "ls -alh /var/log && df -h
한 줄 스크립트 #4
현재 경로에 tmp 디렉토리가 없는 경우 생성 후 , 파일 생성 & 파일 읽기
if [[ ! -d ./tmp ]]; then mkdir ./tmp; fi && touch ./tmp/tmp.txt; echo "tmp" > ./tmp/tmp.txt; cat./tmp/tmp.txt
한 줄 스크립트 #5
서버에서 sshd 프로세스 갯수 확인
$ ssh nfs-client@x.x.x.x -p 9706 'ps -ef | grep sshd* | grep -v grep | wc | awk '{print $1}''
한 줄 스크립트 #6
파일 찾기
if [[ -e /var/log/syslog ]]; then cat /var/log/syslog | tail -n 15; else echo "파일 없음";fi
숫자 맞추기
GOAL=$[ ${RANDOM}% 100+1 ] # OR GOAL=$((${RANDOM}% 100+1))
loop=true
COUNT=1
while [ "${loop}" ];
do
# 입력 기회 20번으로 제한
if [[ ${COUNT} -eq 21 ]]; then
echo "아쉽네요, 다음 기회에 !"
break
fi
read -p "1~100 까지의 숫자를 입력해보세요 (게임 종료 : 'q') : " num
# 사용자가 'q'를 누른 경우
if [[ ${num} = "q" ]]; then
echo "게임이 종료됩니다"
echo""
break
fi
# 입력된 값이 없는경우
if [[ ! ${num} ]]; then
echo "숫자가 입력되지 않았습니다! 다시 입력해주세요"
echo ""
fi
# 지정된 범위를 초과하는 경우
if [[ ${num} -gt 100 ]]; then
echo "숫자가 너무 커요! 다시 입력해주세요 (1 ~ 100)"
echo ""
continue
elif [[ ${num} -lt 0 ]]; then
echo "숫자가 지정된 범위보다 작습니다 (1 ~ 100)"
echo ""
continue
fi
# 숫자가 아닌 값이 입력 되었을 경우
if [[ ${num} =~ [^0-9]$ ]]; then
echo -e "입력된 값이 숫자가 아닙니다!\n입력하신 값 : ${num}"
continue
fi
# 숫자 비교
if [[ ${num} -gt ${GOAL} ]]; then
echo -e "입력 값이 더 커요 ! \n남은 기회 : $((20 - ${COUNT}))"
elif [[ ${num} -lt ${GOAL} ]]; then
echo -e "입력 값이 더 작아요 ! \n남은 기회 : $((20 - ${COUNT}))"
elif [[ ${num} -eq ${GOAL} ]]; then
echo "축하합니다! 총 ${COUNT}번 만에 맞추셨어요!"
break # exit 0 : while / shell 스크립트 종료 코드 ( 성공 )
# exit 1 : ( 실패 )
# echo ${?}
fi
((COUNT+=1)) # ((COUNT=COUNT + 1 )) , $((COUNT+=1)) , $[ COUNT+=1 ]
done
디스크 용량 체크
#!/bin/bash
PER=${1}
if [[ ${#} -ne 1 ]]; then
echo -e "해당 스크립트 사용방법\n${0} [PERCENT ( 1 ~ 100 % )]"
exit 1
fi
if [[ ${PER} -gt 100 ]] || [[ ${PER} -lt 0 ]]; then
echo -e "PERCENT : 1 ~ 100\n다시 입력해주세요"
exit 1
fi
if [[ ${PER} =~ [^0-9] ]]; then
echo -e "DISK PERCENT를 입력해주세요 [ 1 ~ 100 ]"
exit 1
fi
DISK_LISTS=($(df -h | awk '{gsub(/%/,""); print $5}' | grep -vi 'use'))
MNT=($(df -h | awk '{gsub(/%/,""); print $6}' | grep -vi "mounted" ))
for idx in "${!DISK_LISTS[@]}";
do
disk="${DISK_LISTS[${idx}]}"
mount="${MNT[${idx}]}"
if [[ $disk -ge ${PER} ]]; then
echo -e "${disk}\t${mount}\n"
fi
done
확장자 파일 이동
#!/bin/bash
function AUTOMATION_DIR() {
PATH_AFTER="/home/leejaehyo/jobs/IMAGE"
PATH_BEFORE="${1}"
IMAGE_FILE_NAME="$(date +'%Y%m%d')_"
# 디렉토리가 없을 시 해당 디렉토리를 해당 경로에 생성
if [[ ! -d ${PATH_AFTER} ]]; then
mkdir ${PATH_AFTER}
echo "디렉토리 생성이 완료되었습니다"
else
echo "해당 이름을 가진 디렉토리가 이미 존재합니다"
fi
# 정리하고 싶은 파일 리스트 가져오기
FILE_LIST_LENG=($(ls -lh ~/jobs | awk '{print $9}' | wc -l))
for idx in $(seq 0 "${FILE_LIST_LENG}")
do
# 파일 리스트 목록 출력 후 배열로 감싸기 (리스트 )
FILE_LIST=($(ls -lh ~/jobs | awk '{print $9}'))
# '.' 확장자를 기준으로 나누고 그것에 2번째 필드(확장자명)을 뽑아온다.
RESULT="$(echo ${FILE_LIST[${idx}]} | awk -F'.' '{print $2}')"
# 파일 목록에 "IMAGE"나 "programming"가 존재하는 경우 continue 처리
if [[ ${FILE_LIST[${idx}]} = "IMAGE" ]] || [[ ${FILE_LIST[${idx}]} = "programming" ]]; then
continue
fi
# -n : 변수에 담긴 값이 Null(빈 공백 , 또는 빈 데이터를 담고있는 변수 또는 NULL값을 담고 있는 변수)이 아닌 경우
if [[ -n ${RESULT} ]]; then
mv ${PATH_BEFORE}/${FILE_LIST[${idx}]} ${PATH_AFTER}/${IMAGE_FILE_NAME}${FILE_LIST[${idx}]}
else
if [[ -z ${FILE_LIST[${idx}]} ]]; then
echo "존재하지 않는 파일입니다 🤪"
echo
else
echo "${FILE_LIST[${idx}]} :: 이 파일은 확장자가 존재하지 않는 파일이므로 이동시킬 수 없습니다! 🤪"
echo
fi
fi
done
echo "파일 이동이 끝났습니다 🤟"
}
if [[ ! ${#} -ne 1 ]]; then
AUTOMATION_DIR ${1} # 정리하고싶은 경로 적기
else
echo
echo -e "스크립트 사용방법이 잘못되었습니다\n\n사용방법 :: ${0} [정리하고 싶은 디렉토리 경로]"
exit 1
fi
DB 로그 정리
#!/usr/bin/bash
LOGDIR="/var/log/mysql"
GZIPDAY=1
DELDAY=2
/usr/bin/find "${LOGDIR}" -type f -iname "*.log" -mtime +${GZIPDAY} -exec bash -c "gzip {}" \; 2>&1
/usr/bin/find "${LOGDIR}" -type f -iname "*.gz" -mtime +${DELDAY} -exec bash -c "rm -f {}" \; 2>&1
이메일 보내기
- df -h 출력 결과를 이메일로 전송하기
#!/bin/bash
####################
# IFS Setting
IFS_BACK=${IFS}
#
#####################
# sudo
sudo=$(which sudo)
#
####################
# File Name
FILE="./df.log"
#
#####################
# To Email Address
TO_EMAIL="$(cat ./.address.mail | awk -F'=' '{print $2}')"
#
#####################
# Disk Free Checking
function df_checking() {
df_leng=$(df -h | awk '{print $1}' | grep -v "[A-Z]" | wc -l)
usages=($(df -h | awk '{print $5}' | grep -v "[A-Z]" | awk -F'%' '{print $1}'))
mounts=($(df -h | awk '{print $6}' | grep -v "[A-Z]" | awk -F'%' '{print $1}'))
exec 3> ${1}
for idx in $(eval seq 0 $[ ${df_leng} - 1 ])
do
usage=${usages[${idx}]}
mount=${mounts[${idx}]}
filesystem=${filesystems[${idx}]}
echo -e "${usage}\t${mount}%" >&3
done
}
# Send Email Function
function send() {
# 디스크 체킹
df_checking ${1}
# IFS Setting Change
IFS='\t'
# MAIL MSG
EMAIL_MSG=$(cat ${1})
# Subject
SUBJECT="Shell Script : Disk Free Monitoring"
# To
TO_EMAIL="yshrim12@naver.com"
echo "${EMAIL_MSG}" | /usr/bin/mail -s "${SUBJECT}" "${TO_EMAIL}"
}
send ${FILE}
.address.mail 파일 내용
MAIL_ADDRESS=YourEmail@.com
주기적으로 명언 가져오기
main.sh
#!/bin/bash
python=$(which python3)
quote_url='http://www.quotationspage.com/qotd.html'
check_url=$(/usr/bin/wget -nv --spider ${quote_url} 2>&1 | awk '{print $5}' ) || exit 1
if [[ ${check_url} != 200 ]]
then
echo -e "RESPONSE ERROR! : ${check_url}"
exit 1
fi
if [[ ! -e /tmp/quote ]]
then
echo "Creating Quote Directory"
/usr/bin/mkdir /tmp/quote
echo -e "\nDone!"
fi
wget -o /tmp/quote/quote.log -O /tmp/quote/quote.html ${quote_url}
${python} parsing.py
find /tmp/daily_quote/ -iname "*.txt" -mtime +3 | xargs -I % sh -c '{echo Removing %;rm -f %}'
parsing.py
from datetime import datetime
from bs4 import BeautifulSoup as bs
import requests as rq
import os
import re
def get_soup_obj(html)-> bs:
with open(html,'r',encoding='UTF-8') as fp:
soup : bs = bs(fp.read(),'html.parser')
return soup
def parsing(soup)-> Dict[str,str]:
data : Dict[str,str] = dict()
head : str = str(soup.select_one('div.qotdhead').text.strip()).split('-')[-1].strip()
quotes : str = ''.join([_.text.strip() for _ in soup.select('dl > dt.quote')])
author : str = soup.select_one('td#content dl > dd > b').text.strip()
TEXT : str = f"{'=' * 10} Daily Quote - {head} {'=' * 10 }\n\n{quotes}\n\t\tAuthor : {author}"
data['author'] = author.split('(')[0].strip()
data['text'] = TEXT
return data
def new_quote_file(data :dict)-> None:
today : str = datetime.today().strftime('%Y%m%d')
DIR : str = f'/tmp/daily_quote/{today}'
os.makedirs(DIR,exist_ok=True)
fileName : str = os.path.join(DIR,data['author'] + '.txt')
# 파일 쓰기
with open(fileName,'w') as fp:
fp.write(data['text'])
print(f'파일이 정상적으로 쓰였습니다!\n{fileName}')
def main()-> None:
# HTML FILE
html = '/tmp/quote/quote.html'
# get Soup
soup = get_soup_obj(html=html)
# Staring Parsing
data : Dict[str,str] = parsing(soup=soup)
# Create New File
new_quote_file(data=data)
if __name__ == '__main__':
main()
디스크 모니터링
main.sh
#!/bin/bash
PWD=$(pwd)
HOST=${USER}
IP_ADDR=$(ip ad sh | grep "inet" | awk -F' ' '{print $2}' | sort | grep "/24")
TELE_FILE="${PWD}/telegram.sh"
USAGES=($(du -h / --max-depth=1 2>/dev/null | grep "G" | awk -F'G' '{print $1}' | awk -F'.' '{print $1}'))
U_PATH=($(du -h / --max-depth=1 2>/dev/null | grep "G" | awk -F'G' '{print $2}'))
for idx in ${!USAGES[@]};
do
usage=${USAGES[${idx}]}
path=${U_PATH[${idx}]}
if [[ ${usage} -gt 3 ]]; then
TEXT="${path}==>${usage}G"
# 텔레그램 메시지 보내기
${TELE_FILE} "${HOST}" "${IP_ADDR}" "${TEXT}"
fi
done
telegram.sh
# TELEGRAM TOKEN
TOKEN=''Your TOKEN"
# TELEGRAM CHAT ID
CHATID=''Your Chat ID"
# Request URL
URL="https://api.telegram.org/bot${TOKEN}/sendMessage"
function alarm() {
# === Telegram 봇 관련 정보 ===
# 날짜
DATE=$(date +"%Y.%m.%d %H:%M")
# 보낼 메시지 작성
TEXT="${1}(${2}) - ${3}"
# 메시지 보내기
curl -s -d "chat_id=${CHATID}&text=${TEXT}" ${URL} > /dev/null
echo "Done"
}
alarm ${1} ${2} ${3}
ssh 로 클라이언트에 특정 명령 보내기
#!/bin/bash
# 배열 정의
declare -a server_list_len
declare -a server_list
# FILE
FILE='/home/wogy12395/git/shell-script/04_ssh_command_to_client/server_list.txt'
server_list_len=$(cat ${FILE} | wc -l)
server_list=($(cat ${FILE}))
# 0번째 인자 ~ 9번째 인자 (10개)
for idx in $(eval seq 0 $[ ${server_list_len} -1]);
do
echo "${server_list[${idx}]}"
ssh user@"${server_list[${idx}]}" -p 9706 "ls -alht ~/"
done
Field seperator 예제 #1
#!/bin/bash
IFS=:
users=($(cat /etc/passwd))
for user in "${users[@]}"
do
echo ${user}
done
Field seperator 예제 #2
#!/bin/bash
# Changing the IFS value
IFS.OLD=${IFS}
IFS=$'\n'
for entry in $(cat /etc/passwd)
do
echo "Values in ${entry} -"
IFS=:
for value in ${entry}
do
echo -e "\t${value}"
done
echo
done
Loop Output
#!/bin/bash
for file in ${HOME}/*
do
if [[ -d ${file} ]]
then
echo "${file} is a directory"
elif [[ -f ${file} ]]
then
echo "${file} is a file"
fi
done >| output.txt
cat ./output.txt
지속적 리다이렉트 (exec)
- exec 명령은 새로운 쉘을 시작하고 STDOUT 파일 디스크립터를 파일로 리다이렉트 함
#!/bin/bash
# redirecting output to different locations
exec 2>testerror
echo "This is the start of the script"
exec 1>testout
echo " This output should go to the testout file"
echo " but this should go to the testerror file" >&2
사용자 정의 리다이렉트
$ vim 05_script.sh
#!/bin/bash
# using an alternative file descriptor
exec 3>test13out
echo "This should display on the monitor"
echo "and this should be stored in the file" >&3
echo "Then this should be back on the monitor"
$ ./05_script.sh
-----------------------------------------------------------------------------
This should display on the monitor
Then this should be back on the monitor
-----------------------------------------------------------------------------
$ cat ./test13out
-----------------------------------------------------------------------------
and this should be stored in the file
-----------------------------------------------------------------------------
리다이렉트 활용 고급예제
#!/bin/bash
# read file and create INSERT statements for MySQL
outfile='members.sql'
IFS=','
while read lname fname address city state zip
do
cat >> ${outfile} << EOF
INSERT INTO member (lname,fname,address,city,state,zip) VALUES ('${lname}' , '${fname}' , '${address}' , '${city}' , '${state}' , '${zip}');
EOF
done < ${1}
done