개요

 

안녕하세요 피터입니다.    

오늘은 Bash 쉘 스크립트에서 사용되는 변수(variable)에 대해서 설명드리겠습니다. 

변수는 모든 프로그래밍 언어와 스크립트 언어에서 핵심적인 기능을 합니다. 데이터를 조작하기 위한 연산이나 문자열을 파싱(parsing)하는데 있어서 없어서는 안될 꼭 필요한 존재입니다.

 

변수는 단지 데이터를 담고 있는 메모리상의 위치를 나타내는데 어떤 변수에 어떤 데이터가 담겨있는지 쉽게 알 수 있게 이름을 붙여놓은 것입니다. 

 

 

변수 할당(assignment)

 

데이터를 담는 공간인 변수를 사용하려면 먼저 변수를 할당(assignment) 해야 합니다.

 

변수는 할당 연산자 = 를 사용해서 할당합니다.

 

a=100
b="hello"

 

주의 해야 할 것은 할당 연산자 앞뒤로 공백이 없어야 한다는 것입니다.  

(또한 테스트 연산자도 = 심볼을 쓰기 때문에 헷갈리지 말아야 합니다. 상황에 따라 해석이 달라지니 주의해주세요. 이 부분은 나중에 테스트 연산자 설명드릴 때 다시 말씀드리겠습니다.)

 

Bash 는 다른 프로그래밍 언어들과는 달리, 변수를 "타입"으로 구분하지 않습니다.

Bash 변수는 본질적으로 문자열이지만 Bash 가 문맥에 따라서 정수 연산이나 변수를 비교해 줍니다. 이 동작을 결정짓는 요소는 그 변수값이 숫자로만 되어 있는냐 아니냐 입니다.

 

 

let 명령어로 할당 할 수도 있습니다.

let은 bash 의 내장 명령어 중에 하나로 간단한 산술식을 수행 할 수 있습니다.

 

let a=1000+4
let "a = 1000 + 4"   # 위와 같음

 

가독성을 위해서는 " " 를 이용해서 쿼우팅(quoting) 하고 연산자 사이에 빈칸(space)을 넣어주는게 좋습니다. 

 

 

변수를 할당 할 때는 위의 숫자 100이나 문자열 "hello"와 같은 리터럴 상수(literal constant) 뿐만 아니라 명령어의 결과를 할당 할 수도 있습니다. 

 

바로 명령어 치환(command substitution)을 사용하는 방법인데요.  역따옴표(` `) - 백틱(backticks)으로 명령어를 감싸면 해당 명령어의 결과로 치환되어 그 결과를 변수에 바로 할당 할 수가 있습니다. 

 

ret=`ls -l`

 

명령어 치환에 대해서는 다룰 내용이 좀 더 많기 때문에 나중에 포스팅을 추가로 하겠습니다. 

 

 

 

변수 치환(substitution)

 

변수는 데이터를 담고 있는 그릇 역할을 하므로, 할당하였으면 이제 변수에 담겨있는 데이터를 사용 할 수 있어야 합니다. 

변수에는 어떤 계산을 하기 위해 임시로 저장한 중간값이나 특정 명령어의 결과값 등이 저장되어 있는데 이 값들을 확인하거나 적절히 활용하기 위해서는 치환(substitution)을 통해 변수의 데이터를 참조해야 합니다.

 

치환은 ${variable} 구문을 이용하여 사용하는데 $variable 로 줄여 쓸 수 있습니다. 

 

참조되는 값을 큰따옴표(" ")로 묶어도 변수 치환이 일어나는 것을 막지 못합니다.

이를 부분적 쿼우팅(partial quoting)이나 약한 쿼우팅(weak quoting)이라고 합니다. 

 

작은따옴표를 쓰게 되면 변수 이름이 그냥 문자 그대로 해석되어 아무런 일도 일어나지 않습니다.

이를 완전한 쿼우팅(full quoting)이나 강한 쿼우팅(strong quoting)이라고 합니다.

 

#!/bin/bash

a=1004
echo "$a"  # $a 변수 치환이 일어남 
echo '$a'  # $a를 문자 그대로 해석 


실행 결과
100
$a

 

 

변수를 할당하지 않고 참조하게 되면 문제가 생깁니다.

변수에 어떤 값을 처음 할당 하는 것을 초기화(initialize)라고 하는데, 초기화가 안 된 변수는 "null" 값을 가집니다.

