우분투 실전 명령어 | systemd-run으로 일회성 작업 안전 실행

서비스 파일을 만들기 전에 일회성 배치 작업을 systemd로 안전하게 돌려야 할 때가 자주 있습니다. 이럴 때 systemd-run을 쓰면 실행 이력 확인, 타임아웃, 자원 제한까지 한 번에 챙길 수 있습니다.

언제 쓰는가

  • 수동으로 긴 작업을 실행하되 로그와 종료 코드를 남기고 싶을 때
  • cron 등록 전, 운영 서버에서 작업을 먼저 검증할 때
  • nohup으로 돌리던 작업을 systemd 기준으로 관리하고 싶을 때
  • 특정 작업에 메모리 상한, 실행 시간 제한을 걸고 싶을 때

바로 쓰는 명령어

# 즉시 실행: 이름을 붙여 일회성 유닛으로 실행
sudo systemd-run --unit=backup-once --collect /usr/local/bin/backup.sh

# 5분 뒤 실행
sudo systemd-run --unit=cleanup-later --on-active=5m /usr/local/bin/cleanup.sh

# 매일 03:10 실행(캘린더 표현식)
sudo systemd-run --unit=log-rotate-once --on-calendar='*-*-* 03:10:00' /usr/local/bin/rotate-log.sh
# 실행 상태/로그 확인
systemctl status backup-once.service --no-pager
journalctl -u backup-once.service -n 100 --no-pager

# 유닛 메타 정보 확인
systemctl show backup-once.service -p ActiveState -p SubState -p Result -p ExecMainStatus

핵심 옵션/패턴

  • --unit=
    • 유닛 이름을 고정해 추적성을 높입니다.
    • 이름을 안 주면 run-xxxx.service 형태로 생성되어 추적이 번거롭습니다.
  • --collect
    • 종료된 유닛 리소스를 자동 정리합니다.
    • 일회성 작업을 자주 실행하는 서버에서 특히 유용합니다.
  • --on-active=, --on-calendar=
    • 타이머처럼 지연/예약 실행을 걸 수 있습니다.
    • 정기 작업 전 사전 검증 단계에서 많이 씁니다.
  • -p
    • systemd 속성을 즉시 주입합니다.
    • 예: -p MemoryMax=500M -p CPUQuota=50% -p RuntimeMaxSec=1800
# 자원 제한 + 타임아웃을 건 실행 예시
sudo systemd-run \
  --unit=report-job \
  --collect \
  -p MemoryMax=500M \
  -p CPUQuota=60% \
  -p RuntimeMaxSec=1200 \
  /usr/local/bin/make-report.sh

명령 출력 예시

$ systemctl status backup-once.service --no-pager
● backup-once.service - /usr/local/bin/backup.sh
     Loaded: loaded (/run/systemd/transient/backup-once.service; transient)
  Transient: yes
     Active: inactive (dead) since Thu 2026-02-19 01:31:42 KST; 4s ago
    Process: 29417 ExecStart=/usr/local/bin/backup.sh (code=exited, status=0/SUCCESS)
   Main PID: 29417 (code=exited, status=0/SUCCESS)
        CPU: 1.204s
$ systemctl show backup-once.service -p Result -p ExecMainStatus
Result=success
ExecMainStatus=0

자주 하는 실수

  • sudo 없이 실행하고 권한 오류를 작업 실패로 오해
    • 백업/로그 정리 작업은 root 권한이 필요한 경우가 많습니다.
  • --unit 이름을 매번 다르게 만들어 이력 추적이 어려워짐
    • 목적별로 고정 이름 규칙을 정해두는 게 좋습니다.
  • 실패 원인을 status만 보고 끝냄
    • 실제 에러는 journalctl -u에서 확인해야 정확합니다.
  • 장시간 작업에 RuntimeMaxSec을 너무 짧게 설정
    • 정상 작업이 중간에 SIGTERM으로 끊길 수 있습니다.

검증 방법

# 1) 성공/실패 코드 확인
systemctl show report-job.service -p Result -p ExecMainStatus

# 2) 로그에서 에러 라인 확인
journalctl -u report-job.service --since '10 min ago' --no-pager

# 3) 설정된 제한 확인
systemctl show report-job.service -p MemoryMax -p CPUQuotaPerSecUSec -p RuntimeMaxUSec

정상 기준은 Result=success, ExecMainStatus=0, 그리고 로그에 에러 스택이 없는 상태입니다.

운영 팁

  • 운영 서버에서는 유닛 이름 규칙을 팀 단위로 고정하세요.
    • 예: ops-backup-once, ops-cleanup-once
  • 반복 실행 전에는 같은 명령을 스테이징에서 먼저 systemd-run으로 검증하세요.
  • cron으로 바로 넣기보다 systemd-run 예약 실행으로 1~2회 검증하면 장애 확률이 크게 줄어듭니다.
  • 실패한 작업 재실행 전에 journalctl로 첫 에러 시점을 먼저 확인하면 원인 파악이 빨라집니다.

출처

  • Ubuntu Manpage
  • systemd 공식 문서
  • Debian Wiki