μ•ˆλ…•ν•˜μ„Έμš” Mambo μž…λ‹ˆλ‹€.

μ„œλ²„μ—μ„œ 싀행쀑인 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ€ μ–Έμ œλ“ μ§€ 예기치 μ•Šμ€ μƒν™©μœΌλ‘œ 쀑단될 수 μžˆμŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, μΌμ‹œμ μœΌλ‘œ μ „λ ₯이 μ°¨λ‹¨λ˜μ–΄ μ„œλ²„ μž₯λΉ„κ°€ λ‹€μ‹œ μ‹œμž‘λ˜κ±°λ‚˜ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ ν”„λ‘œμ„ΈμŠ€κ°€ μ„œλ²„ μžμ›μ„ 많이 μ‚¬μš©ν•΄μ„œ ν”„λ‘œμ„ΈμŠ€κ°€ μ€‘λ‹¨λ˜λŠ” 상황이 λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

κ·Έλž˜μ„œ 였늘 μ•Œμ•„λ³Ό λ‚΄μš©μ€ λ¦¬λˆ…μŠ€μ—μ„œ 예기치 μ•Šμ€ μƒν™©μœΌλ‘œ μΈν•˜μ—¬ ν”„λ‘œμ„ΈμŠ€κ°€ μ€‘λ‹¨λ˜μ—ˆμ„ 경우 μžλ™μœΌλ‘œ ν”„λ‘œμ„ΈμŠ€λ₯Ό λ‹€μ‹œ μ‹€ν–‰μ‹œν‚΄μœΌλ‘œμ¨ ν”„λ‘œμ„ΈμŠ€ μ‹€ν–‰ μƒνƒœλ₯Ό μœ μ§€ν•˜κΈ° μœ„ν•œ λ°©λ²•μž…λ‹ˆλ‹€.

ν”„λ‘œμ„ΈμŠ€ μ‹€ν–‰ μœ μ§€

λ¨Όμ €, μŠ€ν”„λ§ λΆ€νŠΈ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ λ‹€μŒκ³Ό 같이 μ‹€ν–‰ν•  수 μžˆλ‹€κ³  κ°€μ • ν•˜κ² μŠ΅λ‹ˆλ‹€.

nohup java -jar -Xmx500m demo.war 1> app.log 2>&1 &
# [1] 227

ls -l
# total 21M
# -rw-r--r-- 1 ec2-user ec2-user 2.0K Oct  8 15:19 app.log
# -rw-r--r-- 1 ec2-user ec2-user    3 Oct  8 15:19 app.pid
# -rwxr-xr-x 1 ec2-user ec2-user  20M Oct  8 12:28 demo.war*

cat app.pid
# 227

μœ„ μ˜ˆμ‹œμ—μ„œ nohup λͺ…λ Ήμ–΄λ₯Ό μ‚¬μš©ν•˜κ³  좜λ ₯된 ν”„λ‘œμ„ΈμŠ€ 아이디와 μŠ€ν”„λ§ λΆ€νŠΈ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ ApplicationPidWriter에 μ˜ν•΄ μƒμ„±λœ ν”„λ‘œμ„ΈμŠ€ 아이디 파일이 λ™μΌν•œ 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

ν”„λ‘œμ„ΈμŠ€ 아이디 ν™•μΈν•˜κΈ°

μ•žμ„œ μŠ€ν”„λ§ λΆ€νŠΈ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ²˜λŸΌ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 자체적으둜 ν˜„μž¬ 싀행쀑인 ν”„λ‘œμ„ΈμŠ€ 아이디λ₯Ό μ €μž₯ν•  수 μžˆλŠ” κΈ°λŠ₯을 ν¬ν•¨ν•˜κ³  μžˆλ‹€λ©΄ μ’‹κ² μ§€λ§Œ 그렇지 μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ 이미 싀행쀑인 ν”„λ‘œμ„ΈμŠ€ 아이디λ₯Ό ν™•μΈν•˜κ³  κ°€μ Έμ˜¬ 수 μžˆλŠ” 방법을 μ•Œμ•„μ•Ό ν•©λ‹ˆλ‹€.

