J'essayais de sauvegarder certains fichiers via SSH, mais au lieu de tar
ceux que je voulais, j'ai mon dossier personnel. J'ai fait d'autres tests et cela se résume à ceci:
ssh root@server /bin/sh -c "cd /boot && ls -l"
Qui à ma grande surprise liste des fichiers dans /root
pas /boot
. Mais si j’exécute l’ensemble de la /bin/sh
commande à partir d’un terminal, il cd
s’imprime correctement et affiche les /boot
fichiers.
Qu'est-ce qu'il se passe ici?
shell
ssh
cd-command
Ambroz Bizjak
la source
la source
ssh root@server /bin/sh -c "ls -l /boot"
?Réponses:
ssh ne vous permet pas de spécifier une commande précisément, comme vous l'avez fait, sous la forme d'une série d'arguments à transmettre à execvp sur l'hôte distant. Au lieu de cela, il concatène tous les arguments dans une chaîne et les exécute via un shell distant. À mon avis, c’est là un défaut de conception majeur dans ssh. C’est un outil unix bien conçu dans la plupart des cas, mais quand vient le temps de spécifier une commande, il a choisi d’utiliser une seule chaîne monolithique au lieu d’un argv, comme il a été conçu pour MSDOS ou quelque chose comme ça!
Puisque ssh passera votre commande sous forme de chaîne unique
sh -c
, vous n'avez pas besoin de fournir la vôtresh -c
. Quand vous le faites, le résultat estavec la citation d'origine perdu. Donc, les commandes séparées par le
&&
sont:Le premier de ceux-ci exécute un shell avec le texte de commande "cd" et
$0
="boot"
. La commande "cd" se termine avec succès, le$0
est sans importance et/bin/sh -c
indique le succès, puis lels -l
se produit.la source
ssh
se comporter de la sorte. Sinon, il faudrait s’appelersexec
, nonssh
.ssh
est la version sécurisée dersh
(qui se comporte de la même manière à cet égard) etrlogin
(rsh
appeléerlogin
lorsqu'elle n'est pas passée en ligne de commande). C'est juste dommage que cela ne soit pas misrexec
en œuvre aussi bien."`printf "%q " "$@"`"
avec bashprintf
pour citer une chaîne ou des chaînes avec des échappements de shell.C'est une citation. Ssh exécute déjà la commande que vous passez dans un shell. Lorsque vous transmettez plusieurs paramètres, ils sont concaténés avec un espace entre eux pour créer une chaîne. La commande distante que vous exécutez à distance est donc
/bin/sh -c cd /boot && ls -l
(pas de guillemets, car ceux-ci ont été interprétés par le shell local)./bin/sh -c cd /boot
pistes/bin/sh
et lui dit de lancer la commandecd
et aussi ensemble$0
à/boot
. Une fois que cela est fait, le shell parent (celui lancé parsshd
) s'exécutels -l
.Dans votre cas, supprimez simplement ce
sh -c
qui est complètement inutile à moins que votre shell distant (comme indiqué dans/etc/passwd
ou une autre base de données de mots de passe) ne comprenne pas cette commande.Si vous avez besoin d'appeler un autre shell, vous devez citer la commande distante pour le protéger contre l'expansion du shell distant invoqué par
sshd
. Par exemple, si votre shell de connexion est Dash et que vous souhaitez exécuter une commande bash:la source
Je pense que cela a plus à voir avec la façon dont les options sont analysées par le shell. Par exemple, cela fonctionne:
Cela a le même problème que votre commande:
Si vous activez le
-v
commutateur,ssh
vous pouvez voir ce qui se passe:1ère commande:
2ème commande:
En règle générale, lorsque vous envoyez des commandes,
ssh
vous devez porter une attention particulière à la citation et insérer des guillemets entre guillemets à mesure que les différentes couches les suppriment. Aussi, ne vous embêtez pas d'envoyer/bin/sh
.Vous pouvez faire une chose très utile une fois que vous avez compris comment citer
ssh
ce qui suit. Cela exécutera la commande sur le serveur distant mais collectera les résultats dans un fichier situé localement sur le système sur lequel vous avez exécuté lassh
commande:ou ceci, où vous tarifiez un répertoire sur un serveur distant et le créez sur le système local:
Les références
la source
En règle générale, vous n'avez pas à spécifier le shell à utiliser. Cela marche:
Mais si votre shell par défaut est problématique, assurez-vous simplement de citer la commande entière , y compris l'invocation du shell. Une des oeuvres suivantes
la source
cd /boot && pwd
fonctionne dans tous les shells des grandes familles (Bourne, csh, rc),/bin/sh -c "cd /boot && pwd"
il ne fonctionnerait pas si le shell distant est de larc
famille où il"
n’est pas spécial.