J'ai une instruction if
pour calculer des fichiers et supprimer tous sauf les trois derniers fichiers. Mais je veux exécuter cette commande à distance. Comment puis-je combiner ssh
avec une condition if
?
J'ai essayé cela mais sans succès.
#!/bin/bash
ssh -t [email protected] "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 eu:
ls: impossible d'accéder à * .tgz: aucun fichier ou répertoire de ce type
NOTE: il y a en fait deux couches à la question ici. La première est "Je veux exécuter une tâche non triviale sur un serveur distant accessible via SSH". La seconde est "J'essaie de passer un complexe chaîne à une commande, et l'argument finit par être différent de celui que je voulais. "Je réponds à la question de bas niveau sans indiquer si l'approche utilisée est" correcte "(commode, non sujette aux erreurs, sécurisée, etc.) comme indiqué dans les autres réponses et commentaires, ce n’est peut-être pas le cas.
Votre ligne de commande est généralement correcte. il suffit de changer un peu la citation.
Le principal problème est que les chaînes entre guillemets sont développées par votre shell local. Les parties $(...)
seront donc évaluées sur votre système local. Pour les transférer au système distant, vous devez inclure le script entre guillemets simples.
Vous avez également des guillemets incorporé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. Cela a pour effet d’omettre les guillemets, ce qui ne gêne pas le echo
s, mais gâchera le script awk, car le signe supérieur à deviendra une redirection de sortie. Ainsi, après avoir modifié les guillemets extérieurs en guillemets simples, modifiez ceux-ci en guillemets doubles.
Ceci est votre script avec la citation corrigée. Le script peut avoir d'autres problèmes, je viens de corriger la syntaxe.
#!/bin/bash
ssh -t [email protected] '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'
Oui, vous pouvez exécuter des scripts complexes via ssh
name__
#!/bin/bash -e
ssh_cmd="$(cat <<-EOF
cd /var/www/test.com/backup;
if [ \$(ls | wc -l) -lt 3 ]; then
echo "less"
Elif [ \$(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]; then
echo "deleted"
else
echo "something else"
fi
EOF
)"
ssh -t [email protected] "$ssh_cmd"
Cet exemple utilise un bash ici document pour générer la chaîne de commande. Dans tous les cas, le fait de passer des scripts via ssh est sujet aux erreurs, car il est difficile de citer et échapper des variables (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
name__, puis de l'exécuter sur l'hôte cible.
Je n'ai pas essayé de corriger votre script , mais voici un exemple montrant comment le comptage et la suppression sur un hôte distant peuvent fonctionner:
#!/bin/bash -e
tmp_dir="$(mktemp -d)"
ssh_cmd="$(cat <<-EOF
cd "$tmp_dir"
cnt_tgz=(\$(find . -type f -name "*.tgz"))
if [[ \${#cnt_tgz[@]} -lt 3 ]]; then
echo "less"
else
rm "\${cnt_tgz[@]}"
echo "deleted"
fi
EOF
)"
touch "$tmp_dir/1.tgz"
ssh -t localhost "$ssh_cmd"
touch "$tmp_dir/2.tgz" "$tmp_dir/3.tgz"
ssh -t localhost "$ssh_cmd"
Le ls -t *.tgz
ne fonctionnera pas, car le globbing ne se produit que sur le système local. Utiliser également ls
pour compter les fichiers n'est pas une bonne idée, car il renvoie également des entrées telles que .
, ..
et des répertoires.
Je pense que cette citation compliquée est une preuve suffisante pour ne pas l'utiliser, mais utiliser un script à la place. Si vous souhaitez éviter plusieurs connexions ssh
name__, dirigez le script vers l'autre hôte et laissez-le s'exécuter en une seule commande:
Fichier local, dites myscript.sh
:
cd /var/www/test.com/backup;
if [ $(ls | wc -l) -lt 3 ]; then
echo "less"
Elif [ $(ls -t *.tgz|awk 'NR >3'|xargs rm -f) ]; then
echo "deleted"
else
echo "something else"
fi
Ensuite:
cat myscript.sh | \
ssh -t [email protected] \
"cat - > /tmp/ms.sh && sh /tmp/ms.sh && rm /tmp/ms.sh"
Ou (en évitant tilisation inutile du chat ):
ssh -t [email protected] \
"cat - > /tmp/ms.sh && sh /tmp/ms.sh && rm /tmp/ms.sh" \
< myscript.sh
Cela dirige le script local myscript.sh
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é les erreurs dans le script d'origine, mais je voulais simplement montrer l'idée. Aucune citation sujet aux erreurs n'est nécessaire et toutes les commandes du script sont exécutées du côté distant.
Je préférerais placer le script sur l'instance distante et simplement l'exécuter via ssh, mais voici ma suggestion: comment cela pourrait-il être réalisé comme vous le souhaitez:
#!/bin/bash
Host='[email protected]'
REMOTE_PATH='/var/www/test.com/backup'
COMMAND1="ssh \"$Host\" 'ls \"$REMOTE_PATH\" | wc -l'"
COMMAND2="ssh \"$Host\" 'ls -t \"$REMOTE_PATH\"/*.tgz'"
COMMAND3="xargs ssh \"$Host\" rm -rf"
if [[ $(eval "$COMMAND1") -le 3 ]]
then
echo "Less"
else
eval "$COMMAND2" | awk 'NR > 3' | eval "$COMMAND3" && echo "Deleted"
fi
Remarques:
-lt
est remplacée par -le
.eval
- construit une commande en concaténant des arguments.\"
dans l'expression $COMMAND{1..3}
, mais j'ai décidé de les ajouter.