컬에서 bash 스크립트 실행이 실패하고 파일에서 bash 스크립트 실행이 성공했습니다.

컬에서 bash 스크립트 실행이 실패하고 파일에서 bash 스크립트 실행이 성공했습니다.

install.sh기본적으로 다음과 같은 스크립트가 있습니다 .

#!/bin/bash

if [[ ! -f "/usr/bin/jq" ]]; then
  apt-get update && apt-get install -y jq
fi

echo $(date) >> install.log

서버에 놓고 다음과 같이 실행하면:

curl -s0 https://myserver.com/install.sh | bash

미친 apt-get출력 후에 echo는 마지막 줄을 실행하는 대신 해당 줄을 echo $(date) >> test.log출력으로 인쇄합니다. 반면에 install.sh디스크에 저장 하고 실행하면 ./install.sh예상대로 작동합니다. 에코 라인을 실행하고 install.log추가합니다.

문제를 추가로 재현하기 위해 다음과 같이 로컬에서 실행했습니다.

cat install.sh | bash

또한 동일한 문제가 있습니다.

apt-get remove jq각 테스트 전에 수동으로 실행합니다 . 설치 하면 jq둘 다 예상대로 작동합니다. 그렇다면 다운로드에서 실행하는 것과 로컬 파일에서 실행하는 것이 왜 다른가요?

이 문제를 설명하기 위해 짧은 비디오를 녹화했습니다.https://www.youtube.com/watch?v=lYvGXI7AibA

답변1

일반적 bash으로 파일( bash foobash <foo: . 그러나 이제는 apt-get사용자에게 묻고자 하는 명령( )을 시작 하고 STDIN을 사용하여 그렇게 합니다.

그래서 이상한 일이 일어납니다. bash는 STDIN에서 명령을 읽고 하나씩 실행합니다. 이제 명령 중 하나가 STDIN에서 읽고 파일의 다음 줄을 읽습니다. 그 후 bash는 STDIN에서 다음 줄을 읽으므로 다른 명령이 이미 읽은 명령 하나를 건너뜁니다.

이 작은 스크립트는 무슨 일이 일어나고 있는지 보여줍니다.

echo "hello"
read -p "how do you do? "
echo "I understand"
echo "you are '$REPLY'."
echo "bye"

파일에 저장하고 bash -x foo먼저 as를 실행한 다음 as를 실행합니다 bash -x <foo.

귀하의 경우에도 같은 일이 발생합니다.

한 가지 해결책은 프로세스 대체를 사용하는 것입니다.

bash -x <(cat foo)

또는 귀하의 경우 간단히:

bash <(curl -s0 https://myserver.com/install.sh)

몇 가지 참고사항:

쉘 스크립트가 이상한 일을 할 때마다 bash -x무슨 일이 일어나고 있는지 확인하는 데 사용하십시오.

글쓰기 cat foo| ...가 불린다고양이에게 쓸모없는 용도. 리디렉션을 사용하면 됩니다.

관련 정보