WRITTEN BY
정현석
이것저것 끄적끄적....

,

WRITTEN BY
정현석
이것저것 끄적끄적....

,
출처 : http://greenfishblog.tistory.com/43

shell script는 반복적인 shell 작업을 자동화 하는데 훌륭한 도구입니다. Bash 뿐만 아니라 다른 shell은 loop, 조건 검사, case문 등과 같은 프로그래밍을 할 수 있는 기본적인 구조를 제공하고 있습니다. 단지 다른점은, string 타입의 변수만 지원된다는 점입니다.


script를 편집하고 실행하기

shell script는 간단한 text 파일입니다. 그래서 당신이 선호하는 text editor(vi)를 이용하여 만들 수 있습니다. 실행을 위해서 shell script 파일은 실행가능해야 합니다. 예를 들어, 만약 당신이 myscript.sh 이름으로 shell script를 생성했다면, 다음을 통해 실행가능하게 만드는 것이 필요합니다.

chmod u+x myscript.sh

그리고, bash script의 첫 line은 반드시 다음과 같아야 합니다.

#! /bin/bash

#는 comment의 시작을 알립니다. #! syntax는 이러한 특수한 문법을 적용하지 말라고 shell에게 알려주는 역할을 합니다. /bin/bash 부분은 bash나 다른 shell과 같은 어떤 동작 가능한 shell에게 script를 실행해라는 뜻입니다.

당신이 작성한 실행 가능한 shell script는 PATH 혹은 전체 경로 혹은 상대경로에 있어야 합니다. 다시 말해 script를 실행할 때 다음과 같은 결과를 얻을 수 있습니다.

$ myscript.sh
myscript.sh: command not found
현재 디렉토리에 myscript.sh가 있어도, 해당 PATH에 포함되지 않은 경우입니다. 이러한 문제를 해결하기 위해, PATH에 추가하던가 아니면 전체 경로 혹은 상대경로로 실행합니다.
$ mkdir ~/bin ; cp myscript.sh ~/bin/ ; PATH=$PATH:~/bin
$ cp myscript.sh /user/local/bin
$ ./myscript.sh
$ /home/greenfish/work/myscript.sh


Script에 내용 추가하기

shell script는 명령의 단순 나열이지만, 또한 훌륭한 programming language이기도 합니다. 예를 들어, 주어진 다른 input으로 발생된 다른 output의 different를 추출할 수 있습니다. if/else, case 그리고 for/while loop 같은 명령들을 다루기로 하겠습니다.

다음의 예제 코드는 abc를 MYSTRING 변수에 할당하는 것을 보여줍니다. 그리고, abc인지 테스트하며, 그 결과를 보여줍니다. 테스트는 [ ]에 의해 구성됩니다.

MYSTRING=abc
if [ $MYSTRING = abc ] ; then
echo "The variable is abc"
fi
부정 조건 테스트는 !=를 사용합니다.
if [ $MYSTRING != abc ] ; then
echo "$MYSTRING is not abc";
fi

다음은 숫자에 대한 테스트를 보여줍니다.
MYNUMBER=1
if [ $MYNUMBER -eq 1 ] ; then echo "MYNUMBER equals 1"; fi
if [ $MYNUMBER -lt 2 ] ; then echo "MYNUMBER <2"; fi
if [ $MYNUMBER -le 1 ] ; then echo "MYNUMBER <=1"; fi
if [ $MYNUMBER -gt 0 ] ; then echo "MYNUMBER >0"; fi
if [ $MYNUMBER -ge 1 ] ; then echo "MYNUMBER >=1"; fi

이제 파일 이름에 대한 테스트를 확인해 봅시다. 아래 예는, 파일의 존재 여부 체크 (-e), 정규 파일 체크 (-r), 디렉토리 체크 (-d)와 같습니다. 이러한 체크는 if/then으로 구성됩니다. 만약 일치되지 않는다면 그에 상응되는 결과를 보고합니다.

