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.)
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.)
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. :-)
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
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.
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.