Host-Dedicated-Server-Resource-Cleanup.md에서 식별한 가장 큰 단일 회수 기회(GUI 로그인 세션 683MB)를 실행에 옮긴 기록. 로그아웃해도 절전 방지가 유지되는지 단계별로 겹쳐서 검증한 뒤에만 다음 단계로 넘어갔다 — 이 서버는 Tailscale로만 접근 가능한 유일한 원격 인프라라, 절전 방지가 실패하면 물리적으로 가지 않는 한 복구 수단이 없다(Remote-Wake-and-Downtime-Alerting.md에서 이미 결론 낸 제약).

왜 Amphetamine을 그냥 못 쓰나

Amphetamine은 GUI 세션이 살아있어야 절전 방지 기능이 동작한다. 로그아웃하면 이 가정 자체가 깨진다. caffeinate -disu를 LaunchDaemon으로 등록하면 GUI 세션과 무관하게 root 권한으로 절전 방지가 가능해서, 이 전환의 핵심 전제였다.

핵심 리스크 — 클램쉘(뚜껑 닫힘) 오버라이드가 caffeinate에서도 되는가

이 호스트는 뚜껑을 닫은 클램쉘 상태로 돌아간다(AppleClamshellState = Yes). caffeinate 커맨드라인 도구는 일반적으로 클램쉘 절전을 못 막는다는 보고가 많아서(외부 디스플레이/키보드가 붙어있어야 하는 Apple 공식 클램쉘 모드 요건과 별개의 문제), 이걸 확인 안 하고 그냥 바꾸면 Amphetamine 없앤 순간 오히려 사고가 재현될 수 있었다.

검증 결과: AppleClamshellCausesSleep은 Amphetamine이 잡고 있을 때도, caffeinate로 교체한 뒤에도 동일하게 No로 유지됐다 — 즉 이 필드는 앱 종류와 무관하게 활성 PreventSystemSleep assertion이 있으면 동적으로 오버라이드되는 구조였다. 이게 확인된 뒤에야 다음 단계로 진행했다.

실행 순서 — 안전하게 겹쳐서 전환

1. pmset 설정 백업

pmset -g > /tmp/pmset-before-caffeinate-migration.txt
pmset -g assertions > /tmp/pmset-assertions-before.txt

2. caffeinate LaunchDaemon 설치 (Amphetamine은 그대로 둔 채)

/Library/LaunchDaemons/com.parksangmin.caffeinate.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.parksangmin.caffeinate</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/caffeinate</string>
        <string>-disu</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/var/log/caffeinate-daemon.log</string>
    <key>StandardErrorPath</key>
    <string>/var/log/caffeinate-daemon.log</string>
</dict>
</plist>

KeepAlive=true라서 caffeinate 프로세스가 어떤 이유로든 죽으면 launchd가 즉시 재기동시킨다 — Amphetamine(죽으면 그냥 안 뜸)보다 오히려 더 견고한 지점.

sudo launchctl bootstrap system /Library/LaunchDaemons/com.parksangmin.caffeinate.plist

3. 겹친 상태에서 1차 검증

pmset -g assertions | grep -iE 'caffeinate|amphetamine'
# caffeinate(root, LaunchDaemon)와 Amphetamine 둘 다 독립적으로 assertion을 잡고 있음을 확인
pmset -g | grep sleep
# "sleep prevented by caffeinate, caffeinate, Amphetamine, powerd"

4. Amphetamine 종료 후 caffeinate 단독 검증 (가장 중요한 단계)

osascript -e 'quit app "Amphetamine"'
pmset -g | grep sleep
# "sleep prevented by caffeinate, caffeinate, nsurlsessiond, powerd" -- Amphetamine 없이도 유지
ioreg -r -k AppleClamshellState -d 4 | grep -i clamshell
# AppleClamshellCausesSleep = No 그대로 -- 클램쉘 오버라이드도 caffeinate 단독으로 유지됨

이 단계가 실패했다면(클램쉘 오버라이드가 풀렸다면) 바로 open -a Amphetamine으로 되돌리고 로그아웃 자체를 하지 않았을 것이다.

5. SSH가 GUI 세션과 독립적인지 확인