본문 바로가기
IT일반/Linux

Command Line - 그 외 유용한 툴들

by 버섯도리 2022. 6. 22.
[cmd_test@btjeon-naver ~]$ { ls -l; echo "Listing of foo.txt"; cat foo.txt; } > output.txt
[cmd_test@btjeon-naver ~]$ ll output.txt 
-rw-rw-r-- 1 cmd_test cmd_test 7320 Jun 22 06:06 output.txt

그룹 명령 사용 예제. 중괄호로 해당 명령어를 감싼다. 반드시 공백으로 구분되어야 하고 마지막 중괄호 이전에 세미콜론이나 개행으로 끝나야 한다.

→ 그룹 명령은 그 명령들을 현재 쉘에서 실행한다. 그룹 명령의 처리 속도가 서브쉘보다 훨씬 빠르고 메모리를 적게 사용한다.

 

[cmd_test@btjeon-naver ~]$ (ls -l; echo "Listing of foo.txt"; cat foo.txt) > output.txt
[cmd_test@btjeon-naver ~]$ ll output.txt 
-rw-rw-r-- 1 cmd_test cmd_test 7320 Jun 22 06:07 output.txt

서브쉘 사용 예제. 괄호로 해당 명령어를 감싼다.

→ 서브쉘은 현재 쉘의 복사본인 자식 쉘에서 수행한다. 이는 쉘의 환경이 복사되고 새 개체가 주어진다는 것을 의미한다. 서브쉘을 종료할 때 복사된 환경은 사라진다.

 

[cmd_test@btjeon-naver ~]$ echo "foo" | read
[cmd_test@btjeon-naver ~]$ echo $REPLY

파이프라인의 명령들은 항상 서브쉘에서 실행되기 때문에 REPLY 변수의 값은 항상 비어 있다.

 

[cmd_test@btjeon-naver ~]$ read < <(echo "foo")
[cmd_test@btjeon-naver ~]$ echo $REPLY
foo

프로세스 치환을 통해 위의 문제를 해결할 수 있다.

 

[cmd_test@btjeon-naver ~]$ vi pro-sub.sh
----------------------------------------------------------------------------------------------
#!/bin/bash

# pro-sub : demo of process substitution

while read attr links owner group size dt1 dt2 dt3 filename; do

        cat <<- EOF
                Filename:       $filename
                Size:           $size
                Owner:          $owner
                Group:          $group
                Modified:       $dt1 $dt2 $dt3
                Links:          $links
                Attributes:     $attr

        EOF
done < <(ls -l | tail -n +2)
----------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ ./pro-sub.sh | head -n 20
Filename:	30840
Size:		6
Owner:		cmd_test
Group:		cmd_test
Modified:	Jun 6 10:42
Links:		2
Attributes:	drwxrwxr-x

Filename:	arith-loop.sh
Size:		252
Owner:		cmd_test
Group:		cmd_test
Modified:	Jun 18 15:45
Links:		1
Attributes:	-rwxrw-r--

Filename:	array-sort.sh
Size:		185
Owner:		cmd_test
Group:		cmd_test

디렉토리 목록의 모든 행을 read로 반복 수행한다. 마지막 줄에서 프로세스 치환의 결과를 반복문의 표준 입력으로 재지정한다.

 

[cmd_test@btjeon-naver ~]$ vi trap-demo.sh
---------------------------------------------------------------------------------------------
#!/bin/bash

# trap-demo : simple signal handling demo

trap "echo 'I am ignoring you.'" SIGINT SIGTERM

for i in {1..5}; do
        echo "Iteration $i of 5"
        sleep 5
done
---------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ ./trap-demo.sh 
Iteration 1 of 5
Iteration 2 of 5
^CI am ignoring you.
Iteration 3 of 5
^CI am ignoring you.
Iteration 4 of 5
Iteration 5 of 5

trap 명령어는 시그널 처리 루틴을 제공한다. 이 스크립트는 실행 중에 SIGINT 또는 SIGTERM 시그널을 받으면 echo 명령을 실행하는 트랩을 정의한다. Ctrl+C를 클릭하면 위와 같이 동작한다.

 

[cmd_test@btjeon-naver ~]$ vi trap-demo2.sh
--------------------------------------------------------------------------------------------
#!/bin/bash

# trap-demo2 : simple signal handling demo

exit_on_signal_SIGINT () {
        echo "Script interrupted." 2>&1
        exit 0
}

exit_on_signal_SIGTERM () {
        echo "Script terminated." 2>&1
        exit 0
}

trap exit_on_signal_SIGINT SIGINT 
trap exit_on_signal_SIGTERM SIGTERM

for i in {1..5}; do
        echo "Iteration $i of 5"
        sleep 5
done
--------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ ./trap-demo2.sh 
Iteration 1 of 5
Iteration 2 of 5
^CScript interrupted.

각 시그널에 해당하는 함수를 정의하여 프로세스가 종료되도록 작성한 스크립트이다.