filename="$HOME"
if [ -e $filename ] ; then echo "$filename exists"; fi
if [ -f "$filename" ] ; then
 echo "$filename is a regular file"
elif [ -d "$filename" ] ; then
 echo "$filename is a directory"
else
 echo "I have no idea what $filename is"
fi

아래 표는 파일, 문자열 그리고 변수에 대한 테스트에 필요한 Operator를 보여줍니다.

Operator 설명
 -a file  파일 존재 여부 체크 (-e와 동일) 
 -b file  special block device 파일인지 체크 
 -c file  special device 파일인지 체크 (예, serial device) 
 -d file  디렉토리 체크 
 -e file  파일 존재 여부 체크 (-a와 동일) 
 -f file  파일이 존재하고 정규 파일인지 체크
 (directory, socket, pipe, link, device 등은 아님) 
 -g file  set-group-id bit가 세팅된 파일인지 체크 
 -h file  심볼릭 링크인지 체크 (-L과 동일) 
 -k file  sticky bit가 세팅된 파일인지 체크
 -L file  심볼릭 링크인지 체크 (-h와  동일)
 -n string  문자열 길이가 0 byte 이상인지 체크 
 -o file  당신이 소유한 파일인지 체크 
 -p file  named pipe 파일인지 체크 
 -r file  당신이 읽을 수 있는 파일인지 체크
 -s file  파일이 존재하고, socket인지 체크
 -t fd  terminal에 연결된 파일 descriptor인지 체크 
 -u file  set-user-id bit가 세팅된 파일인지 체크 
 -w file  당신이 쓸수 있는 파일인지 체크 
 -x file  당신이 실행할 수 있는 파일인지 체크
 -z string  문자열 길이가 0 byte 인지 체크
 expr1 -a expr2  처음과 두번째 expression이 true인지 체크 
 expr1 -o expr2  처음과 두번째 expression중 하나가 true인지 체크 
 file1 -nt file2  처음 파일이 두번째 파일보다 새 파일인지 체크 
 file1 -ot file2  처음 파일이 두번째 파일보다 오래된 파일인지 체크 
 file1 -ef file2  두개의 파일이 하드 혹은 심볼릭 링크로 연결되어 있는지 체크 
 var1 = var2  두개의 값이 동일한지 체크 
 var1 -eq var2  두개의 값이 동일한지 체크 
 var1 -ge var2  첫번째 값이 두번째 값보다 같거나 큰지 체크 
 var1 -gt var2  첫번째 값이 두번째 값보다 큰지 체크 
 var1 -le var2  첫번째 값이 두번째 값보다 같거나 작은지 체크 
 var1 -lt var2  첫번째 값이 두번째 값보다 작은지 체크 
 var != var2  두개의 값이 다른지 체크 
 var -ne var2  두개의 값이 다른지 체크 

그다음으로 자주 사용되는 명령은 case 입니다. case를 이용하여 각각 다른 값의 테스트를 할 수 있습니다. 프로그래밍언어의 보통 switch 구문과 유사합니다. case 구문은 몇개 단계의 if 구문으로 구성될 수 있습니다.

case “$VAR” in
 string1)
  { action1 };;
 string2)
  { action2 };;
 *)
  { default action } ;;
esac

그리고, case의 예제를 /etc/init.d/ 경로에 start-up script를 통해 찾을 수 있습니다. 각각의 initscript는 어떤 파라미터(start, stop, ...)가 들어왔는지 체크하고 선택합니다.

/etc/init.d$ cat networking
#!/bin/sh -e
### BEGIN INIT INFO
# Provides:          networking
# Required-Start:
# Required-Stop:     $local_fs
# Default-Start:
# Default-Stop:      0 6
# Short-Description: Raise network interfaces.
### END INIT INFO

PATH="/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"

[ -x /sbin/ifup ] || exit 0

. /lib/lsb/init-functions

# helper function to set the usplash timeout. https://launchpad.net/bugs/21617
usplash_timeout () {
        TIMEOUT=$1
        if [ -x /sbin/usplash_write ]; then
            /sbin/usplash_write "TIMEOUT $TIMEOUT" || true
        fi
}

