리눅스에서 세션이 끊어져도 프로세스 유지하기

이 포스트에서는 리눅스에서 세션이 끊어져도 프로세스를 유지하는 방법을 설명합니다.

리눅스 서버를 다루는 경우 SSH를 이용해 시스템에 로그인하는데 세션이 끊어져도 프로세스를 유지해야 하는 상황이 발생할 수 있습니다. 이럴 때 nohup 명령어를 사용합니다. 리눅스에서는 세션이 끊어지면 SIGHUP이라는 시그널을 보내고 이 시그널을 받은 프로세스는 자동으로 종료되는데, nohup 명령어는 이 SIGHUP 시그널을 무시하도록 하는 명령입니다.

사용법은 다음과 같습니다.

$ nohup (실행할 명령) &

여기서 nohup 다음에 실행할 명령을 쓰고 & 표시로 끝냅니다. & 표시는 앞에 오는 명령을 백그라운드 상태로 실행하는 명령어입니다.

일단, 다음과 같은 셸 스크립트를 작성해 봅시다.

#!/usr/bin/bash

for var in {99..1..-1};
do
    if [ $var -gt 1 ]
    then
        echo "$(expr $var) bottles of beer on the wall. $(expr $var) bottles of beer."
    else
        echo "1 bottle of beer on the wall. 1 bottle of beer."
    fi
    echo -n "Take one down pass it around. "
    if [ $var -gt 2 ]
    then
        echo "$(expr $var - 1) bottles of beer on the wall."
    elif [ $var -eq 2 ]
    then
        echo "1 bottle of beer on the wall."
    else
        echo "no more bottles of beer on the wall."
    fi
    echo ""
    sleep 1
done

echo "No more bottles of beer on the wall, no more bottles of beer."
echo "Go to the store and buy some more, 99 bottles of beer on the wall."

99병의 맥주 노래의 가사를 출력하는데 한 병이 줄어들 때마다 1초씩 멈춥니다. 즉 이 스크립트가 완전히 실행되려면 1분 39초(99초)가 걸립니다. 이 스크립트의 이름을 99_bottles.sh라고 저장했다고 가정하고, 다음과 같은 명령어를 쳐 봅시다.

$ chmod +x 99_bottles.sh
$ nohup ./99_bottles.sh > 99_bottles.txt &
[1] 31920
nohup: ignoring input and redirecting stderr to stdout
$ logout

일단 chmod 명령어를 사용하여 99_bottles.sh 파일을 직접 실행이 가능하게 만든 다음 nohup 명령어를 써서 이 스크립트를 세션이 끊어져도 유지되게 하면서 끝에 & 표시를 붙여 백그라운드로 실행합니다.
그리고 실행하자마자 곧바로 로그아웃으로 세션을 종료한 다음 다시 로그인하여 다음 명령을 실행해 봅시다.

$ ps x
  PID TTY      STAT   TIME COMMAND
(편의상 생략)
31920 ?        S      0:00 /usr/bin/bash ./99_bottles.sh
(편의상 생략)
$

만약 스크립트가 종료되기 전에 위의 명령을 실행하면 실행했을 때 뜬 PID가 똑같이 나오며 백그라운드로 실행중인 상태임을 알 수 있습니다. 즉 세션이 끊어져도 프로세스는 유지되었음을 알 수 있습니다. 만약 스크립트가 이미 종료된 뒤에 실행하면 뜨지 않습니다.

스크립트가 종료된 뒤에 출력 파일(여기서는 99_bottles.txt)을 확인해 보면

$ cat 99_bottles.txt
99 bottles of beer on the wall. 99 bottles of beer.
Take one down pass it around. 98 bottles of beer on the wall.

98 bottles of beer on the wall. 98 bottles of beer.
Take one down pass it around. 97 bottles of beer on the wall.

(편의상 생략)

1 bottle of beer on the wall. 1 bottle of beer.
Take one down pass it around. no more bottles of beer on the wall.

No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.
$

이렇게 스크립트의 결과가 완전히 파일로 출력되었음을 알 수 있습니다.

여기서 잠깐,

$ (실행할 명령) &

위와 같이 nohup 명령어 없이 그냥 뒤에 & 표시만 붙이면 세션이 끊어졌을 때 어떻게 될까요?

답은 ‘SH 옵션에 따라 다르다’입니다.
shopt 명령으로 볼 수 있는 SH 옵션 중 huponexit라는 항목이 있는데 이는 로그아웃시 SIGHUP 시그널을 보낼지의 여부로, 이 항목이 off로 설정되어 있으면 nohup 명령어 없이 그냥 백그라운드로만 실행해도 nohup 명령어를 실행했을 때와 같은 효과가 발동합니다. 단 다른 이유로 SIGHUP 시그널이 보내지면 프로세스가 종료됩니다.
그러나 on으로 설정되어 있으면 백그라운드로 실행중인 프로세스도 nohup 명령어 없이 실행한 프로그램이면 로그아웃으로 세션이 끊어짐과 동시에 종료됩니다.

답글 남기기

이메일 주소는 공개되지 않습니다.