# echo $!
nohup java -jar -Xmx500m demo.war 1> app.log 2>&1 & echo $! > app.pid

# JPS(JVM Process Status)
jps -v | grep war | awk '{print $1}'

# ps -ef
ps -ef | grep java | grep -v grep | awk '{print $2}'

# netstat -tnlp
netstat -tnlp | grep java | awk '{print $7}' | awk -F '/' '{print $1}'

# pgrep
pgrep java

첫번째 방식에 μ‚¬μš©λœ echo $! λŠ” λ§ˆμ§€λ§‰μœΌλ‘œ λ°±κ·ΈλΌμš΄λ“œμ—μ„œ μ‹€ν–‰λœ λͺ…령어에 λŒ€ν•œ PID값을 좜λ ₯ν•  수 μžˆλŠ” λͺ…λ Ήμ–΄μž…λ‹ˆλ‹€.

Crontab으둜 ν”„λ‘œμ„ΈμŠ€ μœ μ§€ν•˜κΈ°

일반적으둜 μ‚¬μš©λ˜λŠ” 고전적인 방식은 μ•žμ„œ λ‹€μ–‘ν•œ λ°©μ‹μœΌλ‘œ μΆ”μΆœλœ ν”„λ‘œμ„ΈμŠ€ 아이디에 λŒ€ν•œ ν”„λ‘œμ„ΈμŠ€ μ‹€ν–‰ μƒνƒœλ₯Ό μ²΄ν¬ν•˜λŠ” 슀크립트λ₯Ό Crontab을 톡해 주기적으둜 μ‹€ν–‰ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

#!/bin/sh

PID_FILE="app.pid"

autorun () {
  # ... & echo $! > app.pid
}

if [ -f "$PID_FILE" ] && [ ! -z `cat "$PID_FILE"` ]; then
  PID=$(cat $PID_FILE)
  if ps -p $PID > /dev/null; then
    echo "$PID_FILE($PID) is running"
  else
    autorun
  fi
else
  autorun
fi

SystemD

더 효율적인 방식은 Nginx와 같은 νŒ¨ν‚€μ§€λ₯Ό APT λ˜λŠ” YUM으둜 μ„€μΉ˜ν•  λ•Œ SystemD μ„œλΉ„μŠ€μ— μžλ™μœΌλ‘œ λ“±λ‘ν•˜λŠ” κ²ƒμ²˜λŸΌ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μ‹€ν–‰ν•˜λŠ” λͺ…λ Ήμ–΄ λ˜λŠ” 슀크립트λ₯Ό SystemD μ„œλΉ„μŠ€λ‘œ λ“±λ‘ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

/etc/systemd/system/demo.service

[Unit]
Description=Demo
After=syslog.target

[Service]
User=ec2-user
WorkingDirectory=/home/ec2-user
ExecStart=/usr/bin/java -jar -Xmx500m demo.war
ExecStop=kill -9 `cat app.pid`
SuccessExitStatus=143
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

μœ„μ™€ 같이 슀크립트λ₯Ό μ •μ˜ν–ˆλ‹€λ©΄ λ‹€μŒκ³Ό 같이 μ„œλ²„κ°€ 싀행될 λ•Œ μ„œλΉ„μŠ€κ°€ μ‹œμž‘λ˜λ„λ‘ ν™œμ„±ν™”ν•˜κ±°λ‚˜ 직접 μ„œλΉ„μŠ€λ₯Ό μ‹€ν–‰ν•˜κ³  μ’…λ£Œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

sudo systemctl daemon-reload
sudo systemctl enable demo.service
sudo systemctl start demo.service

κ°μ‚¬ν•©λ‹ˆλ‹€.