Computer >> 컴퓨터 >  >> 프로그래밍 >> Bash 프로그래밍

Bash 제어 연산자(&&, ||)를 활용한 명령어 조합과 흐름 제어 완벽 가이드

명령줄에서 여러 명령을 한 줄로 이어서 실행하는 것과 같은 간단한 복합 명령은 매우 자주 사용됩니다. 이러한 명령들은 세미콜론(;)으로 구분되며, 세미콜론은 명령의 끝을 정의합니다. 한 줄에 간단한 셸 명령 시리즈를 만들려면 다음과 같이 각 명령을 세미콜론으로 구분하기만 하면 됩니다.

command1 ; command2 ; command3 ; command4 ;

마지막 세미콜론은 생략해도 됩니다. Enter 키를 누르는 것이 마지막 명령의 끝을 의미하기 때문입니다. 다만 일관성을 위해 붙여도 전혀 문제되지 않습니다.

오류가 발생하면 어떻게 될까?

위와 같이 나열된 모든 명령은 오류가 발생하지 않는 한 아무 문제 없이 실행됩니다. 하지만 오류가 발생하면 어떻게 될까요? Bash에 내장된 &&|| 제어 연산자를 사용하면 오류를 미리 예측하고 대응할 수 있습니다. 이 두 연산자는 흐름 제어 기능을 제공하여 코드 실행 순서를 변경할 수 있게 해줍니다. 참고로 세미콜론과 개행(newline) 문자 역시 Bash의 제어 연산자로 간주됩니다.

&& 연산자: 성공 시에만 다음 명령 실행

&& 연산자는 "command1이 성공하면 command2를 실행하라"는 의미입니다. command1이 어떤 이유로든 실패하면 command2는 실행되지 않습니다. 기본 문법은 다음과 같습니다.

command1 && command2

이것이 동작하는 이유는 모든 명령이 실행 성공 여부를 셸에 반환 코드(return code)로 알리기 때문입니다. 관례상 반환 코드(RC)가 0이면 성공을, 양수이면 일종의 실패를 나타냅니다. 일부 시스템 관리 도구는 실패를 단순히 1로만 반환하지만, 많은 도구들이 실패 유형을 구분하기 위해 다른 양수 코드를 사용합니다.

Bash 셸의 $? 변수는 스크립트에서, 명령 목록의 다음 명령에서, 심지어 시스템 관리자가 직접 확인할 수도 있습니다. 실제로 반환 코드를 살펴보겠습니다. 간단한 명령을 실행한 직후 RC를 확인하면, RC는 항상 마지막으로 실행된 명령에 해당합니다.

[student@studentvm1 ~]$ ll ; echo "RC = $?"
total 284
-rw-rw-r-- 1 student student 130 Sep 15 16:21 ascii-program.sh
drwxrwxr-x 2 student student 4096 Nov 10 11:09 bin
<snip>
drwxr-xr-x. 2 student student 4096 Aug 18 10:21 Videos
RC = 0
[student@studentvm1 ~]$

반환 코드가 0이므로 명령이 성공적으로 완료되었음을 의미합니다. 이번에는 권한이 없는 디렉터리에 대해 같은 명령을 실행해 보겠습니다.

[student@studentvm1 ~]$ ll /root ; echo "RC = $?"
ls: cannot open directory '/root': Permission denied
RC = 2
[student@studentvm1 ~]$

이 반환 코드의 의미는 ls 명령의 man 페이지에서 확인할 수 있습니다.

&& 연산자 실습 예제

이제 && 제어 연산자를 명령줄 프로그램에서 실제로 활용하는 방법을 살펴보겠습니다. 간단한 예제부터 시작합니다. 새 디렉터리를 생성하고, 그 작업이 성공하면 그 안에 새 파일을 생성하는 것입니다.

먼저 테스트를 진행할 수 있는 임시 디렉터리를 홈 디렉터리에 생성합니다.

[student@studentvm1 ~]$ cd ; mkdir testdir

