J'ai une if
déclaration pour calculer les fichiers et supprimer tout sauf les trois derniers fichiers. Mais je veux exécuter cette commande à distance. Comment puis-je combiner ssh
avec une if
condition?
J'ai essayé mais sans succès.
#!/bin/bash
ssh -t test@192.168.94.139 "cd /var/www/test.com/backup ;
if [ $(ls | wc -l) -lt 3 ]
then
echo "Less"
else [ $(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]
echo "deleted"
fi"
L'erreur que j'ai eue:
ls: impossible d'accéder à * .tgz: aucun fichier ou répertoire de ce type
command-line
bash
ssh
Janith
la source
la source
$(
)
partie de la commande est exécutée par le shell local avant même de démarrer lassh
commande. Cela est vrai à la fois lorsqu'il$(
)
est autonome et lorsqu'il est encadré par l'"
art. Cependant, s'il$(
)
était à l'intérieur de'
s, il ne serait pas exécuté par le shell local.Réponses:
REMARQUE: il y a en fait deux couches à la question ici. L'une est «Je veux exécuter une tâche non triviale sur un serveur distant accessible via SSH». L'autre est «J'essaie de passer une chaîne complexe à une commande, et l'argument finit par être différent de ce que je voulais». Je réponds à la question de bas niveau sans discuter si l'approche utilisée est "correcte" (pratique, sans risque d'erreur, sécurisée, etc.) pour résoudre la question de haut niveau. Comme indiqué par les autres réponses et commentaires, ce n'est probablement pas le cas.
Votre ligne de commande est généralement correcte; il suffit de changer un peu la citation.
Le problème principal est que les chaînes entre guillemets doubles sont développées par votre shell local, et donc les
$(...)
pièces seront évaluées sur votre système local. Pour les transmettre au système distant, vous devez placer le script entre guillemets simples.Vous disposez également de guillemets intégrés. Dans votre script d'origine, il y a les arguments pour les deux
echo
s; si vous changez la citation externe en guillemets simples, ce sera le script awk. Ces résultats entraînent la suppression des guillemets, ce qui ne dérange pas leecho
s, mais cela gâchera le script awk, car le signe supérieur à deviendra une redirection de sortie. Ainsi, après avoir modifié les guillemets externes en guillemets simples, changez-les en guillemets doubles.Ceci est votre script avec la citation fixe. Le script peut avoir d'autres problèmes, je viens de corriger la syntaxe.
la source
/var/www/test.com/backup
une variable appelée "BACKUPDEST" etcd $BACKUPDEST
pouvez-vous me dire comment procéder?BACKUPDEST
? Si cela se produit du côté distant, incluez-le simplement dans le script normalement. Si vous voulez le définir localement (par exemple le calculer dans le script local, ou le passer comme argument de ligne de commande), vous pouvez changer la première ligne par exemple"cd $BACKUPDEST"' ;
- le shell étend la partie entre guillemets, conserve le guillemet simple partie intacte, concatène les deux et passe le résultat comme dernier argument àssh
."cd '$BACKUPDEST'"' ;
au cas où le chemin dans cette variable contient un peu de bizarrerie (par exemple un espace). Encore une fois: dire simplement que cela peut être fait de cette façon, et non que cela devrait être fait de cette façon.Oui, vous pouvez exécuter des scripts complexes via
ssh
Cet exemple utilise un document bash here pour générer la chaîne de commande. Dans tous les cas, la transmission de scripts via ssh est sujette aux erreurs, car la citation et l'échappement des variables est difficile (faites attention à la barre oblique inverse avant les commandes). Si le script devient trop complexe, il est préférable de le copier via
scp
puis de l'exécuter sur l'hôte cible.Je n'ai pas essayé de corriger votre script , mais voici un exemple sur la façon dont le comptage et la suppression sur un hôte distant pourraient fonctionner:
Le
ls -t *.tgz
ne fonctionnera pas, car le globbing ne se passe sur le système local. L'utilisationls
de comptage de fichiers n'est pas non plus une bonne idée, car elle renvoie également des entrées comme.
,..
et des répertoires.la source
syntax error near unexpected token elif'
,elif [ $(ls -t |awk 'NR >3'|xargs rm -f) ]; then'
;
manquant dans la première instruction if. Mais je ne vous ai pas corrigé le script! Il y a beaucoup plus de problèmes, par exemple lels *.tgz
$(...)
intérieur d'une chaîne entre guillemets doubles, donc le shell local l'a évaluée. L'échapper\$(...)
comme vous l'avez montré dans le premier exemple, ou utiliser des guillemets simples dans tout le script, empêche le shell local de le développer, donc il est envoyé au système distant, il est développé par le shell distant et le script fonctionne comme prévu.printf
développer des variables - cela sera toujours plus facile à gérer que d'essayer d'échapper toutes les variables du shell. En outre, cela éviterait d'avoir à utilisercat
simplement pour capturer le document ici dans une variable!Je pense que tout ce truc de citation compliqué est une preuve suffisante pour ne pas l'utiliser mais utiliser un script à la place. Si vous souhaitez éviter plusieurs
ssh
connexions, dirigez le script vers l'autre hôte et laissez-le s'exécuter à partir d'une seule commande:Fichier local, dites
myscript.sh
:Alors:
Ou (en évitant une utilisation inutile du chat ):
Cela
myscript.sh
redirige le script local vers le côté distant où il est redirigé vers un fichier (temporaire)/tmp/ms.sh
, exécuté et finalement supprimé.Remarque: je n'ai pas vérifié le script d'origine pour les erreurs, mais je voulais juste montrer l'idée. Aucune citation sujette aux erreurs n'est nécessaire et toutes les commandes du script sont exécutées du côté distant.
la source
ssh user@host bash <myscript.sh
.mktemp
quelque chose de similaire.Je préférerais placer le script sur l'instance distante et l'exécuter simplement via ssh, mais voici ma suggestion comment cela pourrait être fait comme vous le souhaitez:
Remarques:
-lt
est remplacée par-le
.eval
- construire la commande en concaténant des arguments.\"
dans l'$COMMAND{1..3}
expression, mais je décide de les ajouter.la source