이는 값이 할당 안 된 것이지 0 이라는 값을 갖는다는 이야기가 아닙니다. 

 

변수를 참조하기 전에 반드시 할당을 먼저 해주시기 바랍니다. 

 

 

 

 

-Peter의 우아한 프로그래밍

여러분의 공감과 댓글은 저에게 크나큰 힘이 됩니다. 오류 및 의견 남겨주시면 감사하겠습니다.

 

 

 

블로그 이미지

친절한 Peter Ahn

IT 정보 공유, 프로그래밍 지식 공유

댓글을 달아 주세요

 

개요

 

안녕하세요 피터입니다.

오늘은 Bash 쉘에서 프로그램을 종료(exit) 하는 방법과 종료 상태(exit status)를 얻는 방법에 대해 설명드리겠습니다.

종료 상태는 리턴값(return value, return status)이라고 부르기도 하는데 이전에 수행했던 명령어나 프로그램이 종료 될 때 넘겨주는 값을 의미하기도 해서 그렇습니다.

 

종료 상태 또는 반환값이 중요한 이유는 쉘 스크립트를 작성하는데 있어서 특정 명령어의 성공 여부에 따라 분기해야 하는 경우 이전 명령어가 정상적으로 수행되었는지 아는 것이 필수적이기 때문입니다.

 

쉘 스크립트 내에서 exit 명령어가 실행되면 스크립트가 종료되며 부모 프로세스에 종료 상태를 전달할 수 있는데 이 값은 프로그램 내에서 임의로 지정할 수도 있습니다. 

 

이렇게 전달되는 하위 프로세스의 종료 상태는 스크립트를 자동화하는데 있어서 매우 중요한 기준을 제공합니다. 

(일반적으로 명령어의 종료 상태가 0이면 성공(success)로 판단하며 오류가 있는 경우 오류 코드를 반환하게 됩니다)

 

 

종료 (exit)

 

exit 명령어는 매개변수로 주어진 값을 리턴합니다. 

#!/bin/bash

echo "hello"

exit 100

 

예를들면 위와 같이 exit 100 이라고 작성하면 스크립트를 종료하면서 100 이라는 값을 리턴하는 것이죠.

이 때 종료 상태로 사용할 수 있는 값의 범위는 0 부터 255 까지입니다. 

일반적으로 unix 관행을 잘 따르는 경우 0은 성공, 1 ~ 255 는 오류 코드(error code)로 인식되고 있습니다. 

 

만일 exit 를 매개변수 없이 사용하게 되면 exit 가 실행되기 이전에 가장 마지막으로 수행됐던 명령어의 종료 상태를 반환하게 됩니다.

 

 

종료 상태 (exit status)

 

$? 는 가장 최근 명령어의 종료 상태를 나타냅니다. 

위 스크립트가 100을 반환한다고 했는데 정말 그런지 실행 후 종료 상태를 출력해보겠습니다.

 

[root@peterdev sh]# cat test.sh
#!/bin/bash

echo "hello"

exit 100
[root@peterdev sh]# sh test.sh
hello
[root@peterdev sh]# echo $?
100

 

위와 같이 echo $? 명령어에서 100이 출력되는 것을 확인할 수 있습니다.

 

만일 잘못된 명령어를 입력하여 오류가 발생한 경우는 아래와 같이 오류코드가 반환되는 것을 확인할 수 있습니다.

[root@peterdev sh]# eeee
-bash: eeee: command not found
[root@peterdev sh]# echo $?
127

 

아래 스크립트에서는 echo "hello" 가 정상적으로 수행되었기 때문에 0이 반환된 것을 확인할 수 있습니다.

[root@peterdev sh]# echo "hello"
hello
[root@peterdev sh]# echo $?
0

 

 

-Peter의 우아한 프로그래밍

여러분의 공감과 댓글은 저에게 크나큰 힘이 됩니다. 오류 및 의견 남겨주시면 감사하겠습니다.

 

 

블로그 이미지

친절한 Peter Ahn

IT 정보 공유, 프로그래밍 지식 공유

댓글을 달아 주세요

 

개요

 

안녕하세요 피터입니다.

오늘은 Bash 쉘로 만들어진 프로그램(보통 스크립트-script라고 말합니다) 실행하는 방법을 설명드리겠습니다.

 

가장 기본적인 형태의 bash 스크립트는 여러개의 명령어를 나열한 것입니다.

그러면 명령어를 매번 하나하나 입력할 필요 없이 스크립트 파일을 실행하는 것으로 시간을 절약할 수 있습니다.

