web-dev-qa-db-fra.com

Citant dans SSH $ Host $ FOO et SSH $ hôte "Sudo SU User -C $ FOO" Type constructions

Je finis souvent par émettre des commandes complexes sur SSH; Ces commandes impliquent une tuyauterie à une oncle AWK ou PERL, et, par conséquent, contiennent des devis simples et $. Je n'ai pas été capable de trouver une règle difficile et rapide pour faire la citation correctement, ni trouver une bonne référence pour cela. Par exemple, considérons les éléments suivants:

# what I'd run locally:
CMD='pgrep -fl Java | grep -i datanode | awk '{print $1}'
# this works with ssh $Host "$CMD":
CMD='pgrep -fl Java | grep -i datanode | awk '"'"'{print $1}'"'"

(Notez les citations supplémentaires dans la déclaration AWK.)

Mais comment puis-je obtenir cela pour travailler avec, par exemple. ssh $Host "Sudo su user -c '$CMD'"? Y a-t-il une recette générale pour gérer des citations dans de tels scénarios? ..

31
Leo Alekseyev

Comme - Chris Johnson décrit très bien , vous avez quelques niveaux d'indirectement cité ici; Vous demandez à votre local Shell _ d'instruire la télécommande Shell via ssh _ il doit instruire Sudo d'instruire su pour instruire la télécommande Shell pour exécuter votre pipeline pgrep -fl Java | grep -i datanode | awk '{print $1}' comme user. Ce genre de commandement nécessite beaucoup de fastidieux \'"quote quoting"\'.

Si vous prenez mon conseil, vous aurez goûté à tous les non-sens et faites:

% ssh $Host <<REM=LOC_EXPANSION <<'REMOTE_CMD' |
> localhost_data='$(commands run on localhost at runtime)' #quotes don't affect expansion
> more_localhost_data="$(values set at heredoc expansion)" #remote Shell will receive m_h_d="result"
> REM=LOC_EXPANSION
> commands typed exactly as if located at 
> the remote terminal including variable 
> "${{more_,}localhost_data}" operations
> 'quotes and' \all possibly even 
> a\wk <<'REMOTELY_INVOKED_HEREDOC' |
> {as is often useful with $awk
> so long as the terminator for}
> REMOTELY_INVOKED_HEREDOC
> differs from that of REM=LOC_EXPANSION and
> REMOTE_CMD
> and here you can | pipeline operate on |\
> any output | received from | ssh as |\
> run above | in your local | terminal |\
> however | tee > ./you_wish.result
<desired output>

Pour plus d'informations:

Consultez mon (peut-être trop long) de réponse à pistes de tuyauterie avec différents types de guillemets pour la substitution SLASH dans lequel je discute de la théorie de la raison pour laquelle cela fonctionne.

-Mike

2
mikeserv

Que diriez-vous d'utiliser plus de citations supplémentaires?

Ensuite, votre ssh $Host $CMD Devrait fonctionner simplement avec celui-ci:

CMD="pgrep -fl Java | grep -i datanode | awk '{print $1}'"

Maintenant, au plus complexe, le ssh $Host "Sudo su user -c \"$CMD\"". Je suppose que tout ce que vous avez à faire est d'échapper aux personnages sensibles dans CMD: $, \ Et ". Je vais donc essayer de voir si cela fonctionne: echo $CMD | sed -e 's/[$\\"]/\\\1/g'.

Si cela semble bien, enveloppez l'écho + sed dans une fonction de coquille et vous êtes prêt à partir avec ssh $Host "Sudo su user -c \"$(escape_my_var $CMD)\"".

0
alex