나는 buildkite 스크립트에서 발생한 문제를 추적해 왔으며 이것이 내가 얻은 결과입니다.
먼저 docker 이미지의 셸을 입력합니다.
docker run --rm -it --entrypoint bash node:12.21.0
이 Docker 이미지에는 텍스트 편집기가 없으므로 파일에 연결하여 셸 스크립트를 만들었습니다.
touch a.sh
chmod +x a.sh
printf '#!/bin/sh\necho ${1:0:1}' >> a.sh
touch b.sh
chmod +x b.sh
printf '#!/bin/bash\necho ${1:0:1}' >> b.sh
이제 스크립트를 실행합니다.
./a.sh hello
>./a.sh: 2: ./a.sh: Bad substitution
./b.sh hello
>h
누군가 여기에 문제가 무엇인지 간단히 말해 줄 수 있습니까?
이 AskUbuntu 질문bash와 sh는 다른 쉘이며 많은 시스템에서 sh는 bash에 심볼릭 링크됩니다.
이 도커 이미지에 정확히 무슨 일이 일어났나요? 내가 어떻게 알 수 있나요?
답변1
/bin/sh
POSIX 쉘일 것으로 예상되며 POSIX 쉘일 것입니다.매개변수 확장의 하위 문자열을 인식하지 못함.
POSIX"명령 해석기(또는 "셸")를 포함한 표준 운영 체제 인터페이스 및 환경을 정의합니다." 전통적인 Unix 스타일 환경에서 널리 사용되는 표준입니다. 바라보다POSIX란 정확히 무엇입니까?더 넓은 설명을 위해. POSIX 기반 환경에서는 /bin/sh
POSIX 스타일 쉘이 제공되어야 하며, /bin/sh
Shebang으로 사용되는 스크립트에서는 POSIX 기능에만 의존할 수 있습니다(대부분의 실제 구현에서는 /bin/sh
더 많은 기능을 제공하지만). 고급 쉘을 사용하는 것은 완벽하지만 이에 따라 shebang을 조정해야 합니다.
귀하의 스크립트는 bash 기능에 의존하기 때문에 올바른 shebang은 그것이 실행되는 환경이 무엇 #!/bin/bash
이든 상관없습니다 . #!/usr/bin/env bash
어떤 경우에는 그냥 작동할 수도 있지만 #!/bin/sh
그것은 단지 행복한 우연일 뿐입니다.
답변2
스크립트는 매개변수 확장에 POSIX가 아닌 확장을 사용하므로 대부분의 쉘에서는 실행되지 않습니다.
bash
이는 스크립트가 다음과 같은 쉘에 의해 실행되도록 강제하여 수행할 수 있습니다.POSIX 쉘 스크립트 작성, 이는 많은 상황에서 좋은 습관입니다.
zsh
불행하게도 인수의 첫 번째 문자를 가져오는 with 와 같은 우아한 방법 은 없습니다 $1[1]
. 따라서 using을 사용할 수 있습니다.
"$(echo "$1" | cut -c1-1)"
또는"$(printf %.1s "$1")"
또는- 이상한 점은 문자열에서
"${1%"${1#?}"}"
첫 번째 문자( )가 없는 문자열을 제거한다는 것입니다.${1#?}