Bourne Shell Builtins
Shell 내부에 builtin 되어서 제공되는 명령들입니다. 외부에 파일로 존재하지 않으므로 sudo, env, 또는 find 의 -exec 등으로 실행할 수 없고 shell 환경에서만 사용할 수 있습니다.
.
. filename [arguments]
.
( dot ) 은 as
어셈블러나 ld
링커 스크립트에서 현재 위치를 나타내는데 사용됩니다.
shell 에서는 현재 위치에 filename 내용을 include 하는데 사용됩니다.
bash 에서는 동일한 기능의 source 명령을 추가로 제공합니다.
가령 AA.sh 파일 내용 중에 . BB.sh
라인이 있다면 해당 라인이 위치한 곳에
BB.sh 파일을 읽어들인 후 실행하는 것과 같습니다.
function 과 동일하게 arguments 를 줄 수 있으며 BB.sh 에서는 return 명령을 사용할 수 있습니다. 인수를 주지 않을 경우 AA.sh 실행시 사용된 인수가 동일하게 적용됩니다.
filename 에 경로를 지정하지 않으면 $PATH
를 검색하는데 찾지 못하면 오류메시지와 함께 non-zero 를 리턴합니다.
간혹 쉘 스크립트 파일을 프롬프트 상에서
.
나source
명령으로 실행시키는 경우가 있는데 옳은 방법이 아닙니다. 그렇게 되면 shebang 라인도 적용이 안되고 스크립트 파일 내의 모든 라인을 현재 프롬프트 shell 에서 실행하는 것과 같게 되는 것입니다.
$ cat AA.sh
#!/bin/bash
echo AA.sh start...
. BB.sh # '.' 명령을 이용해 BB.sh 을 include 합니다.
echo AA.sh end...
$ cat BB.sh # include 되는 BB.sh 은 shebang 라인이 필요없음.
echo BB.sh start...
echo args : $1 $2 $3
echo BB.sh end...
########## 실행결과 ############
$ ./AA.sh
AA.sh start...
BB.sh start...
args :
BB.sh end...
AA.sh end...
$ ./AA.sh 11 22 33 # 11 22 33 인수 추가
AA.sh start...
BB.sh start...
args : 11 22 33 # AA.sh 에서 사용한 인수가 적용된다.
BB.sh end...
AA.sh end...
##### 다음은 AA.sh 에서 '.' 명령에 직접 인수를 추가
$ cat AA.sh
#!/bin/bash
echo AA.sh start...
. BB.sh 44 55 66 # '.' 명령에 44 55 66 인수 추가
echo AA.sh end...
$ ./AA.sh 11 22 33
AA.sh start...
BB.sh start...
args : 44 55 66 # '.' 명령에 사용한 인수가 적용된다.
BB.sh end...
AA.sh end...
##### 다음은 include 되는 BB.sh 의 중간에 return 명령 추가
$ cat BB.sh
echo BB.sh start...
return 3
echo args : $1 $2 $3
echo BB.sh end...
$ cat AA.sh
#!/bin/bash
echo AA.sh start...
. BB.sh 44 55 66
echo $? # BB.sh 의 return 값을 조회할수 있다.
echo AA.sh end...
$ ./AA.sh
AA.sh start...
BB.sh start... # return 되어 BB.sh start... 만 표시된다.
3 # BB.sh return 값
AA.sh end...
:
:
아무일도 하지 않는 명령입니다. 종료 상태 값으로 항상 0 을 리턴합니다.
실질적으로 true
명령과 동일합니다 ( 예전에는 true 명령이 이 명령의 alias 였습니다 ).
간단한 스크립트 테스트를 할 때 true 가 올수 있는 자리에 대신 사용하기에 편합니다.
또한 실행 시에 인수 부분에서 변수확장, 명령치환, 산술확장이 이루어지므로 디버깅 시에
특정 값을 보기 위해 사용할 수도 있습니다. 여러모로 활용성이 있는 명령입니다.
while :; do echo $(( i++ )); sleep 1; done
if :; then :; else :; fi
# dir 변수가 존재하지 않거나 null 값일 경우 '/usr/local' 을 대입
: ${dir:=/usr/local}
break
break [n]
for, while, until 반복문에서 사용되는 명령입니다.
현재 실행되고 있는 반복을 중단하는 역할을 합니다.
반복문이 중첩 될수있는데 이때 n
인자를 사용할수 있습니다.
반복문을 break 명령으로 종료했을 경우 종료 상태 값은 0
이됩니다.
cd
cd [-L|[-P [-e]] [-@]] [dir]
현재 작업중인 디렉토리를 변경합니다. -P
옵션을 주면 심볼릭 링크 디렉토리 구조를 따르지 않고 물리적 디렉토리 구조를 따름니다
continue
continue [n]
for, while, until 반복문에서 사용되는 명령입니다.
continue 명령이 실행되면 현재 반복을 중단하고 다음 반복으로 넘어갑니다.
반복문이 중첩될 수 있는데 이때 n
인자를 사용할 수 있습니다.
eval
eval [arg ...]
eval 메뉴 참조.
exec
exec [-cl] [-a name] [command [arguments ...]] [redirection ...]
프로그램 loader 라고도 하는데 현재 shell process 를 command 로 대체합니다. 그러니까 디스크에서 프로그램 이미지를 읽어와서 현재 shell process 가 차지하고 있는 메모리 주소공간을 대체하는것 입니다. 따라서
ps
목록에 보이는 이름도 바뀌게 됩니다. command 를 실행할수 없을경우 프롬프트 상에서와 달리 스크립트 실행시에는 exit 됩니다. ( exit 을 방지하기 위해서 execfail 옵션을 사용할수 있습니다. )현재 shell 에 redirection 을 적용시킵니다.
bash 전용 옵션
-a
name : 0 번째 인수는 명령 자신의 이름을 나타내는데 이 옵션으로 변경할수 있습니다.
(/proc/$PID/cmdline
값과 관련된 것으로ps
목록에도 변경된 이름이 나타납니다. )-c
: empty environment 상태로 명령을 실행합니다. ( env -i 와 같은 역할 )-l
: login shell 로 실행합니다. 명령이름 앞에-
문자가 붙게됩니다.
$ ( exec -a testps ps -o pid,ppid,cmd )
PID PPID CMD
24889 3379 /bin/bash
28594 24889 testps -o pid,ppid,cmd # "ps" 명령 이름이 "testps" 로 변경돼 출력
$ ( exec -l -a testps ps -o pid,ppid,cmd )
PID PPID CMD
24889 3379 /bin/bash
28611 24889 -testps -o pid,ppid,cmd # testps 이름앞에 '-' 문자가 붙는다
$ ( exec sh -c 'echo $EDITOR' )
/usr/bin/vim
$ ( exec -c sh -c 'echo $EDITOR' ) # -c 옵션은 empty environment
$
exit
exit [n]
shell 을 exit 합니다. n
은 종료 상태 값이 되며 $?
를 통해 구할수 있습니다. n
값을 설정하지 않으면 이전 명령의 종료 상태 값이 사용됩니다.
export
export [-fn] [name[=value] ...] or export -p
A.sh 스크립트 내에서 B.sh 스크립트를 실행시키면 A.sh 은 parent, B.sh 은 child process 가 됩니다. 이때 A.sh 에서 설정한 변수, 함수들은 B.sh 에서 사용할 수가 없는데 export 명령을 이용하면 child process 인 B.sh 에서도 사용할 수가 있게 됩니다.
export 는 처음 한번만 해주면 됩니다.
함수를 export 할 때는
-f
옵션을 사용합니다.명령 실행시 인수를 주지 않으면 export 된 값을 출력합니다.
sh
에서는 변수만 export 할 수 있고 function 은 export 할 수 없습니다.
getopts
getopts optstring name [arg]
명령행에서 사용되는 옵션들을 처리하기 위해 사용되는 명령입니다.
hash
hash [-lr] [-p pathname] [-dt] [name ...]
프롬프트 상에서 명령을 실행할 때 절대 경로를 사용하지 않으면 $PATH
환경 변수에
설정된 순서대로 디렉토리를 검색해서 명령을 찾습니다.
그리고 한번 찾은 명령은 다음에 재검색 없이 실행하기 위해서 hash 테이블에 저장해 놓는데요.
hash 명령을 사용하면 $PATH
를 검색해서 찾은 명령들의 목록을 볼 수 있고
삭제할 수 있습니다.
기본적으로
$PATH
환경 변수를 재설정하면 자동으로 저장된 목록이 reset 됩니다.sh
에서도 동일함 ( 예:PATH="$VIRTUAL_ENV/bin:$PATH"
)
pwd
pwd [-LP]
현재 작업 중인 디렉토리를 출력하는 방법에는 $PWD
변수, pwd
빌트인 명령
그리고 pwd
외부 명령도 있는데 모두 결과는 같습니다.
pwd 명령의 경우 -P
옵션을 사용하면 심볼릭 링크를 해석해서 physical 디렉토리를 출력해 줍니다.
pwd 빌트인 명령의 경우는 -L
옵션이 디폴트고, pwd 외부 명령의 경우는 -P
옵션이 디폴트입니다.
# physical 절대경로를 구해 SDK_DIR 변수에 대입.
SDK_DIR=$( cd "${BIN_DIR}/.." && pwd -P )
readonly
readonly [-aAf] [name[=value] ...] or readonly -p
readonly 변수나 함수를 설정할 때 사용합니다.
설정 후 변경을 시도하면 오류메시지와 함께 종료 상태 값으로1
을 반환합니다.
readonly 변수가 되면 unset 할 수도 없습니다.
sh
에서는 readonly 변수만 설정할 수 있습니다.
-a indexed array 변수
-A associative array 변수
-f shell functions
-p readonly 변수들을 출력 ( -f 를 추가하면 함수만 출력 )
----------------------------------------------------------------------
$ readonly AA=100 $ BB=( [aa]=100 [bb]=200 )
$ AA=200 $ readonly -A BB
bash: AA: readonly variable
$ BB+=( [cc]=300 )
$ echo $? bash: BB: readonly variable
1
$ echo $?
$ unset -v AA 1
bash: unset: AA: cannot unset: readonly variable
$ echo $?
1
$ declare -p EUID UID PPID
declare -ir EUID="1000" # readonly 변수는 "r" 이 추가된다.
declare -ir UID="1000"
declare -ir PPID="2515"
return
return [n]
function 또는 source 한 스트립트 에서 리턴합니다. n
값은 종료 상태 값으로 사용되어 $?
변수를 통해 얻을수 있습니다. return 명령을 사용하지 않을경우 마지막 실행명령의 종료 상태 값이 사용됩니다.
shift
shift [n]
positional parameters 메뉴 참조.
test
test [expr]
Test 메뉴 참조.
trap
trap [-lp] [[arg] signal_spec ...]
trap 메뉴 참조.
umask
umask [-p] [-S] [mode]
User file-creation mode mask 는 파일과 디렉토리를 생성할때 기본적으로 어떤 퍼미션으로 생성할지를 8진수값으로 설정합니다. mask 를 전혀주지 않는다면 ( 000 ) 기본적으로 파일은 666, 디렉토리는 777 로 생성됩니다. 마스크값을 022 로 준다면 파일은 666 에서 각자리수 별로 빼기계산을 하면 644 로 생성이 되고 디렉토리는 755 로 생성이 되게 됩니다. 좀더 자세한 내용은 여기 를 참고하세요.
unset
unset [-f] [-v] [-n] [name ...]
현재 설정돼있는 변수나 함수를 삭제하여 존재하지 않는 상태로 만듭니다. readonly 속성이 있을경우 unset 되지 않습니다. AA=, AA="", AA='' 는 값은 null 이지만 현재 존재하는 ( set 돼있는 ) 변수입니다. unset 을하면 존재하지 않는 상태가 됩니다. [ -v name ]
으로 테스트 해볼수 있습니다. 이때 name 에는 $
를 붙이지 않습니다.
명령 실행시 옵션을 주지 않으면 첫번째로 변수를 unset 시도하고
실패할 경우 함수를 unset 시도합니다.
따라서 변수를 unset 할때는 항상 -v
옵션을 사용하는 것이 좋습니다.
-v
name 을 변수로 취급합니다.-f
name 을 함수로 취급합니다.-n
name 을 reference 로 취급합니다.
Bash Builtins
[
[ arg... ]
test
명령과 동일한 명령입니다. Test 메뉴를 참조하세요.
alias
alias [-p] [name[=value] ... ]
alias 를 설정하는데 사용합니다. alias 는 기본적으로 non-interactive shell 에서는 사용할수 없습니다.
bg
bg [job_spec ...]
job control 메뉴 참조
bind
bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]
readline 의 설정 파일인 inputrc 에서 할수있는 옵션설정, key binding 을 이 명령을 통해서 동일하게 할 수 있습니다. 사용할 수 있는 함수나 옵션의 목록을 볼수도 있으며 현재 설정 상태도 확인할 수 있습니다.
builtin
builtin [shell-builtin [arg ...]]
우선순위가 높은 alias, function 이름을 피해 builtin 명령을 실행 할때 사용합니다.
caller
caller [expr]
현재 실행중인 함수의 call stack 을 표시합니다. 인수없이 사용하면 라인넘버, 파일이름 (${BASH_LINENO[0]} ${BASH_SOURCE[1]}
) 을 표시하고 숫자를 인수로 주면 라인넘버, 호출함수, 파일이름 (${BASH_LINENO[$i]} ${FUNCNAME[$i+1]} ${BASH_SOURCE[$i+1]}
) 을 표시합니다. stack trace 에 사용할수 있습니다.
$ cat ./caller.sh
#!/bin/bash
die() {
echo "$1"
local frame=0
while caller $frame; do
let frame++
done
}
foo1() { die "*** an error occured ***" ;}
foo2() { foo1 ;}
foo3() { foo2 ;}
foo3
------------------------------------------
$ ./caller.sh
*** an error occured ***
12 foo1 ./caller.sh
13 foo2 ./caller.sh
14 foo3 ./caller.sh
16 main ./caller.sh
command
command [-pVv] command [arg ...]
우선순위가 높은 alias, function 이름을 피해 외부명령을 (builtin 명령 포함) 실행 할때 사용합니다.
-v
옵션은 명령이 존재하는지 체크하는데 사용할 수 있습니다.
if command -v python > /dev/null; then ...
compgen
compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
명령 자동완성에 사용될 단어들를 생성하는데 사용됩니다. 주로 자동완성 함수를 작성할때 COMPREPLY 배열에 값을 채워 넣기 위해 사용합니다. 사용 가능한 옵션은 complete 명령과 거의 동일하며 마지막에 word 인수가 주어지면 word 와 매칭되는 단어들만 선택됩니다.
# -A 옵션에 사용할 수 있는 action 들
$ compgen -A [tab]
alias builtin disabled file helptopic keyword setopt stopped
arrayvar command enabled function hostname running shopt user
binding directory export group job service signal variable
$ compgen -a # 현재 설정되어 있는 aliases
$ compgen -b # builtin commands
$ compgen -c # $PATH 에의해 접근 가능한 시스템 전체 명령 (builtin 명령 포함)
$ compgen -d # 현재 위치에서 디렉토리만 표시
$ compgen -e # export 한 환경변수들
$ compgen -f # 현재 위치에서 모든 파일 표시 (디렉토리, 심볼릭 링크 모두)
$ compgen -g # /etc/group 에 등록된 group
$ compgen -j # background 로 실행중인 모든 job 들
$ compgen -k # shell keywords
$ compgen -s # /etc/services 에 등록된 service
$ compgen -u # /etc/passwd 에 등록된 user
$ compgen -v # 현재 쉘에 설정되어 있는 모든 변수들 (export 안한것 포함)
complete
complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]
특정 이름의 자동완성을 등록하고 설정하는 역할을 합니다.
자세한 내용은 Command Completion 메뉴를 참조하세요
compopt
compopt [-o|+o option] [-DE] [name ...]
complete 으로 등록되어 사용 중인 명령 자동완성 에대해서 옵션을 변경할 수 있습니다.
-o
은 on 을 나타내고, +o
는 off 를 나타냅니다.
name
은 자동완성이 적용된 명령이름 입니다.
한가지 중요한 기능은 자동함수 내에서 name 없이 사용하면 현재 tab 실행에 대해서만 옵션을 적용시킬 수 있습니다.
# clang 명령의 자동완성에 대해서 nospace 옵션이 이후 지속적으로 적용된다.
compopt -o nospace clang
# 현재 실행중인 tab 실행에 대해서만 옵션이 적용된다.
compopt -o nospace
declare
declare [-aAfFgilnrtux] [-p] [name[=value] ...]
변수를 선언하고 속성을 적용합니다. 값을 대입하지 않으면 존재하지 않는 상태 (unset 상태) 로 남습니다. 변수, array 의 현재 속성과 값을 보거나 함수정의를 볼때도 사용합니다. 유효하지 않은 옵션을 사용하거나 값을 대입할때 오류가 나면 종료 상태 값으로 non-zero 를 리턴합니다.
sh
에서는 사용할 수 없습니다. 하지만 함수 내에서 local 은 사용할 수 있습니다.
- Associative array 를 만들때는
declare -A
명령을 사용해야 합니다. - 함수 내에서 사용되면 기본적으로 local 변수로 설정됩니다.
(-g
옵션으로 global 변수로 설정할 수 있습니다. ) declare -n
을 이용하여 named reference 기능을 이용할 수 있습니다.declare -t -f 함수명
을 사용하면 해당 함수에서 DEBUG, RETRUN trap 을 할 수 있습니다.
Options:
옵션 | 설명 |
---|---|
-f | 함수 정의를 볼때 사용합니다. 특정 action 을 함수에 적용시킬때 사용합니다. |
-F | 함수 이름만 표시합니다. ( shopt -s extdebug 디버깅 시에는 line number 와 source file 도 표시합니다 ) |
-g | 함수 내에서 declare 는 기본적으로 local 변수를 만듭니다. 하지만 이 옵션을 사용하면 global 변수가 됩니다. ( 동일한 이름의 global 변수가 이미 존재하면 안됩니다.) |
-p | NAME 의 속성과 값을 볼때 사용합니다. |
속성을 줄때 사용하는 옵션
-
대신에 +
를 사용하면 해당 속성이 off 됩니다.
옵션 | 설명 |
---|---|
-a | NAME 에 indexed arrays 속성을 줍니다. |
-A | NAME 에 associative arrays 속성을 줍니다. |
-i | NAME 에 integer 속성을 줍니다. ( 값을 대입할때 let 명령과 같이 산술연산을 할 수 있습니다. ) |
-n | NAME 에 named reference 속성을 줍니다. |
-r | NAME 에 readonly 속성을 줍니다. ( 한번 readonly 속성이 되면 변경할 수 없습니다. ) |
-t | NAME 에 trace 속성을 줍니다. 함수에만 적용되는 옵션입니다. |
-l | NAME 에 값을 대입할때 소문자로 변환합니다. |
-u | NAME 에 값을 대입할때 대문자로 변환합니다. |
-x | NAME 을 export 합니다. |
declare -i idx
로 idx 변수에 integer 속성을 주더라도idx++
와 같은 문법은 사용할 수 없습니다. 왜냐하면 쉘 에서는 idx++ 가 명령 이름이 되기 때문입니다. 대신에idx+=1
와 같은 대입 연산에서는 integer 속성이 적용될 수 있습니다.
declare -i idx=0
idx++ # 오류! 여기서 idx++ 는 명령 이름이 된다.
idx+=1 # ok
# let 을 사용하면 declare 가 필요없다.
idx=0
let idx++ # ok
dirs
dirs [-clpv] [+N] [-N]
pushd, popd 명령과 함께 directory stack 을 다루는데 사용되는 명령으로 현재 stack 내용을 보여줍니다. 0 번은 항상 현재 디렉토리를 나타냅니다.
[ pushd, popd, dirs 로 cd 명령 만들기 ]
disown
disown [-h] [-ar] [jobspec ...]
job control 메뉴 참조
echo
echo [-neE] [arg ...]
주어진 인수들을 출력합니다.
quotes 을 사용하지 않을 경우 whitespace ( space, tab, newline ) 문자들은 single space 로 변경되어 출력됩니다.
기본적으로 escape 문자는 처리하지 않으며 라인 마지막에 newline 을 붙이는데 필요하지 않을경우 -n
옵션을 사용할수 있습니다. -e
옵션을 사용하면 escape 문자가 처리됩니다.
-n
: 출력시 기본적으로 마지막에 newline 이 붙는데 이 옵션을 사용하면 붙이지 않습니다.-e
: escape 문자 처리를 enable 합니다.-E
: escape 문자 처리를 disable 합니다.
sh
의 경우 echo
명령은 bash 의 echo -e
와 동일하게 동작합니다.
enable
enable [-a] [-dnps] [-f filename] [name ...]
builtin 명령을 enable 또는 disable 시키는데 사용합니다.
기본적으로 제공되는 builtin 명령 외에 bash-builtins
패키지를 설치하면 추가적으로 명령을 builtin 으로 사용할 수 있습니다.
builtin 명령과 동일한 이름의 외부 명령이 있을경우 builtin 명령을 disable 시키면 외부 명령이 사용됩니다.
$ enable # 현재 enable 되어있는 builtin 명령을 볼 수 있습니다.
enable . # disable 되어 있는 명령도 함께보려면 '-a' 옵션을 사용합니다.
enable :
enable [
enable alias
enable bg
. . .
. . .
$ type -a echo
echo is a shell builtin
echo is /bin/echo
$ enable -n echo # echo builtin 명령을 disable 시킵니다.
$ type -a echo
echo is /bin/echo
$ enable echo # 다시 echo 명령을 enable 시킵니다.
$ enable | grep echo
enable echo
다음은 bash-builtins
패키지를 설치하여 sleep 명령을 builtin 으로 사용하는 예입니다.
builtin 명령은 사용자가 직접 제작하여 사용할 수도 있는데
dpkg -L bash-builtins
출력에서 예제 소스를 볼 수 있습니다.
-f
Load builtin NAME from shared object FILENAME-d
Remove a builtin loaded with -f
$ sudo apt install bash-builtins
# 사용할수 있는 명령의 목록을 볼 수 있습니다.
$ ls -l /usr/lib/bash/
# /usr/lib/bash/sleep 파일을 로드하여 builtin 으로 enable 시킵니다.
$ enable -f /usr/lib/bash/sleep sleep
$ type -a sleep
sleep is a shell builtin
sleep is /bin/sleep
$ enable -d sleep # '-f' 옵션으로 로드한 파일을 remove 합니다.
false
false
항상 종료 상태 값 1
을 리턴하는 명령입니다.
명령이므로 실행이 돼야 종료 값을 얻을 수 있습니다.
$ echo false
false
$ false
$ echo $?
1
fc
fc [-e ename] [-lnr] [first] [last]
command history 에서 지정한 범위의 명령들을 에디터로 불러와 수정하여 스크립트 처럼 한번에 실행시킬수 있습니다.
fc -s [pat=rep] [command]
!
을 이용한 history 확장처럼 명령을 검색하여 실행할수 있습니다.
$ printf "%s\n" "hello\tworld"
hello\tworld
$ fc -s %s=%b printf
printf "%b\n" "hello\tworld"
hello world
fg
fg [job_spec]
job control 메뉴 참조
help
help [-dms] [pattern ...]
Shell builtin 명령의 도움말을 보여줍니다.
history
history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...]
command history 메뉴 참조.
jobs
jobs [-lnprs] [jobspec ...] or jobs -x command [args]
job control 메뉴 참조
kill
kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
kill 메뉴 참조.
let
let arg [arg ...]
산술연산 표현식을 위한 명령입니다. 식을 작성할땐 기본적으로 공백없이 붙여야 합니다. 그러나 quote 를 할경우는 공백을 사용할 수 있습니다. 좀 더 자세한 내용은 special commands 메뉴를 참조하세요
local
local [option] name[=value] ...
local 변수를 설정할때 사용합니다. 그러므로 함수 내에서만 사용할 수 있습니다.declare
명령에서 사용하는 옵션들을 동일하게 사용할 수 있습니다.
예를 들어 bash 에서 +=
연산자는 기본적으로 스트링으로 처리하므로
숫자라도 concatenation 이 됩니다.
$ cnt=100
$ cnt+=20
$ echo $cnt # 숫자가 스트링으로 처리되어 concatenation 된다.
10020
이때 -i
옵션을 이용해 integer 속성을 설정하면 산술연산을 할 수 있습니다.
$ f1() {
local -i cnt=100 # cnt 변수의 속성을 integer 로 설정
echo $cnt
cnt+=20 # integer 속성을 가지고 있으므로
echo $cnt # cnt=$(( cnt + 20 )) 로 하지 않아도 된다.
}
$ f1
100
120
변수 선언을 먼저 하고 대입 연산은 뒤에 할 수 있습니다.
$ f1() {
local AA # 먼저 변수를 local 로 선언
AA=100
BB=200
}
$ f1; echo AA : $AA; echo BB : $BB
AA :
BB : 200
logout
logout [n]
login shell 일 경우에 logout 합니다. login shell 이 아니면 오류가 발생합니다.
mapfile
mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
라인을 array 변수로 읽어들입니다. 변수명을 주지 않으면 MAPFILE
이 사용됩니다.
몇번째 라인부터 얼마나 읽어들일지, 저장되는 array 에는 몇번째 index 부터 입력할지 정할수 있고 callback 함수를 설정할 수도 있습니다.
mapfile -t arr < datafile # 이명령은 실질적으로 아래와 같습니다.
while read -r line
do
arr[i++]=$line
done < datafile
-t
읽어들이는 라인에서 newline 을 제거합니다.-s count
몇번째 라인부터 읽어들일지 지정합니다.-n count
몇개의 라인을 읽어들일지 지정합니다. 0 이면 전체 라인을 읽어들입니다.-O origin
array 변수에 몇번째 index 부터 입력할지 지정합니다.-u fd
file descriptor 로부터 라인을 읽어들입니다.
입력되는 array 와 별개로 callback 명령을 사용할 수 있습니다.
-C callback
callback 명령을 지정합니다.-c quantum
몇개의 라인을 읽어들인후 callback 을 호출할지 지정합니다.
$ cat datafile
100 Emma Thomas
200 Alex Jason
300 Madison Randy
400 Sanjay Gupta
500 Nisha Singh
# callback 명령의 $1 에는 index 값이, $2 에는 라인이 전달됩니다.
$ f1() { echo "$1 : $2" ;}
$ mapfile -t -C f1 -c 1 < datafile # -c 1 설정
0 : 100 Emma Thomas
1 : 200 Alex Jason
2 : 300 Madison Randy
3 : 400 Sanjay Gupta
4 : 500 Nisha Singh
$ mapfile -t -C f1 -c 2 < datafile # -c 2 설정
1 : 200 Alex Jason
3 : 400 Sanjay Gupta
$ mapfile -t -C f1 -c 3 < datafile # -c 3 설정
2 : 300 Madison Randy
callback 에서 read 명령을 사용하면 array 에 입력되는 라인이 skip 됩니다.
$ f1() { read -r line ;}
$ mapfile -t -C f1 -c 1 arr < datafile
# 200, 400 라인이 skip 되었다.
$ echo "${arr[0]}"
100 Emma Thomas
$ echo "${arr[1]}"
300 Madison Randy
$ echo "${arr[2]}"
500 Nisha Singh
popd
popd [-n] [+N | -N]
pushd, dirs 명령과 함께 directory stack 을 다루는데 사용되는 명령으로 stack 에서 디렉토리 항목을 삭제하고 cd 합니다.
[ pushd, popd, dirs 로 cd 명령 만들기 ]
printf
printf [-v var] format [arguments]
printf 메뉴 참조
pushd
pushd [-n] [+N | -N | dir]
popd, dirs 명령과 함께 directory stack 을 다루는데 사용되는 명령으로 인수로 사용된 디렉토리를 stack 에 추가하고 cd 합니다.
[ pushd, popd, dirs 로 cd 명령 만들기 ]
mug896@EliteBook:~$ dirs
~
mug896@EliteBook:~$ pushd /usr # pushd 를 하면 현재 디렉토리가
/usr ~ # 변경되면서 stack 에 추가된다.
mug896@EliteBook:/usr$ pushd /usr/local
/usr/local /usr ~
mug896@EliteBook:/usr/local$ pushd /usr/local/bin
/usr/local/bin /usr/local /usr ~
mug896@EliteBook:/usr/local/bin$ dirs -v -l
0 /usr/local/bin
1 /usr/local
2 /usr
3 ~
mug896@EliteBook:/usr/local/bin$ popd # popd 를 하면 현재 디렉토리가
/usr/local /usr ~ # 변경되면서 stack 에서 삭제된다.
mug896@EliteBook:/usr/local$ popd
/usr ~
mug896@EliteBook:/usr$ popd
~
mug896@EliteBook:~$
read
read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
read 메뉴 참조.
readarray
readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]
mapfile
명령과 동일합니다.
set
set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
Shell option 을 설정하거나 명령의 인수값을 나타내는 $1
$2
$3
... 변수를 설정하는데 사용합니다. enable 된 옵션은 $SHELLOPTS
변수에 :
로 분리되어 저장되며 $-
변수에는 옵션 flags 가 저장됩니다. 주의할점은 enable 시에는 -
기호를 disable 시에는 +
기호를 사용한다는 것입니다. [ -o 옵션명 ]
으로 현재 설정값을 테스트해볼 수 있습니다.
shopt
shopt [-pqsu] [-o] [optname ...]
Bash option 을 설정하는데 사용합니다. enable 된 옵션은 $BASHOPTS
변수에 :
로 분리되어 저장됩니다. enable 시에는 -s
를 disable 시에는 -u
옵션을 사용하고 -q
옵션을 사용해 값의 설정 여부를 테스트할 수 있습니다.
-o
: 이 옵션은set -o
옵션 값을 출력하는데 사용됩니다.-p
: 현재 옵션 상태를 출력하는데 결과를 바로 쉘에서 명령으로 사용할 수 있습니다.-q
: 아무런 출력을 하지 않게 합니다.-s
: 옵션을 enable 합니다.-u
: 옵션을 disable 합니다.
$ shopt -s nullglob
$ shopt -q nullglob; echo $?
0
$ shopt -u nullglob
$ shopt -q nullglob; echo $?
1
-------------------------------
# 1. noglob 은 set 옵션이므로 -o 옵션을 사용.
# 2. -p 옵션은 현재 옵션 상태를 출력합니다.
$ shopt -po noglob
set +o noglob
# 따라서 다음과 같이 현재 옵션을 백업하고 복구하는데 사용할 수 있습니다.
reset=$(shopt -po noglob)
set -o noglob
. . .
$reset
source
source filename [arguments]
. (a period)
명령과 동일합니다.
bash 에서만 사용할수 있고 filename 을 찾을때 $PATH
에서 찾지 못하면 현재 디렉토리 에서도 찾습니다.
$ source <( echo 'AA=100; f1() { echo $AA ;}' )
$ f1
100
$ echo $AA
100
.................................................
# 인수로 11 22 를 전달하면 각각 $1, $2 에 할당됩니다.
$ source <( echo 'echo "XX, $1, $2, ZZ"' ) 11 22
XX, 11, 22, ZZ
suspend
suspend [-f]
job control 메뉴 참조
true
true
항상 종료 상태 값 0
을 리턴하는 명령입니다.
명령이므로 실행이 돼야 종료 값을 얻을 수 있습니다.
$ echo true
true
$ true
$ echo $?
0
times
Display process times.
Prints the accumulated user and system times for the shell and all of its child processes.
type
type [-afptP] name [name ...]
-a
옵션과 함께 사용할경우 alias, keyword, function, builtin, 외부 명령을 모두 구분해서 보여줍니다.-f
검색에서 shell function 은 제외합니다.-p
옵션은 name 이 실행 가능한지 테스트할 때 사용할 수 있습니다. 여기에는 alias, keyword, function, builtin, 외부 명령 모두 포함됩니다. 외부 명령의 경우에는 파일만 존재하면 참이 됩니다. ( executable 은 체크하지 않습니다 )
# time 은 keyword, ls 는 alias, cd 는 function, history 는 builtin, awk 는 외부 명령
$ type -p time ls cd history awk
/usr/bin/awk
$ echo $?
0
# xxx 가 존재하지 않는다.
$ type -p time ls cd history xxx awk
/usr/bin/awk
$ echo $?
1
-P
옵션은 name 이 외부 파일로 존재하는지 테스트할 때 사용할 수 있습니다. 이 옵션은which
명령과 비슷한데 다른 점은 which 명령은 파일이 executable 인지도 체크합니다.
$ type -P ls date sed
/bin/ls
/bin/date
/bin/sed
$ echo $?
0
# 이번 경우는 history 가 builtin 명령이라 외부 파일로 존재하지 않는다.
$ type -P ls date history
/bin/ls
/bin/date
$ echo $?
1
-t
name 의 타입을 표시합니다 ( alias, keyword, function, builtin, file ). 중복되어 존재할 경우 처음 하나만 표시됩니다.
typeset
typeset [-aAfFgilrtux] [-p] name[=value]
A synonym for declare
(Obsolete)
ulimit
ulimit [-SHabcdefilmnpqrstuvxT] [limit]
shell 의 리소스 제한을 설정합니다. hard limit (-H
) 은 root 유저만 설정할 수 있고
soft limit (-S
) 은 hard limit 이내에서 일반 유저가 설정할 수 있습니다.
설정된 값은 child process 에게도 상속됩니다.
한 가지 터미널에서 설정할 때는 따로 옵션을 주지 않으면 hard limit 설정이 됩니다.
일반 유저는 한번 hard limit 을 내리면 다시 올릴 수 없으므로 -S
옵션을
사용해 설정해야 합니다.
웹서버나 데이터베이스 서버 등을 운영할 때 설정값이 너무 낮으면 열린 파일 수가 너무 많다거나 스레드를 생성할 수 없다는 리소스 관련 오류가 발생할 수 있습니다. 이때는 startup 스크립트 파일에서 ulimit 명령을 이용하여 관련된 리소스를 설정하거나 또는 시스템 설정 파일을 수정하여 reboot 후에도 유지되게 합니다.
현재 실행중인 프로세스의 설정 상태는 pid 를 구한후에 cat /proc/$pid/limits
명령으로 알아볼 수 있습니다.
# 다음은 프로세스당 열수있는 최대 파일수를 설정하는 예입니다.
# limits.conf 파일 설정은 pam_limits.so 모듈에 의해 처리됩니다.
# "*" 는 모든 유저를 뜻하고 nofile 은 (number of open files )
$ cat /etc/security/limits.conf
. . .
* soft nofile 65535
* hard nofile 65535
root soft nofile 65535 # "*" 는 root 에게는 적용이 안되므로
root hard nofile 65535
$ cat /etc/pam.d/login
. . .
session required pam_limits.so
다음은 recursion 을 이용해 현재 stack limit 을 확인하는 것입니다.
int
자료형은 보통 4 bytes 이므로arr[100000]
는400000
bytes 만큼 stack 을 차지하게 됩니다.
$ ulimit -s $ ulimit -S -s 4096
8192 $ ulimit -s
4096
$ gcc -xc - <<\EOF && ./a.out $ gcc -xc - <<\EOF && ./a.out
#include <stdio.h> #include <stdio.h>
int i = 0; int i = 0;
void sub() void sub()
{ {
int arr[100000]; i++; int arr[100000]; i++;
printf ("recursion %d : %d\n", \ printf ("recursion %d : %d\n", \
i, i * 400000); i, i * 400000);
sub(); sub();
} }
int main() { sub(); } int main() { sub(); }
EOF EOF
. . . . . .
. . . . . .
recursion 16 : 6400000 recursion 6 : 2400000
recursion 17 : 6800000 recursion 7 : 2800000
recursion 18 : 7200000 recursion 8 : 3200000
recursion 19 : 7600000 recursion 9 : 3600000
recursion 20 : 8000000 # 8M recursion 10 : 4000000 # 4M
Segmentation fault (core dumped) Segmentation fault (core dumped)
gcc 의 -fsplit-stack 옵션 을 사용하면 stack 을 제한없이 사용할 수 있습니다.
unalias
unalias [-a] name [name ...]
설정된 alias 를 삭제 하는데 사용합니다.
-a
: 현재 설정되어 있는 전체 alias 를 삭제합니다.
wait
wait [-n] [id ...]
job control 메뉴 참조
pushd, popd, dirs 로 cd 명령 만들기
다음은 pushd, popd, dirs 명령을 이용하여 기존 cd 명령을 확장하는 예입니다.
기존 cd 명령은 history 기능이 없는데 pushd, popd 명령을 이용하여 history 기능을 구현합니다.cd --
로 history 목록을 볼 수 있고 cd -숫자
로 해당 디렉토리로 이동할 수 있습니다.cd -
는 기존 명령과 동일하게 바로 이전 디렉토리로 이동합니다.
# 아래 내용을 cd.sh 파일에 저장 후 `source cd.sh` 하면 새로운 cd 명령을 사용할 수 있습니다.
function cd()
{
local new_dir index dir cnt
# 기존 builtin cd 명령의 옵션을 사용할 경우 처리를 위한 코드
if ! [ $# -eq 0 ]; then
if [[ $# -eq 2 && $1 == "--" ]]; then
shift
else
if ! { [ $# -eq 1 ] && [[ $1 =~ ^(-[0-9]{,2}|-|--|[^-].*)$ ]] ;}
then
builtin cd "$@"
return
fi
fi
fi
[ "$1" = "--" ] && { dirs -v; return ;}
new_dir=${1:-$HOME}
# 인수가 '-숫자' or '-' 형태일 경우
if [[ "$new_dir" =~ ^-[0-9]{,2}$ ]]; then
index=${new_dir:1}
if [ -z "$index" ]; then
new_dir=$OLDPWD
else
new_dir=$(dirs -l +$index) || return
fi
fi
# $new_dir 로 cd 하고 동시에 stack 의 top 에 항목을 add 합니다.
pushd -- "$new_dir" > /dev/null || return
# 15 개의 history 만 사용할 것이므로 16번째 항목이 생길경우 stack 에서 삭제합니다.
popd -n +16 &> /dev/null || true
# 마지막으로 기존 history 를 검색해서 현재 디렉토리와 중복되는 항목이 있으면 삭제합니다.
new_dir=$PWD cnt=1
while dir=$(dirs -l +$cnt 2> /dev/null); do
if [ "$dir" = "$new_dir" ]; then
popd -n +$cnt > /dev/null
continue
fi
let ++cnt
done
}