process_options() {
    [ -e /etc/network/options ] || return 0
    log_warning_msg "/etc/network/options still exists and it will be IGNORED! Read README.Debian of netbase."
}

check_network_file_systems() {
    [ -e /proc/mounts ] || return 0

    if [ -e /etc/iscsi/iscsi.initramfs ]; then
        # probably root on iSCSI
        log_warning_msg "not deconfiguring network interfaces: root filesystem appears to be on iSCSI."
        exit 0
    fi

    exec 9<&0 < /proc/mounts
    while read DEV MTPT FSTYPE REST; do
        case $DEV in
        /dev/nbd*|/dev/nd[a-z]*|/dev/etherd/e*)
            log_warning_msg "not deconfiguring network interfaces: network devices still mounted."
            exit 0
            ;;
        esac
        case $FSTYPE in
        nfs|nfs4|smbfs|ncp|ncpfs|cifs|coda|ocfs2|gfs|pvfs|pvfs2|fuse.httpfs|fuse.curlftpfs)
            log_warning_msg "not deconfiguring network interfaces: network file systems still mounted."
            exit 0
            ;;
        esac
    done
    exec 0<&9 9<&-
}

case "$1" in
start)
        /lib/init/upstart-job networking start
        ;;

stop)
        check_network_file_systems

        log_action_begin_msg "Deconfiguring network interfaces"
        if [ "$VERBOSE" != no ]; then
            if ifdown -a --exclude=lo; then
                log_action_end_msg $?
            else
                log_action_end_msg $?
            fi
        else
            if ifdown -a --exclude=lo >/dev/null 2>/dev/null; then
                log_action_end_msg $?
            else
                log_action_end_msg $?
            fi
        fi
        ;;

force-reload|restart)
        process_options

        log_action_begin_msg "Reconfiguring network interfaces"
        ifdown -a --exclude=lo || true
        if ifup -a --exclude=lo; then
            log_action_end_msg $?
        else
            log_action_end_msg $?
        fi
        ;;

*)
        echo "Usage: /etc/init.d/networking {start|stop|restart|force-reload}"
        exit 1
        ;;
esac

exit 0


bash shell은 또한 표준 loop 방식을 제공합니다. 다음을 숫자 0~9를 출력합니다.
for NUMBER in 0 1 2 3 4 5 6 7 8 9
do
    echo The number is $NUMBER
done

아래는 ls 명령의 결과를 제공받아 for 구문에 전달하는것을 보여주고 있습니다.
for FILE in `/bin/ls`; do echo $FILE; done

다음과 같이 while loop를 이용하여 VAR 변수가 0에서 3으로 증가하는 것을 확인할 수 있습니다.
"VAR=0"
while [ $VAR -lt 3 ]; do
    echo $VAR
    VAR=$[$VAR+1]
done


WRITTEN BY
정현석
이것저것 끄적끄적....

,
출처 : http://greenfishblog.tistory.com/41
 


Command Line Completion 사용하기


Tab키를 이용하여 command line을 완성키킬 수 있습니다.

$ tracer<Tab> : tracerout6 완성
$ cd /home/gre<Tab> : cd /home/greenfish/ 완성
$ cd ~gre<Tab> : cd /home/greenfish/ 완성
$ echo $PA<Tab> : echo $PATH 완성


stdin과 stdout으로 redirect하기

shell에서 typing하면 interactive하게 동작합니다. 결과를 보고하는 process는 두개의 output stream을 가집니다.
  • stdout : 일반 command의 output
  • stderr : error output

아래의 예로, /tmpp가 없는 경우, 에러 메시지는 stderr로 보내지고, /tmp의 list로 부터 나온 output은 stdout으로 출력됩니다.

ls /tmp /tmpp
ls: cannot access /tmpp: No such file or directory
/tmp:
orbit-gdm  pulse-PKdhtXMmr18n

