disown

구루의 기술뉴스에서 예전에 본 글이다.

“몇년전부터 알았으면?”하는 리눅스명령어는? 1등이 bash의 내장코맨드인 disown 이군요. 쉘종료하면 죽어버리는 Job들에 대해 내꺼아냐! 라고 선언해서 안죽이게 하는 명령

오늘 장시간의 rsync 명령을 사용할 일이 생겼다. 그래서 명령어를 실제로 사용해 보려고 했다.

어떻게 사용하는지 몰라서 원문을 찾아 들어갔다. 그랬더니 친절하게 사용법이 설명돼 있었다.

ssh 세션에서 매우 긴 rsync를 시작한 뒤 노트북을 끄고 밖으로 나가야 했던 경험이 있을 거다. screen이나 nohup으로 시작하는 걸 까먹었을 거다. 일단 일시정지를 하고(ctrl+z), 백그라운드 작업으로 돌릴 수 있다.(bg) 그리고 disown 으로, 당신이 세션을 종료했을 때 SIGHUP로부터 보호받도록 할 수 있다. Bash에는 (그리고 공정히 말하면, zsh와 다른 것들도 비슷할 텐데) 사람들이 잘 모를 수 있는 좋은 작업 제어 명령들이 있다. 심지어 20년 경력의 베테랑이라 해도 말이다. 더 알고 싶다면 이 페이지를 참고하라.

즉, 아래처럼 명령을 내리면 쉘에서 빠져나와도 백그라운드에서 프로세스가 계속 돌고 있게 된다.

rsync {from} {to}
# 명령을 내린 뒤 ctrl-z를 눌러 rsync 프로세스를 일시정지하고 쉘로 빠져나온다.
bg
# rsync 프로세스가 백그라운드에서 일시정지가 풀리고 돌기 시작한다.
disown
# 방금 돌린 프로세스와 shell의 연결을 끊어서 shell이 종료돼도 프로세스가 종료되지 않게 한다.
exit
# 쉘 접속을 끊어도 rsync는 종료되지 않는다.

nohup

아래와 같이 명령 맨 앞에 nohup을 붙여 실행하는 방법도 있다.

nohup rsync {from} {to}
# nohup으로 명령을 시작한다. 즉, 프로세스와 터미널을 연결하지 않고 프로세스를 시작한다.
# ctrl-z를 눌러 rsync 프로세스를 일시정지하고 쉘로 빠져나온다.
bg
# rsync 프로세스가 백그라운드에서 일시정지가 풀리고 돌기 시작한다.
exit
# 쉘 접속을 끊어도 rsync는 종료되지 않는다.

rsync 말고 sleep 100 같은 별일 없는 명령을 내린 뒤 쉘을 종료하고 다시 접속해 보자. ps aux | grep sleep으로 프로세스가 돌고 있는지 확인해 보면 돌고 있음을 알 수 있다.

이하는 각 용어에 대한 설명.

nohup의 의미

nohup 명령도 있고, disown은 뒤늦게 nohup을 선언하는 것이라고 했다. 그래서 nohup가 뭔지 찾아 봤다.

쉘에서 로그아웃할 때 쉘과 연결된(즉, 해당 쉘에서 시작한) 프로세스들에게 쉘을 끄니깐 너희도 종료하라는 신호가 간다. 이를 SIGHUP이라고 부르는데, Signal Hang Up(종료 신호)의 약자다.

즉, nohup은 쉘 종료시 이 프로세스에 종료 신호를 보내지 않겠다는 뜻이 된다. 정확히는 해당 프로세스를 쉘의 작업 목록에서 빼는 것을 뜻한다고 한다. (참고/번역문서)

그런데 “nohup와, 백그라운드 작업”이라는 글을 보니, 요새는 굳이 nohup으로 명령을 시작하지 않아도 자동으로 nohup이 된다고 한다. 확인은 못 해 봤다. bash 설정을 확인하면 되는데,

명령줄에 shopt | grep huponexit 라고 치면
huponexit off
라고 나옵니다.
huponexitexit 할 때 SIGHUP을 모든 job에게 보낸다는 옵션인 것 같습니다.
이게 기본으로 켜 있지 않네요.

라고 한다. 즉 huponexitoff면 세션을 종료할 때 job이 죽지 않는다는 말이리라. 그러면 그냥 Ctrl+Z 를 눌러 일시정지를 한 뒤, bg를 쳐서 백그라운드작업으로 돌린 뒤, 세션을 나오면 되는 듯하다. 물론 나는 그래도 불안하니 disown을 치고 나서 나오련다.

screen

마지막으로 터미널용 멀티 세션 관리자인 screennohup와 같은 용도로 사용할 수 있다. (참고1, 참고2)

# screen [ -options ] [ cmd [ args ] ] 형태로 사용한다.
screen -S {세션명} rsync {from} {target}
# 이후 ctrl-a,d를 눌러 빠져나온다.

이러면 끝이다. ctrl-a,d만 기억하면 비교적 쉽다. ctrl-a는 터미널 커맨드라인에서 맨 앞으로 커서를 옮기는 것이고, ctrl-d는 터미널에 종료 신호를 보낼 때 사용하는 단축키이므로 기억하기 좋다. ctrl-d 자체가 커서가 맨 앞에 있을 때만 작동하므로 커서를 맨 앞으로 옮긴 뒤 screen을 종료하는 것이라고 생각하면 된다.

아까 하던 작업은 어떻게 확인할까? 우선 screen -ls 명령은 현재 떠 있는 스크린 목록을 출력해 준다.

$ screen -ls
There are screens on:
	81742.my-session2	(Detached)
	81581.my-session1	(Detached)
2 Sockets in /var/folders/xj/3gthk3gx64b7sg6pt8f6n_qm0000gn/T/.screen.

위 코드는 screen -ls 명령을 내렸을 때 출력된 것을 보여 주고 있다. 2개의 스크린이 떠 있고(2 Sockets), 해당 스크린의 정보를 알 수 있다.

  • 81742.my-session2: 81742번 프로세스가 돌고 있으며 screen 세션의 이름은 my-session2다.

원하는 스크린으로 들어가고 싶을 때는 아래처럼 명령을 내린다. 아래 명령은 my-session2 스크린으로 들어가는 방법이다.

screen -r my-session2

다시 원 쉘로 나오려면 ctrl-a,d를 누른다.