0

I have 2 systems and they have the same directory strcuture. I want to execute a couple of commands on local system and the same on remote system.

I use the wildcards so when I have a new version of package I do not need to edit bash script again!

My bash script has some lines like this:

varWheelsDir="/tmp/wheels"
set -x
# Install local
pip3 install --force-reinstall --user "${varWheelsDir}/bbw"*
# Install remote
ssh -t admin@otherhost "pip3 install --user '${varWheelsDir}/bbw$*'"

This expands too

+ pip3 install --user /tmp/wheels/bbw-2.10.0-py3-none-any.whl
+ ssh -t admin@otherhost 'pip3 install --user '\''/tmp/wheels/bbw'\'''

Which obviously the expand for SSH line does not work.

Any idea how can I feed that into ssh -t

DEKKER
  • 948
  • 8
  • 20

3 Answers3

2

Which obviously the expand for SSH line does not work.

Leaving aside the syntax issues in this statement, it is far from obvious that the expand "does not work", merely that it does not do what you expect. It would have been help if you had included HOW it was expanded and WHAT you expected.

I suspect that you mean you want the expansion to occur on the remote host and not at the ssh client. In which case you simply need to escape the argument you pass to the local shell - but you also need to change your quoting to allow expansion remotely:

ssh -t admin@otherhost "pip3 install --user \"\${varWheelsDir}/bbw\*\""
symcbean
  • 5,540
0

You have to check what parts get expanded when the ssh command is "build", whats the result, and what is expanded when the command is executed on the remote host.

For your first try

ssh -t admin@otherhost "pip3 install --user '${varWheelsDir}/bbw$*'"
# expands to
ssh -t admin@otherhost "pip3 install --user '/tmp/wheels/bbw'"
# and executes on the other host
pip3 install --user '/tmp/wheels/bbw'

$* expands to the positional parameters and you probably have none here. See https://www.gnu.org/software/bash/manual/html_node/Special-Parameters.html#index-_002a

If you do

ssh -t admin@otherhost "pip3 install --user '${varWheelsDir}/bbw'*"
# it should expand to
ssh -t admin@otherhost "pip3 install --user '/tmp/wheels/bbw'*"
# which executes on the other host
pip3 install --user '/tmp/wheels/bbw'*

(note that the is * is inside the double quotes to prevent globbing on the local host but outside the single quotes to do file globbing on the remote host)

I tired it with

x=/tmp
ssh -t otherhost "ls -l '$x/'*"

Worked for me and listed all directories in temp on remote host.

0

Many systems have AcceptEnv LC_* in their sshd configuration, so you can do:

export LC_DIR="$varWheelsDir"
shell_code='
  pip3 install --force-reinstall --user "$LC_DIR"/bbw*
'
eval "$shell_code" # interpreted by current shell

ssh -e SendEnv=LC_DIR -t admin@otherhost "$shell_code"

interpreted by the login shell of admin on otherhost,

assuming it is Bourne-like

With the same shell code run locally and remotely, and sharing a $LC_DIR variable with the same contents.

Alternatively, if the local shell is zsh and you know the login shell of admin on otherhost is Bourne-like, you can construct the shell code where the contents of the local $varWheelsDir variable is embedded and quoted in a safe way with:

pip3 install --force-reinstall --user "${varWheelsDir}"/bbw* # local
ssh -t admin@otherhost "
  pip3 install --force-reinstall --user ${(qq)varWheelsDir}/bbw"* # remote

Where ${(qq)var} quotes the contents of $var in sh syntax using single quotes (the safest form of quoting for arbitrary data).

Recent versions of bash have a ${var@Q} operator to expanded $var, quoted, but it produces non-portable bash-specific syntax in some circumstances, and not only using single quotes, so you can only use it if the login shell of admin on otherhost happens to be bash (preferably of the same version and running in the same locale).

If you can't guarantee the login shell of admin on otherhost is Bourne-like, see How to execute an arbitrary simple command over ssh without knowing the login shell of the remote user? for possible approaches.