Table of Contents
- 1. ch. 2
- 2. ch.3 shell variables and env
- 2.1. system variable
- 2.2. variable 사용
- 2.3. default variable
- 2.4. naming
- 2.5. echo
- 2.6. printf
- 2.7. quoting (expansion)
- 2.8. backslash 기타 기능
- 2.9. export
- 2.10. unset
- 2.11. read ( user input)
- 2.12. arithmetic operation
- 2.13. readonly (constant var)
- 2.14. variable null check
- 2.15. customize the bash shell environments
- 2.16. command history
- 3. ch3-2
- 4. ch.4 conditionals execution
- 5. ch4-2
- 6. ch.5 bash loops
- 7. ch.6 shell redirection
- 8. ch. 7 pipes and filters
- 9. ch. 8 Traps
- 10. ch. 9 Functions
- 11. ch. 10 interactive
- 12. 기타
1 ch. 2
1.1 shell 실행
처음에 os가 로딩되면 로그인 쉘 로딩 됨.
/etc/profile에서 시스템 init
/etc/bash.bashrc 에서 interactive shell을 실행
etc/bash.logout
$HOME.bashprofile -> 유저의 홈에서 각자 shell 띄움.
1.2 shell 이란
linux kernel의 유저 인터페이스로 등장
linux는 linus tovalz 가 만들었다.
bash shell (bash) 은 여러 쉘 중 default 로 지정된 쉘로,
bourn shell (sh?)을 개조해서 만들었다.
shell종류는 여러가지가 있는데 설치된 shell들은 /etc/shells 에서 확인 가능.
shebang이라는 #!기호로 시작하는 라인이 스크립트 파일 제일 위에 온다.
이는 사용할 interpreter위치를 명시하는 줄이다.
안적어줘도 default bash shell을 쓸 수 있긴 하지만 비추.
#!/bin/bash
1.3 permission
ls -l script.sh
chmod +x(755) -> 누구나 실행
chmod u+x(700) -> owner만 실행
ug=rx -> user,group에 대해 rx 권한
1.4 스크립트 실행
chmod +x script.sh
./script.sh
하거나 bash script.sh
하거나 . script.sh
. 명렁어는 dot command로 해당 파일을 실행하는 명령.
배쉬 실행에도 몇 가지 옵션이 있다.
bash -x script (디버깅 모드)
shebang에 있는 라인이 인터프리터 패스인데, 거기에다 실행 옵션을 적어줄 수도 있다.
#!/bin/bash -x
2 ch.3 shell variables and env
2.1 system variable
set 또는 env를 입력시 시스템 변수가 출력됨
대표적으로 HOME, HOSTNAME 등..
2.2 variable 사용
${HOME} 은 해당 변수 값을 뜻한다.
printf "%s\n" ${HOME}
{}는 생략 가능한데 다른 문자와 섞어 쓸 경우 혼동스러울 수 있다.
-— {}는 변수를 싸는 것이고, $()는 명령어를 싸는 것이다. $()는 생략 불가.
echo "$HOMEIS" -> 아무 값도 없다.
echo "${HOME}IS" -> /home/dahyunIS
2.3 default variable
${a:=d}
a라는 변수에 값이 지정되어 있지 않는 경우 디폴트 값으로 d를 지정한다.
die () {
local error=${1:-undefined error}
echo "$0: $LINE $error"
}
die "file not found" die -> $1 value가 비어 있어서 undefine error
die "file not found" die -> $1 value가 비어 있어서 undefine error
2.4 naming
알파벳 _ 으로 시작 가능하고 알파벳 숫자 _ 조합으로 명명 가능.
값을 지정할때 space 를 두면 안되고 딱 붙여야함.
no=10
null variable 정의 가능
vech= 또는
vech=""
2.5 echo
변수 값만 치환하고 문자 그대로 출력
2.6 printf
거의 c에서 쓰는거랑 비슷함.
\" -> "
%% -> %
포맷팅 문법은
"%w.pL" ->
w는 최소한의 필드 길이,
p는 소숫점 자릿수,
L은 conversion character 로 s(string), d(integer), e(exponential), f(floating point)
가 있다. 그러니깐
var=10.234
"%1.2f" $var
-> 10.2
2.7 quoting (expansion)
echo \"${SHELL} $(date) .c\" -> variable, command, wildcard 모두 치환
echo "\"${SHELL} $(date) *.c/"" -> variable, command 치환은 되지만 wildcard ()은 치환 안됨.
echo '\"${SHELL} $(date) *.c\"'-> 모두 치환 안됨.
backslash를 특수 기호 앞에 붙이면 특수 기호 기능이 상실되고 그 문자 그대로 나옴.
현 디렉토리에 asdf1.c asdf2.c 가 있으면 find . -name *.c 라고 할 때 에러가 난다. 왜냐면 쉘에서 find 함수에 전달되는 parameter는 *.c가 아니고 asdf1.c asdf 2.c 이기 때문이다. 레귤러 익스프레션 파싱은 find 함수 안에서 되야 한다. 그러므로 find . -name "*.c" 혹은 \.c 이렇게 적어줘야 맞다.
현 디렉토리에 asdf1.c asdf2.c 가 있으면 find . -name *.c 라고 할 때 에러가 난다. 왜냐면 쉘에서 find 함수에 전달되는 parameter는 *.c가 아니고 asdf1.c asdf 2.c 이기 때문이다. 레귤러 익스프레션 파싱은 find 함수 안에서 되야 한다. 그러므로 find . -name "*.c" 혹은 \.c 이렇게 적어줘야 맞다.
2.8 backslash 기타 기능
\v vertical tab
\\ backslash
\e escape char
\a alert
\' single quote
\n new line
\ 는 continue command on next line 기능도 있음.. 매크로에서 처럼. echo " asdf \ > asdf asdf \ asdf" \ 는 물론 스크립트 파일 안에서도 사용 가능.
\ 는 continue command on next line 기능도 있음.. 매크로에서 처럼. echo " asdf \ > asdf asdf \ asdf" \ 는 물론 스크립트 파일 안에서도 사용 가능.
2.9 export
a=b
c=d
export "$a"
bash
쉘에서 bash를 치면 새로운 bash가 뜬다. (창은 그대로고)
ps를 하면 child bash가 생긴 것을 확인 할 수 있다.
여기서 a는 parent의 것을 전달 받음. c는 없음.
export -p를 하면 전달받은 variable들이 죽 리스팅 되는데
특이한 점은 여기에 시스템 변수들도 있다는 거다.
2.10 unset
설정한 변수 삭제
2.11 read ( user input)
read 라는 명령어가 있는데 scanf랑 거의 같다.
read -p "enter your name and gender: " name gender
enter your name and gender: 가 뜨고
enter your name and gender: dahyun female 입력하면
name 과 gender 가 각각 저장된다.
option: -p: prompt message -t : timeout , -s : handling input as secret (password)
다음 스크립트에서 read -p "who are you" name echo "$name" 하고 사용자가 Me Mike Emma라고 입력하면 name에 다 저장이 되는데 IFS로 분리 가능. (???? 라인은 알겠는데, 단어는 ? 라인이랑 단어 구분이랑 다른거 같던데?) -> $IFS internal field seperator 라는 변수가 있음. cat -etv <<<"\(IFS" ^I\) $
-etv -> tab, end 컨트롤 문자를 보여줘 <<<는 "$IFS"가 파일이 아닌 스트링이기 때문에 인풋 스트림을 만들어줘야 함.
여기서 ^I$ 는 tab and newline (white space 아니다..) $는 end of line
즉 IFS는 token delimeter 가 들어있다.
portals="naver daum yahoo" read -r p1 p2 p3 <<< portals 하면 p1, p2, p3에 각 포탈들이 쪼개져서 저장된다.
그러니까 변수를 쪼갤 일이 있으면 IFS에 들어있는 delimeter로 쪼개진다. IFS는 변경 가능하다.
oldifs=$IFS IFS=: :를 delimeter 로 쪼개고 나서 IFS=$oldifs
다음 스크립트에서 read -p "who are you" name echo "$name" 하고 사용자가 Me Mike Emma라고 입력하면 name에 다 저장이 되는데 IFS로 분리 가능. (???? 라인은 알겠는데, 단어는 ? 라인이랑 단어 구분이랑 다른거 같던데?) -> $IFS internal field seperator 라는 변수가 있음. cat -etv <<<"\(IFS" ^I\) $
-etv -> tab, end 컨트롤 문자를 보여줘 <<<는 "$IFS"가 파일이 아닌 스트링이기 때문에 인풋 스트림을 만들어줘야 함.
여기서 ^I$ 는 tab and newline (white space 아니다..) $는 end of line
즉 IFS는 token delimeter 가 들어있다.
portals="naver daum yahoo" read -r p1 p2 p3 <<< portals 하면 p1, p2, p3에 각 포탈들이 쪼개져서 저장된다.
그러니까 변수를 쪼갤 일이 있으면 IFS에 들어있는 delimeter로 쪼개진다. IFS는 변경 가능하다.
oldifs=$IFS IFS=: :를 delimeter 로 쪼개고 나서 IFS=$oldifs
2.12 arithmetic operation
$((expression))
위의 형태로 arithmetic operation을 할 수 있다.
expression형태나 할 수 있는 연산은 c에서와 같은 형태.
bitor, shift, compare, conditional operator(?:) 다 됨..
bitor, shift, compare, conditional operator(?:) 다 됨..
2.13 readonly (constant var)
shell 끝날 때 까지 살아있고, 변하지 않고, 지울 수 없는 변수
readonly DATA=asdf 하고나면 overwrite이나 unset 불가능
2.14 variable null check
만약 parameter 변수가 필요한 시점에 변수 안에 값이 없을 경우 null check가 필요.
스크립트 안에
path=${1:?Error command line argument not passed} -> argument 1 로 전달되는 값이 없으면 스크립트를 멈추고 위 스트링을 출력한다.
path=${1:?Error command line argument not passed} -> argument 1 로 전달되는 값이 없으면 스크립트를 멈추고 위 스트링을 출력한다.
2.15 customize the bash shell environments
customizing -> prompt를 커스터마이징 하거나
search path, environment variables 등을 미리 세팅한다.
변수 종류는 local, environment 두 가지. export 하지 않는 이상 쉘에서 정의한 변수는 local변수임. environment variable는 서브 프로세스에 전달 되는 변수다.
쉘 build in command는 set 명령어로 볼 수 있고 bash가 정의한 변수들은 모두 대문자로. man bash 를 통해 bash가 정의한 environment 변수를 볼 수 있음
export를 이용해 local 변수를 environment var로 만들면 env에 등록됨. -> export 로 해당 변수 편집 가능 !!<- 하지만 주의 해야겠지 잘못되면 man bash 참조.
echo $PATH /usr/local/sbin:/usr/local/bin <- output exprot PATH=/usr/local/sbin:/usr/local/bin:/usr/games
env 입력 시 environment var 모두 출력.
주요 einvironment var HOME : home dir path PATH : executable serch path PWD : current working dir
which [command]: 현재 환경에서 실행 될 수 있는 실행 파일의 path 를 출력 whereis [command]: binary, source, man page path 출력 whatis [command]: command 에 대한 간단한 설명
변수 종류는 local, environment 두 가지. export 하지 않는 이상 쉘에서 정의한 변수는 local변수임. environment variable는 서브 프로세스에 전달 되는 변수다.
쉘 build in command는 set 명령어로 볼 수 있고 bash가 정의한 변수들은 모두 대문자로. man bash 를 통해 bash가 정의한 environment 변수를 볼 수 있음
export를 이용해 local 변수를 environment var로 만들면 env에 등록됨. -> export 로 해당 변수 편집 가능 !!<- 하지만 주의 해야겠지 잘못되면 man bash 참조.
echo $PATH /usr/local/sbin:/usr/local/bin <- output exprot PATH=/usr/local/sbin:/usr/local/bin:/usr/games
env 입력 시 environment var 모두 출력.
주요 einvironment var HOME : home dir path PATH : executable serch path PWD : current working dir
which [command]: 현재 환경에서 실행 될 수 있는 실행 파일의 path 를 출력 whereis [command]: binary, source, man page path 출력 whatis [command]: command 에 대한 간단한 설명
2.16 command history
bash는 커맨드 히스토리를 ~/.bashhistory에 저장하고 있음.
history 라는 built in command로 출력해 볼 수 있음.
그런데 history는 built in이긴 하지만 set 으로 overwrite가 가능.
방향 키로 이전 커맨드를 다시 띄울 수 있음. C r : reverse-i-search 매칭 되는 커맨드 라인을 reverse i search로 찾음. !!: 직전 커맨드를 불러옴 !somethig: 히스토리에서 somethig을 reverse-i-search 하고 가장 처음 매치되는 커맨드를 불러옴. history를 입력하면 번호 + 명령이 나오는데 ![history line number] 입력하면 해당 라인 커맨드를 불러옴.
방향 키로 이전 커맨드를 다시 띄울 수 있음. C r : reverse-i-search 매칭 되는 커맨드 라인을 reverse i search로 찾음. !!: 직전 커맨드를 불러옴 !somethig: 히스토리에서 somethig을 reverse-i-search 하고 가장 처음 매치되는 커맨드를 불러옴. history를 입력하면 번호 + 명령이 나오는데 ![history line number] 입력하면 해당 라인 커맨드를 불러옴.
3 ch3-2
3.1 path name expansion
3.1.1 curly baraces {}
대체 문을 만듬.
주의할 점은 안에 comma랑 단어 모두 붙여 써야함.
echo I like {tom,jerry} I like tom jerry (이거는 잘 모르겠다. )
echo file{1,2,3}.txt -> file1.txt file2.txt file3.txt
echo file{1..5}.txt rm -v hello.{sh,py,pl,c} <- 이런 명령에서 굳이 파일이 존재하지 않아도 된다.
주의할 점은 안에 comma랑 단어 모두 붙여 써야함.
echo I like {tom,jerry} I like tom jerry (이거는 잘 모르겠다. )
echo file{1,2,3}.txt -> file1.txt file2.txt file3.txt
echo file{1..5}.txt rm -v hello.{sh,py,pl,c} <- 이런 명령에서 굳이 파일이 존재하지 않아도 된다.
3.1.2 wildcards
- : 아무 스트링. null도 괜찮다.
text?.[ch] -> text2.h text3.c
3.2 create and use aliases
alias는 그냥 커맨드 쇼트컷임.
명령어를 alias 로 저장할 수 있다.
alias c='clear'
alias cp='cp -i' #옵션, 기타 argument또한 저장 가능
unalias c # 커맨드 c alias를 없앤다.
unalias -a # 전부 unalias
영구적으로 alias를 설정하는 방법. 모든 유저 -> etc/bashrc 또는 /etc/profile.d/useralisas.sh (파일 생성 해야한다) 개인 -> /$HOME.bashrc 수정
alias로 expand시키지 않으려면 backslash를 이용하거나 ""을 이용한다. alias는 var이 아니라서 expand 안됨. /ls 또는 "ls"
영구적으로 alias를 설정하는 방법. 모든 유저 -> etc/bashrc 또는 /etc/profile.d/useralisas.sh (파일 생성 해야한다) 개인 -> /$HOME.bashrc 수정
alias로 expand시키지 않으려면 backslash를 이용하거나 ""을 이용한다. alias는 var이 아니라서 expand 안됨. /ls 또는 "ls"
3.3 tilde
~ : HOME
~+ : PWD (현 path)
~-: OLDPWD (이전에 있던 path)
3.4 startup scripts
3.4.1 script execution order
etc/profile: 처음에 리눅스 시스템 환경에서 처음으로 돌아가는 스크립트
/etc/profile.d: etc/profile에서 이 폴더 안에 있는 스크립트를 순서대로 실행 시킨다.
($HOME).bashprofile: 이 파일이 유저 단위의 배쉬 설정에 해당되는데 이 파일은 또 ~/.bashrc를 부른다.
스크립트가 순차적으로 불리는데, 최근에 불린 스크립트에서 수정한 것이 이전 설정을 overwrite한다.
bashrc 파일을 설정해 함수, alias, var, path, default editor 등을 수정할 수 있다.
~/.bashrc를 열고
alias vi='vim'
입력 후 닫는다. 설정을 로딩하기 위해 ~/bashrc를 쳐주거나 bash를 다시 켠다. alias를 입력하면 설정한 alias를 볼 수 있다.
bashrc 파일을 설정해 함수, alias, var, path, default editor 등을 수정할 수 있다.
~/.bashrc를 열고
alias vi='vim'
입력 후 닫는다. 설정을 로딩하기 위해 ~/bashrc를 쳐주거나 bash를 다시 켠다. alias를 입력하면 설정한 alias를 볼 수 있다.
3.4.2 dot file 보기
ls -a 를 하면 dot file 까지 list 됨.
3.5 changine bash prompt
prompt는 터미널에 커맨드 입력받는 줄 앞에 프린트되는 문구다.
$PS1에 저장되어 있다.
echo \(PS1
/@/h: \w\\)
PS1도 var로 수정이 가능하다. PS1='command:'
PS1도 var로 수정이 가능하다. PS1='command:'
3.5.1 backslash-escaped
수정시 backslash-escaped 문자를 사용할 수 있는데
많이 쓰이는 것은
\h : host name
\n : neline
\t : current time in 24-hour HH:MM:SS format
\d : date in weekday-month-date format
\u : username
\v : bash version
\w : current workin directory
\! : hlistory number of command
\$ : if the effective uid is 0, a # otherwise a $
\e : escpate ascii
\[ \] : 이 괄호 안에 있는 애는 non-printing sequence 인데 .. 보기 좋으라고 쓰는 듯?
export PS1='\[\e[1;32m\][\u@\h \w]\$\[\e[0m\]' 이게 노말 유저 어카운트를 초록색으로 설정하는 명령이라고 함. ~/.bashrc에 적어주면 항상 유지 됨.
export PS1='\[\e[1;32m\][\u@\h \w]\$\[\e[0m\]' 이게 노말 유저 어카운트를 초록색으로 설정하는 명령이라고 함. ~/.bashrc에 적어주면 항상 유지 됨.
3.5.2 PROMPTCOMMAND variable
이 변수를 설정해 놓으면 특정 명령이 실행되고 나서 이 PROMPTCOMMAND가 실행됨.
$ PROMPTCOMMAND="echo asdf"
asdf
$date
Tue Oct 20 23:30:21 IST 2009
asdf # 요거.
3.5.3 setting shell options
쉘 내장 기능들이 있고 이 기능을 쓸지 말지 결정하는 옵션이 있다.
이 옵션은 set, shopt 두 커맨드로 끄거나 켜는 것이 가능하다.
set -o -> 옵션 리스트가 뜬다. set -o option -> option이 켜진다. set +o option -> option이 꺼진다.
shopt -p -> 옵션 리스트가 뜬다. shopt -s option -> option이 켜진다. shopt -u option -> option이 꺼진다.
예를 들면 cdspell 이라는 옵션이 있는데 이 옵션의 디폴트는 꺼져있는 것이다.
shopt -s cdspell cd /etcc /etc 오타를 고쳐서-> etc로 이동하는 cdspell의 기능.
set -o -> 옵션 리스트가 뜬다. set -o option -> option이 켜진다. set +o option -> option이 꺼진다.
shopt -p -> 옵션 리스트가 뜬다. shopt -s option -> option이 켜진다. shopt -u option -> option이 꺼진다.
예를 들면 cdspell 이라는 옵션이 있는데 이 옵션의 디폴트는 꺼져있는 것이다.
shopt -s cdspell cd /etcc /etc 오타를 고쳐서-> etc로 이동하는 cdspell의 기능.
3.5.4 bashrc
~/.bashrc에다가
shopt -q -s cdspell set -o notify export HISTSIZE=5000 export JAVAHOM/usr/lib/jvm/java-5-sun/jre export PATH=$PATH:$ORACLEHOME/bin:$HOME/bin:$JAVAHOME/bin source /etc/bashcompletion #Turn on bash command completion alias grep='grep –color' alias ipconfig='ifconfig'
이런 식으로 설정
shopt -q -s cdspell set -o notify export HISTSIZE=5000 export JAVAHOM/usr/lib/jvm/java-5-sun/jre export PATH=$PATH:$ORACLEHOME/bin:$HOME/bin:$JAVAHOME/bin source /etc/bashcompletion #Turn on bash command completion alias grep='grep –color' alias ipconfig='ifconfig'
이런 식으로 설정
4 ch.4 conditionals execution
4.1 bash structured language constructs
arithmetic operation 에서 bool 연산
echo $((5!=2))
echo $((5<2))
4.2 test command
file attribute, string, arithmetic comparison에 사용할 수 있다.
condition? true-command : false-command 랑 비슷함. 아래와 같이 쓸 수 있다. test condition test condition && true-command test condition || false-command test condition && true-command || false-command
test 5 -gt 2 && echo "yes" #-gt: greater, -ge : greater or equal -eq: equal -lt test 5 != 10 && echo yes || echo no test -f /etc/reslv.conf && echo "file found" || echo "file not found"
condition? true-command : false-command 랑 비슷함. 아래와 같이 쓸 수 있다. test condition test condition && true-command test condition || false-command test condition && true-command || false-command
test 5 -gt 2 && echo "yes" #-gt: greater, -ge : greater or equal -eq: equal -lt test 5 != 10 && echo yes || echo no test -f /etc/reslv.conf && echo "file found" || echo "file not found"
4.3 if
if condition1 # if [conditions]
then
cmd1
elif condition2
then
cmd2
elif condition3
then
cmd3
else
cmd4
fi
if test var == val then cmd1 else cmd2 fi
#!/bin/bash read -p "enter a password" pass if test "$pass" == "jerry" then echo "pass verified" fi
-> nesting 도 가능하다. 인덴트는 알아서 잘 하자.
if test var == val then cmd1 else cmd2 fi
#!/bin/bash read -p "enter a password" pass if test "$pass" == "jerry" then echo "pass verified" fi
-> nesting 도 가능하다. 인덴트는 알아서 잘 하자.
4.4 exit status of a command
커맨드는 그 수행을 하고 리턴 값이 있다.
리턴값이 $?에 저장된다.
0은 정상 종료를 의미하고
1-255 의 값은 에러를 의미한다.
커맨드를 입력한 후에
echo $?
치면 리턴값이 출력된다.
주의할 점은 ! 리턴 값이 0이면 true 이다. !!!!
주의할 점은 ! 리턴 값이 0이면 true 이다. !!!!
4.5 logical and && and or ||
command1 && command2
command1 이 true (0 을 리턴) 해야지만 command2가 실행된다.
command1 || command2 command1 이 false (non-zero 을 리턴) 해야지만 command2가 실행된다.
command1 || command2 command1 이 false (non-zero 을 리턴) 해야지만 command2가 실행된다.
4.6 logical not !
! expression
[! expression]
4.7 numeric comparison
eq : equal
ge : greater or eq
gt : greater
le : less
lt : less than
ne : not equal
4.8 string comparison
그냥 =
STR1 = STR2 STR1 != STR2
STR1 = STR2 STR1 != STR2
4.8.1 기타
-z str : str 길이가 0인가.
-e file : 파일이 있는가 -f file : 파일이 있고 정식 파일인가 (? regular file) -g file : true if file exists and is set group id -l file : true if file exists and is a symbolic link -p file : true if file exists and is a pipe -r/w/x file : true if file exists and is readable/writable/executable 등 ..
-d : 디렉토리가 있는가.
if test -z $pass then echo "no pass entered" exit 1 fi
[! -f /path/to/file] && echo "file not found"
-e file : 파일이 있는가 -f file : 파일이 있고 정식 파일인가 (? regular file) -g file : true if file exists and is set group id -l file : true if file exists and is a symbolic link -p file : true if file exists and is a pipe -r/w/x file : true if file exists and is readable/writable/executable 등 ..
-d : 디렉토리가 있는가.
if test -z $pass then echo "no pass entered" exit 1 fi
[! -f /path/to/file] && echo "file not found"
5 ch4-2
5.1 arguments
$0: 커맨드나 스크립트 이름
아규먼트는 순서대로 $1 $2 .. $9 등 순차적으로 접근 가능
$# : 총 아규먼트 수
$* 또는 $@ : 모든 커맨드라인 아규먼트 값들.
둘의 차이는 $*의 경우는 아규먼트 사이에 그냥 스페이스($@)가 아닌 IFS안에 들어있는 value를 넣는다.
IFS에 ,들어있으면 아규먼트 사이에 ,가 있는 형태로 나열된다.
5.2 parameters set by the shell
$* $@ :arguments
$# : number of parmas
$- : flags supplied to the shell
$? : return value of prev command
$$ : process number of current shell
$! : process nuber of the last background command
이러한 특수 parameter에 특정 값을 지정해 넣는 것은 불가능하다.
이러한 특수 parameter에 특정 값을 지정해 넣는 것은 불가능하다.
5.3 usage command 예시
[$# -eq 0] &&{echo "usage: $0 username" ; exit 1;}
5.4 exit command
exit N
N 을 리턴 하며 종료한다.
c 의 return과 비슷.
5.5 case 문
case $var in
pattern1|pattern2)
cmd1
…
cmdN
;;
pattern3|pattern4|patter5)
cmd1
…
cmdN
;;
patter6)
cmd1
…
cmdN
;; # break
*) # wildcard
esac # 이거 case를 거꾸로 쓴거네 ㅋㅋㅋ
5.6 dealing with case sensitive pattern
case나 condition에서 대소문자 구분이 중요한 스크립트에서 대소문자 처리를 하는 방법
5.6.1 tr 함수 사용
echo "TeSt" | tr '[:upper:]' '[:lower:]'
var="TesT" tr '[:upper:]' '[:lower:]' <<< "$var"
var="TesT" tr '[:upper:]' '[:lower:]' <<< "$var"
5.6.2 regexp 사용
tar Tar tAR 등을 위해
[Tt][Aa][Rr]으로 매치
case $1 in [Tt][Aa][Rr]) … ;;
case $1 in [Tt][Aa][Rr]) … ;;
5.6.3 nocasematch option 사용
shopt -s nocasematch
이 옵션은 case 문이나 [[ conditional command 에서 케이스 insensitve 하게 매치하게 한다.
shopt -s nocasematch 을 케이스 문 앞에 쓴 뒤 shopt -u nocasematch 를 케이스 문 끝에 다시 써준다.
shopt -s nocasematch 을 케이스 문 앞에 쓴 뒤 shopt -u nocasematch 를 케이스 문 끝에 다시 써준다.
6 ch.5 bash loops
6.1 for loop
6.1.1 for syntax
for var in item1 item2 … itemN
do
cmd1
…
cmdN
done
6.1.2 for var in list-of-values
for car in bmw ford toyta
for command in date pwd df
6.1.3 for var in $fileNames
files="/etc/passwd /etc/group /etc/shadow"
for f in $files
do
[-f $f] && echo "$f file found" ||echo "error - $f file missing"
done
6.1.4 for in array
Array=(./*.conf)
for var in "{Array[@]}"
for i in {1..10} do echo "$s * $i = $ (($i * $n))" done
for i in {1..10} do echo "$s * $i = $ (($i * $n))" done
6.1.5 for var in $(Linux-command-name)
for 문에 명령어 사용하려면 $()로 반드시 감싸야 한다.
for f in $(ls /tmp/*)
for f in $(ls /tmp/*)
6.1.6 for ((EXP1; EXP2; EXP3)) # c style
for ((i = 1; i <=5; i++))
do
….
done
6.2 while loop
6.2.1 while loop syntax
while [condition]
do
cmd1
…
done
while (($n <= 5)) do echo "$n" n=$((n+1)) done
done 끝에 있는 걸 IFS로 잘라서 line에 저장한다. IFS -> 한 라인
while IFS= read -r line # -r 옵션은 백슬래쉬를 문자 그대로 읽겠다는 뜻 (while IFS= read -r filed1 filed2 filed3 ) do cmd on $line …. done < "/path/to/file"
file=/etc/passwd while IFS=: read -r user enpass uid gid do [$uid -ge 500] && echo " $user …" done < $file
while (($n <= 5)) do echo "$n" n=$((n+1)) done
done 끝에 있는 걸 IFS로 잘라서 line에 저장한다. IFS -> 한 라인
while IFS= read -r line # -r 옵션은 백슬래쉬를 문자 그대로 읽겠다는 뜻 (while IFS= read -r filed1 filed2 filed3 ) do cmd on $line …. done < "/path/to/file"
file=/etc/passwd while IFS=: read -r user enpass uid gid do [$uid -ge 500] && echo " $user …" done < $file
6.3 infinite while loop
쉘에 true, false, : 내장 커맨드가 있다.
true: successfully (always returns exit code 0)
false: unsuccessfully (always returns exit code 1)
\ : : this command do nothing (always returns exit code 0)
infine loop 를 사용하려면 condition에 true 나 :을 적어줄 수 있다. (false는 아무 것도 안한다.) 근데 여기선 true 보다 :이 recommended.
while : do clear read -p "Enter [1 - 4] " choice case $choice in
infine loop 를 사용하려면 condition에 true 나 :을 적어줄 수 있다. (false는 아무 것도 안한다.) 근데 여기선 true 보다 :이 recommended.
while : do clear read -p "Enter [1 - 4] " choice case $choice in
- echo 1 ;;
- echo 2 ;;
6.4 until loop
while 이랑 비슷한데, 가장 큰 차이는 while은 condition 이 0를 리턴할 때까지 실행되는 반면
until은 nonzero 를 리턴할 때 까지 실행되며, 최소 한 번은 실행된다.
6.4.1 until loop syntax
while 자리에 until 써준다.
6.5 select loop
prompt 명령의 일종인 PS3을 위한 루프다.
선택지들을 화면에 보여주고 선택을 할 수 있도록 한다.
유저 인풋으로 선택지를 받으면 루프가 한 번 실행되고 다시 인풋을 받는 상태로 돌아간다.
PS3="ENTER number: " select country in korea japan china exit do case $country in korea) echo "korea" readEnterKey ;; japan) echo "japan" readEnterKey ;; china) echo "china" readEnterKey ;; exit) break ;;
*) echo "try again" readEnterKey #enter 키 입력을 받는 것을 기다린다. done
->
유저 인풋으로 선택지를 받으면 루프가 한 번 실행되고 다시 인풋을 받는 상태로 돌아간다.
PS3="ENTER number: " select country in korea japan china exit do case $country in korea) echo "korea" readEnterKey ;; japan) echo "japan" readEnterKey ;; china) echo "china" readEnterKey ;; exit) break ;;
*) echo "try again" readEnterKey #enter 키 입력을 받는 것을 기다린다. done
->
- korea 2) japan 3) china 4)exit
6.6 break
break 써주면 루프 탈출인데 특이 한 점은
argument 숫자를 주면 루프를 그 숫자만큼 탈출할 수 있다.
for in do for in do break 2 done done
for in do for in do break 2 done done
6.7 continue
6.8 command substitution
$() 하면 커맨드가 치환.
NOW=$(date) echo "$NOW"
for f in $(ls /etc/*.conf) 도 가능하지만 추천은 for f in /etc/*.conf
NOW=$(date) echo "$NOW"
for f in $(ls /etc/*.conf) 도 가능하지만 추천은 for f in /etc/*.conf
7 ch.6 shell redirection
linux 의 모든 것은 파일이다. 하드웨어 장비도 파일인데
0: input (stdin)
여기서 <
1: output (stdout)
여기서 >
2: error (stderr)
여기서 2>
> : stdout 1> : stdout 2> : stderr >> : append &> : stdout + stderr
이 세 숫자는 posix number, 미리 저장되어있는 fd임.
여기서 <
1: output (stdout)
여기서 >
2: error (stderr)
여기서 2>
> : stdout 1> : stdout 2> : stderr >> : append &> : stdout + stderr
이 세 숫자는 posix number, 미리 저장되어있는 fd임.
7.1 /dev/null /dev/zero로 오는 (> 2> &>) 스트림은 쉘이 다 지워 버린다.
예시
grep vivek /etc/passwd >/dev/null && echo "found" || echo "not found"
원래는 grep의 결과가 echo 이전에 함께 출력된다.
7.2 HERE document
7.2.1 syntax
command <<HERE
text1 … # 여기서 부터
textN
$varName
HERE # 여기까지 현 소스
<< 는 쉘에 입력하는 인풋이고 HERE HERE는 어떤 단어이고 아랫 줄부터 이어지는 현 소스에 대해 커맨드를 실행함. 인풋을 주는 거임.
아래는 단어 수를 세는 명령 echo 'This is a test.' |wc -w 4
wc -w <<EOF > This is a test > Apple juice > EOF 6
<< 는 쉘에 입력하는 인풋이고 HERE HERE는 어떤 단어이고 아랫 줄부터 이어지는 현 소스에 대해 커맨드를 실행함. 인풋을 주는 거임.
아래는 단어 수를 세는 명령 echo 'This is a test.' |wc -w 4
wc -w <<EOF > This is a test > Apple juice > EOF 6
7.2.2 예시 - 백업 상태를 메일로 보내는 스크립트.
#!/bin/bash
tar -cfv /dev/st0 /www /home 2>/dev/null
[$? -eq 0] && status="success" || "failed"
mail -s 'backup status' vivek@nixcraft.co.in <<ENDOFMAIL the baackup job finished end date : $(date) hostname : $(hostname) status : $(status)
ENDOFMAIL
mail -s 'backup status' vivek@nixcraft.co.in <<ENDOFMAIL the baackup job finished end date : $(date) hostname : $(hostname) status : $(status)
ENDOFMAIL
7.3 here strings
7.3.1 syntax
command <<<$word
command arg1 <<<"$word"
grep arg1 arg2 의 경우 arg1은 찾고자 하는 문구, arg2는 문구를 찾으려는 파일이다. 근데 파일대신 스트링을 바로 넣고 싶은 경우
target file 대신 <<<"target string"을 적어준다.
var=asdf grep "a" "asdf" # 안됨 grep "a" $var # 안됨 grep "a" <<<"adf" #됨 grep "a" <<<var #됨
다른 많이 쓰는 방법으로 쉘파이프가 있다. echo $var | grep -q "a"
grep arg1 arg2 의 경우 arg1은 찾고자 하는 문구, arg2는 문구를 찾으려는 파일이다. 근데 파일대신 스트링을 바로 넣고 싶은 경우
target file 대신 <<<"target string"을 적어준다.
var=asdf grep "a" "asdf" # 안됨 grep "a" $var # 안됨 grep "a" <<<"adf" #됨 grep "a" <<<var #됨
다른 많이 쓰는 방법으로 쉘파이프가 있다. echo $var | grep -q "a"
7.4 stdout
date > now.txt
sudo bash -c "cat file.txt >/dev/lp0"
echo "today is $(date)" 1> tmp/now.txt
echo "goodmorning" 1>> tmp/now.txt
7.5 stdout and stderr
command &> file
command > file 2>&1 # stdout을 파일로, stderr를 stdout으로
command > /dev/null 2>&1 # command stderr stdout 둘 다 버림
7.6 avoid overwriting to files
set -C
하면 > 로 인한 파일 오버라이트 방지.
오버라이트 허용하려면
set +C
echo "a" >test.txt set -C echo "b" >test.txt # 실패. 오버라이트 안됨. set +C echo "c" >test.txt # overwritted
echo "a" >test.txt set -C echo "b" >test.txt # 실패. 오버라이트 안됨. set +C echo "c" >test.txt # overwritted
7.7 reading and writing from files
sort < output.txt # output.txt 를 읽는다.
sort < output.txt > sorted.txt
#output.txt를 읽어 소트하고 sorted.txt에 저장한다.
(인풋 아웃풋 순서가 바뀔 순 없다.)
7.8 asigns the file descriptor to file
7.8.1 syntax
exec fd> ouput.txt 하면 fd 번호에 w파일을 지정하는 것.
exec fd< input.txt 하면 fd 번호에 r파일을 지정하는 것.
exec fd<> input.txt 하면 fd 번호에 rw파일을 지정하는 것.
write :
command >&fd
read
command <&fd
fd 지정 해제는 exec fd<&- 단 fd는 0, 1, 2는 이미 지정되어 있으므로 3이상이어야 한다.
fd 지정 해제는 exec fd<&- 단 fd는 0, 1, 2는 이미 지정되어 있으므로 3이상이어야 한다.
7.8.2 read from the file descriptor
read -u option은 키보드가 아니라 파일로 부터 읽는다는 옵션.
read -u fd var1 var2 … varN
while IFS= read -u fd -r line do command1 on $line command N on $line while
read -u fd var1 var2 … varN
while IFS= read -u fd -r line do command1 on $line command N on $line while
7.8.3 shell script to display its own fds
#!/bin/bash
file exec 3< /etc/resolv.conf
file exec 4> /tmp/output.txt
read -u 3 a b
echo "my pid is $$" mypid=$$
echo "currently open files by $0 scripts" ls -l /proc/$mypid/fd
exec 3<&- # 지정 해제 exec 4>&-
file exec 3< /etc/resolv.conf
file exec 4> /tmp/output.txt
read -u 3 a b
echo "my pid is $$" mypid=$$
echo "currently open files by $0 scripts" ls -l /proc/$mypid/fd
exec 3<&- # 지정 해제 exec 4>&-
7.8.4 shell script to read file line by line
#! /bin/bash
FILE="$1"
[$# -eq 0] && {echo "usage: $0 filename"; exit 1;}
[! -f $FILE ] && {echo "error file $FILE is not exists"; exit 2;}
[! -r $FILE ] && {echo " $FILE is not readonly"; exit 3;}
exec 3<$FILE
IFS=$(echo -en "\n\b")
while read -u 3 -r line do echo $line done
exec 3<&- exit 0
exec 3<$FILE
IFS=$(echo -en "\n\b")
while read -u 3 -r line do echo $line done
exec 3<&- exit 0
8 ch. 7 pipes and filters
8.1 linking commands
cmd1; cmd2 seperate commands that are executed in sequence.
cmd1 & command runs in background
cmd1 && cmd2 cmd2 runs if and only if cmd1 returns true.
cmd1 || cmd2 cmd2 runs if and only if cmd1 returns false.
cmd 1 | cmd2 | is pipe. cmd1's output goes to input of cmd2
8.2 job control
fg : palce job in the foreground
bg : place job in the background
jobs : lists the acitve jobs on screen.
find /nas -name "*.mp3" > /tmp/filelist.txt & # background로 find 실행
find /nas -name "*.mp3" > /tmp/filelist.txt & # background로 find 실행
8.3 pipe examples
mount | column -t
who | wc -l
tar zcvf - /home | ssh user@server "cat > /backup/homefs.workstation.tar.gz"
(cat에 input argument)리모트 세션에다가 백업파일 저장.
echo "TesT" | tr '[:upper:]' '[:lower:]'
who | wc -l
tar zcvf - /home | ssh user@server "cat > /backup/homefs.workstation.tar.gz"
(cat에 input argument)리모트 세션에다가 백업파일 저장.
echo "TesT" | tr '[:upper:]' '[:lower:]'
8.4 filters
awk
cut
grep
gzip
head
paste
perl
sed
sort
split
strings
tac
tail
tee
tr
uniq
wc
등 필터와 파이프를 잘 사용하자
등 필터와 파이프를 잘 사용하자
8.5 ch 8.
9 ch. 8 Traps
trap command to catch signals and handle errors under linux shell scripts
9.1 process
A process is to perform specific job.
it has unique id, PID
PID starts from 0 to 65535, pid 1 is always init process, which is first process started at boot time.
A parent process is a linux process that has created one or more child processes. In UNIX every process is created using fork and exec method.
type command in the shell -> shell makes child process : fork. duplicate shell's pages of memory and then execute the command.
(근데 페이지 듀플리케이트는 copy-on-write로 이뤄짐)
A parent process is a linux process that has created one or more child processes. In UNIX every process is created using fork and exec method.
type command in the shell -> shell makes child process : fork. duplicate shell's pages of memory and then execute the command.
(근데 페이지 듀플리케이트는 copy-on-write로 이뤄짐)
9.1.1 process의 상태
fork (parnet) –————> wait (parent)
-> exec(child) -> exit (child)
D - uninterruptible sleep : process is sleeping and cannot be bring back until an event occurred. R - running S - sleeping : waiting for an event or a signal T - traced or stopped : stopped by signals such as SIGINT or SIGSTOP Z - zombile or defunct : remaing dead process caused by no removal by parent process
ps -C processName -o pid=,cmd,stat -> pid cmd stat 이렇게 출력 됨. CMD STAT 1644 /usr/bin/php-cgi S
D - uninterruptible sleep : process is sleeping and cannot be bring back until an event occurred. R - running S - sleeping : waiting for an event or a signal T - traced or stopped : stopped by signals such as SIGINT or SIGSTOP Z - zombile or defunct : remaing dead process caused by no removal by parent process
ps -C processName -o pid=,cmd,stat -> pid cmd stat 이렇게 출력 됨. CMD STAT 1644 /usr/bin/php-cgi S
9.2 how to view processes
9.2.1 ps
ps
ps aux | less
ps aux | grep "process-name"
pas aux | grep "httpd"
9.2.2 pstree
pstree # display a tree of processes
9.2.3 pgrep
pgrep은 현재 running processes에 대해 해당 조건에 맞는 것을 찾아줌.
pgrep -u vivek php-cgi # processes called php-cgi, ownd by vivek user
pgrep -u vivek,krish # list processes owned by bibek or krish
9.3 sending signal to processes
9.3.1 kill
kill의 기본 시그널은 TERM인데, 다른 시그널도 선택가능하다.
kill -l # list options
많이 쓰는 시그널은, SDIGHUP (1) : hangup detected on controlling terminal or death of controlling process SIGINT (2) : interrupt from keyboard SIGKILL (9) : kill running process SIGSTOP (19) : stop process SIGCONT (18) : continue process if stopped
시그널 번호 조회 : kill -l SIGTSTP # signal name as list option arg 전체 시그널 리스트 조회는 : more /usr/include/linux/signal.h (? 안나오는데?)
kill -9 1234 # pid 1234에 sigkill signal 을 보낸다. kill -KILL 1234 kill -SIGKILL 1234
- SIGHUP 2)SIGINT 3) SIGQUIT …..
- SIGCONT …
- SIGTERM …
- SIGSTOP ….
많이 쓰는 시그널은, SDIGHUP (1) : hangup detected on controlling terminal or death of controlling process SIGINT (2) : interrupt from keyboard SIGKILL (9) : kill running process SIGSTOP (19) : stop process SIGCONT (18) : continue process if stopped
시그널 번호 조회 : kill -l SIGTSTP # signal name as list option arg 전체 시그널 리스트 조회는 : more /usr/include/linux/signal.h (? 안나오는데?)
kill -9 1234 # pid 1234에 sigkill signal 을 보낸다. kill -KILL 1234 kill -SIGKILL 1234
9.3.2 killall : kill processes by name
killall fiefox-bin # 기본 시그널은 SIGTERM이다.
killall -s SIGKILL firefox-bin # SIGKILL을 시그널로 보낸다.
9.3.3 pkill : kill process
kill에 옵션이 추가된 버전.
process name, user name, group name, terminal, uid, euid, gid 등을 이용해 끌 수 있다.
pkill -KILL php-cgi pkill -KILL -u vivek php-cig pkill -HUP sshd
pkill -KILL php-cgi pkill -KILL -u vivek php-cig pkill -HUP sshd
9.4 terminating processes
Ctrl c 누르면 foreground 프로세스에 TERM시그널을 보낸다. (SIGTERM)
background 프로세스를 죽이려면 kill -9 pid
Ctrl z 누르면 foreground 프로세스를 suspend한다.
다시 resume하려면 fg command를 사용한다.
fg jobid
fg 1
SIGTERM의 경우 트랩이 가능한 시그널인데, 트랩을 걸게 되면 프로세스는 종료되는 것이 아니라, 트랩 명령을 수행한다. trap 이 가능하고 불가능한 시그널이 있는데 트랩 불가능인 시그널은 무시도 불가능하고 시그널 명령을 수행해야 함. SIGKILL (9), SIGSTOP (19) sigkill 받으면 그냥 프로세스가 꺼진다.
SIGTERM의 경우 트랩이 가능한 시그널인데, 트랩을 걸게 되면 프로세스는 종료되는 것이 아니라, 트랩 명령을 수행한다. trap 이 가능하고 불가능한 시그널이 있는데 트랩 불가능인 시그널은 무시도 불가능하고 시그널 명령을 수행해야 함. SIGKILL (9), SIGSTOP (19) sigkill 받으면 그냥 프로세스가 꺼진다.
9.5 trap statement
시그널을 받았을 때 처리 문구.
9.5.1 syntax
trap arg signal
trap command signal
trap 'action' signal1 signal2
trap 'echo "exit 0 signal detected."' 0
쉘 안에서 트랩을 설정할 수 있는데 trap "echo "asdf"" 0 1 2 3 15
설정후 trap 하면 설정된 트랩 리스트가 나온다. ctrl c 누르면 echo "asdf" 가 실행되는 것을 볼 수 있음.
trap 'echo "exit 0 signal detected."' 0
쉘 안에서 트랩을 설정할 수 있는데 trap "echo "asdf"" 0 1 2 3 15
설정후 trap 하면 설정된 트랩 리스트가 나온다. ctrl c 누르면 echo "asdf" 가 실행되는 것을 볼 수 있음.
9.5.2 clear trap
trap - signal1 signal2 # 트랩을 지울 대상 시그널(번호나 이름)을 적는다.
shell script 안에서 트랩을 설정했으면 마지막에 꼭 해제를 해주자!
trap "echo "disabled signal"" 0 SIGINT ..somethig… trap - 0 SIGINT
trap "echo "disabled signal"" 0 SIGINT ..somethig… trap - 0 SIGINT
9.5.3 die function. use the trap statement to catch signals and handle errors
die는 죽기 전 에러 처리 등을 위한 함수.
예시 1) file="/tmp/data.$$" #arguments string
die () { echo "$@" #arguments string exit 2 }
[! -f $file] && dile "$0: file $file not found" || echo "$0: file #file found."
예시 2) dile () { echo "…" } trap 'die' 1 2 3 15
예시 1) file="/tmp/data.$$" #arguments string
die () { echo "$@" #arguments string exit 2 }
[! -f $file] && dile "$0: file $file not found" || echo "$0: file #file found."
예시 2) dile () { echo "…" } trap 'die' 1 2 3 15
9.6 subshell
() 안의 커맨드는 모두 서브쉘에서 실행된다.
터미널에 치는 일반 커맨드도 서브쉘이라고 보면된다.
$BASHSUBSHELL: 몇 번째 서브 쉘인지 나타냄. 최상위는 0, 그 아래 서브쉘은 1, … echo "curr: $BASHSUBSHELL"; (echo "sub: $BASHSUBSHELL") curr: 0 sub: 1
$BASHSUBSHELL: 몇 번째 서브 쉘인지 나타냄. 최상위는 0, 그 아래 서브쉘은 1, … echo "curr: $BASHSUBSHELL"; (echo "sub: $BASHSUBSHELL") curr: 0 sub: 1
9.6.1 exporting functions and variables
서브 쉘은 부모 쉘의 정의된 변수, 함수를 export 해야만 상속받을 수 있다.
WWWJAIL=/apache.jail export WWWJAIL # 변수 export die() {echo "$@"; exit 2;} export -f die # 함수 export /etc/nixcraft/setupjail -d cyberciti.com
WWWJAIL=/apache.jail export WWWJAIL # 변수 export die() {echo "$@"; exit 2;} export -f die # 함수 export /etc/nixcraft/setupjail -d cyberciti.com
9.6.2 use exec command to avoid subshell
The exec command replaces this shell with the specified program without swapping a new subshell or process.
exec command
#redirect the shells stderr to null exec 2>/dev/null
exec command
#redirect the shells stderr to null exec 2>/dev/null
9.7 dot command (source command랑 같음 ????)
. script.sh 이런식을 사용하는데 dot command는 스크립트를 읽어와 current shell 에서 실행하게 되는데
이건 스크립트 안에서만 수정되는 것이아니라, 스크립트 종료후에도 current shell variable이 바뀌어 있다.
exec 과는 차이는 source는 실행한 파일의 변수와 함수를 라이브러리에 추가한다는 것!!!
실행하는 주체가 쉘인 경우에 sh에 +x permission 을 설정하지 않아도 됨… (exec source .) ./script.sh 의 경우는 chmod +x 필요..
실행하는 주체가 쉘인 경우에 sh에 +x permission 을 설정하지 않아도 됨… (exec source .) ./script.sh 의 경우는 chmod +x 필요..
9.8 compound command
9.8.1 ()
( list )
( cmd1; cmd2)
() 의 경우 :
hostname ; date; who | wc -l >tmp/output.txt 는 who | wc -l 의 결과만 redirect 된다.
(hostname ; date; who | wc -l) >tmp/output.txt 는 세 커맨드 모두가 redirect 된다.
() 의 경우 :
hostname ; date; who | wc -l >tmp/output.txt 는 who | wc -l 의 결과만 redirect 된다.
(hostname ; date; who | wc -l) >tmp/output.txt 는 세 커맨드 모두가 redirect 된다.
9.8.2 {}
{ cmd1; cmd2}
이 경우에는 모든 커맨드가 current shell environment에서 돌아가는 것과 같게 해 준다.
[$# -eq 0] && {echo "usage: $0 filename"; exit 1;} # $0는 사실 parent shell variable…
9.9 exec
서브쉘 대신 현 쉘에서 돌아가게 한다.
보통 환경변수 등을 설정하는 후 커맨드를 실행하는 래퍼 스크립트에 많이 사용한다.
PHPCGI=/usr/local/bin/php-cgi export PHPFCGICHILDREN=4 export PHPFCGIMAXREQUESTS=1000 exec $PHPCGI
PHPCGI=/usr/local/bin/php-cgi export PHPFCGICHILDREN=4 export PHPFCGIMAXREQUESTS=1000 exec $PHPCGI
10 ch. 9 Functions
xrpm() { rpm2cpio "$1" | cpio -idmv }
hello() {echo "hello world"}
10.1 decleare
declare -f : 정의된 함수들을 볼 수 있다.
declare -f fucntionName : functionName의 함수 정의를 볼 수 있다.
unset 명령으로 함수 정의를 뺄 수 있다. unset functionName
unset 명령으로 함수 정의를 뺄 수 있다. unset functionName
10.2 define function syntax
10.2.1 1
name () {
} yday () { date –date='1 day ago' }
} yday () { date –date='1 day ago' }
10.2.2 2
name {
}
}
10.2.3 3
name() compoundcommand
yday() { date –date='1 day ago';}
10.3 writing function
초기에 정의된 함수는 /etc/init.d/functions 파일에 들어있다.
less /etc/init.d/functions 으로 확인 가능.
모든 쉘 함수는 커맨드로 사용할 수 있다.
함수 정의가 함수 사용보다 앞에 와야한다. 다만 recursive function 사용은 가능하다. foo () { … foo … }
모든 쉘 함수는 커맨드로 사용할 수 있다.
함수 정의가 함수 사용보다 앞에 와야한다. 다만 recursive function 사용은 가능하다. foo () { … foo … }
10.4 function 백그라운드 실행
커맨드와 마찬가지로 &을 이용해 백그라운에서 실행할 수 있다.
name () {
}
name &
}
name &
10.4.1 source
스크립트의 함수는 . 또는 source로 반드시 로딩을 먼저 해야 한다.
그러면 정의된 함수들은 쉘의 라이브러리에 추가 되게 된다.
. 는 물론 다른 스크립트 안에서 사용할 수 있다.
source 커맨드는 현재 쉘에 함수들을 로딩하고 스크립트를 실행한다.
source functions.sh source functions.sh WWWROOT=/apache.jail (directory를 적어주면 안에 파일 네임이 죽 어레이로 들어간다. argument로 인덱스 주어서 접근 가능)
. functionscript.sh
funcname arg1 arg2
source functions.sh source functions.sh WWWROOT=/apache.jail (directory를 적어주면 안에 파일 네임이 죽 어레이로 들어간다. argument로 인덱스 주어서 접근 가능)
. functionscript.sh
funcname arg1 arg2
10.5 function shell variables
$1 $2 .. $N 은 parameter or argument of function
$0 는 항상 쉘 스크립트 이름.
$* $@ 는 모든 parameters or arguments
$# 파라미터 수.
$0 는 쉘 스크립트 이름이고, 함수 이름은 아니다. 함수 이름의 경우.. FUNCNAME을 이용해 구할 수 있는데 FUNCNAME 은 실행 중인 함수 스택정보를 담은 정렬이다. 현재 실행되고 있는 함수는 FUNCNAME 의 인덱스 0에 있다.
backup () { local d="$1" [[-z $d]] && {echo "${FUNCTNAME}() : directory name not specified"; exit 1; } }
backup $1
$0 는 쉘 스크립트 이름이고, 함수 이름은 아니다. 함수 이름의 경우.. FUNCNAME을 이용해 구할 수 있는데 FUNCNAME 은 실행 중인 함수 스택정보를 담은 정렬이다. 현재 실행되고 있는 함수는 FUNCNAME 의 인덱스 0에 있다.
backup () { local d="$1" [[-z $d]] && {echo "${FUNCTNAME}() : directory name not specified"; exit 1; } }
backup $1
10.6 local variable
함수 안에 정의 된 변수도 기본은 전역 변수이다.
함수 안 스코프로 변수를 만들려면 local 을 붙여줘야 한다.
varglobal=3 varlocal=4
function name () { varglobal=$1 # 이전에 정의된 값이 바뀐다. local varlocal=$2 # 이전에 정의된 값이 안 바뀐다. }
varglobal=3 varlocal=4
function name () { varglobal=$1 # 이전에 정의된 값이 바뀐다. local varlocal=$2 # 이전에 정의된 값이 안 바뀐다. }
10.7 예시
declare -r PASS=/etc/passwd
die () { local message="$1" local exitCode=$2 echo "$message" ["$exitCode" == " "] && exit 1 || exit $exitCode
}
die () { local message="$1" local exitCode=$2 echo "$message" ["$exitCode" == " "] && exit 1 || exit $exitCode
}
10.8 return value
return N
함수를 종료시키고 N을 리턴한다.
특이한 점은 N 이 명시되지 않을 경우 리턴 값으로는 이전 실행한 커맨드의 리턴 값이 들어있게 된다.
11 ch. 10 interactive
dialog 를 apt-get 으로 설정해서 dialog 명령을 통해 dialog box를 만들 수 있다.
menu box, progress bar (gauge box) 등을 dialog명령을 통해 만들 수 있다.
dialog –title "copy file " – gauge "copying file … " 10 75 < <( n=${#DIRS[*]}; i=0 for f in "${DIRS[@]}" do ….
menu box, progress bar (gauge box) 등을 dialog명령을 통해 만들 수 있다.
dialog –title "copy file " – gauge "copying file … " 10 75 < <( n=${#DIRS[*]}; i=0 for f in "${DIRS[@]}" do ….
12 기타
12.1 read options
-p prompt
-t timeout
-u fd
-d delim continue until the first character of delim is read, rather than newline
-r do not allow backslashes to escape any character
-e use Readline to obtain the line in an interactive shell
-p prompt output the string PROMPT without a trailing newline before
attempting to read
-n nchars return after reading NCHARS characters rather than waiting
for a newline, but honor a delimiter if fewer than NCHARS
characters are read before the delimiter
12.2 read line 과 변수 범위! (어려움)
script file 안에서
1번 ) while IFS= read -u fd -r line
do command1 on $line command N on $line while
2번 ) IFS=$(echo -en "\n\b") #? while read -u 3 -r line do echo $line done
3번 ) while IFS= read -u fd -r line
IFS를 리드 라인에 같이 쓰는 것은 따로 분리 해서 쓰는 것과 다르다.
1번 enva=foo # 상위 쉘에서만 유효한 변수 선언 enva 사용하려면 export enva 필요! command # sub shell
2번 enva=foo; command # environment variable을 바로 건든다고 한다. 그래서 이 형태는 원래 설정으로 돌려놓을 수 있게 백업이 필요.
3번 enva=foo command # 두 명령이 같은 서브 쉘에서 처리 됨. 하위 쉘에서는 변수 선언이 있지만 상위 쉘은 없다.
리드는 한 줄 씩 읽는 게 기본이고, 한 줄을 다시 워드로 쪼갤 때는 IFS 에 들어있는 delimeter 사용.
1번 ) while IFS= read -u fd -r line
do command1 on $line command N on $line while
2번 ) IFS=$(echo -en "\n\b") #? while read -u 3 -r line do echo $line done
3번 ) while IFS= read -u fd -r line
IFS를 리드 라인에 같이 쓰는 것은 따로 분리 해서 쓰는 것과 다르다.
1번 enva=foo # 상위 쉘에서만 유효한 변수 선언 enva 사용하려면 export enva 필요! command # sub shell
2번 enva=foo; command # environment variable을 바로 건든다고 한다. 그래서 이 형태는 원래 설정으로 돌려놓을 수 있게 백업이 필요.
3번 enva=foo command # 두 명령이 같은 서브 쉘에서 처리 됨. 하위 쉘에서는 변수 선언이 있지만 상위 쉘은 없다.
리드는 한 줄 씩 읽는 게 기본이고, 한 줄을 다시 워드로 쪼갤 때는 IFS 에 들어있는 delimeter 사용.
12.3 file command
12.4 echo options
-n do not append a newline
-e enable interpretation of the following backslash escapes
-E explicitly suppress interpretation of backslash escapes