`curl의 차이점은 무엇입니까 | sh`와`sh -c“$ (curl)”`?


23

Docker의 쉬운 설치 방법 중 하나는 다음과 같습니다.

curl -sSL https://get.docker.com/ | sh

그러나 도커 예제를 사용하여 다음과 같은 것을 보았습니다.

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

그것들은 기능적으로 동일한 것으로 보이지만, 다른 것을 사용하는 이유가 있습니까? 아니면 단지 선호 / 미적 인 것입니까?

(알 수없는 출처에서 스크립트를 실행할 때는주의해야합니다.)

답변:


39

실질적인 차이가 있습니다.

curl -sSL https://get.docker.com/ | sh시작 curl및 sh출력 연결 동시에 curl의 입력을 가진 sh. 스크립트를 실행할 수있는 한 curl빨리 다운로드합니다 (대략) sh. 서버는 리소스를 파일이나 버퍼로 다운로드하거나 브라우저에서 볼 때 타이밍에서 불규칙성을 감지하여 보이지 않는 악성 코드를 주입 ​​할 수 있습니다.

에서 sh -c "$(curl -sSL https://get.docker.com/)", curl(가) 엄격하기 전에 실행되는 sh실행됩니다. 리소스 sh가 시작 되기 전에 리소스의 전체 내용이 다운로드되어 셸로 전달됩니다 . 쉘 은 종료 sh되었을 때만 시작 curl되고 자원의 텍스트를 전달합니다. 서버가 sh통화를 감지 할 수 없습니다 . 연결이 종료 된 후에 만 ​​시작됩니다. 스크립트를 파일로 먼저 다운로드하는 것과 비슷합니다.

(이는 도커의 경우에는 관련이 없지만 일반적으로 문제가 될 수 있으며 두 명령의 실제 차이점을 강조합니다.)


2
고마워, 이것은 둘 사이의 가장 중요한 차이점처럼 보입니다.
— Sarke

이 주장을 뒷받침하는 자료를 인용 해 주시겠습니까? 서버가 'sh'호출을 감지하는 방법을 알고 싶습니다.
— Alfred Armstrong

1
@ AlfredArmstrong 음, 나는 vulnerable to server-side detection문구에 링크를 넣었습니다 . 블로그 게시물을 통해 어떻게 달성하는지 자세히 설명합니다. TL; DR : 스크립트에서 휴면 상태를 유지하고 서버에서 수신 지연을 관찰하십시오.
— Jonas Schäfer

1
@JonasWielicki 감사합니다-링크가 명확하지 않았습니다-귀하의 잘못이 아니고 SE의 CSS로 생각합니다. 사람들은 훌륭하게 몰래 들리지 않습니까? :)
— Alfred Armstrong

1
이 모든 것이 누군가가 즉시 잡히지 않고 실제로 그 트릭을 시도했는지 궁금하게 만듭니다. 스크립트가 그러한 트릭 없이도 악의적 인 일을 할 수 있기 때문에 중요하지 않을 수 있으며, 전체를 읽지 않는 사람은 취약 할 수 있습니다.
— ilkkachu

11

나는 그들이 실질적으로 동일하다고 생각합니다. 그러나 드문 경우가 있습니다.

$(cmd)의 결과로 대체됩니다 cmd. 해당 결과 명령의 길이가에 의해 반환 된 최대 인수 길이 값을 초과하면 결과 getconf ARG_MAX가 잘리고 예기치 않은 결과가 발생할 수 있습니다.

파이프 옵션에는이 제한이 없습니다. curl명령 의 각 출력 라인은 bash파이프에서 도착할 때 실행됩니다 .

그러나 ARG_MAX는 일반적으로 256,000 자 범위입니다. 도커 설치의 경우 두 방법 중 하나를 사용한다고 확신합니다. :-)


흥미 롭기 때문에 차이가 있습니다. 감사합니다
— Sarke

1
확실하지 않은 경우 파이프 방법을 사용하십시오. 내 대답에 환경 설정을 지정하지 않았지만 파이프를 통해 얼마나 많은 데이터가 들어오는 지 알 수 없기 때문에 이러한 종류의 파이프 방법을 선호합니다.
— Greg Tarsa

2
"결과가 잘립니다"-셸에서 자동으로 잘리지 않는 오류 메시지가 표시됩니다. 테스트 할 때, 심지어 훨씬 아래의 쉘에서 오류가 발생 ARG_MAX합니다 .bash getconf ARG_MAX는 인쇄 할 때 시스템에서 개별 인수를 131072 바이트로 제한 합니다 2097152. 그러나 오류 또는 잘림은 작동하지 않습니다.
— hvd

그러나 Bourne 쉘의 오래된 구현 에는 훨씬 낮은 한계가있었습니다. 4.2BSD에서 한도는 10240 자이며, 이전 시스템에서는 한도가 더 낮았습니다. 물론 30 년 전 이었으므로 오늘날에는 그러한 하한을 겪지 않을 것입니다. 올바르게 기억한다면, 초기 쉘 중 일부는 자동으로 잘립니다.
— AndyB

단일 인수에 대한 128 kB 제한은 Linux에 관한 것이며 Bash에 관한 것이 아닙니다.
— ilkkachu

8

에서 curl -sSL https://get.docker.com/ | sh:

  • 두 명령, curl그리고 sh, 각각의 서브 쉘에서, 같은 시간에 시작됩니다

  • STDOUT curl은 STDIN으로 전달됩니다 sh(이것은 파이프 |가 수행하는 것입니다).

반면 sh -c "$(curl -sSL https://get.docker.com/)":

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

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

  • sh -c (비 대화식, 비 로그인 셸)에서 STDOUT을 실행합니다. curl


1
실제 차이가 있습니까?
— Sarke

@Sarke 네, 이론적으로는 언급했지만 실제로 거의 눈에 띄지 않습니다. (명령 대체를 인용 부호로 두지 않으면 눈에 띄는 효과가 있습니다.)
— heemayl

1
@Sarke, 스크립트가 완전히 다운로드되지 않은 경우 반드시 파이핑시이를 알 수있는 것은 아닙니다. 파이프 연결 프로세스는 해당 신호를 무시할 수 있습니다.
— Janus Troelsen

@JanusTroelsen 완전히 다운로드되지 않았다는 것은 무슨 뜻입니까? 서버 오류를 제외하고 왜 이런 일이 발생합니까?이 경우 sh로 파이프 할 것이 없습니다.
— hasufell

또는 연결 중단 ... 전송이 실패 할 수있는 여러 가지 방법이 있습니다
— Janus Troelsen

0

두 가지 (웹 전체의 다른 답변에서 가져온)의 한 가지 차이점은 전체 스크립트를 한 번에 다운로드하지 않으면 알 수없는 시점에서 스크립트를 절반 쯤 중단하고 명령의 의미를 다음과 같이 변경할 수 있다는 것입니다 처형. 따라서 전체 파일을 먼저 다운로드 한 다음 평가하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.