예를 들어 Docker를 설치하는 간단한 방법은 다음과 같습니다.
curl -sSL https://get.docker.com/ | sh
그러나 다음과 같은 내용도 본 적이 있습니다(Docker 예제 사용).
sh -c "$(curl -sSL https://get.docker.com/)"
기능적으로는 동등한 것처럼 보이지만 다른 것을 사용해야 할 이유가 있습니까? 아니면 이것은 단지 선호/미학인가요?
(알 수 없는 소스에서 스크립트를 실행할 때는 매우 주의해야 한다는 점은 주목할 가치가 있습니다.)
답변1
실질적인 차이가 있습니다.
curl -sSL https://get.docker.com/ | sh
의 출력을 의 입력에 연결 curl
하면서 시작하십시오 . 다운로드는 대략적으로 스크립트 실행 속도로 수행됩니다 . 서버는 다음을 수행할 수 있습니다.sh
curl
sh
curl
sh
타이밍의 불규칙성을 감지리소스를 단순히 파일이나 버퍼에 다운로드하거나 브라우저에서 볼 때 눈에 보이지 않는 악성코드를 삽입합니다.
에서는 sh -c "$(curl -sSL https://get.docker.com/)"
run 전에 엄격하게 실행하십시오 curl
. 시작하기 전에 sh
리소스의 전체 콘텐츠가 다운로드되어 셸에 전달됩니다. sh
쉘은 종료 sh
시 에만 시작되어 curl
리소스 텍스트를 전달합니다. 서버는 sh
호출을 감지할 수 없으며 연결이 종료된 후에만 시작됩니다. 이는 먼저 스크립트를 파일로 다운로드하는 것과 유사합니다.
(이는 docker 상황과 관련이 없을 수도 있지만 일반적으로 문제가 될 수 있으며 두 명령 간의 실제 차이점을 강조합니다.)
답변2
나는 그들이 실제로 동일하다고 믿습니다. 그러나 드문 경우이지만 다릅니다.
$(cmd)
결과로 대체됩니다 cmd
. 결과 명령이 반환된 최대 인수 길이 값보다 길면 getconf ARG_MAX
결과가 잘려서 예측할 수 없는 결과가 발생할 수 있습니다.
파이프 옵션에는 이러한 제한이 없습니다. 명령의 각 출력 행은 파이프에서 도착할 때 실행됩니다 curl
.bash
그러나 ARG_MAX는 일반적으로 256,000자 범위 내에 있습니다. Docker 설치의 경우 두 가지 방법 중 어느 쪽을 사용해도 자신감이 있습니다. :-)
답변3
존재하다 curl -sSL https://get.docker.com/ | sh
:
두 명령 모두 해당 하위 쉘에서 동시에 실행됩니다
curl
.sh
STDOUT from은
curl
STDIN으로 전달됩니다sh
(이것이|
바로 파이프, , 의 용도입니다).
그리고 sh -c "$(curl -sSL https://get.docker.com/)"
:
명령 대체가
$()
먼저 실행됩니다. 즉,curl
서브셸에서 먼저 실행됩니다.명령 대체는
$()
STDOUT으로 대체됩니다.curl
sh -c
(비대화형, 비로그인 쉘)은 STDOUT을 실행합니다.curl
답변4
(웹의 다른 답변에서 가져온) 둘 사이의 한 가지 차이점은 전체 스크립트를 한 번에 다운로드하지 않으면 알 수 없는 지점에서 스크립트의 절반이 잘리고 실행될 명령의 의미가 변경될 수 있다는 것입니다. . 그러니 먼저 전체 파일을 다운받아서 평가해 보시는 것이 좋을 것 같습니다.