Linux나 macOS에서 프로그램을 실행하면 항상 하나의 프로세스 안에서 동작합니다. 그리고 모든 프로세스에는 고유한 이름이 있습니다. 이 이름은 ps, top, htop 같은 명령어를 실행했을 때 화면에 표시되는 것입니다.
htop은 가장 오른쪽 열에 프로세스 이름을 표시합니다.
기본 프로세스 이름의 한계
기본적으로 프로세스의 이름은 실행 중인 프로그램이 담긴 실행 파일의 이름에서 따옵니다. 대부분의 경우 이 방식이 잘 작동합니다. "less"를 실행하면 프로세스 이름도 "less"가 되는 것이 자연스럽기 때문입니다.
하지만 명령줄에서 Ruby 스크립트를 실행할 때는 기본 프로세스 이름이 큰 도움이 되지 않습니다. 아래 예제에서는 5초간 대기하는 Ruby 스크립트를 실행하고 있습니다. 이때 다른 터미널 창에서 "ps"를 실행해 보면 해당 프로세스의 이름이 "ruby sleep_5_seconds.rb"로 표시됩니다. 여기에 명령줄 인수를 추가하면 인수까지 모두 프로세스 이름에 포함되어, 이름만으로 프로세스를 지정하기가 매우 어려워집니다.
전체 ruby 명령이 프로세스 이름으로 표시됩니다
프로세스 이름 변경 방법
다행히 Ruby에서는 현재 프로세스의 이름을 아주 간단하게 변경할 수 있습니다. 다음은 수정된 스크립트로, 프로세스 이름을 "sleeper"로 설정합니다.
# `Process.setproctitle()`은 Ruby 2.1 이상에서 사용 가능
# 그 이전 버전에서는 다음을 사용할 수 있습니다:
# $PROGRAM_NAME = "sleeper"
# 또는
# $0 = "sleeper"
Process.setproctitle("sleeper")
sleep 5
이제 프로그램을 실행한 뒤 ps로 확인해 보면 프로세스 이름이 "sleeper"로 표시됩니다.
Ruby에서 프로세스 제목을 변경하면 ps와 top의 출력 결과가 달라집니다
더 좋은 점은 이제 이름만으로 프로세스를 손쉽게 지정할 수 있다는 것입니다. sleeper가 잠자는 것이 지겨워졌다면 killall sleeper 명령 한 줄로 종료할 수 있습니다.
killall 명령으로 이름 기반으로 프로세스를 종료할 수 있습니다
프로세스 이름으로 서버 상태 표시하기
프로세스 제목을 변경할 수 있게 된 것의 흥미로운 활용 사례 중 하나는 장시간 실행되는 프로세스의 상태 정보를 표시하는 것입니다. Unicorn을 사용해 본 적이 있다면 다음 출력이 익숙할 것입니다:
\-+= 27185 deply unicorn master -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27210 deply unicorn worker[0] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27211 deply unicorn worker[1] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27212 deply unicorn worker[2] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27213 deply unicorn worker[3] -c simple_unicorn_config.rb -l0.0.0.0:8080
네 개의 자식 프로세스를 가진 Unicorn 인스턴스입니다. 앞서 sleep_5_seconds.rb 예제와 마찬가지로 프로세스 이름에는 프로세스를 시작한 명령어만 표시됩니다.
그런데 만약 상태 줄에 각 워커가 바쁜지(BUSY) 유휴 상태인지 함께 표시된다면 훨씬 유용할 것입니다. 다음과 같이 말이죠:
\-+= 27185 deply unicorn master -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27210 deply unicorn worker[0] -c simple_unicorn_config.rb -l0.0.0.0:8080 BUSY
|--- 27211 deply unicorn worker[1] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27212 deply unicorn worker[2] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27213 deply unicorn worker[3] -c simple_unicorn_config.rb -l0.0.0.0:8080 BUSY
사실 Rack 미들웨어를 사용하면 이 기능을 꽤 쉽게 구현할 수 있습니다. 다음은 그 구현 예시입니다:
class UpdateProcessTitle
def initialize(app)
@app = app
end
def call(env)
title = $0
$0 = $0 + " BUSY"
status, headers, body = @app.call(env)
$0 = title
[status, headers, body]
end
end
모든 웹 요청마다 프로세스 제목을 설정하는 것이 성능에 어떤 영향을 미치는지는 확실하지 않으므로, 이 내용은 어느 정도 걸러서 받아들이시기 바랍니다. 그래도 꽤 흥미로운 아이디어인 것은 분명합니다.
이 아이디어를 더 발전시킨 구현, 즉 실제 프로덕션 환경에서 사용된 사례를 보고 싶다면 Thomas Varaneckas의 "Overriding Unicorn Worker Process Names"라는 훌륭한 블로그 포스트를 참고해 보세요.