기본적으로 모든 output은 스크린에 직접 표시됩니다. >문자를 사용하여 output을 파일로 저장할 수 있습니다. 특별히 standard output stream은 >를, standard error stream은 2>를 사용하여 파일로 저장합니다.
ls /tmp /tmmp > output.txt
ls: cannot access /tmmp: No such file or directory
$ ls /tmp /tmmp 2> errors.txt
/tmp:
orbit-gdm  pulse-PKdhtXMmr18n
ls /tmp /tmmp 2> errors.txt > ouptput.txt
ls /tmp /tmmp > everything.txt 2>&1

위 설명대로라면, 첫 예제는 output.txt에 stdout 내용이 저장(redirect)이 되며, stderr은 화면에 출력하게 됩니다. 두 번째 예제는 stderr은 errors.txt로 저장(redirect)되며, stdout은 화면에 출력됩니다. 세번째 예제는 첫 번째, 두 번째가 조합된 경우입니다. 그리고 마지막 예제는 두개 모두의 stream을 everything.txt에 저장(redirect)합니다. 만일 덮어 쓰기(overwrite) 대신에 파일에 추가하고 싶다면, >>를 사용합니다.

만약, 어떠한 output stream을 보고 싶지 않다면, 특별한 bit bucket 파일인 /dev/null로 redirect하여 해결할 수 있습니다.

ls /tmp
orbit-gdm  pulse-PKdhtXMmr18n
ls /tmp > /dev/null
$

다음은 pipe와 조합했을때의 경우입니다.
아래의 예에서는, stderr을 표시하지 않고, sort된 경로를 표시하는 방법을 보여줍니다.
$ ls /tmp/ /tmmp | sort
ls: cannot access /tmmp: No such file or directory
orbit-gdm
pulse-PKdhtXMmr18n
/tmp/:
ls /tmp/ /tmmp 2> /dev/null | sort
orbit-gdm
pulse-PKdhtXMmr18n
/tmp/:

$

또한 pipe는 다음과 같이 많은 것에 사용됩니다.
dpkg-query -l | grep -i sql | wc -l
3
ps auwx | grep firefox
1000      3136  0.0  0.1   3320   808 pts/6    S+   19:04   0:00 grep --color=auto firefox
ps auwx | less
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.3   2664  1608 ?        Ss   16:43   0:01 /sbin/init
...
:
...
whereis -m bash | awk '{print $2}'
/usr/share/man/man1/bash.1.gz

첫번째 명령은 설치된 package중에서 대소문자 구별없이 'sql'을 포함하는 것을 나열하되, 그 라인수를 출력하게 합니다. 두번째 명령은 long process 목록으로 부터 firefox process를 표시합니다. 세번째 명령은 process 목록을 페이지 단위로 보여줍니다. 마지막 명령은 "bash: /user/share/man/man1/bash.1.gz"와 같이 표시하는데, 단지 경로만 표시하도록 해줍니다.

