쉘기능을 자유자재로 다루기_12 셸 스크립트 일부에 Perl이나 Ruby 사용하기

 
  • 출처 : 유닉스 리눅스 쉘스크립트 예제사전_한빛미디어

명령어: perl, nc, sleep
키워드: 한 줄 명령어, 펄, 루비, 난수
사용처: 난수 생성 등 셸 스크립트 기능 일부로 펄이나 루비 코드를 사용하고 싶을 때


실행예제

$ ./perl-oneline.sh
Connection to 192.168.2.1 80 port [tcp/http] succeeded!
Wait: 4 sec
Connection to 192.168.2.1 80 port [tcp/http] succeeded!

스크립트

#!/bin/sh

# 테스트 통신할 서버 정의
ipaddr="192.168.2.1"
port=80

# 1에서 10까지 정수값 난수를 펄 한 줄 명령어로 생성
waittime=$(perl -e 'print 1 + int(rand(10))')

# 테스트 명령어를 대기 시간을 두고 2번 실행
nc -w 5 -zv $ipaddr $port
echo "Wait: $waittime sec."
sleep $waittime
nc -w 5 -zv $ipaddr $port

   

해설

이 스립트는 nc 명령어로 네트워크 통신 테스트를 두 번 하는데, 이때 중간 대기 시간을 난수로 지정하는 예제입니다. 난수는 로 생성합니다.

네트워크 확인 시 늘 정해진 대기 시간을 사용하면 타임아웃 설정값 등을 놓칠 수도 있습니다. 따라서 이런 네트워크 확인 도구에서 대기 시간(초)으로 난수를 사용하는 경우도 많습니다.

우선 1은 nc 명령어로 확인 대상 IP 주소와 포트 번호를 정의합니다.

2는 펄 처리 결과를 셸 스크립트에서 사용합니다. 펄이나 루비 같은 스크립트 언어는 무척 강력해서 한 줄 명령어(one liner)라고 부르는 한 줄로 된 스크립트도 자주 사용합니다. 이제부터 셸 스크립트에서 펄 한 줄 명령어를 사용하는 예를 알아봅니다.

펄로 한 줄 명령어를 작성할 때는 perl 명령어에 -e 옵션을 사용해서 명령행 인수에 직접 펄 스크립트를 씁니다. 예를 들어 2를 펄 스크립트로 바꿔쓰면 다음과 같습니다.

  • 파일1 난수를 발생하는 펄 스크립트

    #!/usr/bin/perl
    
    print 1 + int(rand(10));
    

이런 한 줄 명령어를 2처럼 명령어 치환 $( ) 속에 작성해서 결과를 셸 스크립트 셸 변수로 다룰 수있습니다. 날짜 처리나 문자열 처리 등 펄의 능력을 확용해서 셸 스크립트에서는 처리하기 어려운 부분을 간단히 작성할 수 있습니다.

예제에서 2는 셸 스크립트에서 난수를 생성하는데 펄을 사용합니다. 셸 스크립트에서도 /dev/urandom 디바이스 등을 이용해서 난수 생성이 가능하지만 단순히 정수값 난수가 필요할 때 /dev/urandom을 사용하는 것은 꽤 손이 많이 갑니다. 펄이라면 rand 함수를 int형으로 넘기면 바로 정수형 난수를 얻을 수 있습니다. 대기 시간에서 0은 의미가 없으므로 1에서 10 사이 난수를 얻고자 int(rand(10)) 값에 1을 더했습니다.

3은 nc 명령어로 네트워크를 확인합니다. 첫 번째 테스트 뒤에 sleep 명령어로 앞에서 얻은 난수값 초만큼 대기합니다. 이렇게 해서 셸 스크립트 일부에 펄 같은 스크립트 언어 처리를 집어넣을 수 있습니다.

펄 한 줄 명령어

예제에서 소개한 -e 외에도 자주 사용하는 옵션으로 -l(줄 바꿈을 출력), -n(스크립트 전체를 “while(<>) {…}” 반복문으로 처리)이 있습니다. 예를 들어 다음은 sample.txt 라는 파일을 표시하는 cat 명령어처럼 동작합니다.

  • 펄 한 줄 명령어를 사용한 파일 표시

    $ perl -ne 'print "$_" ' sample.txt
    

    이 것을 펄 스크립트로 작성하면 다음 소스처럼 인수로 지정한 파일 내용을 출력하는 처리가 됩니다.

    #!/usr/bin/perl
    
    while (<>) {
        print $_;
    }
    

   

주의사항

  • 루비 한 줄 명령어도 펄처럼 -e 옵션이 있습니다. 여기서 사용하는 to_i는 정수형으로 변환하는 루비 메소드입니다.

    • 루비도 -e옵션으로 한 줄 명령어 사용 가능
    $ ruby -e 'print 1 + rand(10).to_i'
    
  • 한 줄 명령어를 너무 많이 사용한다면 처음부터 해당 스크립트 언어로 모든 처리를 작성하는 것이 나을 수도 있습니다. 셸 스크립트를 사용하는 특별한 이유가 있지 않다면 펄이나 루비로 바꾸는 걸 검토해보기 바랍니다.