검색 엔진의 방문이 늘어나고 있군...

Posted
Filed under 쉘 스크립트
참조 원문 : Recording User Activity with a Script

  'script'라는 명령어는 터미널 세션에 출력되는 모든 글자를 파일에 기록하는 기능을 가지고 있습니다. 이를 스크립트에 이용하여 사용자의 활동을 로그로 남기는 딱히 쓸모없어 보이지만 흥미로운 글을 발견하여 포스팅합니다.
#!/bin/bash
# Capture keystrokes of a user and log

TIMESTAMP=$(date +%m%d%y%H%M%S)
HOST=$(hostname|cut -f1 -d.)
LOGDIR=/var/log/user
LOGFILE=${HOST}.${LOGNAME}.${TIMESTAMP}
touch $LOGDIR/$LOGFILE

chown $LOGNAME ${LOGDIR}/${LOGFILE}
chmod 600 ${LOGDIR}/${LOGFILE}

script ${LOGDIR}/${LOGFILE}
chmod 400 ${LOGDIR}/${LOGFILE}
  위 스크립트는 호스트명, 사용자명, 타임스탬프로 /var/log/user 디렉토리 안에 로그 파일을 만들어 기록하게 만듭니다. 정확히는 적당한 경로에 적당한 이름으로 파일을 만들어 퍼미션을 조정하는 것 뿐이고 정작 중요한 기록은 script 명령어가 다 합니다. 참고로 /var/log/user라는 디렉토리는 기본적으로 없기 때문에 스크립트를 사용하기 전에 미리 만들어야 합니다.

  위 스크립트를 적당한 위치에 적당한 이름으로 놓고 활동을 로깅할 사용자의 홈 디렉토리에 있는 .bash_profile이나 .profile에서 위 스크립트를 실행하도록 만들면 됩니다. 만약 모든 사용자에 대해 위 스크립트를 적용하고 싶다면 /etc/profile 파일에서 위 스크립트를 실행하게 만들면 됩니다.


2011/01/05 10:05 2011/01/05 10:05
Posted
Filed under 쉘 스크립트
참조 원문 : 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}
2010/12/29 13:44 2010/12/29 13:44
Posted
Filed under 쉘 스크립트
참조 원문 : HowTo: Use Bash Parameter Substitution Like A Pro

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


more..


more..


more..


more..


more..


more..


more..



요약: 문자열 조작과 확장 변수
  • ${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} : 검색 및 치환(모두)
2010/12/21 09:53 2010/12/21 09:53
Posted
Filed under 프로그램과 명령어/커맨드 라인 트릭
참조 원문 : My top ten shell/bash tricks!


1. sudo를 사용하는 것을 잊었을 때 !! 활용
  루트 권한이 필요한 명령어를 사용할 때 sudo를 사용하는 것을 잊어서 처음부터 다시 타이핑을 하거나 이전 명령어를 불러 앞 부분에 sudo를 붙이는 경우가 있는데 더 간편하게 하는 방법이 있습니다. 바로 이전에 실행한 명령어로 대체되는 '!!' 문자열을 사용하는 겁니다. 배시 쉘에서 사용이 가능합니다.
$ ethtool eth0
Settings for eth0:
Cannot get device settings: Operation not permitted
Cannot get wake-on-lan settings: Operation not permitted
    Current message level: 0x00000000 (0)
Cannot get link status: Operation not permitted
$ sudo !!
sudo ethtool eth0
[sudo] password for mirashi:


2. Ctrl+R로 이전에 사용한 명령어 찾기
  역시 배시 쉘에서 사용이 가능한 기능으로 Ctrl+R을 누른 후 이전에 사용한 명령어에 포함된 문자나 문자열을 입력하여 이전에 사용한 명령어를 검색할 수 있습니다. 검색은 가장 최근 실행한 것부터 역순으로 검색되며 Ctrl+R을 누를 때마다 검색을 계속 진행합니다. 그냥 Ctrl+R만 계속 누를 경우 이전에 실행한 명령어들을 차례대로 보여줍니다. 역시 배시 쉘에서 가능합니다.

  이전에 실행한 명령어를 검색하는 또 다른 방법으로는 'history | grep 검색할_명령어'를 실행하는 방법이 있습니다.


