Comment puis-je exécuter un script local sur une machine distante et inclure des arguments?

116

J'ai écrit un script qui fonctionne bien lorsqu'il est exécuté localement:

./sysMole -time Aug 18 18

Les arguments "-time" , "Aug" , "18" et "18" ont été transmis avec succès au script.

Désormais, ce script est conçu pour être exécuté sur une machine distante mais à partir d’un répertoire local de la machine locale. Exemple:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole

Cela fonctionne aussi très bien. Mais le problème se pose lorsque j'essaie d'inclure les arguments susmentionnés (-18 août 18-18) , par exemple:

ssh root@remoteServer "bash -s" < /var/www/html/ops1/sysMole -time Aug 18 18

Après avoir exécuté ce script, j'obtiens l'erreur suivante:

bash: cannot set terminal process group (-1): Invalid argument
bash: no job control in this shell

S'il vous plaît dites-moi ce que je fais mal, cela grandement frustrant.

AllenD
la source
1
"Bash -s" est l'un des moyens par lesquels vous pouvez exécuter un script à partir d'une entrée standard (c'est-à-dire un fichier).
AllenD

Réponses:

160

Vous étiez assez proche de votre exemple. Cela fonctionne très bien lorsque vous l'utilisez avec des arguments tels que ceux-ci.

Exemple de script:

$ more ex.bash 
#!/bin/bash

echo $1 $2

Exemple qui fonctionne:

$ ssh serverA "bash -s" < ./ex.bash "hi" "bye"
hi bye

Mais cela échoue pour ces types d'arguments:

$ ssh serverA "bash -s" < ./ex.bash "--time" "bye"
bash: --: invalid option
...

Que se passe-t-il?

Le problème que vous rencontrez est que l'argument, -timeou --timedans mon exemple, est interprété comme un basculement vers bash -s. Vous pouvez calmer le jeu bashen évitant de prendre l'un des arguments de ligne de commande restants pour lui-même à l'aide de l' --argument.

Comme ça:

$ ssh root@remoteServer "bash -s" -- < /var/www/html/ops1/sysMole -time Aug 18 18

Exemples

#1:

$ ssh serverA "bash -s" -- < ./ex.bash "-time" "bye"
-time bye

# 2:

$ ssh serverA "bash -s" -- < ./ex.bash "--time" "bye"
--time bye

# 3:

$ ssh serverA "bash -s" -- < ./ex.bash --time "bye"
--time bye

# 4:

$ ssh  < ./ex.bash serverA "bash -s -- --time bye"
--time bye

NOTE: Juste pour préciser que lorsque la redirection apparaît sur la ligne de commande, cela ne fait aucune différence, car il sshappelle quand même un shell distant avec la concaténation de ses arguments, la citation ne fait pas beaucoup de différence, sauf lorsque vous avez besoin de citer le shell distant. comme dans l'exemple n ° 4:

$ ssh  < ./ex.bash serverA "bash -s -- '<--time bye>' '<end>'"
<--time bye> <end>
slm
la source
4
vous êtes un génie! Que dois-je faire pour atteindre votre niveau? J'ai beaucoup de travail à faire. Merci beaucoup.
AllenD
14
@AllenD - continuez à poser des questions et essayez de participer autant que possible sur le site. J'essaie toujours d'apprendre quelque chose de nouveau chaque jour. Avant votre question, je ne savais pas comment faire cela non plus. 8-) Merci pour votre question!
slm
5
notez que la redirection peut apparaître n'importe où dans la commande: par exemple bash -s -- --time bye < ./ex.bashou même < ./ex.bash bash -s -- --time bye. En effet, le shell supprime d'abord l'instruction de redirection (peu importe où il se trouve dans la commande), puis configure la redirection, puis exécute le reste de la ligne de commande avec la redirection en place.
Lesmana
@ sim J'essaie de faire exactement la même chose, mais à partir d'un script, pas à partir de la ligne de commande. Une idée de comment faire cela? Pour une raison quelconque, inclure votre réponse exacte dans des backticks ne fonctionne pas du tout. Au lieu de cela, il exécute le script spécifié localement et le résultat est envoyé sous forme de commande à bash via ssh
krb686,
@ krb686 - Je le demanderais comme nouveau Q.
slm
5

Sur le traitement des arguments arbitraires

Si vous n'utilisez vraiment qu'une seule chaîne, c'est-à-dire. -time Aug 18 18, alors vous pouvez simplement le coder en dur, et les réponses existantes vous expliquent comment le faire correctement. Par contre, si vous devez transmettre des arguments inconnus (comme un message à afficher sur l’autre système ou le nom d’un fichier créé où les utilisateurs finaux peuvent contrôler son nom), vous devez faire preuve de la plus grande prudence.


Avec bashou kshcomme/bin/sh

Si votre télécommande /bin/shest fournie par bash ou ksh, vous pouvez effectuer les opérations suivantes en toute sécurité avec une liste d'arguments non fiables, de sorte que même les noms malveillants (comme $(rm -rf $HOME).txt) puissent être transmis comme arguments en toute sécurité:

runRemote() {
  local args script

  script=$1; shift

  # generate eval-safe quoted version of current argument list
  printf -v args '%q ' "$@"

  # pass that through on the command line to bash -s
  # note that $args is parsed remotely by /bin/sh, not by bash!
  ssh user@remote-addr "bash -s -- $args" < "$script"
}

Avec tout compatible POSIX /bin/sh

Pour vous protéger contre des données d’argument suffisamment malveillantes (pour tenter de tirer parti des guillemets non conformes à POSIX utilisés par printf %qin bash lorsque des caractères non imprimables sont présents dans la chaîne en cours d’échappement), même avec un /bin/shPOSIX de base (tel que dashou ash), devient un peu plus intéressant:

runRemote() {
  local script=$1; shift
  local args
  printf -v args '%q ' "$@"
  ssh user@remote-addr "bash -s" <<EOF

  # pass quoted arguments through for parsing by remote bash
  set -- $args

  # substitute literal script text into heredoc
  $(< "$script")

EOF
}

Utilisation (pour l'une ou l'autre des réponses ci-dessus)

Les fonctions données ci-dessus peuvent alors être appelées comme suit:

# if your time should be three arguments
runRemote /var/www/html/ops1/sysMole -time Aug 18 18

...ou...

# if your time should be one string
runRemote /var/www/html/ops1/sysMole -time "Aug 18 18"
Charles Duffy
la source
-3

dire aa est un fichier local qui contient ls

$ssh servername "cat | bash" < a.a

changer 127.0.0.1 en quelque soit votre adresse IP distante

ces deux donnent un message sur l'allocation de pseudo tty mais ils fonctionnent.

$ cat a.a | ssh 127.0.0.1

$ ssh 127.0.0.1 <a.a

Ou

$ cat a.a | ssh 127.0.0.1 bash or

$ ssh 127.0.0.1 bash < a.a

barlop
la source
2
J'ai du mal à voir dans quelle mesure cela répond à la question.
ChrisWue
La qualité et la mise en forme est douteuse. Je ne vois aucune nouvelle information utile qui ne soit pas présente dans la réponse acceptée non plus.
Julie Pelletier
@JuliePelletier J'ai donné des exemples de "chat" qui ne figurent pas dans la réponse acceptée. Il est bon de connaître des façons alternatives de faire les choses.
Barlop
Ce n'est pas une bonne chose tes chats sont inutiles.
Scott
2
Oh mon Dieu. J'ai laissé de côté le lien avec l' utilisation inutile du chat parce que je pensais que tout le monde en avait au moins entendu parler; apparemment c'était une mauvaise hypothèse de ma part.
Scott