~/testdir 안에 새 디렉터리를 생성합니다(방금 만들었으므로 비어 있어야 합니다). 그다음 그 새 디렉터리 안에 빈 파일을 하나 생성합니다. 다음 명령이 이 작업들을 수행합니다.

[student@studentvm1 ~]$ mkdir ~/testdir/testdir2 && touch ~/testdir/testdir2/testfile1 
[student@studentvm1 ~]$ ll ~/testdir/testdir2/
total 0
-rw-rw-r-- 1 student student 0 Nov 12 14:13 testfile1
[student@studentvm1 ~]$

testdir 디렉터리에 접근 가능하고 쓰기가 가능했기 때문에 모든 것이 정상적으로 동작했습니다. 이제 testdir의 권한을 변경하여 student 사용자가 더 이상 접근할 수 없도록 만들어 보겠습니다.

[student@studentvm1 ~]$ chmod 076 testdir ; ll | grep testdir
d---rwxrw-. 3 student student 4096 Nov 12 14:13 testdir
[student@studentvm1 ~]$

긴 목록(ll) 명령 뒤에 grep을 사용하면 testdir의 항목만 표시됩니다. student 사용자가 더 이상 testdir 디렉터리에 접근할 수 없음을 확인할 수 있습니다. 이제 앞서와 거의 동일한 명령을 실행하되, testdir 안에 다른 이름의 디렉터리를 생성하도록 변경해 보겠습니다.

[student@studentvm1 ~]$ mkdir ~/testdir/testdir3 && touch ~/testdir/testdir3/testfile1 
mkdir: cannot create directory '/home/student/testdir/testdir3': Permission denied
[student@studentvm1 ~]$

오류 메시지가 출력되었지만, && 제어 연산자 덕분에 touch 명령은 실행되지 않았습니다. testdir3 생성 과정에서 오류가 발생했기 때문입니다. 이런 방식의 명령줄 논리 흐름 제어는 오류가 누적되어 큰 문제로 번지는 것을 방지할 수 있습니다. 이제 조금 더 복잡하게 만들어 보겠습니다.

|| 연산자: 실패 시 대체 명령 실행

|| 제어 연산자를 사용하면 초기 명령이 0보다 큰 코드를 반환할 때(즉, 실패했을 때) 실행할 또 다른 명령을 추가할 수 있습니다.

[student@studentvm1 ~]$ mkdir ~/testdir/testdir3 && touch ~/testdir/testdir3/testfile1 || echo "An error occurred while creating the directory."
mkdir: cannot create directory '/home/student/testdir/testdir3': Permission denied
An error occurred while creating the directory.
[student@studentvm1 ~]$

복합 명령의 일반적인 형태

&&|| 제어 연산자를 사용하는 흐름 제어 복합 명령은 다음과 같은 일반적인 형태를 갖습니다.

preceding commands ; command1 && command2 || command3 ; following commands

제어 연산자를 사용한 복합 명령 앞뒤에는 다른 명령들이 올 수 있습니다. 이 명령들은 흐름 제어 섹션의 명령들과 관련이 있을 수 있지만, 흐름 제어의 영향은 받지 않습니다. 즉, 흐름 제어 복합 명령 내부에서 무슨 일이 일어나더라도 앞뒤의 모든 명령은 조건과 상관없이 실행됩니다.

이러한 흐름 제어 연산자는 판단 로직을 처리하고 문제 발생 시 이를 알려줌으로써 명령줄 작업을 훨씬 더 효율적으로 만들어 줍니다. 저 역시 스크립트뿐 아니라 명령줄에서도 직접 활용하고 있습니다.

실습이 끝났으니 root 사용자로 디렉터리와 그 내용을 삭제하여 정리할 수 있습니다.

[root@studentvm1 ~]# rm -rf /home/student/testdir

Bash 제어 연산자를 어떻게 활용하고 계신가요? 댓글로 여러분의 경험을 공유해 주세요.