3. 가장 많이 실행했던 명령어 10개 보기
$ history | tr '\011' ' ' | tr -s " "| cut -d' ' -f3 | sort | uniq -c | sort -nbr | head -n10
    212 sudo
     38 man
     26 ls
     24 cd
     23 echo
     15 vi
     15 awk
     13 dig
     12 lsof
      9 htpasswd


4. 한방에 시스템을 무너트리는 명령어
  아래의 명령어로 시스템에 DoS 공격을 할 수 있습니다. fork bomb이라고 하는 공격이며 프로세스 복제로 프로세스 테이블을 포화상태로 만듭니다.
:(){ :|:& };:


5. &&로 연쇄 반응 일으키기
  '&&'는 명령어를 순차적으로 실행하게 해줍니다. 만약 '명령어1 && 명령어2'이라는 형식으로 실행하면 '명령어1'이 실행되어 무사히 종료됐을 경우에만 '명령어2'가 실행됩니다. 여기서 중요한 사실은 만약 '명령어1'의 종료 값이 0이 아닐 경우(=비정상 종료했을 경우) '명령어2'가 실행되지 않는다는 겁니다. 아래는 데비안 계열의 배포판에서 이 기법을 활용한 예로 패키지 목록을 업데이트한 후 패키지 업데이트를 실행하는 명령어입니다.
sudo apt-get update && sudo apt-get upgrade


6. screen 명령어로 화면 분할
  먼저 'screen' 명령어를 실행합니다. 그리고 엔터를 눌러 쉘 화면으로 빠져나옵니다. 이제 Ctrl+a를 누른 후 S(대문자)를 누르면 화면이 분할됩니다. 이제 Ctrl+a를 누른 후 탭을 누르면 다음 창으로 넘어갈 수 있습니다. 분할 후 새로 생긴 창에는 아무것도 없는데 커서가 그런 창에 있는 상태에서 Ctrl+a를 누른 후 c(소문자)를 누르면 쉘이 실행됩니다. 현재 커서가 있는 창을 닫고 싶을 때는 Ctrl+a를 누른 후 X(대문자)를 누르면 됩니다.

2010/12/14 17:05 2010/12/14 17:05
Posted
Filed under 쉘 스크립트
참조 원문 : Single vs. Double Quotes in Bash

  배시 쉘을 쓰다보면 백 쿼트(`), 싱글 쿼트('), 더블 쿼트(")의 기능이 햇갈리기 마련입니다. 특히 싱글 쿼트와 더블 쿼트는 똑같이 문자열을 처리하기 위해 존재하지만 둘 사이에는 작은 차이가 있고 그 작은 차이도 파고들면 복잡해집니다.

  백 쿼트(`)는 그 안에 있는 명령어의 실행 결과(정확히는 표준 출력-stdout-)를 다시 입력으로 바꾸는 기능을 가지고 있습니다. 주로 변수에 어떤 명령어의 출력 결과를 집어넣을 때 사용합니다. 말로 설명하면 어렵지만 아래의 예로 쉽게 이해할 수 있으리라 생각합니다.
mirashi@myservlab:~$ echo Today is `date +%A`
Today is Tuesday