☞ 이러한 시그널 처리 루틴은 강제 종료시 임시 파일들을 제거하는 데 유용하다.

보안 문제 등의 외부 공격을 피하기 위해 다음과 같이 예측할 수 없는 임시 파일을 만들 수 있다.

tmpfile=$(mktemp /tmp/foobar.$$.XXXXXXXXXX)

$$ 확장 값은 PID를 의미하며 X 문자는 임의의 글자와 숫자로 교체된다. 다음과 같은 파일명이 만들어질 수 있다.

/tmp/foobar.6593.UOZuvM6654

 

일반 사용자의 스크립트에서 임시 파일을 만들 때에는 사용자 홈 디렉토리에 임시 파일을 만들기 위해 다음과 같이 디렉토리를 만들 수 있다.

[[ -d $HOME/tmp ]] || mkdir $HOME/tmp

 

[cmd_test@btjeon-naver ~]$ vi async-parent.sh
---------------------------------------------------------------------------------------------
#!/bin/bash

# async-parent : Asynchronous execution demo (parent)

echo "Parent: startring..."
echo "Parent: launching child script..."
./async-child.sh &
pid=$!
echo "Parent: child (PID= $pid) launched."

echo "Parent: continuing..."
sleep 2

echo "Parent: pausing to wait for child to finish..."
wait $pid

echo "Parent: child is finished. Continuing..."
echo "Parent: parent is done. Exiting."
---------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ vi async-child.sh
---------------------------------------------------------------------------------------------
#!/bin/bash

# async-child : Asynchronous execution demo (child)

echo "Child: child is running..."
sleep 5
echo "Child: child is done. Exiting."
---------------------------------------------------------------------------------------------
[cmd_test@btjeon-naver ~]$ ./async-parent.sh 
Parent: startring...
Parent: launching child script...
Parent: child (PID= 21687) launched.
Parent: continuing...
Child: child is running...
Parent: pausing to wait for child to finish...
Child: child is done. Exiting.
Parent: child is finished. Continuing...
Parent: parent is done. Exiting.

비동기 실행 예제. wait 명령어는 명시된 프로세스(예를 들어, 자식 스크립트)가 완료될 때까지 부모 스크립트의 실행을 멈추게 한다.

쉘 매개변수 $!은 항상 백그라운드에 진입한 마지막 프로세스 ID를 가리킨다.

 

<Terminal 1>

[cmd_test@btjeon-naver ~]$ mkfifo pipe1
[cmd_test@btjeon-naver ~]$ ll pipe1 
prw-rw-r-- 1 cmd_test cmd_test 0 Jun 23 14:28 pipe1
[cmd_test@btjeon-naver ~]$ ls -l > pipe1

<Terminal 2>
[cmd_test@btjeon-naver ~]$ cat < pipe1 
total 3916
drwxrwxr-x   2 cmd_test cmd_test       6 Jun  6 10:42 30840
-rwxrw-r--   1 cmd_test cmd_test     252 Jun 18 15:45 arith-loop.sh
-rwxrw-r--   1 cmd_test cmd_test     185 Jun 21 06:23 array-sort.sh
-rwxrw-r--   1 cmd_test cmd_test     147 Jun 23 14:20 async-child.sh
-rwxrw-r--   1 cmd_test cmd_test     399 Jun 23 14:22 async-parent.sh
drwxrwxr-x   2 cmd_test cmd_test      22 Jun  3 13:59 bin
-rwxrw-r--   1 cmd_test cmd_test     297 Jun  7 06:36 case_example.sh
-rwxrw-r--   1 cmd_test cmd_test     587 Jun  8 06:22 case_menu2.sh
-rwxrw-r--   1 cmd_test cmd_test     570 Jun  7 06:19 case_menu.sh
drwxrwxr-x   2 cmd_test cmd_test       6 Jun  6 10:42 cd
-rw-rw-r--   1 cmd_test cmd_test  141057 Jun  3 15:18 diction-1.11.tar.gz
-rw-rw-r--   1 cmd_test cmd_test   10230 Jun  1 13:32 dirlist-bin.txt
...

Named Pipe를 설정하고 사용하는 예이다.

먼저 mkfifo 명령어로 Named Pipe를 설정한다. 첫번째 터미널에서 명령어(ll)의 출력 결과를 Named Pipe로 재지정한 후 두번째 터미널에서 해당 Pipe에서 입력을 읽어들이면 첫번째 터미널의 출력 내용이 cat 명령으로 출력된다.

(사용할 일이 있을지는....)

 

 

 

 

 

 

출처 : 리눅스 커맨드라인 완벽 입문서

 

'IT일반 > Linux' 카테고리의 다른 글

VI editor reference  (0) 2022.06.21
Command Line - 배열  (0) 2022.06.18
Command Line - 문자열과 수  (0) 2022.06.17
Command Line - 흐름 제어 : for 루프  (0) 2022.06.13
Command Line - 위치 매개변수  (0) 2022.06.08