카테고리 보관물: study

awk 기초

참조 원문 : Introduction to awk
관련 글 : awk를 이용한 검색, awk에서 변수 사용, 6가지 awk 트릭

  awk는 패턴을 찾아 그와 관련된 문자열을 처리하는 유틸리티로 텍스트 파일에서 정보를 찾아 필요한 형식으로 재생성, 파일의 서식 변경, 데이터베이스 생성과 데이터를 이용한 수학 계산에 사용합니다. awk라는 이름은 프로그램 제작자들의 이름인 Aho, Weinberger, Kernighan의 앞글자들을 따서 만든 겁니다. 그 외에 awk의 최신 버전에 해당하는 nawk라는 것이 있고 GNU 버전인 gawk라는 것도 있습니다. 리눅스의 경우 awk 명령어가 심볼릭 링크를 통해 gawk를 가리키고 있는 경우가 많습니다. 참고로 우분투의 경우 awk가 심볼릭 링크를 통해 mawk(mike’s awk)라는 프로그램으로 링크되어 있는데 사실상 둘이 다를 게 거의 없기 때문에 신경쓰지 않아도 됩니다.

  awk는 표준 입력(=stdin, 키보드로부터 받은 입력), 파일, 다른 프로세스의 출력으로부터 데이터를 받습니다. 데이터를 받으면 입력한 패턴과 일치하는 줄을 찾습니다.


awk 사용

awk [ -F<char> ] {pgm} | { -f <pgm_file> } [ <vars> ] [ – | <data_file> ]

  • char: 필드 구분 문자
  • pgm: 실행할 명령어
  • vars: 변수
  • data file: 입력 데이터 파일

  기본적으론 공백이나 탭이 필드 구분 문자로 사용되지만 -F 옵션을 사용하면 다른 문자를 필드 구분 문자로 사용할 수 있습니다. 예를 들어 필드가 콜론(:)으로 나눠져 있을 경우 아래와 같이 사용합니다.

awk -F:


파일 내용을 입력
  아래는 awk를 이용하여 특정 파일에서 지정한 패턴을 찾는 문법과 실제 사용 예로 ps 명령어의 출력 결과를 텍스트 파일로 만든 후 awk를 이용해 “apache”라는 문자열이 있는 줄을 검색하는 것을 보여주고 있습니다.

문법: awk ‘pattern’ filename

$ ps aux > processes 
$ awk ‘/apache/’ processes 
apache    2206  0.0  1.0 207376  3972 ?   S   22:20   0:00 /usr/sbin/httpd
apache    2207  0.0  1.0 207376  3972 ?   S   22:20   0:00 /usr/sbin/httpd
…생략…

  아래는 패턴 대신 액션을 사용한 예입니다. 출력 결과가 위와 다른데 그 이유는 “$1″을 사용하여 모든 줄의 첫 번째 필드를 출력하게 했기 때문입니다. 필드 구분 문자를 따로 지정하지 않았기 때문에 공백을 필드 구분 문자로 사용합니다.

문법: awk ‘action’ filename

$ ps aux > processes 
$ awk ‘{print $1}’ processes
root
root
…생략…

  아래는 패턴과 액션을 섞어서 처음 결과에서 첫 번째 필드만 뽑아내는 문법과 예입니다.

문법: awk ‘pattern {action}’ filename

awk ‘/apache/{print $1}’ processes
apache
apache
apache

배시에 관한 몇 가지 팁

참조 원문 : 8 More Bash Tips for Working Faster With the Shell

  날이면 날마다 오는 배시 관련 포스팅입니다.

앨리어스 등록
  일반적으로 앨리어스를 등록할 때는 ~./bashrc 파일에 아래와 같은 형식으로 원하는 내용을 집어넣습니다.

alias name=’command’

  그냥 이렇게 평범하게 등록하고 쓰는 방법도 있지만 앨리어스 전용 파일을 별도로 만들고 그 파일을 읽는다면 관리가 더 깔끔하겠죠? 이를 위해 .bash_aliases 파일을 만들어 앨리어스들을 넣은 후 ~./bashrc 파일에서 아래와 같이 파일을 읽어들입니다.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi


히스토리를 탐색할 때 페이지 업/다운 키 사용
  ~/.inputrc라는 파일을 만들고 아래의 두 줄을 집어넣으면 PageUp 키와 PageDown 키로 히스토리를 탐색할 수 있습니다. 파일을 만든 후 다시 로그인을 해야 적용됩니다.

