logo hsb.horse
← 블로그 목록으로 돌아가기

블로그

sh -c 거동 및 zsh 구성 파일 읽기 규칙

sh -c 명령의 거동, 환경 변수의 상속 룰, shebang의 유효성, zsh 설정 파일(.zshrc, .zshenv등)이 스크립트 실행시에 어떻게 읽혀지는지를 정리.

게시일:

sh -c 명령이나 거기에서 스크립트를 호출했을 때의 거동, 특히 zsh 주위의 설정 파일(.zshrc 등)이 어떻게 읽히는지에 대해 정리한다.

Docker의 엔트리 포인트나 CI/CD의 설정, 외부 툴로부터의 호출로 수수하게 빠지는 포인트다.

sh -c 란 무엇입니까?

한마디로 말하면 「인수의 캐릭터 라인을 커멘드로서 해석해 실행한다」 녀석.

Terminal window
sh -c "echo Hello World"

보통 커맨드를 치는 것과 무엇이 다른가 하는 이야기지만, 주로 이하의 장면에서 필수가 된다.

sudo로 리디렉션하고 싶을 때

sudo echo "text" > /etc/file은 권한 오류가 발생합니다. 리디렉션은 일반 사용자 권한으로 이루어지기 때문이다.

sudo sh -c "echo 'text' > /etc/file"이라면 쉘 전체가 root로 움직이기 때문에 성공한다.

Docker / K8s에서 && 또는 |를 사용하고 싶을 때

CMD나 ENTRYPOINT로 복수의 커멘드를 연결하거나 파이프를 사용하고 싶은 경우, 쉘을 개입시키지 않으면 구문 분석되지 않는다.

Go 바이너리 등을 sh 경유로 실행하고 싶을 때

sh ./my-binary는 “바이너리를 쉘 스크립트로 읽으려고합니다” 때문에 오류가 발생합니다.

sh -c ./my-binary는 “그 경로에 있는 명령을 실행하라”가 되므로 바이너리에서도 실행할 수 있다.

환경 변수 상속 규칙

sh -c로 호출 된 스크립트에 환경 변수가 전달됩니까?

검증 코드

Terminal window
# 親側
export MY_ENV="hoge"
sh -c "./sample.sh"
sample.sh
echo "$MY_ENV"

결과

  • export하고 있으면 건너는 (hoge로 나온다)
  • export하지 않으면 통과하지 않는다 (비어 있음)

export 된 변수는 하위 프로세스 (sh -c)에서 손자 프로세스 (sample.sh)로 이어집니다. 당연하지만, sh -c는 다른 프로세스가 일어나는 것을 의식해 둘 필요가 있다.

Shebang (시방)이 유효합니까?

main.sh에서 sh -c을 통해 zsh용 스크립트를 호출한 경우.

main.sh```sh sh -c ”./sample.sh”

**sample.sh**```sh
#!/usr/bin/env zsh
# zsh特有の処理...

결과

**제대로zsh로 움직인다. **

sh는 단순한 런처로서 기능하고, OS가 sample.sh의 1행째(Shebang)를 보고 zsh를 기동해 준다.

다만, source(또는 .)로 읽어들인 경우는 NG.

  • sh -c "./sample.sh" → zsh가 시작되고 실행 (Shebang 활성화)
  • sh -c ". ./sample.sh" → sh로 로드됨(Shebang 무시 = 구문 오류)

zsh 설정 파일을 읽습니까?

sample.sh (zsh 스크립트)가 실행되면 .zshrc 또는 .zprofile가로드됩니다.

결론: 거의 로드되지 않음

파일 이름로드됨?이유
.zshenvYES유일하게 읽힌다. 모든 모드에서 유효.
.zprofileNO”로그인 쉘”이 아니기 때문에 무시.
.zshrcNO** “대화형 쉘”이 아니기 때문에 무시. **
.zloginNO”로그인 쉘”이 아니기 때문에 무시.

스크립트 실행(비대화 모드)에서는 불필요한 출력이나 별칭에 의한 사고를 방지하기 위해 .zshrc은 스킵된다.

.zshrc에 쓴 별칭이 스크립트 내에서 효과가 없을 때 이것이 원인입니다.

아무래도 읽고 싶은 경우

스크립트 내에서 명시적으로 source 할 수밖에 없다.

#!/usr/bin/env zsh
source ~/.zshrc # 無理やり読み込む
my_alias_command

다만 .zshrc에 echo등의 출력이 포함되어 있으면 스크립트의 출력에 섞이므로 비추천.

스크립트에서 필요한 환경 변수는 .zshenv에 쓰는 것이 정답 (좋은지 나쁜지는 놓아두고).

요약

sh -c는 편리하지만 프로세스의 경계나 설정 파일의 로드 룰을 이해하고 있지 않다고 빠진다.

특히 Docker나 CI/CD 환경에서는 로컬에서 움직여도 컨테이너 내에서 움직이지 않는 경우가 있다. 환경 변수의 export을 잊어 버리거나 .zshrc에 의존하기 때문에 종종 발생합니다.

스크립트에서 사용하는 설정은 .zshenv에 집약하고 별칭이 아니라 함수나 스크립트로 대응하는 것이 무난하다.