`Curl | arasındaki fark nedir sh` ve `sh -c“ $ (curl) ”`?


23

Docker için kolay bir yükleme yöntemi (örneğin) şudur:

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

Ancak, bunun gibi görünen bazılarını da gördüm (Docker örneğini kullanarak):

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

İşlevsel olarak aynı görünüyorlar, ancak birini üst üste kullanmanın bir nedeni var mı? Yoksa sadece tercih / estetik bir şey midir?

(Not, bilinmeyen kökenlerden komut dosyası çalıştırırken çok dikkatli olun.)

Yanıtlar:


39

Pratik bir fark var.

curl -sSL https://get.docker.com/ | shbaşlar curlve shaynı zamanda, çıktısının curlgirişi ile bağlanır sh. curlİndirme (kabaca) shkomut dosyasını çalıştırabildiğiniz kadar hızlı gerçekleştirir . Sunucu , zamanlamadaki düzensizlikleri tespit edebilir ve kaynağı bir dosyaya veya arabelleğe indirirken veya bir tarayıcıda görüntülerken görünmeyen zararlı kodları enjekte edebilir.

In sh -c "$(curl -sSL https://get.docker.com/)", curlkesinlikle çalıştırılmadan önce shçalıştırılır. Kaynağın tüm içeriği indirilmeden önce shbaşlatılmalı ve kabuğunuza aktarılmalıdır . Sizin kabuk sadece başladığında shzaman curlçıkıldı ve buna kaynak metin geçirir. Sunucu sharamayı algılamıyor ; yalnızca bağlantı sona erdikten sonra başlatılır. Önce betiği bir dosyaya indirmeye benzer.

(Bu, liman işçisi ile ilgili olmayabilir, ancak genel olarak bir sorun olabilir ve iki komut arasındaki pratik bir farkı vurgulamaktadır.)


2
Teşekkürler, bu ikisi arasındaki en önemli fark gibi görünüyor.
Sarke

Lütfen bu iddiayı destekleyen bir kaynak gösterebilir misiniz? Sunucunun 'sh' çağrısını nasıl algılayabileceğini bilmek çok isterim.
Alfred Armstrong

1
@AlfredArmstrong Uhm, vulnerable to server-side detectioncümle üzerinde bir link koydum . Nasıl yaptıklarını ayrıntılı bir şekilde açıklayan bir blog gönderisine yol açar. TL; DR: betiğinize bir uyku koyun ve sunucudaki alımdaki gecikmeyi izleyin.
Jonas Schäfer

1
@JonasWielicki teşekkürler - bağlantı çok açık değildi - SE'nin CSS'sine kadar senin suçun değil. İnsanlar zekice sinsidir, değil mi? :)
Alfred Armstrong

1
Bunların hepsi, birisinin bu numarayı hemen yakalanmadan yapmayı denemiş olup olmadığını merak etmemi sağlıyor. Senaryo, muhtemelen sadece senaryo böyle hileler olmadan bile kötü niyetli bir şeyler yapabileceğinden beri önemli değildir.
ilkkachu

11

Neredeyse aynı olduklarına inanıyorum. Ancak, farklı oldukları nadir görülen durumlar vardır.

$(cmd)sonuçları ile değiştirilir cmd. Bu sonuç komutunun uzunluğu getconf ARG_MAX, döndürülen maksimum argüman uzunluğu değerini aşarsa , sonucu kesebilir ve bu tahmin edilemez sonuçlara neden olabilir.

Boru seçeneğinde bu sınırlama yoktur. Komuttan çıkan her çıktı satırı , borudan geldiğinde curltarafından yürütülür bash.

Ancak ARG_MAX genellikle 256.000 karakter aralığındadır. Liman işçisi kurulumu için iki yöntemden de emin olabilirim. :-)


İlginç, yani bir fark var. Teşekkürler
Sarke

1
Şüphe durumunda, boru yöntemini kullanın. Cevabımda bir tercih belirtmedim, ancak bu tür kullanım için boru yöntemini tercih ederim çünkü borudan ne kadar veri geldiğini asla bilemezsiniz.
Greg Tarsa

2
"sonucu kesecek" - Kabuk sessizce kesmemesi için bir hata mesajı vermeli. Test ederken, çok aşağıdaki kabuktan bir hata bile alıyorum ARG_MAX, bash getconf ARG_MAXbaskılar sırasında sistemimdeki bağımsız bir argümanı 131072 bayta sınırlandırıyor 2097152. Ama her iki durumda da, hata veya kesme, işe yaramaz.
HVD

Ancak Bourne kabuğunun eski uygulamalarının çok daha düşük sınırları vardı. 4.2BSD'de limit 10240 karakterdi ve önceki sistemlerde daha da düşüktü. Tabii ki 30 yıl önceydi, bu yüzden bugün böyle düşük limitlerle karşılaşmanız pek mümkün değil. Doğru hatırlıyorsam, bu eski kabuklardan bazıları sessizce kısaldı.
AndyB,

Tek bir argüman için 128 kB sınırı bir Linux olayıdır, Bash ile ilgili değildir.
ilkkachu

8

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

  • Her iki komut da curlve shaynı anda ilgili alt kabuklarda başlayacaktır.

  • STDOUT from curlSTDIN olarak iletilecektir sh(bu, ne |yapar?)

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

  • Komut değiştirme, $()ilk curlönce çalıştırılacak, yani önce bir alt kabukta çalıştırılacak

  • Komut yerine, $()gelen STDOUTcurl

  • sh -c (etkileşimli olmayan, giriş yapmayan kabuk) STDOUT’yu curl


1
Peki, gerçek bir fark var mı?
Sarke

@Sarke Evet, teorik olarak bahsettiğim gibi, ancak neredeyse hiç farkedilmez. (Komut yerine
koyma işlemini işaretsiz

1
@Sarke, scriptler tamamen indirilmezse, mutlaka boru ile dikkat edin. Borulu işlem bu sinyali görmezden gelebilir.
Janus Troelsen

@JanusTroelsen tamamen indirilmeden ne demek istiyorsun? Bu neden bir sunucu hatası dışında olur ki bu durumda sh ile işlenen hiçbir şey olmayacaktır.
hasufell

Veya bağlantı kesintisi ... transferin başarısız olabileceği çok fazla yol var
Janus Troelsen

0

İkisi arasındaki fark (web'deki diğer cevaplardan alınmış), betiğin tamamını bir kerede indirmezseniz, betiğin tamamını bilinmeyen bir noktada kesebilir ve komutun anlamını değiştirebilir. idam. Öyleyse ilk önce bütün dosyayı indirdikten sonra değerlendirmek daha iyi olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.