읽기 명령을 실행할 때 sh가 대화형 옵션을 사용하지 않는 이유는 무엇입니까?

읽기 명령을 실행할 때 sh가 대화형 옵션을 사용하지 않는 이유는 무엇입니까?

read구성 스크립트를 다운로드하고 일부 구성 매개변수를 읽고 실행하고 싶습니다 .

curl http://example.com/provisioning.sh | sh

문제는 기본값을 제공하기 위해 매개변수를 사용하여 read스크립트에서 명령을 호출하는 것 입니다.-i

read -p "Name: " -i joe name
echo $name

스크립트를 다운로드하고 +x권한을 설정하고 실행하면 모든 것이 정상입니다.

cat provisioning.sh | sh다음을 사용하여 실행하거나 sh provisioning.sh다음과 같이 실패 하면 :

read: Illegal option -i

sh를 통해 실행하는 경우 기본값 읽기에 대한 지원이 제공되지 않는 이유는 무엇입니까?

하지만 어쨌든 삭제 -i하고 남길게요

read -p "Name: " name
echo $name

이제 를 통해 스크립트를 실행하면 cat provisioning.sh | sh아무 작업도 수행되지 않습니다. 왜 그런 겁니까?

우분투 14.04.

답변1

의 출력을 파이프 curl하면 sh스크립트 텍스트를 셸의 표준 입력으로 만들어 실행할 명령으로 수신하게 됩니다. 그 후에는 아무것도 남지 않습니다 read. 시도하더라도 터미널 입력에 연결되어 있지 않기 때문에 터미널 입력에서 아무것도 얻지 못합니다. 파이프는 sh프로세스의 표준 입력을 대체했습니다 .

다음 질문 read -i아니요POSIX sh 함수이지만 에서 지원하는 확장입니다 bash.우분투는dash, 기본적으로 최소한의 확장을 갖춘 최소한의 POSIX 호환 셸입니다 /bin/sh. 이것이 -i옵션을 명시적으로 거부하는 이유입니다(지원하긴 하지만 -p).

더 강력한 셸을 직접 사용하는 경우 다음을 시도해 볼 수 있습니다.

bash <(curl http://example.com/provisioning.sh)

bash의 출력을 읽기 위한 파이프를 생성 curl하고 이를 스크립트 파일 인수로 제공합니다. 이 경우 스크립트의 표준 입력은 여전히 ​​터미널에 연결되어 있으며 read작동합니다(그러나 해당 줄 아래에 중요한 경고가 있습니다).


제가 또 주목하고 싶은 점은" curl | sh" 예일반적으로 말하면 찌푸린 얼굴 ~ 위에명백한 보안 문제이지만 스크립트가 처한 상황은 사용자가 가장 잘 알고 있습니다.

답변2

또 다른 이식성 있는 접근 방식은 또 다른 파일 설명자를 만드는 것입니다.

exec 3<>/dev/tty
read -u 3 -p "Gimme some stuff: " stuff

여기서 내가 찾은 것: https://superuser.com/questions/834502/possible-to-get-a-bash-script-to-accept-input-from-terminal-if-its-stdin-has-bee

내 경우에는 이것이 작동하도록 스크립트에서 빠르게 찾기 및 바꾸기를 수행했습니다.

exec 3<>/dev/tty
read_cmd="read -u 3"

$read_cmd -p "name: " my_name
$read_cmd -p "email: " my_email
$read_cmd -s -p "password: " my_password

관련 정보