mirashi@myservlab:~$ uname
Linux
mirashi@myservlab:~$ UNAME_RET=`uname`
mirashi@myservlab:~$ echo $UNAME_RET
Linux

  이제 싱글 쿼트(')에 대해 알아보겠습니다. 두 싱글 쿼트 사이에 있는 문자열은 어떤 해석도 거치지 않고 문자 그대로 인식합니다. 아래의 예를 봅시다.
mirashi@myservlab:~$ name="Juliet Kemp"
mirashi@myservlab:~$ echo "$name"
Juliet Kemp
mirashi@myservlab:~$ echo '$name'
$name
  이렇듯 싱글 쿼트는 변환이고 해석이고 뭐고 가차 없이 문자열을 있는 그대로 받아들입니다. 참 솔직한 녀석이 아닐 수 없습니다. 그러므로 문자열에 특수 문자가 많을 때 유용합니다. 물론 같은 이유로 변수를 다루는 부분에서 쓰면 영 좋지 않겠죠?


  더블 쿼트(")는 좀 더 유연한 녀석입니다. 안에 있는 문자열에서 몇 가지 특수 문자를 재해석합니다. 재해석하는 문자로는 공식적으로 달러($), 백쿼트(`), 그리고 이스케이프(\ 로 시작) 문자가 있습니다만...디폴트 상태의 배시 쉘이라면 여기에 느낌표(!)가 추가됩니다. 여기에 대한 이야기는 조금 있다가 하도록 하겠습니다.

  더블 쿼트는 문자열 중간에 공백이 있을 때, 변수와 함께 사용할 때, 명령어의 인수로 사용할 문자열에 공백 문자가 포함되어 하나의 인수가 둘로 인식되는 것을 막을 때 유용합니다. 셋 중 앞의 2개는 바로 위에 있는 싱글 쿼트 예제의 첫 번째 줄과 두 번째 줄에서 차례대로 볼 수 있습니다. 아래는 세 번째 내용을 설명하기 위한 예제입니다.
mirashi@myservlab:~$ mkdir my directory
mirashi@myservlab:~$ ls -l
drwxr-xr-x 2 mirashi mirashi 4096 2010-10-21 19:38 directory
drwxr-xr-x 2 mirashi mirashi 4096 2010-10-21 19:38 my
mirashi@myservlab:~$ mkdir "my directory"
mirashi@myservlab:~$ ls -l
drwxr-xr-x 2 mirashi mirashi 4096 2010-10-21 19:38 directory
drwxr-xr-x 2 mirashi mirashi 4096 2010-10-21 19:38 my
drwxr-xr-x 2 mirashi mirashi 4096 2010-10-21 19:38 my directory
  전자의 경우 my와 directory라는 2개의 디렉토리가 만들어졌지만 후자는 공백 문자가 포함된 my directory라는 디렉토리가 만들어졌습니다. 그렇다면 이번에는 변수와 함께 사용할 때 어떻게 유용한지 볼까요?
mirashi@myservlab:~$ NameToRemove="my directory"
mirashi@myservlab:~$ rmdir "$NameToRemove"
mirashi@myservlab:~$ ls -l
drwxr-xr-x 2 mirashi mirashi 4096 2010-10-21 19:38 directory
drwxr-xr-x 2 mirashi mirashi 4096 2010-10-21 19:38 my
mirashi@myservlab:~$ rmdir $NameToRemove
mirashi@myservlab:~$ ls -l
mirashi@myservlab:~$
  둘의 차이가 보이십니까? 변수를 인수로 사용할 때 변수명을 더블 쿼트로 감싸면 변수의 내용 전체가 하나의 인수로 인식되는 것을 볼 수 있습니다. 변수의 내용을 변수명 대신 그대로 대입해보면 위 내용을 쉽게 이해할 수 있으리라 생각합니다. 또 다른 예로 아래와 같은 경우가 있습니다.
mirashi@myservlab:~$ ls
abcdef
mirashi@myservlab:~$ dpkg-query -l abc*
No packages found matching abcdef.
mirashi@myservlab:~$ dpkg-query -l "abc*"
No packages found matching abc*.
  사용자가 있는 디렉토리에는 abcdef라는 이름의 파일이 있습니다. 이 상태에서 abc라는 이름으로 시작하는 패키지를 검색하기 위해 dpkg-query -l abc* 라고 명령어를 실행했습니다. 그랬더니 abc*가 확장되어 abcdef로 변한 다음 dpkg-query 명령어가 실행되는 것을 볼 수 있습니다. 그래서 abc*를 더블 쿼트로 묶어 실행했더니 의도대로 명령어가 실행되는 것을 볼 수 있습니다.


  아까 더블 쿼트에서 달러($), 백쿼트(`), 그리고 이스케이프 문자 외에 느낌표(!)도 재해석되는 문자에 포함된다고 했는데 사실 엄밀히 따지자면 더블 쿼트와는 관계가 없습니다. 배시 쉘에서 느낌표는 '히스토리 익스팬션(History Expansion)'이라는 것의 디폴트 문자로 쓰이는데 이것은 배시 쉘의 히스토리 기능을 이용한 일종의 명령어 단축 실행 기능이라고 할 수 있습니다. 대충 아래와 같은 기능입니다.
mirashi@myservlab:~$ echo "history expansion"
history expansion
mirashi@myservlab:~$ !e
echo "history expansion"
history expansion
  문제는 이 히스토리 익스팬션 문자라는 것은 백슬래시(\)와 싱글 쿼트(')로만 문자 자체로서 표시(Quote)할 수 있다는 겁니다. 그럼 혹자는 '느낌표 앞에 백슬래시를 쓰면 되겠네?'라고 생각하겠지만 아래처럼 그 방법은 안 통합니다.
mirashi@myservlab:~$ echo "hi\!"
hi\!
  느낌표가 히스토리 익스팬션 문자로 쓰이는 것은 막았으나 더블 쿼트에서 재해석되는 문자는 달러($), 백쿼트(`), 이스케이프 문자 밖에 없기 때문에 백슬래시도 그대로 출력되어 버립니다. 그러면 느낌표를 어떻게 해야 출력할 수 있을까요? 혹자는 아래와 같은 해결 방안을 제시할 수도 있습니다.
mirashi@myservlab:~$ echo hi!
hi!
  네. 되긴 됩니다. 근데 쿼트를 아예 안 쓰고 억지고 해결했다는 문제는 제끼더라도 저게 과연 제대로 작동하고 있는 걸까요? 아래를 봅시다.
mirashi@myservlab:~$ echo hi!yo
-bash: !yo: event not found
  결국 눈가리고 아웅이라는 겁니다. 출력은 됐을지언정 그 출력된 느낌표는 여전히 히스토리 익스팬션 문자로서 역할을 하고 있는 것이죠. 이 문제를 해결하는 방법은 2가지가 있는데 하나는 싱글 쿼트를 사용하는 겁니다. 이 포스트에서 가장 먼저 설명했듯이 싱글 쿼트는 다음 싱글 쿼트가 나오기 전까지의 모든 문자를 문자 그대로 받아들입니다. 조금 전에도 히스토리 익스팬션 문자는 백슬래시(\)와 싱글 쿼트(')로만 문자 자체로서 표시할 수 있다고 했었지요.
mirashi@myservlab:~$ echo 'hi!'
hi!
  다른 방법은 히스토리 익스팬션 문자를 다른 것으로 바꾸거나 아예 없애버리는 겁니다. 히스토리 익스팬션 문자는 'histchars'이라는 이름의 쉘 변수를 통해 지정할 수 있습니다. 참고로 오타 아니고 정말 소문자 맞습니다. 아래처럼 저 변수에 빈 값을 넣으면 자연스럽게 이 기능을 사용하지 않게 되는 것이죠.
mirashi@myservlab:~$ histchars=
mirashi@myservlab:~$ echo "hi!"
hi!
  그런데 배시 쉘은 디폴트로 느낌표를 히스토리 익스팬션 문자로 사용하기 때문에 이 방법은 별로 좋은 방법이라고 할 수 없겠습니다. 자기 호스트에서 저렇게 설정하고 저걸 기준으로 스크립트를 짰다가 다른 호스트에 복사해서 그대로 사용했다간...별로 좋지 못하겠죠. 히스토리 익스팬션은 정말 뻘스러운 기능이 아닌가 싶습니다. 마지막으로 원문의 리플에 달린 뻘스럽지만 그래서 좋은 예제를 보며 포스트를 마치겠습니다.
bash$ cost=2.79
bash$ echo "Alice's sister said, \"Gas costs \$$cost/gal"'!'"\""
Alice's sister said, "Gas costs $2.79/gal!"
bash$ echo 'Bob'"'"'s reply was, "$'"$cost"' is too much!"'
Bob's reply was, "$2.79 is too much!"


2010/10/21 18:00 2010/10/21 18:00