“\e[5~”: history-search-backward
“\e[6~”: history-search-forward


이맥스 스타일의 단축키들
  화살표까지 손을 옮기기 귀찮을 때 사용하면 편합니다.

  • ^A – go to the start of line
  • ^E – go to the end of line
  • ^H – erase one character to the left
  • ^D – erase one character to the right, it also exits the shell by default if there is no character to delete
  • ^U – erase everything from the cursor to start
  • ^K – erase everything from the cursor to end
  • ^P – bring the previous command in history
  • ^N – bring the next command in history
  • ^C – interrupt character, sends SIGTERM to the current application


매뉴얼 페이지에 색깔 적용
  아래의 내용을 ~./bashrc 파일에 넣습니다.

export LESS_TERMCAP_mb=$’\E[01;31m’ # begin blinking
export LESS_TERMCAP_md=$’\E[01;38;5;74m’ # begin bold
export LESS_TERMCAP_me=$’\E[0m’ # end mode
export LESS_TERMCAP_se=$’\E[0m’ # end standout-mode
export LESS_TERMCAP_so=$’\E[38;5;246m’ # begin standout-mode – info box
export LESS_TERMCAP_ue=$’\E[0m’ # end underline
export LESS_TERMCAP_us=$’\E[04;38;5;146m’ # begin underline

  그리고 .bashrc 파일을 다시 읽어들입니다.

. ~/.bashrc

 


파일 이름의 뒷부분에 원하는 문자열 추가
  만약 ‘filename‘이란 이름의 파일이 있을 때 이 파일을 백업 파일로 만들 때는 ‘filename.backup‘ 같은 식으로 이름을 바꾸기 마련입니다. 이때 보통 아래와 같은 방법으로 이름을 바꿉니다.

mv filename filename.backup

  이때 아래의 형식으로 명령을 내리면 같은 효과를 볼 수 있습니다.

mv filename{,.backup}

 

배시 파라미터를 대입(Substitution)하는 방법들

참조 원문 : HowTo: Use Bash Parameter Substitution Like A Pro

달러($) 문자는 파라미터 확장과 명령어 대입에 사용됩니다. 이걸 이용하면 sed나 awk 같은 외부 명령어 없이 필요에 따라 변수를 조작하거나 확장할 수 있습니다.
 

문자열 조작과 확장 변수

  • ${parameter:-defaultValue} : 디폴트 쉘 변수 값을 사용
  • ${parameter:=defaultValue} : 디폴트 쉘 변수 값을 설정
  • ${parameter:?”Error Message”} : 파라미터가 설정되어 있지 않았을 경우 에러 메시지 출력
  • ${#var} : 문자열의 길이 계산
  • ${var%pattern} : 오른쪽에서 패턴과 일치하는 부분 제거
  • ${var%%pattern} : 패턴과 일치하는 부분들 중 가장 왼쪽 부분부터 끝까지 제거
  • ${var:num1:num2} : 문자열 추출
  • ${var#pattern} : 왼쪽에서 패턴과 일치하는 부분 제거
  • ${var##pattern} : 패턴과 일치하는 부분들 중 가장 오른쪽 부분부터 처음까지 제거
  • ${var/pattern/string} : 검색 및 치환(1개)
  • ${var//pattern/string} : 검색 및 치환(모두)

6가지 awk 트릭

참조 원문 : 6 Tricks with awk
관련 글 : awk 기초, awk를 이용한 검색, awk에서 변수 사용

  AWK는 텍스트 기반의 데이터(파일이나 데이터 스트림)를 처리하기 위한 프로그래밍 언어입니다. 주로 문자열 데이터타입, 배열, 정규 표현식을 사용합니다.

  AWK는 본 쉘과 더불어 표준 유닉스 환경에서 사용할 수 있는 스크립트 언어이며 LSB(Linux Standard Base) 사양서에 반듯이 있어야 하는 것으로 규정된 명령어 중 하나입니다.

  비록 AWK가 1줄 프로그래밍을 지원하고 또 대부분 그렇게 사용되지만 하나의 완벽한 프로그램을 짜는 것도 가능합니다.


1. 파일에서 정렬 없이 중복 내용 삭제
  정렬을 하지 않고도 중복된 내용을 찾아 지우고 다른 파일로 리다이렉트하는 방법입니다.

awk ‘!x[$0]++’

  그리고 아래는 그 예와 결과입니다.

$ echo -e “aaa\nbbb\naaa\naa\nccc\naa”|awk \!’x[$0]++’
aaa
bbb
aa
ccc


2. 특정 파일 그룹의 총 용량 합산
  아래는 디렉토리 내에 모든 파일의 크기를 합산하는 방법입니다.

ls -l | awk ‘{s = s+$5 }; END { print s }’

  그리고 아래는 현재 디렉토리와 서브디렉토리 내에 있는 .mp3 파일들의 용량을 합산하는 방법입니다.

ls -lR |grep .mp3 | awk ‘{s = s+$5 }; END { print s }’


3. find 명령어와 연계
  아래는 find로 컴퓨터 내의 모든 .mp3 파일들을 찾아 위에서 본 것과 비슷한 방식으로 용량을 합산하는 방법입니다.

find / -name “*.mp3” -exec ls -l {} \; | awk ‘{s = s+$5 }; END { print s }’


4. 사용횟수로 기준으로 내림차순으로 정렬하여 히스토리 출력

history | awk ‘{a[$’`echo “1 2 $HISTTIMEFORMAT” | wc -w`’]++}END{for(i in a){print a[i] “\t” i}}’ | sort -rn | head


5. AWK 필드 분석
  각 줄마다 번호를 매기고 다시 각 줄의 아래에 해당 줄에 있는 필드마다 번호를 매겨 출력합니다.

awk ‘{print NR”: “$0; for(i=1;i<=NF;++i)print “\t”i”: “$i}’


6. 여러 파일의 파일명을 한 번에 변경
  아래는 특정 파일들의 파일명 끝에 ‘.new’를 붙이는 방법입니다. 앞 부분의 ‘ls -al pattern’을 변경하여 다양한 활용이 가능합니다.

ls -1 pattern | awk ‘{print “mv “$1” “$1″.new”}’ | sh

 

우분투 스타트업 시 스크립트 실행에 대하여

참조 원문 : How to Run Scripts at Ubuntu Startup

  우분투로 부팅할 때 어떤 스크립트를 실행시키게 만드는 일은 레드햇 기반의 리눅스에 비해 어려운 편인데 그 이유는 우분투가 전통적인 Sys-V Init 스크립트 방식 대신 진일보적인 업스타트라는 방식을 메인으로 사용하기 때문입니다. 지금으로서 우분투에서 부팅 시 스크립트를 돌리는 방법으로는 총 세 가지가 있습니다.(업스타트에 대한 자세한 설명은 없군요.)

1. Upstart 방식
  /etc/init.d 디렉토리에는 ‘업스타트 방식을 지원하는 프로그램들의 업스타트 스크립트에 대한 링크’가 전통적인 Sys-V Init 스크립트와 함께 공존하고 있습니다. 예를 들어 아래 중 apache2는 업스타트 방식을 사용하지 않지만 vsftpd는 업스타트를 사용한다는 것을 볼 수 있습니다.

ls -l /etc/init.dtotal 180
-rwxr-xr-x 1 root root 7476 2011-02-22 11:32 apache2
lrwxrwxrwx 1 root root 21 2011-05-21 04:37 vsftpd -> /lib/init/upstart-job


2. 하위호환을 위한 System-V 방식
  우분투가 업스타트를 사용하긴 하지만 많은 프로그램들이 업스타트를 지원하지 않는 탓에 여전히 Sys-V 방식을 지원합니다. 당연히 활용 방식은 다른 레드햇 기반과 동일합니다. 먼저 /etc/init.d 디렉토리 안에 스크립트를 집어넣고 아래와 같은 명령어로 해당 스크립트의 퍼미션을 변경합니다.

chmod 755 myscript

    그 후 원하는 런레벨에 해당하는 디렉토리 안에 심볼릭 링크를 만들어 해당 스크립트에 연결시킵니다. 예를 들어 위 스크립트를 런레벨2(우분투의 디폴트 런레벨로 그래픽 부팅에 해당)에서 실행되게 하려면 /etc/rc2.d 디렉토리 안에 심볼릭 링크를 만들면 됩니다. 역시 다른 리눅스와 마찬가지로 심볼릭 링크의 파일명에서 첫 글자를 S로 하고 그 뒤에 실행 순서용 숫자를 적어줍니다. 높은 숫자일수록 늦게 실행되죠.

ln -s /etc/init.d/myscript /etc/rc3.d/S99myscript

  팁으로 아래 프로그램을 설치 및 실행하여 위 작업을 더 편하게 할 수 있습니다. 물론 설치와 실행 모두 root 권한이 필요합니다.

sudo apt-get install sysv-rc-conf


3. rc.local 파일 사용
  가장 원시적인 방법으로서 /etc/rc.local 파일 안에 실행하고 싶은 명령어를 집어넣으면 2~5 런레벨일 때 해당 명령어를 실행합니다. 디폴트로 주석과 마지막 줄의 exit 0 빼고는 비어있습니다.

LSB Init 표준을 기반으로 리눅스 Init 스크립트를 작성하는 법

참조 원문 : How to Write Linux Init Scripts Based on LSB Init Standard

  LSB란 Linux Standard Base의 약자로서 리눅스 재단이 배포판 사이의 차이점을 줄여 다른 배포판으로 이식할 때 드는 비용을 줄이기 위해 만든 표준입니다. Init 스크립트도 표준화된 것들 중 하나입니다.

  Init 스크립트는 소프트웨어나 서비스를 시작하거나 중단할 때 사용합니다. 예를 들어 postgresql 소프트웨어를 사용하고 있다면 /etc/init.d/postgresql 이라는 Init 스크립트를 가지고 있을 것이며 인자로 start, stop, restart, reload, force-reload, status를 사용할 수 있습니다.

  LSB 호환 Init 스크립트는 아래 사항을 지켜야 합니다.

  • 최소한 ‘start, stop, restart, force-reload, status’를 제공해야 한다.
  • 적절한 exit code를 return해야 한다.
  • 실행 의존성(run-time dependencies)을 문서화해야 한다.

  추가적으로 이 스크립트들은 메시지를 남기기 위해 “log_success_msg”나 “log_failure_msg” 같은 init.d 함수를 사용할 수 있습니다.

  LSB는 /lib/lsb/init-functions에 있는 기본 함수들을 제공합니다. Init 스크립트로 실행되는 프로세스들은 /var/run/ 디렉토리에 프로세스의 pid를 기록하는데 이것은 Init 스크립트가 프로세스의 상태를 조사할 때 큰 도움이 됩니다.

  이제 Init 스크립트를 작성해봅시다. 먼저 아래처럼 헤더를 넣습니다.

### BEGIN INIT INFO
# Provides:          my_daemon
# Required-Start:    postgresql networking
# Required-Stop:     postgresql networking
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: This is a test daemon
# Description:       This is a test daemon
#                    This provides example about how to
#                    write a Init script.
### END INIT INFO

  Provides에는 해당 Init 스크립트가 제공하는 기능(facility=서비스)을 적습니다. 이 이름은 유일해야 합니다.

  Requred-Start에는 이 서비스를 시작하기 전에 작동하고 있어야 하는 일련의 기능들을 적습니다. 이 예제의 경우 postgresql과 networking이 미리 실행되어 있어야 함을 나타내고 있습니다. 기억해야 할 점은 이 ‘postgresql’가 ‘Provides: postgresql’이라고 적힌 별도의 Init 스크립트를 가지고 있어야 한다는 것입니다. 이를 통해 부팅 시 의존성을 보장합니다. ‘inserv’ 명령어나 ‘update-rc.d’ 명령어를 사용할 때 이 의존성을 바탕으로 대상 런레벨 디렉토리에 적절한 순번을 매겨 집어넣게 됩니다.

/etc/rc2.d/S12postgresql
/etc/rc2.d/S03networking
/etc/rc2.d/S13my_daemon

  예를 들어 위와 같은 엔트리가 있을 경우 networking, postgresql, my_daemon 순서로 실행됩니다.

  Required-Stop에는 이 기능을 중단한 후에만 중단할 수 있는 일련의 기능들을 적습니다. 이 예제의 경우 my_daemon이 중단된 후에만 postgresql과 networking 기능을 중단할 수 있습니다.

  Default-Start Default-Stop에는 이 서비스가 시작되거나 중단돼야 하는 런레벨을 정의합니다.

  Short-Description Description에는 해당 기능에 대한 설명을 적습니다. Short-Description에는 한 줄만 적을 수 있으며, Description에는 여러 줄에 걸쳐 적을 수 있습니다.

  아래는 실제 Init 스크립트의 예입니다.

### BEGIN INIT INFO
# Provides:          my_daemon
# Required-Start:    postgresql networking
# Required-Stop:     postgresql networking
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: This is a test daemon
# Description:       This is a test daemon
#                    This provides example about how to
#                    write a Init script.
### END INIT INFO

# Using the lsb functions to perform the operations.
. /lib/lsb/init-functions
# Process name ( For display )
NAME=my-daemon
# Daemon name, where is the actual executable
DAEMON=/home/user1/my_daemon
# pid file for the daemon
PIDFILE=/var/run/my_daemon.pid

# If the daemon is not there, then exit.
test -x $DAEMON || exit 5

case $1 in
 start)
  # Checked the PID file exists and check the actual status of process
  if [ -e $PIDFILE ]; then
   status_of_proc -p $PIDFILE $DAEMON “$NAME process” && status=”0″ || status=”$?”
   # If the status is SUCCESS then don’t need to start again.
   if [ $status = “0” ]; then
    exit # Exit
   fi
  fi
  # Start the daemon.
  log_daemon_msg “Starting the process” “$NAME”
  # Start the daemon with the help of start-stop-daemon
  # Log the message appropriately
  if start-stop-daemon –start –quiet –oknodo –pidfile $PIDFILE –exec $DAEMON ; then
   log_end_msg 0
  else
   log_end_msg 1
  fi
  ;;
 stop)
  # Stop the daemon.
  if [ -e $PIDFILE ]; then
   status_of_proc -p $PIDFILE $DAEMON “Stoppping the $NAME process” && status=”0″ || status=”$?”
   if [ “$status” = 0 ]; then
    start-stop-daemon –stop –quiet –oknodo –pidfile $PIDFILE
    /bin/rm -rf $PIDFILE
   fi
  else
   log_daemon_msg “$NAME process is not running”
   log_end_msg 0
  fi
  ;;
 restart)
  # Restart the daemon.
  $0 stop && sleep 2 && $0 start
  ;;
 status)
  # Check the status of the process.
  if [ -e $PIDFILE ]; then
   status_of_proc -p $PIDFILE $DAEMON “$NAME process” && exit 0 || exit $?
  else
   log_daemon_msg “$NAME Process is not running”
   log_end_msg 0
  fi
  ;;
 reload)
  # Reload the process. Basically sending some signal to a daemon to reload
  # it configurations.
  if [ -e $PIDFILE ]; then
   start-stop-daemon –stop –signal USR1 –quiet –pidfile $PIDFILE –name $NAME
   log_success_msg “$NAME process reloaded successfully”
  else
   log_failure_msg “$PIDFILE does not exists”
  fi
  ;;
 *)
  # For invalid arguments, print the usage message.
  echo “Usage: $0 {start|stop|restart|reload|status}”
  exit 2
  ;;
esac

  위 스크립트는 LSBInit 스크립트 작성을 위한 템플릿입니다. DAEMON, PIDFILE, NAME 변수, 헤더 등을 적절히 바꿔 사용할 수 있습니다.

  LSB가 제공하는 함수에 대해 더 알고 싶다면 InitScript Functions를 참조하시기 바랍니다.

  Init 스크립트를 작성한 후 자동으로 시작되거나 중단되게 만들려면 아래 형식으로 명령어를 실행합니다.(데비안 계열 기준)

update-rc.d filename defaults

  이 명령어는 지정한 런레벨에 의존성을 고려한 적절한 순번을 가진 ‘S’와 ‘K’ 엔트리를 추가합니다.

예제로 배우는 sed

참조 원문1 : SED(Stream EDitor ) Explained in detail for Linux/Unix
참조 원문2 : Learn SED with examples

1. 검색과 치환(s는 search의 약자)
  아래는 단어를 찾아 다른 단어로 치환하는 문법이다.
sed ‘s/searchterm/replaceterm/’ inputfile
또는
cat inputfilename | sed ‘s/searchterm/replaceterm/’
또는
echo “This is test message” | sed ‘s/searchterm/replaceterm/’

예제1: test.txt 파일에서 google을 찾아 yahoo로 치환
sed ‘s/google/yahoo/’ test.txt

예제2: sed는 기본적으로 처음 찾은 단어만 치환한다. 모든 단어를 치환하려면 g 스위치를 사용해야 한다.
echo “sheena leads, sheila needs” | sed ‘s/sh/le/g’

예제3: Separator 변경법. Separator가 검색하려는 단어에 포함된 경우 유용하다. 예를 들어 /var/ftp/pub을 검색하여 /opt/ftp/com으로 치환하려고 할 때 아래처럼 해도 제대로 작동하지 않는다.
sed ‘s//var/ftp/pub//opt/ftp/com/’ test.txt
이럴 땐 separator를 /에서 #나 $ 같은 다른 문자로 바꿔야 한다. 아래는 _를 사용하는 예제다.
sed ‘s_/var/ftp/pup_/opt/ftp/com_’ test.txt

예제4: 아래는 surendra를 Mr. surendra로 바꾸는 예제다.
sed ‘s/surendra/Mr. &/’ test.txt

예제5: 아래는 abc123suri 같은 패턴을 suriabc123으로 바꾸는 예제다.
echo “abc123suri” | sed ‘s/([a-z]*)([0-9]*)([a-z]*)/312/’


2. 출력(-n과 p 스위치)
예제6: 기본적으로 sed는 모든 줄을 출력하지만 -n(출력 억제)과 p 옵션을 사용하여 바뀐 줄만 출력할 수 있다.
cat tem.txt | sed -n ‘s/surendra/bca/p’


3. 수정(-i, w, d 스위치와 쉘 리다이렉션)
예제7: -i 옵션을 사용하면 변경점을 원본 파일에 적용할 수 있다.
sed –i ‘s/bca/Surendra/’ tem.txt

예제8: 리다이렉션으로도 같은 일을 할 수 있다.
sed ‘s/baby/dady/’ < tem.txt > abc.txt

예제9: w 옵션으로 변경점을 다른 파일에 저장할 수 있다.
sed ‘s/baby/dady/w abc.txt’ tem.txt


4. 여러 SED 명령어와 연속 연산자(-e와 ; 스위치)
예제10: Surendra, mouni, baby를 bca, mca, bba로 치환
sed -e ‘s/surendra/bca/’ -e ‘s/mouni/mca/’ -e ‘s/baby/bba/’ tem.txt

예제11: ;(연속 연산자)로 더 위보다 더 줄이기
sed ‘s/Surendra/bca/;s/mouni/mca/;s/baby/bba/’ tem.txt


5. 줄 번호 연산자(,와 = 스위치)
예제12: 3번째 줄 내용만 검색해서 치환하기
sed ‘3 s/Surendra/bca/’ tem.txt

예제13: 1~4번째 줄 내용만 검색해서 치환하기
sed ‘1,4 s/Surendra/bca/’ tem.txt

예제14: 2번째 줄에서부터 문서 끝까지 검색해서 치환하기
sed ‘2,$ s/Surendra/bca/’ tem.txt

예제15: 매 두 줄마다 한 줄로 결합. 아래는 N 옵션으로 두 줄을 합치는 예제. 치환으로 \n을 공백 같은 것으로 바꿔줘야 원하는 의도대로 나온다. sed는 기본적으로 한 줄씩 처리하여 출력하는데 두 줄을 하나로 합쳐놔도 라인피드(\n)가 그대로 남아있기 때문에 전혀 변하지 않은 것처럼 보이기 때문이다. 그리고 사실 아래 소개할 예제를 위해서 말고는 잘 안 쓰인다.
sed ‘N;s/\n/ /’ tem.txt

예제16: 검색해서 치환 후 모든 줄에 번호 넣기(‘=’ 옵션 사용)
sed = tem.txt

예제17: 번호를 같은 줄에 넣기
sed = tem.txt | sed ‘N;s/n/t/’


6. 검색 연산자(/단어/)
예제18: 한 단어를 검색해서 걸린 줄에서 작업하기
sed ‘/surendra/ s/audi/xyz/’ tem.txt

예제19: 위를 응용해서 특정 범위의 줄 내에서 작업하기
sed ‘3,/Surendra/ s/audi/xyz/’ tem.txt

예제20: 더 응용해서 찾은 단어가 있는 줄부터 문서 끝까지를 범위로 작업하기
sed ‘/Surendra/,$ s/audi/xyz/’ tem.txt


7. 부정 연산자(!)
  이 연산자는 w, p, d 옵션과 함께 사용한다.
예제21: abc 라는 단어가 없는 모든 줄을 출력
sed –n ‘/abc/ !p’ tem.txt

예제22: surenda 라는 단어가 있는 줄을 제외한 모든 줄을 삭제
sed ‘/surendra/ !d’ tem.txt

예제23: 1~3 줄만 빼고 모든 줄 삭제
sed ‘1,3 !d’

bash의 잘 알려지지 않은 기능 7가지

참조 원문 : 7 hidden features of bash

1. 이전 명령어 다시 실행
  sudo를 사용 안 하고 root 권한이 필요한 명령어를 했을 때 아주 유용한 기능. 파라미터로 !! 를 입력하면 마지막으로 실행했던 명령어를 반복한다. 예를 들어 apt-get 명령어를 사용했는데 sudo를 쓰지 않아서 앞에 sudo를 붙여 다시 실행해야 하다면 sudo !! 라고 실행한다.

2. bash 스크립트
bash -n bashscript.sh  ->  실제로 스크립트를 실행하지 않고 문법만 검사.
bash -x bashscript.sh  ->  디버그 모드로 스크립트 실행. 각 명령어와 그 결과를 단축하여 출력.

3. 이전 명령어의 특정 문자열을 치환
  ^이전문자열^새문자열^ 문법으로 달성할 수 있다.

$ sudo apt-get install wrongpackagename
$ ^wrongpackagename^rightpackagename^
sudo apt-get install rightpackagename

  sed나 vi와 비슷한 다른 방법도 있다.

$ sudo apt-get install wrongpackagename
$ !!:s/wrongpackagename/rightpackagename
sudo apt-get install rightpackagename


4. 이전 줄의 마지막 파라미터 사용
  가끔 명령어에서 긴 파라미터를 썼는데 그걸 또 써야 할 때가 있다. 예를 들어 어떤 디렉토리를 만들고 그 디렉토리로 이동하려고 할 때 아래와 같은 방법으로 이동할 수 있다.

# mkdir -p /this/is/mylong/pathto/some/directory
# cd $_

  $_는 마지막에 사용했던 명령어의 마지막 파라미터를 뜻한다. 그 이전 명령어들의 마지막 파라미터를 사용하고 싶다면 ‘Alt + .’ 단축키를 사용하면 된다. 이 단축키를 사용하면 마지막 파라미터를 출력하며, 한 번 더 누를 때마다 그 이전 명령어의 마지막 파라미터를 출력한다.

5. 지금 있는 디렉토리에서 하위 디렉토리만 출력

ls -d */

  -d 옵션은 디렉토리 엔트리만 보여주는 옵션이지만 파라미터를 입력하지 않으면 현재 디렉토리를 파라미터로 사용하기 때문에 ‘.’만 나온다.

6. 예전 명령어 검색
  ‘Ctrl + r’을 누르면 예전에 사용한 명령어를 검색할 수 있다. Ctrl + r을 누르고 타이핑을 치면 입력한 모든 텍스트를 포함하고 있는 명령어들 중 가장 최근에 사용한 것을 보여주며 Ctrl + r을 누를 때마다 더 오래된 명령어를 보여준다. 만약 지나쳤다면 Ctrl + s를 눌러 앞으로 검색하면 된다.

  하지만 Ctrl + s는 일반적으로 XOFF(interrupt data flow)로 맵핑되어 있는데 현대에는 거의 필요가 없는 기능이므로 stty -ixon 명령어를 통해 맵핑을 끊으면 된다.

7. 길고 복잡고 어려운 명령어를 입력하기 위해 기본 편집기($EDITOR 환경 변수에 설정된 에디터) 즉시 소환
  명령어를 쓰다가 Ctrl + x + e를 누르면 편집기가 실행되면서 쓰던 명령어가 그곳에 적힌다. 편집기에서 명령어를 완성하고 저장 후 종료하면 작성했던 내용이 쉘에서 실행된다.

고가용성 환경에서 cron을 운용하기 위한 rcron

참조 원문 : What is RCRON.. & How to Setup High Availability of cron Jobs Using RCRON

  HA(High Availability) 환경에서 cron을 사용해보신 분들이라면 이 프로그램이 유용하단 걸 동감하실 수 있으실 겁니다. 서버가 2대 있고 이 2대가 클러스터 구성일 때 액티브 서버에서만 실행되어야 할 cron 스케줄이 있다면 꽤 귀찮은 일이 생깁니다. 액티브와 스탠바이가 바꼈을 때 두 서버의 cron을 수동으로 수정해야 하기 때문이죠. Rcron은 이런 경우에 사용하는 프로그램으로서 구성 서버들 간의 상태를 확인하고 액티브 상태의 서버에서만 지정한 작업을 실행할 수 있게 해줍니다.

  그런데 rcron은 다른 서버의 생존을 파악하는 능력이 없기 때문에 그 역할을 위한 프로그램을 추가로 함께 사용해야 합니다. 이를 위해 이 글에서는 keepalived라는 별도의 데몬을 사용할 것입니다. Keepalived는 상대 노드에 신호를 보내고 응답이 없을 경우 링크가 죽었다고 판단하는 역할을 합니다.

  여기서는 하나의 노드를 keepalived 마스터로 설정하고 다른 한 노드를 keepalived 백업으로 설정할 겁니다. 마스터 노드는 rcron 상태가 액티브로 되며, 백업 노드는 패시브로 설정됩니다. 마스터 노드는 죽을 때 백업 노드에게 0 우선순위 신호를 보내며 이를 받은 백업 노드는 마스터 노드가 되어 rcron을 액티브 상태로 전환합니다. 그러다가 이전의 마스터 노드가 다시 살아나면 마스터 권한을 넘긴 후 백업 모드로 돌아가게 설정할 겁니다.

  설정 환경은 레드햇 계열 배포판인 것으로 가정합니다.


1. /etc/sysctl.conf 파일을 수정하여 두 노드의IP 포워딩 활성화시키기

net.ipv4.ip_forward = 1
# sysctl -p      ; 리부팅 없이 변경사항 적용


2. 두 노드에 EPEL 저장소 추가

# wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
# rpm -ivh epel-release-6-8.noarch.rpm


3. 두 노드에 필요한 패키지 설치

# yum install subversion byacc flex gcc


4. 프록시 서버를 통해 인터넷 연결을 할 경우 svn에 대한 http_proxy 설정(직접 인터넷 연결을 할 경우 생략)

# mkdir /root/.subversion/
#  vi ~/.subversion/servers
http-proxy-exceptions = *.example.com
http-proxy-host = www.example.com
http-proxy-port = 8080
http-compression = no


5. SVN으로 rcron 설치

# cd /root;
# svn co http://rcron.googlecode.com/svn/trunk rcron
# cd rcron/rcron
# ./configure
# make
# make install


6. 두 노드에 디렉토리 및 설정 파일 생성

# mkdir /etc/rcron/
# vi /etc/rcron/rcron.conf

(1) 마스터 서버 노드
  아래 내용 입력

# An arbitrary name
cluster_name        = cluster

# A file containing either the word “active” or the word “passive”
state_file          = /var/run/rcron/state

# The default state in case state_file can’t be read
#default_state       = active
syslog_facility     = LOG_CRON
syslog_level        = LOG_INFO

# We can tune jobs niceness/priorities
nice_level          = 19

  아래 명령어 실행

# mkdir /var/run/rcron
# touch /var/run/rcron/state
# echo “active” > /var/run/rcron/state

(2) 백업 서버 노드
  아래 내용 입력

# An arbitrary name
cluster_name = cluster
# A file containing either the word “active” or the word “passive”
state_file = /var/run/rcron/state
# The default state in case state_file can’t be read
#default_state = passive
syslog_facility = LOG_CRON
syslog_level = LOG_INFO
# We can tune jobs niceness/priorities
nice_level = 19

  아래 명령어 실행

# mkdir /var/run/rcron
# touch /var/run/rcron/state
# echo “passive” > /var/run/rcron/state


7. 두 노드에 Keepalive 패키지 설치
(1) 최신 소스 다운로드

# cd /root
# wget http://cgit.luffy.cx/keepalived/snapshot/keepalived-1.2.7.tar.gz

(2) RPM BUILD 패키지 설치

# yum -y install rpm-build

(3) 압축 풀기 및 keepalived.spec.in 파일 수정

# tar -zxvf keepalived-1.2.7.tar.gz
# mkdir -p /root/rpmbuild/SOURCES/
# cp /root/keepalived-1.2.7.tar.gz /root/rpmbuild/SOURCES/
# vi /root/keepalived-1.2.7/keepalived.spec.in
(Version 1.2.2를 Version 1.2.7로 수정)
# yum -y install popt*
# cd /root/keepalived-1.2.7
# rpmbuild -ba keepalived.spec.in

  위 명령어를 사용하면 소스를 이용해 컴파일된 RPM이 /root/rpmbuild/RPMS/x86_64/keepalived-1.2.7-5.x86_64.rpm라는 경로 및 파일명으로 생성됩니다. 이 파일을 이용해 설치합니다.

# rpm -ivh /root/rpmbuild/RPMS/x86_64/keepalived-1.2.7-5.x86_64.rpm


8. keepalived 설정
(1) 마스터 노드(172.16.243.144)

# vi /etc/keepalived/keepalived.conf

vrrp_instance VI_1 {
state MASTER
interface eth0
lvs_sync_daemon_inteface eth0
virtual_router_id 31
priority 101
advert_int 5
vrrp_unicast_bind 172.16.243.144
vrrp_unicast_peer 172.16.243.145

authentication {
auth_type PASS
auth_pass 1111
}

notify_backup “/bin/echo passive > /var/run/rcron/state”
notify_master “/bin/echo active > /var/run/rcron/state”
notify_fault “/bin/echo passive > /var/run/rcron/state”
}

(2) 백업 노드(172.16.243.145)

# vi /etc/keepalived/keepalived.conf

vrrp_instance VI_1 {
state BACKUP
interface eth0
lvs_sync_daemon_inteface eth0
virtual_router_id 31
priority 100
advert_int 5
vrrp_unicast_bind 172.16.243.145
vrrp_unicast_peer 172.16.243.144

authentication {
auth_type PASS
auth_pass 1111
}

notify_backup “/bin/echo passive > /var/run/rcron/state”
notify_master “/bin/echo active > /var/run/rcron/state”
notify_fault “/bin/echo passive > /var/run/rcron/state”
}


9. 두 노드에 실험용 crontab 항목 생성

* * * * * /usr/local/bin/rcron –conf /etc/rcron/rcron.conf echo `date` >> /tmp/output

  두 노드 모두 keepalive 서비스를 시작합니다.

# service keepalived start ; chkconfig keepalived on


10. keepalived 데몬이 죽을 경우에 대비
  아래의 crontab 항목을 추가합니다.

* * * * * * /root/keep-alive-monitor

  그리고 아래 스크립트를 생성합니다.

# vi /root/keep-alive-monitor

#!/bin/sh
echo “test” >> /tmp/monitor;
ps -ef|grep -v grep|grep -i keepalived;
if [ $? -eq 0 ] ; then
exit 0
else
echo “passive” > /var/run/rcron/state;
/etc/init.d/keepalived restart;
fi

 

mysql replication

MySQL 에서  Replication 이 적용되는 방식은 아래 그림을 요약할 수 있다.

1. Master 에서 데이터의 변경작업이 발생하면 Master DB의 변경 실행

2. 변경된 이력을 Binary Log 에 기록

3. Slave 의 IO Thread 가 Master 의 변경 Event 를 감지하고 Master 의 Binary Log 를 자신(Slave)의 Relay Log 에 기록한다.

4. Slave 의 SQL Thread 는 Relay Log 를 읽고 자신(Slave)의 DB에 기록한다.

위 그림에서처럼 Master 에서 Slave 방향으로 단방향으로만 처리가 이루어 지므로 변경작업(Write)는 Master에만 하여야 한다.

Slave에서 변경작업을 할 경우 Master에는 당연히 반영이 안되며, Slave에서 변경작업한 Object 에 대하여 Master 서 변경작업을 다시 시도할 경우 변경은 되지만 다시 slave에 는 적용되지 않는다.