직교하는 두 축
셸이 어떤 시작 파일을 읽는지 보려면 두 가지를 따로 물어봐. 로그인 셸이야? 대화형 셸이야? 둘은 별개고, 실행 방식과 옵션에 따라 조합이 달라져.
- 로그인 셸: 로그인 세션의 시작 셸이거나 로그인 방식으로 호출된 셸이야.
- 대화형 셸: 사람에게 프롬프트를 보여 주고 입력을 기다리는 셸이야.
네 조합은 읽는 파일과 기대할 수 있는 환경이 서로 달라.
매트릭스 (zsh)
| 대화형 | 비대화형 | |
|---|---|---|
| 로그인 | .zshenv → .zprofile → .zshrc → .zlogin | .zshenv → .zprofile → .zlogin |
| 비로그인 | .zshenv → .zshrc | .zshenv만 |
실제 케이스
- Terminal.app의 새 창: 프로필 설정에 따라 로그인 대화형 zsh인 경우가 흔해.
ssh user@host: 원격 계정 셸과 가상 터미널 할당 여부에 따라 달라져.ssh user@host 'echo hi': 원격 서버가 명령을 비대화형으로 실행하고, 시작 파일 규칙은 셸마다 달라../script.sh: shebang이 고른 인터프리터를 비대화형으로 실행해.- zsh 안에서 다시
zsh: 보통 비로그인 대화형 셸이야. - cron이나 launchd 작업: 선언한 프로그램을 직접 실행해. zsh를 고르지 않았다면 zsh 시작 파일 규칙 자체가 적용되지 않아.
여기서 사람들이 미끄러져
터미널의 .zshrc에서 보인 값이 예약 작업에서 비어 있는 이유는 실행 환경이 다르기 때문이야. 비밀을 .zshenv로 옮겨 모든 zsh에 퍼뜨리지 말고, 스케줄러의 환경 선언이나 권한이 제한된 래퍼와 자격 증명 저장소를 통해 필요한 프로세스에만 넣어.
런타임 확인
[[ -o login ]] && echo login과 [[ -o interactive ]] && echo interactive로 현재 zsh의 상태를 직접 볼 수 있어. 이름표를 추측하는 것보다 실제 실행 파일, 인자, 환경을 함께 확인하는 편이 빨라.
호출자를 보면 읽힐 파일이 보여
터미널 앱, SSH 서버, 스케줄러, shebang 가운데 누가 프로세스를 만들었는지부터 따라가. 그 호출자가 인터프리터와 인자를 정하고, 그 결과로 로그인·대화형 규칙이 결정돼.
예약 작업은 대화형 셸을 물려받지 않아
cron과 launchd는 터미널 세션을 복제하지 않고 zsh를 실행하지 않을 수도 있어. 인터프리터, 경로, 작업 디렉터리, 비밀 아닌 필수 값은 작업 선언에 적고 비밀은 권한이 좁은 자격 증명 경계에서 받아.