`컬 | sh` 및 `sh -c "$(curl)"`?

`컬 | sh` 및 `sh -c "$(curl)"`?

예를 들어 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하면서 시작하십시오 . 다운로드는 대략적으로 스크립트 실행 속도로 수행됩니다 . 서버는 다음을 수행할 수 있습니다.shcurlshcurlsh타이밍의 불규칙성을 감지리소스를 단순히 파일이나 버퍼에 다운로드하거나 브라우저에서 볼 때 눈에 보이지 않는 악성코드를 삽입합니다.

에서는 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은 curlSTDIN으로 전달됩니다 sh(이것이 |바로 파이프, , 의 용도입니다).

그리고 sh -c "$(curl -sSL https://get.docker.com/)":

  • 명령 대체가 $()먼저 실행됩니다. 즉, curl서브셸에서 먼저 실행됩니다.

  • 명령 대체는 $()STDOUT으로 대체됩니다.curl

  • sh -c(비대화형, 비로그인 쉘)은 STDOUT을 실행합니다.curl

답변4

(웹의 다른 답변에서 가져온) 둘 사이의 한 가지 차이점은 전체 스크립트를 한 번에 다운로드하지 않으면 알 수 없는 지점에서 스크립트의 절반이 잘리고 실행될 명령의 의미가 변경될 수 있다는 것입니다. . 그러니 먼저 전체 파일을 다운받아서 평가해 보시는 것이 좋을 것 같습니다.

관련 정보