우분투 컨테이너 내에서 실행되는 스크립트가 있습니다.
#!/bin/sh
name=$(cat < /etc/os-release | grep "^NAME" | cut -d "=" -f 2)
if [ $name = "Ubuntu" ]
then
echo "This should return"
else
echo "This is wrong"
fi
다음을 실행하여 컨테이너를 시작합니다.
docker run -it -v $(pwd):/scripts ubuntu:latest /bin/sh /scripts/test.sh
내가 받은 출력은 "This iswrong"입니다. 이는 잘못된 것입니다. 내 노트북이 Ubuntu이므로 $name의 출력이 "Ubuntu"라는 것을 알고 있지만 이런 일이 발생하는 이유를 찾을 수 없습니다. 스크립트에 경로가 있는 이유는 무엇입니까? 컨테이너 외부의 노트북에서도 동일한 작업을 수행합니다.
답변1
이 파일에는 /etc/os-release
쉘 호환 변수 할당 목록이 포함되어 있습니다. 쉘 스크립트에서 구문 분석할 필요가 없으며 관련 변수를 사용하기 source
만 하면 됩니다..
$ cat ex.sh
#!/bin/sh
. /etc/os-release
echo "$NAME"
$ ./ex.sh
Ubuntu
답변2
데비안에서 이 특정 줄은 다음과 같습니다.
NAME="Debian GNU/Linux"
오른쪽의 따옴표를 주목하세요. Ubuntu에서도 사용할 수 있는 경우 name
따옴표는 에 특별한 것이 아니기 때문에 에서도 문자 그대로 따옴표를 받게 됩니다 cut
. 또 다른 문제는 문자열에 공백이 포함될 수 있다는 것입니다. 이 경우 토큰화가 문자열에서 따옴표가 없는 변수 확장에 도달 [ $name = "Ubuntu" ]
하고 테스트에서 오류가 발생할 수 있습니다.
이러한 문제를 방지하려면 변수 확장을 인용하고 비교 문자열 주위에 리터럴 인용을 추가하십시오.
if [ "$name" = '"Ubuntu"' ]; then ...
또는 문자열의 시작과 끝에서 따옴표를 제거 name=${name#\"}; name=${name%\"}
하고 여전히 quote 를 사용합니다 "$name"
.
답변3
이 특별한 경우에는 다음과 같이 스크립트를 단순화할 수 있습니다.
#!/bin/sh
if grep -q Ubuntu /etc/os-release; then
echo "This should return"
else
echo "This is wrong"
fi
grep
, 이 -q
옵션을 전달하면 아무것도 인쇄되지 않지만 문자열이 발견되면 코드 0으로 종료되고 그렇지 않으면 0이 아닌 코드로 종료됩니다. if
결국 그것이 우리가 기대하는 것입니다.
답변4
단순한
$ grep -q Ubuntu /etc/os-release && echo "This should return" || echo "This is wrong"
또는
$ . /etc/os-release && echo "$NAME"
또는 lsb_release
다음 명령을 사용할 수도 있습니다.
$ lsb_release -i -s