web-dev-qa-db-fra.com

Quelle est la différence entre `curl | sh` et `sh -c" $ (curl) "`?

Une méthode d'installation facile pour Docker (par exemple) est la suivante:

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

Cependant, j'en ai également vu certains qui ressemblent à ceci (en utilisant l'exemple Docker):

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

Ils semblent être fonctionnellement les mêmes, mais y a-t-il une raison de les utiliser les uns par rapport aux autres? Ou est-ce juste une préférence/une chose esthétique?

(À noter, soyez très prudent lorsque vous exécutez un script d'origine inconnue.)

25
Sarke

Il y a une différence pratique.

curl -sSL https://get.docker.com/ | sh Démarre curl et sh en même temps, en connectant la sortie de curl à l'entrée de sh. curl exécutera le téléchargement (à peu près) aussi vite que sh pourra exécuter le script. Le serveur peut détecter les irrégularités dans le timing et injecter du code malveillant non visible lors du simple téléchargement de la ressource dans un fichier ou un tampon ou lors de sa visualisation dans un navigateur.

Dans sh -c "$(curl -sSL https://get.docker.com/)", curl est exécuté strictement avant l'exécution de sh. Tout le contenu de la ressource est téléchargé et transmis à votre shell avant le démarrage de sh. Votre shell démarre uniquement sh lorsque curl est terminé et lui transmet le texte de la ressource. Le serveur ne peut pas détecter l'appel sh; il n'est démarré qu'après la fin de la connexion. Cela revient à télécharger d'abord le script dans un fichier.

(Cela peut ne pas être pertinent dans le cas du docker, mais cela peut être un problème en général et met en évidence une différence pratique entre les deux commandes.)

42
Jonas Schäfer

Je pense qu'ils sont pratiquement identiques. Cependant, il existe de rares cas où ils sont différents.

$(cmd) est remplacé par les résultats de cmd. Si la longueur de cette commande de résultat dépasse la valeur de longueur d'argument maximale renvoyée par getconf ARG_MAX, il tronquera le résultat, ce qui peut entraîner des résultats imprévisibles.

L'option pipe n'a pas cette limitation. Chaque ligne de sortie de la commande curl sera exécutée par bash lorsqu'elle arrivera du tube.

Mais ARG_MAX est généralement dans la plage de 256 000 caractères. Pour une installation de docker, je serais confiant en utilisant l'une ou l'autre méthode. :-)

12
Greg Tarsa

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

  • Les deux commandes, curl et sh, démarreront en même temps, dans les sous-coques respectives

  • Le STDOUT de curl sera passé en tant que STDIN à sh (c'est ce que fait le tuyau, |)

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

  • La substitution de commande, $(), sera exécutée en premier, c'est-à-dire que curl sera exécuté en premier dans un sous-shell

  • La substitution de commande, $(), sera remplacée par le STDOUT de curl

  • sh -c (Shell non interactif et sans connexion) exécutera la STDOUT à partir de curl

9
heemayl

Avec la version pipe, vous perdez l'interactivité du script, comme vous dirigez curl stdout vers sh stdin. Donc, aucune saisie au clavier et plantage de script possible en attente de saisie.

D'autres réponses ici sont également importantes.

1
Ondrej Galbavý

Une différence entre les deux (tirée d'autres réponses sur le Web) est que si vous ne téléchargez pas le script en une seule fois, il pourrait couper à mi-chemin du script à un moment inconnu et changer la signification de la commande à réalisé. Il semble donc que le téléchargement du fichier entier puis l'évaluation soit préférable.

0
Lance Pollard