Ansible을 이용한 백그라운드 프로세스의 안정적인 실행 방법

Ansible을 사용하여 원격 서버에서 Java 애플리케이션과 같은 백그라운드 프로세스를 실행할 때, 명령어가 성공적으로 수행되었음에도 불구하고 실제로는 프로세스가 즉시 종료되는 현상이 발생하곤 합니다. 이는 Ansible의 동작 방식과 SSH 세션의 특성에서 비롯된 문제입니다.

프로세스가 종료되는 원인

기본적으로 Ansible은 SSH를 통해 원격 호스트에서 작업을 수행합니다. 각 태스크는 독립적인 SSH 세션과 연결된 터미널(TTY) 환경에서 실행되는데, 태스크가 완료되어 세션이 닫히면 해당 터미널과 연관된 모든 자식 프로세스에게 종료 신호가 전달됩니다. 결과적으로 백그라운드(&)로 실행한 프로세스라 할지라도 부모 프로세스가 종료되면서 함께 소멸하게 됩니다.

또한, Ansible은 non-login shell 방식을 사용하므로 /etc/profile이나 ~/.bash_profile과 같은 환경 설정 파일을 자동으로 로드하지 않습니다. 이로 인해 JDK 경로 등 필수적인 환경 변수가 누락되어 실행에 실패하는 경우도 빈번합니다.

해결 방법 1: nohup 사용

터미널이 종료되어도 프로세스가 계속 실행되도록 하려면 nohup(no hangup) 명령어를 사용해야 합니다. 이를 통해 SIGHUP 신호를 무시하도록 설정할 수 있습니다.

# 개선 전 실행 스크립트 예시
cd /opt/service-app
java -Dapp.name=myService -jar service.jar > ./logs/console.log 2>&1 &

위의 방식을 nohup을 적용하여 다음과 같이 수정합니다.

# nohup 적용 후
cd /opt/service-app
nohup java -Dapp.name=myService -jar service.jar > ./logs/console.log 2>&1 &

해결 방법 2: 환경 변수 명시적 로드

nohup을 사용했음에도 불구하고 프로세스가 정상적으로 뜨지 않는다면, 환경 변수 로드 문제일 가능성이 높습니다. 특히 Java 실행 파일의 경로가 잡히지 않는 문제를 해결하기 위해 프로필 파일을 직접 source 명령어로 불러와야 합니다.

# 환경 변수 로드와 nohup을 결합한 최종 형태
source /etc/profile
source ~/.bash_profile

cd /opt/service-app
nohup java -Xms1G -Xmx2G \
     -Dserver.port=8080 \
     -cp ".:./lib/*:./config" \
     com.service.MainLauncher > ./logs/app.out 2> ./logs/app.err &

Ansible 플레이북에서의 적용

Ansible의 shell 모듈을 사용하여 이를 실행할 때는 다음과 같은 구조를 권장합니다.

- name: 백그라운드 서비스 시작
  shell: |
    source ~/.bash_profile
    nohup java -jar /opt/service-app/app.jar > /dev/null 2>&1 &
  args:
    chdir: /opt/service-app

이와 같이 source를 통한 환경 변수 주입과 nohup을 통한 세션 분리 처리를 병행하면, Ansible 태스크 완료 후에도 백그라운드 프로세스가 안정적으로 유지되는 것을 확인할 수 있습니다.

태그: Ansible SSH java DevOps BackgroundProcess

6월 18일 22:30에 게시됨