셸에선 되는 sudo가 자동화에서 실패한다면, 범인은 sudoers의 안전장치다
대화형 셸과 자동화(cron·CI·배포 스크립트)의 차이는 tty와 환경이다. sudo는 보안을 위해 이 둘을 일부러 다르게 다루기 때문에, 같은 명령이 사람 손에서는 되고 자동화에서는 조용히 막힌다. 원인은 대개 넷이다.
1) secure_path — sudo가 PATH를 갈아끼운다
sudoers의 Defaults secure_path가 있으면 sudo는 호출자의 PATH를 무시하고 이 값으로 강제 교체한다. 자동화가 부른 도구가 /usr/local/bin, /opt/...처럼 secure_path에 없는 경로에 있으면 “command not found”가 난다. 절대경로로 부르거나 secure_path에 경로를 추가한다.
2) requiretty — tty가 없어서 막힌다
일부 배포판/설정은 Defaults requiretty라, tty 없는 자동화에서 sudo가 “sorry, you must have a tty to run sudo”로 죽는다. 해당 서비스 계정에 Defaults:svc !requiretty 예외를 준다.
3) env_reset — 넘긴 환경변수가 사라진다
sudo는 기본적으로 환경을 비운다(env_reset). 스크립트가 설정한 HTTP_PROXY, 클라우드 자격증명 같은 변수가 sudo 안에서 없어진다. 필요한 변수는 Defaults env_keep += "HTTP_PROXY"로 명시하거나, 정책이 허용하면 sudo -E로 넘긴다.
4) 비밀번호 프롬프트에서 멈춘다
비대화형이라 암호 입력 프롬프트에서 영원히 대기하다 타임아웃된다. 자동화가 쓰는 명령에는 NOPASSWD: 규칙을 그 명령에 한정해 준다(전체 NOPASSWD는 피한다).
확인 순서
sudo -l -U <svc> # 그 계정에 실제 허용된 규칙(NOPASSWD 포함)
sudo env # sudo 안에서 살아남는 환경변수
절대경로/secure_path → NOPASSWD → env_keep 또는 -E → requiretty 순으로 지운다. “사람이 하면 되니 코드 문제”라는 판단이 가장 큰 함정이다.
빠른 진단 체크리스트
sudo -l로 그 계정에 허용된 규칙을 먼저 본다- secure_path가 PATH를 강제 교체함을 감안한다
- 자동화 도구가 secure_path에 없으면 절대경로로 부른다
- tty 없는 환경이면 requiretty를 예외 처리한다
- env_reset로 넘긴 환경변수가 사라지는지 확인한다
- 필요한 변수는 env_keep 또는
sudo -E로 넘긴다 - 비대화형이라 암호 프롬프트에서 멈추면 NOPASSWD를 좁혀 준다
sudo env로 sudo 안에서 살아남는 환경을 본다