반응형

 


 

작성일: 2024년 2월 21일

 

Shell script 작성할 때마다 책꽂이 어딘가에 있을 책을 찾는 것이 귀찮고, 인터넷에서 검색하는 것도 귀찮아서, 
내가 자주 사용하는 Shell script use case를 정리하는 것이 편하겠다는 생각이 들었다.

 

 

Bash Shell Programming 추천 문서

추천 문서 1

  • Link: https://www.lesstif.com/lpt/bash-shell-script-programming-26083916.html
  • 이 문서가 다루는 내용
    • For loop
    • Script parameter, argument ($0, $1, ... $n, $@)   // CLI를 통해서 받은 argument를 처리하는 방법
    • getopt
    • compare operator (비교 연산자, if then fi, else, elif, ... )
    • File test (디렉토리 존재 여부, 파일 존재 여부, 실행 파일 여부 등 검사)
    • String test (문자열이 공백인지 검사,  Regular expression 정규식)
    • File 읽기 (Text file을 line by line으로 읽어서 변수에 담기)
    • nohup + stdin/out redirect (스크립트를 background로 실행시켜 terminal이 끊길 때 스크립트가 종료되는 것을 방지)
    • EUID 활용법 (일반 계정, root 계정으로 실행했는지 테스트)
    • $? 변수 체크 (외부 명령을 실행 후, 그 결과가 성공/실패인지를 체크)

추천 문서 2

  • Link: https://velog.io/@markyang92/declaretypeset
  • 이 문서가 다루는 내용
    • 변수 이름 작명 규칙
    • 변수 선언, 변수 사용(값 참조)
    • eval 키워드 사용법
    • export, declear, set 키워드를 사용하는 이유 및 활용 사례
    • unset, typeset 키워드 사용 사례
    • 미리 정의된 환경 변수 (HOME, PATH, LANG, SHELL, USER, DISPLAY, PS1, PS2, LINES, LS_COLORS 등)