`를 이용하여 한 section의 명령을 먼저 실행하고, 명령줄의 나머지 명령의 output을 입력(feed)합니다.
which bash
/bin/bash
ls -l /bin/bash
-rwxr-xr-x 1 root root 818232 2010-04-18 18:51 /bin/bash
ls -l `which bash`
-rwxr-xr-x 1 root root 818232 2010-04-18 18:51 /bin/bash
즉, 위 예처럼, which bash의 결과를 ls -l에 입력하여 실행이 됩니다.

좀더 결과를 입력하는 좀더 강력한 방법은 xargs command를 사용하는 것입니다.
ls /bin/b*
/bin/bash     /bin/bzcat   /bin/bzegrep  /bin/bzgrep        /bin/bzless
/bin/bunzip2  /bin/bzcmp   /bin/bzexe    /bin/bzip2         /bin/bzmore
/bin/busybox  /bin/bzdiff  /bin/bzfgrep  /bin/bzip2recover
dpkg-query -S /bin/bash
bash: /bin/bash
ls /bin/b* | xargs dpkg-query -S
bash: /bin/bash
bzip2: /bin/bunzip2
busybox-static: /bin/busybox
bzip2: /bin/bzcat
bzip2: /bin/bzcmp
bzip2: /bin/bzdiff
bzip2: /bin/bzegrep
bzip2: /bin/bzexe
bzip2: /bin/bzfgrep
bzip2: /bin/bzgrep
bzip2: /bin/bzip2
bzip2: /bin/bzip2recover
bzip2: /bin/bzless
bzip2: /bin/bzmore
ls /bin/b* | xargs -t dpkg-query -S
dpkg-query -S /bin/bash /bin/bunzip2 /bin/busybox /bin/bzcat /bin/bzcmp /bin/bzdiff /bin/bzegrep /bin/bzexe /bin/bzfgrep /bin/bzgrep /bin/bzip2 /bin/bzip2recover /bin/bzless /bin/bzmore
bash: /bin/bash
bzip2: /bin/bunzip2
busybox-static: /bin/busybox
bzip2: /bin/bzcat
bzip2: /bin/bzcmp
bzip2: /bin/bzdiff
bzip2: /bin/bzegrep
bzip2: /bin/bzexe
bzip2: /bin/bzfgrep
bzip2: /bin/bzgrep
bzip2: /bin/bzip2
bzip2: /bin/bzip2recover
bzip2: /bin/bzless
bzip2: /bin/bzmore
위 예에서, dpkg-query -S 명령으로 전달된 output을 전부 출력하고 있습니다. -t를 xargs에 사용하면, xargs를 사용하기 전의 output을 출력한뒤 실행합니다. 이제 dpkg-query 명령에 ls input으로 부터 output을 각각 xargs로 전달해 봅시다.
ls /bin/b* | xargs -t -I{} dpkg-query -S {}
dpkg-query -S /bin/bash
bash: /bin/bash
dpkg-query -S /bin/bunzip2
bzip2: /bin/bunzip2
dpkg-query -S /bin/busybox
busybox-static: /bin/busybox
dpkg-query -S /bin/bzcat
bzip2: /bin/bzcat
dpkg-query -S /bin/bzcmp
bzip2: /bin/bzcmp
dpkg-query -S /bin/bzdiff
bzip2: /bin/bzdiff
dpkg-query -S /bin/bzegrep
bzip2: /bin/bzegrep
dpkg-query -S /bin/bzexe
bzip2: /bin/bzexe
dpkg-query -S /bin/bzfgrep
bzip2: /bin/bzfgrep
dpkg-query -S /bin/bzgrep
bzip2: /bin/bzgrep
dpkg-query -S /bin/bzip2
bzip2: /bin/bzip2
dpkg-query -S /bin/bzip2recover
bzip2: /bin/bzip2recover
dpkg-query -S /bin/bzless
bzip2: /bin/bzless
dpkg-query -S /bin/bzmore
bzip2: /bin/bzmore
output에서 보여진것 처럼, 각각의 dpkg-query -S 명령이 ls에 의해 실행된 것으로 각각 개별적으로 실행됩니다.


alias 사용하기

alias를 세팅하고 나열하는 것으로 alias를 사용합니다. 몇몇 alias들은 이전에 설명되었던 shell initialization 파일에 의해 사용자 지정된 경우 혹은 system-wide한 경우로 이미 세팅되어 있습니다.

$ alias
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'

확인해 볼 수 있는건, 이러한 alias들은 명령에 옵션을 추가할 수 있는 간순한 방법을 제공합니다.
alias la='ls -la'
alias
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -la'
alias ll='ls -alF'
alias ls='ls --color=auto'
la
total 212
drwxr-xr-x 24 greenfish greenfish  4096 2010-10-18 18:27 .
drwxr-xr-x  3 root      root       4096 2010-09-30 16:34 ..
-rw-------  1 greenfish greenfish  9825 2010-10-18 19:50 .bash_history
-rw-r--r--  1 greenfish greenfish   220 2010-09-30 16:34 .bash_logout
-rw-r--r--  1 greenfish greenfish  3103 2010-09-30 16:34 .bashrc
drwx------  4 greenfish greenfish  4096 2010-10-03 20:28 .cache
drwxr-xr-x  6 greenfish greenfish  4096 2010-10-04 01:20 .config
...
unalias la
unalias -a
$ alias
$


Command Watch 하기

만약 command의 output을 계속 눈으로 보기 위한다면, watch 명령을 사용합니다. 아래를 통해 load average를 계속 눈으로 볼 수 있습니다.

watch 'cat /proc/loadavg'

Every 2.0s: cat /proc/loadavg                           Mon Oct 18 20:19:48 2010

0.06 0.06 0.00 1/176 3877

매 2초마다 해당 정보를 화면에 보여줍니다. ctrl+C를 통해 종료할 수 있으며, 갱신 기간을 10초로 하려면,
watch -n 10 'ls -l'
과 같이 하면 됩니다.

만약 변경된 부분을 highlight하고 싶다면, 아래를 참고하십시요.
watch -d 'ls -l'

아래와 같이 tail command로 ctrl+C를 누를 때 까지 파일을 계속 watch할 수도 있습니다.
sudo tail -f /var/log/message


Super user 권한 얻기

당신이 shell을 열면, 당신의 user/group ID와 권한을 기반으로 한 파일과 디렉토리를 접근하고 실행할 수 있습니다. 많은 system은 root user에 제약을 가하고 있습니다.
대략적으로 super user 권한을 얻기 위해서는 다음의 3가지 방법이 있습니다.
  1. root user로 로그인
  2. su 명령으로 임시적인 root user로 되기
  3. sudo 명령으로 root user 권한을 얻어 한번 실행하기

대부분의 경우, root user로 로그인할 필요는 없는데, 의도하지 않았던 변경사항으로 인한 사고를 방지하기 위함입니다. 대부분의 linux user는 일반 login에서 부터 root user로 변경하기 위해 su 명령을 사용하거나, root user로 실행해야 하는 단일 명령을 실행하기 위해 sudo 명령을 이용하기도 합니다.

Ubuntu에서는 sudo 명령으로 user를 추가할 수 있습니다. 대부분 관리자 권한 명령을 실행시킬 때 sudo 명령을 앞에 달아줘야 합니다. 예를 들면 $ sudo useradd -m joe 와 같습니다.

디폴트로, Ubuntu는 root user로 로그인을 하지 못하도록 제약을 걸고 있습니다. 그래서 su로 관리자 권한의 명령을 수행할 수 없습니다.

login as: root
root@xxx.xxx.xxx.xxx's password:
Access denied

su greenfish
Password:
exit
exit
su root
Password:
su: Authentication failure

만약 연속된 관리자 권한 명령 수행을 위해서는 아래와 같이 shell을 다시 띄우는 방법이 있습니다.
sudo bash
# ...
# exit
exit
$

그리고, sudo passwd root를 통해 root의 비밀번호를 변경할 수 있습니다.


sudo를 통한 권한 위임

이와 같이 sudo 명령은 user로 부터 root user로 권한을 위임하도록 해 줍니다. 또한 sudo는 많은 user를 관리할 때 특정 권한을 위임할 때 사용되는 도구이며, 이러한 권한으로 user의 모든 행위를 log해 줍니다.

아무런 옵션이 없는한 sudo는 root로 실행됩니다. Ubuntu linux는 특정 권한 명령을 수행하는데 사용되는데, su 명령보다 선호되는 방법입니다. sudo 명령은 /etc/sodoers에 설정되어 있습니다. (주의! 해당 파일은 필히 visudo로 편집해야 합니다)

/etc/sudoers 파일은 제한되어 있기때문에, sudo visudo를 통해 편집해야 합니다. 해당 명령은 nano editor를 통해 편집하도록 해 줍니다. 

 GNU nano 2.2.2            File: /etc/sudoers.tmp

# /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# See the man page for details on how to write a sudoers file.
#

Defaults        env_reset

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL) ALL

# Allow members of group sudo to execute any command after they have
# provided their password
# (Note that later entries override this, so you might need to move
# it further down)
%sudo ALL=(ALL) ALL
#
#includedir /etc/sudoers.d

# Members of the admin group may gain root privileges
%admin ALL=(ALL) ALL

^G Get Help  ^O WriteOut  ^R Read File ^Y Prev Page ^K Cut Text  ^C Cur Pos
^X Exit      ^J Justify   ^W Where Is  ^V Next Page ^U UnCut Text^T To Spell


root ALL=(ALL) ALL
이 있는데, 이는 모든 user가 모든 host에서 root로 됨을 허락한다는 뜻입니다.

%admin ALL=(ALL) ALL
은 admin group에 있는 모둔 user가 root로 됨을 허락한다는 뜻입니다.

Ubuntu linux를 설치하였다면, 당신이 추가한 user 계정은 자동으로 admin group에 추가됩니다. 추가된 user의 root 권한을 자동으로 하기 위해서는 다음과 같은 Line을 추가합니다.
USERNAME ALL= /usr/bin/less /var/log/messages

만약 USERNAME이 testacc였다면, 다음과 같은 것이 가능합니다.
sudo /usr/bin/less /var/log/messages
Password:
 
그럼, testacc의 비밀번호를 입력하면, /var/log/messages의 내용을 표시합니다.


환경 변수 사용하기

shell 환경에 사용되는 작은 양의 정보는 환경 변수에 저장됩니다. 규약에 따라 환경 변수는 대문자가 사용됩니다. 만약 bash을 사용한다면, 몇몇 환경 변수는 직전에 다뤘던 다양한 bash start scripts로 부터 세팅됩니다.

다음과 같이, 모든 환경 변수를 알파벳 순서로 표시할 수 있습니다.

set | less
BASH=/bin/bash
BASHOPTS=checkwinsize:cmdhist:expand_aliases:extglob:extquote:force_fignore:histappend:interactive_comments:login_shell:progcomp:promptvars:sourcepath
BASH_ALIASES=()
...

그리고 아래와 같이 환경 변수를 set/reset 할 수 있습니다.

echo $ABC

$ ABC=123
$ echo $ABC
123
bash
echo $ABC

exit
exit
echo $ABC
123


그리고, export에 의해 환경 변수를 child process에 상속할 수 있도록 할 수있습니다.

echo $ABC

export ABC=123
echo $ABC
123
bash
echo $ABC

123


WRITTEN BY
정현석
이것저것 끄적끄적....

,
출처 : http://greenfishblog.tistory.com/39

Shell command interpreter(shell)의 사용은 과거 unix로 부터 거슬러 올라갑니다. 이러한 shell은 환경 변수, aliase, 프로그래밍을 위한 여러 기능등 많은 명령을 수행합니다. Bourne Again Shell(bash)이 Linux에서 가장 일반적으로 많이 사용됩니다(sh, csh, ksh, tcsh 등등도 있습니다). 많은 경우, 이러한 shell들은 다른 shell로의 symbolic link를 가지고 있습니다. Ubuntu에서, sh는 /bin/dash에 symbolic link를 가지고 있습니다. 이러한 sh shell은 run script로 실행시킬 shell script를 호출하는데 중요한 역할을 수행합니다.

Shell 사용하기

Shell이 시작될 때 shell environment가 실행시킨 user 기반으로 설정됩니다. bash shell의 모든 user의 설정은 많은 파일에 저장되어 있습니다. 이러한 시스템 세팅을 무시하고 당신만의 버전으로 만들어 사용할 수 있습니다. 이러한 설정을 포함하는 파일은 다음과 같이 두 종류가 있습니다.
  • startup files
  • initialization files

bash는 로그인 shell으로 부터 startup files를 실행시킵니다. 이 파일은 전체 로그인을 넘나들어 적용되는 설정을 정의합니다. bash는 shell의 초기화를 위해 initialization files를 실행시킵니다. 이는 다시 말하면, shell script를 실행시키는것은 아닙니다.

bash는 startup files을 /etc/profile(이는 system-wide) 혹은 user home directory의 .bash_profile, .bash_login, 그리고 .profile와 같이 개인 설정이 저장된 .으로 시작되는 파일을 찾습니다. (다른 linux 시스템에서 system-wide 파일이 /etc/profile과 /etc/profile.d/에 저장이 되어 있는 경우도 있습니다.)

bash는 initialization files를 /etc/bash.bashrc (이는 system-wide) 혹은 user home directory의 .bashrc에서 찾습니다. (다른 linux 시스템에서 system-wide 파일이 /etc/bashrc에 저장되어 있는 경우도 있습니다.)

shell이 끝날 때 user의 ~/.bash_logout 파일이 실행됩니다. 이러한 파일들을 변경하였지만, 이미 동작하고 있는 shell에는 영향을 미치지는 않습니다.

shell environment를 변경하고 나열할 수 있는 여러 가지 방법이 있는데, 가장 흔한 방법은 user를 변경하는 방법입니다.


bash history 사용하기

bash(Bourne Again Shell)은 Linux에서 일반적으로 쓰이는 기본 shell입니다. 다른 shell과 마찬가지로, bash에 의해 설치된 history를 관리하는 기능이 있어, 과거 실행한 command를 보거나 변경하기, 그리고 재사용할 수 있습니다. 이는 매우 길고 복잡한 Linux command을 처리할때 큰 도움을 줍니다.

bash를 시작할 때, ~/.bash_histroy 파일을 읽어 메모리에 로드하게 됩니다. 이 파일은 $HISTFILE 값에 세팅되어 있습니다.

bash session 동안, command는 메모리에 있는 history에 추가하게 됩니다. 그리고 bash가 종료될 때, 메모리에 있는 history는 .bash_history에 저장하게 됩니다. bash session동안 포함할 command 개수는 $HISTSIZE에 세팅되어 있으며, history에 저장될 개수는 #HISTFILESIZE에 세팅되어 있습니다.

echo $HISTFILE $HISTSIZE $HISTFILESIZE
/home/greenfish/.bash_history 1000 2000
history 5
  447  ps
  448  head .bash_history
  449  echo $HISTFILE $HISTSIZE $HISTFILESIZE
  450  clear
  451  history 5
!!
history 5
  458  ps
  459  head .bash_history
  460  echo $HISTFILE $HISTSIZE $HISTFILESIZE
  461  clear
  462  history 5
!458
pwd
/home/greenfish
!458 -aux
ps -aux
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.3   2664  1608 ?        Ss   16:43   0:01 /sbin/init
root         2  0.0  0.0      0     0 ?        S    16:43   0:00 [kthreadd]
...
!?aux?
ps -aux
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.3   2664  1608 ?        Ss   16:43   0:01 /sbin/init
root         2  0.0  0.0      0     0 ?        S    16:43   0:00 [kthreadd]
...
!ps
ps -aux
Warning: bad ps syntax, perhaps a bogus '-'? See http://procps.sf.net/faq.html
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.3   2664  1608 ?        Ss   16:43   0:01 /sbin/init
root         2  0.0  0.0      0     0 ?        S    16:43   0:00 [kthreadd]
...
!ps:s/aux/A
ps -A
  PID TTY          TIME CMD
    1 ?        00:00:01 init
    2 ?        00:00:00 kthreadd
...

  • history 5
    이전의 command 5개를 보여준다.
  • !!
    바로 직전의 command를 실행한다.
  • !458
    458번째의 command를 실행한다.
  • !458 -aux
    458번째의 command에 -aux를 붙여 실행한다.
  • !?aux?
    이전 command중 aux를 포함하고 있는 것을 실행한다.
  • !ps
    이전 command중 ps인것을 실행한다.
  • !ps:s/aux/A
    이전 command중 ps인것을 실행하되 aux를 A로 치환하여 실행한다.

WRITTEN BY
정현석
이것저것 끄적끄적....

,