11. PM2 ecosystem 설정 파일 작성
PM2는 명령행에서 직접 프로그램을 등록할 수도 있지만, 운영 환경에서는 ecosystem 설정 파일을 사용하는 것이 좋습니다.
ecosystem 파일에는 다음 내용을 저장할 수 있습니다.
- 프로그램 이름
- 실행할 스크립트
- 작업 디렉터리
- 인터프리터
- 환경 변수
- 자동 재시작 여부
- 재시작 지연시간
- 로그 파일 위치
- 종료 대기시간
PM2 공식 문서에서도 여러 프로그램과 실행 옵션을 관리할 때 ecosystem.config.js 파일을 사용하는 방법을 안내합니다.
다음 파일을 생성합니다.
nano ~/robot_scripts/ecosystem.config.js
파일 내용은 다음과 같습니다.
const os = require("os");
const path = require("path");
const home = os.homedir();
const user = os.userInfo().username;
module.exports = {
apps: [
{
name: "turtlebot3-robot",
script: path.join(
home,
"robot_scripts",
"turtlebot3_pm2_supervisor.sh"
),
interpreter: "/bin/bash",
cwd: home,
exec_mode: "fork",
instances: 1,
autorestart: true,
watch: false,
restart_delay: 5000,
min_uptime: "30s",
max_restarts: 20,
kill_timeout: 15000,
time: true,
merge_logs: true,
out_file: path.join(
home,
"robot_logs",
"turtlebot3-pm2-out.log"
),
error_file: path.join(
home,
"robot_logs",
"turtlebot3-pm2-error.log"
),
env: {
HOME: home,
USER: user,
ROBOT_CONTROL_SCRIPT: path.join(
home,
"robot_scripts",
"turtlebot3_tmux.sh"
)
}
}
]
};
1) 운영체제 정보 모듈 불러오기
const os = require("os");
Node.js의 기본 모듈인 os를 불러옵니다.
os 모듈은 현재 운영체제와 사용자 환경에 관한 정보를 가져올 때 사용합니다.
이 설정 파일에서는 다음 정보를 얻기 위해 사용합니다.
- 현재 사용자의 홈 디렉터리
- 현재 실행 사용자의 계정 이름
사용자 이름이나 홈 디렉터리를 직접 작성하지 않기 때문에 다른 사용자 계정에서도 설정 파일을 재사용할 수 있습니다.
예를 들어 사용자 계정이 robot이라면 홈 디렉터리는 일반적으로 다음과 같습니다.
/home/robot
사용자 계정이 ubuntu라면 다음 경로가 사용될 수 있습니다.
/home/ubuntu
2) 경로 처리 모듈 불러오기
const path = require("path");
Node.js의 기본 모듈인 path를 불러옵니다.
path 모듈은 여러 경로 문자열을 운영체제 형식에 맞게 연결합니다.
예를 들어 다음 코드는
path.join(
home,
"robot_scripts",
"turtlebot3_pm2_supervisor.sh"
)
사용자의 홈 디렉터리가 /home/robot일 경우 다음 경로를 생성합니다.
/home/robot/robot_scripts/turtlebot3_pm2_supervisor.sh
문자열을 직접 연결하는 방식보다 path.join()을 사용하는 것이 안전합니다.
다음과 같은 문제를 줄일 수 있습니다.
- 경로 구분자 누락
- 중복된
/문자 - 사용자별 홈 디렉터리 차이
- 경로 작성 실수
3) 홈 디렉터리 가져오기
const home = os.homedir();
현재 PM2를 실행하는 사용자의 홈 디렉터리를 가져와 home 변수에 저장합니다.
사용자가 sjyong이라면 다음 값이 저장될 수 있습니다.
/home/sjyong
이 값은 설정 파일 전체에서 다음 경로를 구성할 때 사용합니다.
- Supervisor 스크립트 경로
- PM2 작업 디렉터리
- 로그 파일 경로
- 로봇 제어 스크립트 경로
HOME환경 변수
홈 디렉터리를 변수로 관리하면 사용자 계정이 변경되더라도 설정 파일 내부의 여러 경로를 일일이 수정할 필요가 없습니다.
4) 사용자 이름 가져오기
const user = os.userInfo().username;
현재 프로세스를 실행하는 운영체제 사용자의 이름을 가져옵니다.
예를 들어 PM2를 sjyong계정으로 실행했다면 다음 값이 저장됩니다.
sjyong
이 값은 이후 USER 환경 변수로 Supervisor 스크립트에 전달됩니다.
주의할 점은 os.userInfo().username이 로그인 화면에 표시된 이름이 아니라 실제 리눅스 사용자 계정 이름을 반환한다는 것입니다.
5) PM2 설정 내보내기
module.exports = {
apps: [
Node.js의 module.exports 문법을 사용해 PM2가 읽을 설정 객체를 외부로 내보냅니다.
PM2 ecosystem 파일은 일반적으로 apps 배열 안에 하나 이상의 애플리케이션 설정을 작성합니다.
현재 설정에는 하나의 애플리케이션만 등록되어 있습니다.
apps: [
{
// TurtleBot3 설정
}
]
여러 로봇 프로세스나 보조 프로그램을 함께 관리하려면 apps 배열에 설정 객체를 추가할 수 있습니다.
6) PM2 프로세스 이름
name: "turtlebot3-robot",
PM2에서 표시할 애플리케이션 이름입니다.
PM2 상태를 확인하면 이 이름으로 표시됩니다.
pm2 status
예상 출력은 다음과 비슷합니다.
turtlebot3-robot
PM2 명령에서도 이 이름을 사용합니다.
프로세스 시작:
pm2 start ecosystem.config.js
프로세스 재시작:
pm2 restart turtlebot3-robot
프로세스 중지:
pm2 stop turtlebot3-robot
프로세스 삭제:
pm2 delete turtlebot3-robot
로그 확인:
pm2 logs turtlebot3-robot
이름은 시스템 내에서 중복되지 않도록 작성하는 것이 좋습니다.
7) 실행할 Supervisor 스크립트 지정
script: path.join(
home,
"robot_scripts",
"turtlebot3_pm2_supervisor.sh"
),
PM2가 실제로 실행할 파일을 지정합니다.
사용자의 홈 디렉터리가 /home/sjyong이라면 최종 경로는 다음과 같습니다.
/home/sjyong/robot_scripts/turtlebot3_pm2_supervisor.sh
이 스크립트는 TurtleBot3 관련 tmux 세션을 시작하고 상태를 감시하는 역할을 담당합니다.
일반적인 실행 구조는 다음과 같습니다.
- PM2가 Supervisor 스크립트를 실행합니다.
- Supervisor가 네트워크 상태를 확인합니다.
- Supervisor가 TurtleBot3 tmux 세션을 시작합니다.
- tmux 내부에서 ROS 2 bringup, camera, audio 프로세스를 실행합니다.
- Supervisor가 tmux 세션과 주요 창을 주기적으로 검사합니다.
- 장애가 발생하면 Supervisor가 종료 코드 1을 반환합니다.
- PM2가 Supervisor를 다시 실행합니다.
- TurtleBot3 시스템이 초기 상태부터 다시 시작됩니다.
실행 파일에는 실행 권한이 있어야 합니다.
chmod +x ~/robot_scripts/turtlebot3_pm2_supervisor.sh
스크립트 내부에서 호출하는 로봇 제어 스크립트에도 실행 권한이 필요합니다.
chmod +x ~/robot_scripts/turtlebot3_tmux.sh
8) Bash 인터프리터 지정
interpreter: "/bin/bash",
PM2가 Supervisor 파일을 /bin/bash로 실행하도록 지정합니다.
PM2는 Node.js 프로그램뿐만 아니라 다양한 스크립트를 실행할 수 있습니다. 하지만 실행 대상이 Bash 스크립트이므로 인터프리터를 명시적으로 설정하는 것이 안전합니다.
실제로는 다음과 유사한 형태로 실행됩니다.
/bin/bash /home/sjyong/robot_scripts/turtlebot3_pm2_supervisor.sh
Supervisor 스크립트에서 다음과 같은 Bash 전용 문법을 사용하는 경우 반드시 Bash로 실행해야 합니다.
[[ ]]조건문local변수for (( ))산술 반복문set -Eeuo pipefail- 명령 치환
- Bash 함수
/bin/sh로 실행하면 일부 문법에서 오류가 발생할 수 있습니다.
9) 작업 디렉터리 지정
cwd: home,
프로세스가 실행될 때 사용할 현재 작업 디렉터리를 사용자의 홈 디렉터리로 설정합니다.
사용자가 sjyong이라면 작업 디렉터리는 다음과 같습니다.
/home/sjyong
Bash 스크립트 내부에서 상대 경로를 사용할 경우 cwd를 기준으로 처리됩니다.
예를 들어 스크립트 내부에 다음 코드가 있다면
source robot_ws/install/setup.bash
실제 경로는 다음처럼 해석될 수 있습니다.
/home/sjyong/robot_ws/install/setup.bash
하지만 운영용 스크립트에서는 상대 경로보다 ${HOME}을 이용한 절대 경로를 사용하는 것이 좋습니다.
source "${HOME}/robot_ws/install/setup.bash"
이렇게 작성하면 실행 위치가 달라져도 경로 문제를 줄일 수 있습니다.
10) 실행 모드 설정
exec_mode: "fork",
PM2 실행 모드를 fork로 지정합니다.
PM2의 대표적인 실행 모드는 다음과 같습니다.
fork: 하나의 독립 프로세스로 실행cluster: 여러 Node.js 인스턴스를 실행해 부하 분산
TurtleBot3 제어 시스템은 동일한 프로세스를 여러 개 실행하면 안 됩니다.
여러 인스턴스가 동시에 실행되면 다음과 같은 문제가 발생할 수 있습니다.
- 동일한 tmux 세션 생성 충돌
- 동일한 카메라 장치 중복 점유
- 동일한 시리얼 포트 중복 접근
- ROS 2 노드 중복 실행
- 모터 명령 중복 전송
- 로그 중복 기록
- 로봇 제어 상태 충돌
따라서 단일 프로세스를 실행하는 fork 모드가 적합합니다.
11) 실행 인스턴스 수
instances: 1,
PM2가 실행할 프로세스 수를 1개로 제한합니다.
이 설정은 exec_mode: "fork"와 함께 TurtleBot3 Supervisor가 하나만 실행되도록 보장합니다.
로봇 제어 프로그램에서는 일반적인 웹 서버처럼 여러 인스턴스를 생성하면 안 됩니다.
특히 다음 장치를 사용하는 프로세스는 단일 인스턴스로 운영하는 것이 원칙입니다.
- 모터 제어 포트
- 라이다 시리얼 포트
- 카메라 장치
- 오디오 장치
- GPIO
- CAN 통신 장치
- tmux 세션
12) 자동 재시작 활성화
autorestart: true,
관리 중인 프로세스가 종료되면 PM2가 자동으로 다시 실행합니다.
Supervisor 스크립트가 다음과 같이 종료 코드 1을 반환하면
exit 1
PM2는 이를 비정상 종료로 판단하고 재시작합니다.
TurtleBot3 시스템에서는 다음 상황에서 자동 재시작이 발생할 수 있습니다.
- tmux 세션이 종료된 경우
- bringup 창이 종료된 경우
- camera 창이 종료된 경우
- audio 창이 종료된 경우
- Supervisor 내부 명령이 실패한 경우
- 네트워크 준비 시간이 초과된 경우
- Bash 스크립트에서 처리되지 않은 오류가 발생한 경우
이 설정은 무인 로봇이나 장시간 운영되는 로봇에서 핵심적인 기능입니다.
다만 설정 오류나 하드웨어 고장 때문에 계속 실패하는 경우 반복 재시작이 발생할 수 있으므로 max_restarts 설정과 함께 사용하는 것이 좋습니다.
13) 파일 변경 감시 비활성화
watch: false,
소스 파일이 변경되었을 때 자동으로 프로세스를 재시작하는 PM2 watch 기능을 비활성화합니다.
개발용 웹 서버에서는 파일 수정 시 자동 재시작 기능이 편리하지만, 로봇 운영 환경에서는 불필요한 재시작 원인이 될 수 있습니다.
예를 들어 다음 파일이 변경되었을 때 로봇 전체가 갑자기 재시작될 수 있습니다.
- 로그 파일
- 설정 파일
- 임시 파일
- 카메라 캡처 파일
- ROS 2 기록 파일
- 자동 생성 데이터
로봇 제어 시스템은 실행 안정성이 중요하므로 watch: false가 적절합니다.
설정을 수정한 후에는 다음 명령으로 명시적으로 재시작하는 것이 안전합니다.
pm2 restart turtlebot3-robot
14) 재시작 지연 시간
restart_delay: 5000,
프로세스가 종료된 후 PM2가 다시 실행하기 전까지 대기할 시간을 밀리초 단위로 설정합니다.
5000밀리초는 5초입니다.
5000ms = 5초
즉, 장애가 발생하면 PM2는 즉시 재실행하지 않고 5초 동안 대기합니다.
재시작 지연 시간을 두는 이유는 다음과 같습니다.
- 이전 tmux 프로세스가 완전히 종료될 시간을 확보합니다.
- 카메라와 시리얼 장치가 해제될 시간을 확보합니다.
- 네트워크가 일시적으로 불안정한 상태에서 과도한 재시작을 방지합니다.
- CPU와 메모리의 반복적인 부하를 줄입니다.
- 로그가 지나치게 빠르게 증가하는 것을 방지합니다.
하드웨어 장치의 초기화 시간이 길다면 값을 더 늘릴 수 있습니다.
예를 들어 10초 지연은 다음과 같이 설정합니다.
restart_delay: 10000,
15) 최소 정상 실행 시간
min_uptime: "30s",
PM2가 프로세스를 정상적으로 실행된 것으로 판단하기 위한 최소 시간을 설정합니다.
현재 값은 30초입니다.
Supervisor가 실행된 후 30초 이전에 종료되면 PM2는 안정적으로 실행되지 못한 것으로 판단할 수 있습니다.
이 설정은 반복 장애를 감지하는 데 사용됩니다.
예를 들어 다음과 같은 문제가 있을 수 있습니다.
- tmux가 설치되어 있지 않음
- 스크립트 실행 권한이 없음
- ROS 2 환경 설정 누락
- tmux 창 이름 불일치
- 카메라 장치를 찾지 못함
- 로봇 제어 스크립트의 boot 명령 실패
- 네트워크 기본 경로 미생성
이러한 문제로 Supervisor가 30초 이내에 계속 종료되면 PM2는 불안정한 재시작 상태로 판단합니다.
문자열 대신 밀리초 값을 사용할 수도 있지만 "30s"처럼 시간 단위를 명시하면 설정 의도를 이해하기 쉽습니다.
16) 최대 재시작 횟수
max_restarts: 20,
프로세스가 최소 정상 실행 시간에 도달하지 못한 상태로 반복 종료될 때 허용할 최대 재시작 횟수를 설정합니다.
현재 설정은 최대 20회입니다.
min_uptime: "30s"와 함께 동작하여 프로세스가 30초 이상 유지되지 못하고 반복 종료되는 상태를 제한합니다.
이 설정이 필요한 이유는 다음과 같습니다.
- 잘못된 설정으로 인한 무한 재시작 방지
- 하드웨어 고장 상태에서 반복적인 장치 초기화 방지
- 로그 파일의 무한 증가 방지
- CPU와 저장장치 부하 감소
- 배터리 소모 감소
- 로봇의 반복적인 구동과 정지 방지
주의할 점은 프로세스가 충분히 오랫동안 정상 실행된 후 나중에 장애가 발생하는 경우 재시작 횟수 판단 방식이 달라질 수 있다는 점입니다.
max_restarts는 모든 장애를 영구적으로 20회까지만 재시작한다는 단순한 누적 제한이라기보다, 짧은 시간 안에 반복되는 불안정한 재시작을 제어하기 위한 설정으로 이해하는 것이 좋습니다.
17) 종료 대기 시간
kill_timeout: 15000,
PM2가 프로세스에 종료 신호를 전달한 후 강제 종료하기 전까지 기다리는 시간을 설정합니다.
15000밀리초는 15초입니다.
15000ms = 15초
PM2가 다음 명령을 실행하면
pm2 stop turtlebot3-robot
Supervisor 스크립트는 종료 신호를 받습니다.
Supervisor에는 일반적으로 다음과 같은 트랩이 설정되어 있습니다.
trap shutdown_robot INT TERM HUP
종료 신호를 받으면 다음 작업을 수행합니다.
- 종료 메시지를 출력합니다.
- TurtleBot3 tmux 세션을 종료합니다.
- ROS 2 프로세스를 정리합니다.
- 카메라와 오디오 장치를 해제합니다.
- Supervisor를 종료 코드 0으로 종료합니다.
PM2는 이 정리 작업이 완료될 때까지 최대 15초 동안 기다립니다.
15초 안에 종료되지 않으면 PM2가 프로세스를 강제로 종료할 수 있습니다.
로봇 종료 과정에 시간이 더 필요하다면 값을 늘릴 수 있습니다.
예를 들어 30초를 기다리도록 하려면 다음과 같이 설정합니다.
kill_timeout: 30000,
다만 종료 시간이 지나치게 길면 PM2 재시작이나 시스템 종료가 늦어질 수 있습니다.
18) 로그 타임스탬프 활성화
time: true,
PM2 로그의 각 줄에 시간을 표시합니다.
예상 로그는 다음과 비슷합니다.
2026-07-16T10:20:31: [INFO] TurtleBot3 tmux 세션을 시작합니다.
2026-07-16T10:20:36: [OK] 기본 네트워크 경로가 준비되었습니다.
2026-07-16T11:03:12: [ERROR] 중요 tmux 창이 종료되었습니다: camera
19) 로그 병합 설정
merge_logs: true,
여러 인스턴스에서 발생한 로그를 하나의 파일로 병합하는 설정입니다.
현재는 instances: 1이므로 실질적으로 하나의 프로세스만 실행됩니다. 따라서 이 설정의 영향은 크지 않습니다.
하지만 PM2 설정을 확장하거나 실행 구조가 변경되더라도 로그 파일을 하나로 관리할 수 있다는 장점이 있습니다.
TurtleBot3처럼 하나의 Supervisor만 사용하는 환경에서는 설정을 유지해도 문제가 없습니다.
20) 표준 출력 로그 파일
out_file: path.join(
home,
"robot_logs",
"turtlebot3-pm2-out.log"
),
Supervisor 스크립트의 표준 출력을 저장할 파일 경로입니다.
사용자의 홈 디렉터리가 /home/sjyong이라면 다음 파일에 저장됩니다.
/home/sjyong/robot_logs/turtlebot3-pm2-out.log
표준 출력에는 일반적으로 다음과 같은 정보가 기록됩니다.
[WAIT] 네트워크 준비 대기 중: 1/60
[OK] 기본 네트워크 경로가 준비되었습니다.
[INFO] TurtleBot3 tmux 세션을 시작합니다.
[INFO] PM2 종료 신호를 수신했습니다.
echo 명령에서 별도의 오류 리다이렉션을 사용하지 않으면 기본적으로 표준 출력에 기록됩니다.
로그 디렉터리는 PM2 실행 전에 만들어 두는 것이 안전합니다.
mkdir -p ~/robot_logs
디렉터리 권한도 확인해야 합니다.
ls -ld ~/robot_logs
필요하다면 현재 사용자에게 소유권을 부여합니다.
sudo chown -R "$(whoami):$(whoami)" ~/robot_logs
21) 표준 오류 로그 파일
error_file: path.join(
home,
"robot_logs",
"turtlebot3-pm2-error.log"
),
Supervisor 스크립트의 표준 오류를 저장할 파일 경로입니다.
사용자의 홈 디렉터리가 /home/sjyong이라면 다음 파일에 저장됩니다.
/home/sjyong/robot_logs/turtlebot3-pm2-error.log
Supervisor 스크립트에서 다음처럼 >&2로 출력한 내용이 저장됩니다.
echo "[ERROR] ${reason}" >&2
예상 오류 로그는 다음과 같습니다.
[ERROR] tmux 세션이 종료되었습니다.
[ERROR] 중요 tmux 창이 종료되었습니다: bringup
[ERROR] 중요 tmux 창이 종료되었습니다: camera
[ERROR] 기본 네트워크 경로를 찾을 수 없습니다.
표준 출력과 표준 오류를 파일로 분리하면 정상 동작 로그와 장애 로그를 쉽게 구분할 수 있습니다.
실시간으로 오류 로그를 확인하려면 다음 명령을 사용할 수 있습니다.
tail -f ~/robot_logs/turtlebot3-pm2-error.log
정상 출력 로그는 다음과 같이 확인합니다.
tail -f ~/robot_logs/turtlebot3-pm2-out.log
22) 환경 변수 설정
env: {
HOME: home,
USER: user,
ROBOT_CONTROL_SCRIPT: path.join(
home,
"robot_scripts",
"turtlebot3_tmux.sh"
)
}
PM2가 Supervisor 스크립트를 실행할 때 전달할 환경 변수를 설정합니다.
PM2는 로그인 셸과 다른 환경에서 실행될 수 있습니다.
따라서 스크립트가 반드시 필요로 하는 값은 ecosystem 파일에서 명시적으로 전달하는 것이 안전합니다.
현재 전달되는 환경 변수는 다음과 같습니다.
HOMEUSERROBOT_CONTROL_SCRIPT
23) HOME 환경 변수
HOME: home,
Supervisor 스크립트에 현재 사용자의 홈 디렉터리를 전달합니다.
예를 들어 다음 값이 전달될 수 있습니다.
HOME=/home/sjyong
Bash 스크립트에서는 다음처럼 사용할 수 있습니다.
ROBOT_CONTROL_SCRIPT="${HOME}/robot_scripts/turtlebot3_tmux.sh"
또는 다음처럼 ROS 2 워크스페이스 경로를 구성할 수 있습니다.
source "${HOME}/robot_ws/install/setup.bash"
PM2를 systemd startup 서비스로 실행하면 일반 터미널과 환경 변수가 다를 수 있으므로 HOME을 명시적으로 전달하는 것이 좋습니다.
24) USER 환경 변수
USER: user,
현재 운영체제 사용자 이름을 Supervisor 스크립트에 전달합니다.
예를 들어 다음 값이 전달됩니다.
USER=sjyong
Bash 스크립트에서 사용자 이름을 기준으로 로그를 출력하거나 권한을 확인할 때 사용할 수 있습니다.
echo "[INFO] 실행 사용자: ${USER}"
다만 보안이나 권한 판단을 환경 변수 USER에만 의존하는 것은 적절하지 않습니다.
실제 실행 사용자 확인이 필요하다면 다음 명령을 함께 사용할 수 있습니다.
id -un
25) 로봇 제어 스크립트 경로 전달
ROBOT_CONTROL_SCRIPT: path.join(
home,
"robot_scripts",
"turtlebot3_tmux.sh"
)
Supervisor 스크립트에서 사용할 로봇 제어 스크립트의 절대 경로를 환경 변수로 전달합니다.
사용자의 홈 디렉터리가 /home/sjyong이면 다음 값이 전달됩니다.
ROBOT_CONTROL_SCRIPT=/home/sjyong/robot_scripts/turtlebot3_tmux.sh
Supervisor 스크립트에는 다음과 같은 코드가 있을 수 있습니다.
ROBOT_CONTROL_SCRIPT="${
ROBOT_CONTROL_SCRIPT:-${HOME}/robot_scripts/turtlebot3_tmux.sh
}"
이 코드는 PM2에서 ROBOT_CONTROL_SCRIPT를 전달하면 해당 값을 사용하고, 전달되지 않으면 기본 경로를 사용합니다.
26) ROS 2 환경 변수 추가 예시
현재 설정에는 HOME, USER, ROBOT_CONTROL_SCRIPT만 포함되어 있습니다.
TurtleBot3 운영 환경에 따라 다음 환경 변수를 추가할 수 있습니다.
env: {
HOME: home,
USER: user,
ROS_DOMAIN_ID: "200",
TURTLEBOT3_MODEL: "burger",
RMW_IMPLEMENTATION: "rmw_cyclonedds_cpp",
ROBOT_CONTROL_SCRIPT: path.join(
home,
"robot_scripts",
"turtlebot3_tmux.sh"
)
}
다음 설정은 Bash 스크립트 내부에서 직접 실행하는 것이 좋습니다.
source /opt/ros/humble/setup.bash
source "${HOME}/robot_ws/install/setup.bash"
PM2에서는 대화형 터미널의 .bashrc가 기대한 방식으로 실행되지 않을 수 있으므로 ROS 2 환경을 스크립트에서 명시적으로 설정해야 합니다.
12. PM2에 TurtleBot3 등록
ecosystem 파일을 이용해 로봇 프로그램을 시작합니다.
pm2 start ~/robot_scripts/ecosystem.config.js
상태를 확인합니다.
pm2 status
정상적인 경우 turtlebot3-robot 프로세스가 online 상태로 표시됩니다.
turtlebot3-robot online
PM2 로그를 확인합니다.
pm2 logs turtlebot3-robot --lines 100
tmux 세션을 확인합니다.
tmux ls
ROS 2 터미널 화면에 접속합니다.
tmux attach -t turtlebot3
tmux에서 빠져나오되 세션을 종료하지 않으려면 다음 키를 차례로 입력합니다.
Ctrl+B
D
13. PM2 기본 제어 명령
TurtleBot3 시스템을 중지합니다.
pm2 stop turtlebot3-robot
supervisor가 종료 신호를 받으면 tmux 세션도 함께 종료합니다.
다시 시작합니다.
pm2 restart turtlebot3-robot
상태를 확인합니다.
pm2 status
상세 정보를 확인합니다.
pm2 describe turtlebot3-robot
최근 로그를 확인합니다.
pm2 logs turtlebot3-robot --lines 200
실시간 CPU와 메모리 사용량을 확인합니다.
pm2 monit
PM2 관리 대상에서 완전히 제거합니다.
pm2 delete turtlebot3-robot
다시 등록합니다.
pm2 start ~/robot_scripts/ecosystem.config.js
14. Ubuntu 부팅 시 PM2 자동 실행 설정
PM2에서 프로그램을 실행했다고 해서 서버 재부팅 후 자동으로 실행되는 것은 아닙니다.
다음 두 가지 설정이 필요합니다.
- systemd가 PM2 데몬을 실행하도록 등록
- 현재 PM2 프로세스 목록 저장
먼저 일반 사용자 계정에서 다음 명령을 실행합니다.
pm2 startup
이 명령 자체에는 sudo를 사용하지 않습니다.
PM2는 현재 운영체제의 init 시스템을 감지하고 실행해야 할 명령을 출력합니다. Ubuntu 22.04에서는 systemd가 사용됩니다.
출력 예시는 다음과 비슷합니다.
sudo env PATH=$PATH:/home/ubuntu/.nvm/versions/node/vXX.XX.X/bin \
pm2 startup systemd -u ubuntu --hp /home/ubuntu
중요한 점은 화면에 출력된 명령을 직접 복사해서 실행해야 한다는 것입니다.
특히 NVM으로 Node.js와 PM2를 설치했다면 Node.js 버전별 실행 경로가 포함되므로 출력된 명령을 임의로 수정하면 안 됩니다.
다음으로 현재 PM2 프로세스 목록을 저장합니다.
pm2 save
PM2 공식 문서에서는 pm2 startup으로 시작 서비스를 생성하고 pm2 save로 현재 프로세스 목록을 저장해야 재부팅 후 프로그램이 복원된다고 설명합니다.
저장된 프로세스 목록을 확인합니다.
cat ~/.pm2/dump.pm2
systemd 서비스 상태를 확인합니다.
systemctl status "pm2-${USER}" --no-pager
예를 들어 사용자 이름이 ubuntu라면 서비스 이름은 다음과 같습니다.
systemctl status pm2-ubuntu --no-pager
15. 자동 실행 테스트
모든 설정이 끝나면 로봇을 재부팅합니다.
sudo reboot
로봇이 다시 부팅된 뒤 원격 PC에서 SSH로 접속합니다.
ssh sjyong@192.168.210.12
PM2 상태를 확인합니다.
pm2 status
다음 상태가 표시되어야 합니다.
turtlebot3-robot online
tmux 세션을 확인합니다.
tmux ls
다음과 같이 표시되어야 합니다.
turtlebot3: 4 windows
tmux 세션에 접속합니다.
tmux attach -t turtlebot3
ROS 2 노드를 확인합니다.
ros2 node list
토픽을 확인합니다.
ros2 topic list
LiDAR 토픽 주기를 확인합니다.
ros2 topic hz /scan
카메라 토픽을 확인합니다.
ros2 topic list | grep image
원격 PC의 rqt에서 카메라 영상이 정상적으로 표시되는지도 확인합니다.
16. PM2 재시작 복구 테스트
자동 복구가 실제로 작동하는지 확인해야 합니다.
먼저 PM2 상태를 확인합니다.
pm2 status
tmux 세션을 강제로 종료합니다.
tmux kill-session -t turtlebot3
supervisor 스크립트는 tmux 세션이 사라진 것을 감지하고 오류로 종료됩니다.
PM2는 잠시 후 supervisor를 다시 실행합니다.
pm2 logs turtlebot3-robot
다음과 비슷한 로그가 출력됩니다.
[ERROR] tmux 세션이 종료되었습니다.
[INFO] tmux 세션을 정리한 후 PM2 재시작을 요청합니다.
PM2 상태를 다시 확인합니다.
pm2 status
재시작 횟수가 증가하고 상태는 다시 online이 되어야 합니다.
tmux ls
turtlebot3 세션이 다시 생성되어야 합니다.
17. ROS 2 노드 종료 복구 테스트
이번에는 중요 프로세스 하나를 종료해 봅니다.
tmux에 접속합니다.
tmux attach -t turtlebot3
예를 들어 camera 창으로 이동한 뒤 카메라 프로세스에 Ctrl+C를 입력합니다.
기존 스크립트에서 remain-on-exit on이 설정되어 있으므로 camera 창은 남아 있지만 pane은 종료된 상태가 됩니다.
supervisor는 #{pane_dead} 상태를 확인해 camera 프로세스 종료를 감지합니다.
이후 다음 순서로 복구됩니다.
- supervisor가 비정상 상태를 감지합니다.
- 기존 tmux 세션을 종료합니다.
- supervisor가 오류 코드 1로 종료됩니다.
- PM2가 supervisor를 다시 실행합니다.
- 새 tmux 세션이 생성됩니다.
- Bringup, 카메라, 오디오 노드가 다시 실행됩니다.
로그를 확인합니다.
pm2 logs turtlebot3-robot --lines 100
18. PM2 로그와 tmux 로그의 차이
현재 구성에서 PM2는 supervisor 스크립트의 출력을 저장합니다.
따라서 다음 명령은 자동 실행 및 복구 관련 로그를 보여 줍니다.
pm2 logs turtlebot3-robot
하지만 tmux 내부에서 실행된 ros2 launch의 전체 출력은 PM2 로그에 직접 저장되지 않습니다.
ROS 2 노드의 터미널 출력은 tmux 세션에서 확인합니다.
tmux attach -t turtlebot3
SSH 접속 없이 최근 tmux 내용을 확인하려면 다음 명령을 사용할 수 있습니다.
Bringup 창의 최근 내용을 확인합니다.
tmux capture-pane \
-p \
-t turtlebot3:bringup \
-S -200
카메라 창의 최근 내용을 확인합니다.
tmux capture-pane \
-p \
-t turtlebot3:camera \
-S -200
오디오 창의 최근 내용을 확인합니다.
tmux capture-pane \
-p \
-t turtlebot3:audio \
-S -200
19. PM2 로그 용량 관리
로봇의 저장장치는 데스크톱 PC보다 용량이 작을 수 있습니다.
PM2 로그가 계속 증가하지 않도록 로그 로테이션 모듈을 설치할 수 있습니다.
pm2 install pm2-logrotate
PM2 공식 문서에서도 pm2-logrotate 모듈을 이용한 로그 순환 방식을 안내합니다.
현재 로그 크기를 확인합니다.
du -sh ~/.pm2/logs
du -sh ~/robot_logs
PM2 로그를 비우려면 다음 명령을 사용합니다.
pm2 flush
이 명령은 PM2가 관리하는 로그 내용을 삭제하므로 필요한 로그를 백업한 뒤 실행해야 합니다.
20. ecosystem 설정 변경 적용
ecosystem.config.js 파일을 수정한 뒤에는 PM2 프로세스를 다시 적용해야 합니다.
pm2 restart ~/robot_scripts/ecosystem.config.js
확실하게 새 설정으로 다시 등록하려면 다음 순서로 실행합니다.
pm2 delete turtlebot3-robot
pm2 start ~/robot_scripts/ecosystem.config.js
pm2 save
pm2 save를 실행하지 않으면 현재 터미널에서는 새 설정이 동작하더라도 다음 재부팅에서 이전에 저장된 프로세스 목록이 복원될 수 있습니다.
프로그램을 PM2에서 완전히 제거할 때도 다음과 같이 저장 목록을 갱신해야 합니다.
pm2 delete turtlebot3-robot
pm2 save
21. pm2 등록 삭제
pm2 stop turtlebot3-robot
pm2 delete turtlebot3-robot
pm2 save --force
sudo reboot
ssh sjyong@192.168.210.12
tmux ls
pm2 status