마치 windows의 배치(batch) 파일과 같죠.

 

좀 더 복잡한 스크립트를 만들기 위해서는 쉘 내부 지시자를 사용해야 하는데 그러기 위해서는 맨 첫줄에 #! 로 시작하는 매직 코드(magic code)가 필요합니다.

 

#! 두 바이트는 이 파일이 어떤 명령어 해석기의 집합인지 시스템에 알려주는 역할으르 합니다.

즉, 실행 가능한 스크립트라는 것을 나타내는 특별한 표시자인 것이죠.

#!/bin/sh
#!/bin/bash

#! 뒤에 나오는 경로는 스크립트의 명령어를 해석할 프로그램의 위치를 나타냅니다.

 

/bin/sh 으로 작성하게 되면 기본쉘(리눅스에서는 bash)로 동작을 하게 됩니다.

기본쉘이 본쉘인 다른 유닉스 계열의 OS 에서는 /bin/bash 로 해야 bash 에서 사용되는 내부 명령어들을 사용할 수 있습니다.

리눅스에서는 /bin/sh/bin/bash 를 호출하기 때문에 같은 결과가 됩니다.

 

스크립트 작성

간단하게 log file을 정리하는 스크립트를 작성해보겠습니다.
 

file: cleanup.sh

#!/bin/sh

print_usage()
{
  echo "Usage: $0 filename lines"
  exit 2
}

if [ -n "$1" ]; then
  logfile=$1
else
  print_usage
fi

if [ -n "$2" ]; then
  lines=$2
else
  lines=100
fi

tail -$lines $logfile > log.tmp
/bin/mv log.tmp $logfile

echo "Clean up success"

exit 0

 

명령어 인수(argument)로 파일명과 정리후 남길 라인수를 입력하면 파일을 정리하는 스크립트 입니다.

명령어 인수에 파일명을 입력하지 않으면 Usage를 출력합니다.

라인수를 입력하지 않으면 기본값으로 100줄만 남기도록 동작합니다.

 

tail 명령어는 지정된 라인만큼만 출력하는 명령어입니다.

이 명령어의 결과를 재지향(redirect) 하여 log.tmp 파일로 저장한 뒤

원본에 덮어써서 로그를 정리하는 것입니다.

[참고]

[Linux] tail 로 실시간 로그 보기

[Linux] 재지향(Redirection)에 대한 이해

 

스크립트 실행

자 그럼 스크립트를 실행해볼까요?

아래와 같이 입력하면 스크립트를 실행할 수 있습니다.

 

sh cleanup.sh

또는

bash cleanup.sh

 

그냥 파일명으로 실행을 하기 위해서는 파일에 실행권한이 필요합니다.

chmod 명령어를 통해 스크립트 파일에 권한을 부여할 수 있습니다.

 

[참고]

[Linux] chmod 로 파일 권한 변경하기

 
[root@peterdev sh]# ls -l
total 8
-rwxr-xr-x 1 root root  267 Jun  4 14:16 cleanup.sh

 

이렇게 실행권한이 부여된 상태에서 아래와 같이 실행할 수 있습니다.

[root@peterdev sh]# ./cleanup.sh
Usage: ./cleanup.sh filename lines

 

명령어 인수를 입력하지 않아서 Usage 가 출력되었군요.

스크립트를 작성할 때 사용자가 올바르게 사용할 수 있도록 이렇게 장치를 마련해놓는 것이 좋습니다.

[root@peterdev sh]# ./cleanup.sh /var/log/messages 50
Clean up success

파일명과 라인수를 입력하니 정상적으로 동작합니다.

 

 

 

-Peter의 우아한 프로그래밍

여러분의 공감과 댓글은 저에게 크나큰 힘이 됩니다. 오류 및 의견 주시면 감사하겠습니다.

 

참고

http://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/index.html

 

블로그 이미지

친절한 Peter Ahn

IT 정보 공유, 프로그래밍 지식 공유

댓글을 달아 주세요

 

개요

 

안녕하세요 피터입니다.

오늘은 여러분들이 왜 Bash 쉘 프로그래밍을 배워야 하는지에 대해서 설명드리겠습니다. 

리눅스(Linux) 환경에서 개발을 하거나, 시스템 관리자 업무를 수행하는데 있어서 Bash 쉘을 잘 다룰 수 있다는 점은 굉장한 경쟁력이 됩니다.