추천 문서 3

  • Link: https://blog.gaerae.com/2015/01/bash-hello-world.html
  • 이 문서가 다루는 내용
    • function 선언, function 참조
    • 변수 선언, 변수 사용(값 참조)
    • 예약 변수(Reserved Variable): FUNCNAME, SECONDS, SHLVL, PPID, BASH_ENV, BASH_VERSION, OSTYPE
    • 위치 매개 변수(Positional Parameters): $0,  $1,  $*,  $@,  $#
    • 특수 매개 변수(Special Parameters): $$,  $?,  $!,  $-,  $_
    • 매개 변수 확장(Parameter Expansion): ${변수:-단어}  ${변수#단어}  ${변수/%찾는단어/변경단어}
    • 배열 변수(Array Variable): ${array[3]}  ${array[@]}
    • 변수 타입 지정(Variables Revisited): declare, typeset
    • 논리 연산자(Logical Operator):  &&  -a   ||  -o
    • 산술 연산자(Arithmetic Operator):  **  +=  -=  *=  /= %=
    • 비트 연산자(Bitwise Operator):  <<   <<=  >>=  &   &=  |   |=  ~   ~  ^   ^=
    • 정수 비교(Integer Comparison):  -eq  -ne  >  -gt  >=  -ge  <  -lt  <=  -le
    • 문자열 비교(String Comparision):  =  ==  !=  <  >  -z   -n
    • 파일 비교 연산자(File Test Operator):  -e  -f  -s  -d -b  -c  -p  -nt  -ot  -ef
    • 반복문: for  while  until
    • 조건문:  if elif  else  fi
    • 선택문:  case ... esac
    • 디버깅 방법: Dry run (bash -n my-run.sh)

 


 

유용한 스크립트 예제 모음

 

Remote node의 파일을 가져와서 Local node의 파일과 동일한지 확인 후 Local 장비에 반영하거나 삭제

아래 스크립트에서 유용한 부분은

  • date(날짜) 출력 포맷을 가공
  • 여러 단어(Word)로 구성된 문자열을 cut 명령으로 자르기(cut, split, delimiter)
  • if 조건문 사용
#!/usr/bin/bash

MY_REMOTE_ACCT=my-id@my-domain.kr

CUR_DATE=`date +%+4Y-%m-%d-%H-%M-%S`
ORIGIN_FILE="my-domain.kr.zone"
REMOTE_FILE="${ORIGIN_FILE}_remote"
BACKUP_FILE="${ORIGIN_FILE}_${CUR_DATE}_bkup"
DIR_PATH=/var/cache/bind

cd $DIR_PATH

scp ${MY_REMOTE_ACCT}:${DIR_PATH}/${ORIGIN_FILE} $REMOTE_FILE

## cksum 명령의 결과가 3개의 컬럼으로 출력되는데, 
## 실제 필요한 데이터는 첫번째 column이라서 출력 내용을 cut -f 1 명령으로 잘라냄.
CKSUM_REMOTE_FILE=$(cksum $REMOTE_FILE | cut -d " " -f 1)
CKSUM_ORIGIN_FILE=$(cksum $ORIGIN_FILE | cut -d " " -f 1)

if [ $CKSUM_REMOTE_FILE -eq $CKSUM_ORIGIN_FILE ]; then
        echo "The ${CKSUM_REMOTE_FILE} and the $CKSUM_ORIGIN_FILE are equivalent"
        exit 1
fi

echo "The ${CKSUM_REMOTE_FILE} and the $CKSUM_ORIGIN_FILE are different"

cp $ORIGIN_FILE $BACKUP_FILE
cp $REMOTE_FILE $ORIGIN_FILE

systemctl restart bind9

 

 

##

## TODO: 나중에 추가로 예제를 작성하기

##

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

반응형

 


 

내가 자주 사용하는 형태는 아래와 예제와 같고, find 명령에 대한 자세한 내용은 아래 Web Docs를 참고할 것 !!!

 

$ find /proc -maxdepth 2 -name "comm" -print

$ find /proc -maxdepth 2 -name "comm" -exec cat {} \;

$ find . -maxdepth 2 -name "comm" -type f -mmin +1 -print | xargs grep kubelet
./4305/comm:kubelet
$

 

 

find 명령과 xargs 명령을 조합해서 사용하려면 많은 내용을 길게 입력해야 하는데, 아래와 같이 미리 .bashrc 파일에 function으로 등록하면 쉽게 이용할 수 있다.

 

$ cat .bashrc

... 중간 생략 ...

##
## .c 또는 .h 파일에서 특정 문자열을 찾는 함수
##
function find_xargs() {
    find . -name "*\.[ch]" -type f  -print | xargs grep $1
}

... 중간 생략 ...


##
## 위에서 .bashrc 파일에 추가한 내용을 현재 shell 환경에 적용하기
##

$ . .bashrc


## --------------------------------------------------------------

##
## 위에서 작성한 find_xargs 명령을 이용하여 Source code file에서 ip_hdr 함수를 찾는 예제
##

$ find_xargs  ip_hdr

./net/dccp/ipv6.c:		newnp->mcast_hops  = ip_hdr(skb)->ttl;
./net/dccp/ipv4.c:	return secure_dccp_sequence_number(ip_hdr(skb)->daddr,
./net/dccp/ipv4.c:					   ip_hdr(skb)->saddr,
./net/dccp/ipv4.c:	newinet->mc_ttl	   = ip_hdr(skb)->ttl;
./net/dccp/ipv4.c:	const struct iphdr *iph = ip_hdr(skb);
./net/dccp/ipv4.c:	rxiph = ip_hdr(rxskb);
./net/dccp/ipv4.c:	sk_rcv_saddr_set(req_to_sk(req), ip_hdr(skb)->daddr);
./net/dccp/ipv4.c:	sk_daddr_set(req_to_sk(req), ip_hdr(skb)->saddr);
./net/dccp/ipv4.c:	iph = ip_hdr(skb);
./net/sched/act_ipt.c:	iph = ip_hdr(skb);
./net/sched/act_ctinfo.c:		dscp = ipv4_get_dsfield(ip_hdr(skb)) & ~INET_ECN_MASK;
./net/sched/act_ctinfo.c:				ipv4_change_dsfield(ip_hdr(skb),
./net/sched/act_nat.c:	iph = ip_hdr(skb);
./net/sched/act_nat.c:		iph = ip_hdr(skb);
./net/sched/act_ct.c:	iph = ip_hdr(skb);

... 중간 생략 ...

$

 


 

아래 Web docs에 아주 자세한 설명과 예제가 있다.

 

How to Use the Linux xargs Command

 

반응형

Shell script를 작성하다보면, 10 ~ 60초 정도 대기하는 시간에 멀뚱히 터미널을 쳐다보는 것이 지루할 때가 있다.

지루하지 않더라도 터미널에 수십초 동안 아무것도 출력되지 않으면,

"어~ 스크립트가 중간에 hang up 상태로 빠졌나?"

이런 의심을 하게 된다.

이럴 때, 시간이 흘러가는 것처럼 숫자가 올라가거나 내려가거나(count-up, count-down) 하면 좋다.

긴 설명은 필요없고, 아래 script를 활용하면 대기하는 지루함을 줄일 수 있다.

 

##
## NOTE:
##  macOS와 Ubuntu, CentOS의 date 명령에 대한 output format 옵션이 달라서 script가 조금 다르다.
##  


##
## NOTE: Ubuntu, CentOS에서 동작하는 스크립트
##

#!/usr/bin/bash

function countdown(){
   date_start=$((`date +%s` + $1));
   while [ "$date_start" -ge `date +%s` ]; do
     left_time="$(date -u --date @$(($date_start - `date +%s`)) +%M:%S)";
     echo -ne "Countdown  $left_time \r"
     sleep 0.1
   done
}

countdown 5


---


##
## NOTE: macOS에서 동작하는 스크립트
##

#!/opt/homebrew/bin/bash

function countdown(){
   date_start=$((`date +%s` + $1));

   while [ "$date_start" -ge `date +%s` ]; do
     curr_time=$((`date +%s`))

     left_time=$(($date_start - $curr_time))
     echo -ne "Countdown  $left_time \r"
     sleep 0.1
   done
}

countdown 3

 

반응형

https://engineer-mole.tistory.com/235#:~:text=w%20%ED%8C%8C%EC%9D%BC%EB%AA%85%20%23%20%ED%98%84%EC%9E%AC%EC%9D%98%20%ED%8C%A8%ED%84%B4,%EB%B3%80%ED%99%98%20%EB%AC%B8%EC%9E%90%EB%A1%9C%20%EB%B3%80%ED%99%98%ED%95%9C%EB%8B%A4.

 

[Linux] sed 커맨드 상황별 사용법

쉘에서 데이터를 가공할 때 sed를 자주 사용하게 되는데, 상황에 따른 사용예를 정리한 포스팅이다. sed 커맨드는 Linux/Unix/BSD/OSX의 경우 기본적으로 설치되어 있으므로, sed 커맨드를 사용하기 위

engineer-mole.tistory.com

 

반응형

 

가끔 쉘 프로그래밍을 하다보면, 문자열의 큰 따옴표를 떼어내야 할 경우가 있다.

아래 예제처럼 작성하면 따옴표를 제거할 수 있다.

 

##
## APP_NAME이 "myapp"과 같이 따옴표가 앞 뒤에 포함되어 있다고 가정하자.
## 문자열 시작, 끝에 붙여 있는 따옴표를 떼려면 아래와 같이 sed 명령으로 변경할 수 있다.
## 

APP_NAME=$(sed -e 's/^"//' -e 's/"$//' <<< $APP_NAME)

 

반응형

 

작성일: 2024년 4월 15일

 

 

리스트 형태의 문자열(또는 Text 문서)에서  특정 컬럼만 추출하고 싶을 때가 있다.

이런 경우 cut 명령, awk 명령을 이용해서 아래 예제와 같이 문자열에서 원하는 부분을 분리(split, delimit)할 수 있다.

 

cut 명령 예제

## 예들 들어, "aa.bb.cc." 라는 문자열이 있다면,
## 아래와 같이 실행하면, "aa"만 뽑을 수 있다.

$  echo "aa.bb.cc."  |  cut -d '.' -f1
aa
$  echo "aa.bb.cc."  |  cut -d '.' -f2
bb
$  echo "aa.bb.cc."  |  cut -d '.' -f3
cc
$

 

awk 명령 예제

## 문자열에서 특정 word만 추출하고자 하면, 아래와 같이 실행한다.

$  echo  "10.10.12.49  10.10.12.30  192.168.122.1"  |  awk '{print $1}'
10.10.12.49

$  echo  "10.10.12.49  10.10.12.30  192.168.122.1"  |  awk '{print $2}'
10.10.12.30

$  echo  "10.10.12.49  10.10.12.30  192.168.122.1"  |  awk '{print $2 " -- " $3}'
10.10.12.30 -- 192.168.122.1

'Shell Script' 카테고리의 다른 글

sed 사용법 - 종합  (0) 2022.06.16
문자열에서 따옴표 떼어내기(제거하기)  (0) 2022.01.22
grep command with invert-match option  (0) 2021.10.06
Man page dump하기  (0) 2021.07.15
Bash shell script에서 Random 정수 만들기  (0) 2021.07.13
반응형

grep command를 -v(또는 --invert-match) 옵션과 함께 사용할 때, 여러 개의 조건을 입력하고 싶을 때가 있다.

-v 옵션을 여러 조건과 사용할 때 항상 표현식이 헷갈렸는데, 그래서 메모를 해본다.

$ grep -vE 'aaa|bbb'
ccc
ddd
eee
$

 

반응형

man 명령으로 man page를 읽으면, 위/아래 페이지 이동이나 검색하는 것이 불편하다.

차라리 text 파일을 열어서 검색하는 것이 앞/뒤 문맥을 확인하기 편하고, 전체 페이지 중에서 내가 어디쯤을 읽고 있는지 감을 잡기도 편하다.

그래서 이런 불편함을 해결하려고 man page를 text file로 dump하는 것을 만들었다.

 

##
## Filename:  .bash_profile  또는  .bashrc
##

mandump() {
    man $1 | col -bx > man_page_$1.txt
}

 

위와 같이 .bashrc 파일에 명령 'mandump'를 추가하고,  아래와 같이 실행한다.

$ mandump curl

$ vi man_page_curl.txt

curl(1)                           Curl Manual                          curl(1)
NAME
       curl - transfer a URL

SYNOPSIS
       curl [options / URLs]
       
DESCRIPTION
       curl  is  a tool to transfer data from or to a server, using one of the
       supported protocols (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS,  IMAP,
       IMAPS,  LDAP,  LDAPS,  POP3,  POP3S,  RTMP, RTSP, SCP, SFTP, SMB, SMBS,
       SMTP, SMTPS, TELNET and TFTP). The command is designed to work  without
       user interaction.
 ...
 ...

 

 

 

 

+ Recent posts