Selon la réponse de Zanco , vous ne fournissez pas de commande à distance ssh
, étant donné la façon dont le shell analyse la ligne de commande. Pour résoudre ce problème, modifiez la syntaxe de votressh
appel de commande afin que la commande distante soit composée d'une chaîne multi-lignes syntaxiquement correcte.
Il existe une variété de syntaxes qui peuvent être utilisées. Par exemple, puisque les commandes peuvent être canalisées dans bash
et sh
, et probablement aussi d'autres shells, la solution la plus simple est de simplement combiner l' ssh
invocation du shell avec heredocs:
ssh user@server /bin/bash <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
Notez que l'exécution de ce qui précède sans /bin/bash
entraînera l'avertissement Pseudo-terminal will not be allocated because stdin is not a terminal
. Notez également qu'il EOT
est entouré de guillemets simples, ce qui bash
reconnaît l'heredoc comme un nowdoc , désactivant l'interpolation de variable locale afin que le texte de la commande soit transmis tel quel àssh
.
Si vous êtes un fan de tuyaux, vous pouvez réécrire ce qui suit comme suit:
cat <<'EOT' | ssh user@server /bin/bash
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
La même mise en garde à propos de /bin/bash
s'applique à ce qui précède.
Une autre approche valide consiste à passer la commande à distance multi-ligne en une seule chaîne, en utilisant plusieurs couches d' bash
interpolation variable comme suit:
ssh user@server "$( cat <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
)"
La solution ci-dessus résout ce problème de la manière suivante:
ssh user@server
est analysé par bash, et est interprété comme étant la ssh
commande, suivi d'un argument user@server
à passer à la ssh
commande
"
commence une chaîne interpolée qui, une fois terminée, comprendra un argument à passer à la ssh
commande, qui dans ce cas sera interprété par ssh
comme étant la commande distante à exécuter commeuser@server
$(
commence une commande à exécuter, la sortie étant capturée par la chaîne interpolée environnante
cat
est une commande pour afficher le contenu du fichier suivant. La sortie de cat
sera retransmise dans la chaîne interpolée de capture
<<
commence un hérédoc bash
'EOT'
spécifie que le nom de l'hérédoc est EOT. Les guillemets simples '
entourant EOT spécifient que l'heredoc doit être analysé en tant que nowdoc , qui est une forme spéciale d'heredoc dans laquelle le contenu n'est pas interpolé par bash, mais plutôt transmis au format littéral
Tout contenu rencontré entre <<'EOT'
et <newline>EOT<newline>
sera ajouté à la sortie nowdoc
EOT
termine nowdoc, ce qui entraîne la création et la retransmission d'un fichier temporaire nowdoc à la cat
commande appelante . cat
sort le nowdoc et retransmet la sortie à la chaîne interpolée de capture
)
conclut la commande à exécuter
"
conclut la capture de la chaîne interpolée. Le contenu de la chaîne interpolée sera retransmis en ssh
tant qu'argument de ligne de commande unique, qui ssh
sera interprété comme la commande distante à exécuter commeuser@server
Si vous devez éviter d'utiliser des outils externes comme cat
, et cela ne vous dérange pas d'avoir deux instructions au lieu d'une, utilisez le read
intégré avec un hérédoc pour générer la commande SSH:
IFS='' read -r -d '' SSH_COMMAND <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
ssh user@server "${SSH_COMMAND}"
ssh user@server /bin/bash <<EOT…