그만큼 업무를 효율적으로 수행할 수 있으니까요.

 

Bash"Bourne-Again Shell"의 앞 글자를 딴 것입니다.  Stephen Bourne의 Bourne Shell에 대한 클리쉐로 일종의 말장난 같은 겁니다. Bash는 이제 모든 종류의 유닉스에서 쉘 스크립트에 관한 실질적인 표준입니다.

쉘은 명령어 해석기(command interpreter)로서, 단지 커널과 사용자 중간에 놓여 있는것 이상으로 꽤 강력한 프로그래밍 언어입니다.

일반적으로 스크립트(Script)라고 부르는 쉘 프로그램은 .sh 확장자로 만드는 경우가 많으며 시스템 콜(System call)이나 다른 유틸리티(Utility) 또는 실행 파일 등을 서로 연결하여 특정 목적에 맞는 프로그램을 쉽게 만들 수 있게 해줍니다.

쉘 내부 명령어와 테스트, 루프 등을 활용하여 다소 복잡한 로직의 프로그램도 빠르게 개발이 가능하기 때문에 정식 패치 이전에 즉각적으로 반영이 필요한 긴급 이슈에 대응할 때에도 유용하게 사용될 수 있습니다.

이밖에도 쉘 스크립트는 완전히 구조적인 프로그래밍 언어의 편리한 부가 기능들이 필요없는 작업들, 특별히 시스템 관리자의 시스템 관련 작업이나 반복적인 일들을 처리할 때 굉장히 효율적입니다.

 

쉘 문법은 간단하고 명확하기 때문에 배우는 것은 크게 어렵지 않습니다. 테스트와 디버깅도 쉽습니다.

이런 강점은 실제 프로젝트를 진행하기 앞서서 프로토타이핑(Prototyping) 하기에 좋습니다.

개발에 들어가기 전 설계 단계에서 구조적인 결함을 조기에 발견할 수 있다면 그만큼 전체 프로젝트의 완성도가 높아질 뿐 아니라 리소스 낭비를 대폭 줄일 수 있습니다.

이러한 장점에도 불구하고 쉘 스크립트는 명확한 한계를 갖고 있기 때문에 아래와 같은 프로젝트는 다른 언어로 개발하는 것이 바람직합니다.

 

쉘 스크립트를 쓰면 안 될 때

  • 리소스에 민감한 작업들, 특히 속도가 중요한 요소일 때(정렬, 해쉬 등등)

  • 강력한 산술 연산 작업들, 특히 임의의 정밀도 연산(arbitrary precision)이나 복소수를 써야 할 때(C++을 쓰세요)

  • 플랫폼간 이식성이 필요할 때(C를 쓰세요)

  • 구조적 프로그래밍이 필요한 복잡한 어플리케이션(변수의 타입체크나 함수 프로토타입등이 필요할 때)

  • 업무에 아주 중요하거나 회사의 미래가 걸렸다는 확신이 드는 어플리케이션

  • 보안상 중요해서, 여러분 시스템의 무결성을 보장하기 위해 외부의 침입이나 크래킹, 파괴등을 막아야 할 필요가 있을 때

  • 서로 의존적인 관계에 있는 여러 콤포넌트로 이루어진 프로젝트

  • 과도한 파일 연산이 필요할 때(Bash는 제한적인 직렬적 파일 접근을 하고 , 특히나 불편하고 불충분한 줄단위 접근만 가능)

  • 다차원 배열이 필요할 때

  • 링크드 리스트나 트리같은 데이타 구조가 필요할 때

  • 그래픽이나 GUI를 만들고 변경하는 등의 일이 필요할 때

  • 시스템 하드웨어에 직접 접근해야 할 때

  • 포트나 소켓 I/O가 필요할 때

  • 예전에 쓰던 코드를 사용하는 라이브러리나 인터페이스를 써야 할 필요가 있을 때

  • 독점적이고 소스 공개를 안 하는 어플리케이션을 짜야 할 때(쉘 스크립트는 필연적으로 오픈 소스입니다.)

 

 

 
 

-Peter의 우아한 프로그래밍

여러분의 공감과 댓글은 저에게 크나큰 힘이 됩니다. 오류 및 의견 주시면 감사하겠습니다.

 

참고

http://wiki.kldp.org/HOWTO/html/Adv-Bash-Scr-HOWTO/index.html

 

블로그 이미지

친절한 Peter Ahn

IT 정보 공유, 프로그래밍 지식 공유

댓글을 달아 주세요