pass arguments to remote shell in ssh - bash

for example:
ssh localhost echo *([^.])
requires me to pass -O extglob to the remote shell bash like so:
ssh localhost -O extglob echo *([^.])
however, ssh then thinks the -O is for itself, so I try again:
ssh localhost -- -O extglob echo *([^.])
but then bash thinks -- is for itself.
how can I pass -O extglob to bash through ssh?
thanks.
update: i would prefer not to ask ssh to ask bash to launch another bash:
ssh yourserver bash -O extglob -c "'echo *([^.])'"

Update: As mentioned in the comments the extglob will lead to a syntax error. I've managed it by piping the command to stdin:
ssh yourserver -- bash -O extglob <<'EOF'
echo *([^.])
EOF
I would start an additonal shell remotely. Like this:
ssh yourserver bash -O extglob -c 'ls -al'
Although it is not required in this example I would advice you to use -- after ssh arguments (as you mentioned):
ssh yourserver -- bash -O extglob -c 'ls -al'
This will prevent ssh from parsing the command to execute remotely as arguments.
But you can also pass the option to the shell ssh itself starts for you using the shopt bash builtin. Note that ; separates the two commands.
ssh yourserver -- 'shopt -s extglob; ls -al'

Related

ssh: bash: line 5: syntax error near unexpected token `(' [duplicate]

for example:
ssh localhost echo *([^.])
requires me to pass -O extglob to the remote shell bash like so:
ssh localhost -O extglob echo *([^.])
however, ssh then thinks the -O is for itself, so I try again:
ssh localhost -- -O extglob echo *([^.])
but then bash thinks -- is for itself.
how can I pass -O extglob to bash through ssh?
thanks.
update: i would prefer not to ask ssh to ask bash to launch another bash:
ssh yourserver bash -O extglob -c "'echo *([^.])'"
Update: As mentioned in the comments the extglob will lead to a syntax error. I've managed it by piping the command to stdin:
ssh yourserver -- bash -O extglob <<'EOF'
echo *([^.])
EOF
I would start an additonal shell remotely. Like this:
ssh yourserver bash -O extglob -c 'ls -al'
Although it is not required in this example I would advice you to use -- after ssh arguments (as you mentioned):
ssh yourserver -- bash -O extglob -c 'ls -al'
This will prevent ssh from parsing the command to execute remotely as arguments.
But you can also pass the option to the shell ssh itself starts for you using the shopt bash builtin. Note that ; separates the two commands.
ssh yourserver -- 'shopt -s extglob; ls -al'

Variable doesn't expand while passing as a parameter to docker-compose command inside heredoc block

I was trying to run some docker-compose command over ssh using bash script like below. I mean I have an executable shell script deploy.sh which contains below code snippets
ssh -tt -o StrictHostKeyChecking=no root#142.32.45.2 << EOF
DIR=test
echo \${DIR}
docker-compose --project-name \${DIR} up -d
EOF
But the DIR variable doesn't get expanded while passing as a parameter to docker-compose. It executes like below. While echo \${DIR} gives correct output i.e test.
docker-compose --project-name ${DIR} up -d
ssh -tt -o StrictHostKeyChecking=no root#142.32.45.2 <<'EOF'
DIR=test
echo ${DIR}
docker-compose --project-name ${DIR} up -d
EOF
Get rid of the \$ - it is preventing your variable expansion. But on second review, I see that's your intention. If you want to prevent all variable expansion until your code gets executed on the remote host, try putting the heredoc word in quotes. That way, the $ gets passed to the script being passed to ssh.
As a second suggestion ( as per my comment below ), I would consider just sending a parameterized script to the remote host and then executing it ( after changing its permissions ).
# Make script
cat >compose.sh <<'EOF'
#!/bin/bash
DIR=$1
docker-compose --project-name $DIR
EOF
scp -o StrictHostKeyChecking=no compose.sh root#142.32.45.2:
ssh -o StrictHostKeyChecking=no root#142.32.45.2 chmod +x ./compose.sh \; ./compose.sh test

Bash Script: How to run command with $myVar as one of the arguments?

I have a bash script that SSHes into 2 machines and runs identical commands.
I'd like to store this in a var, but I'm not sure how to reference the contents of the var when running the command
ssh -o StrictHostKeyChecking=no ubuntu#123.123.123 -i ./travis/id_rsa <<-END
sudo su;
...
echo "Done!";
END
ssh -o StrictHostKeyChecking=no ubuntu#456.456.456 -i ./travis/id_rsa <<-END
sudo su;
...
echo "Done!";
END
I tried something like this but it didn't work:
script=$(cat <<-END
sudo su;
...
echo "Done!";
END
)
ssh -o StrictHostKeyChecking=no ubuntu#123.123.123 -i ./travis/id_rsa $script
ssh -o StrictHostKeyChecking=no ubuntu#456.456.456 -i ./travis/id_rsa $script
If I am at all able to understand what you are asking, you really don't want to put the commands in a variable.
for host in 123.123.123 456.456.456; do
ssh -o StrictHostKeyChecking=no ubuntu#"$host" -i ./travis/id_rsa<<-\____here
sudo -s <<-_________there
: your script goes here
________there
echo "Done."
____here
done
If you really wanted to assign a multi-line variable (but trust me, you don't) the syntax for that is simply
script='sudo -s <<\____there
: your commands
____there
echo "Done."'
But there really is no need to do this, andeit actually complicates things down the line. You see, passing in properly quoted strings as arguments to ssh is extremely tricky - you have the local shell and the remote shell and both require additional quoting or escaping in order to correctly pass through shell metacharacters; and the usual caveats with eval apply, only you are effectively running a hidden eval by way of passing in executable code as a string for the remote shell.
I believe you want to do something like this:
cmds="sudo bash -c 'command1; command2; command3;'"
ssh ... "$cmds"

Use Bash with script text from stdin and options from command line

I want to use /bin/bash (possibly /bin/sh) with the option -f passed to, and handled by, the script.
Precisely,
while getopts f OPT
do
case $OPT in
"f" ) readonly FLG_F="TRUE"
esac
done
if [ $FLG_F ]; then
rm -rf $KIBRARY_DIR
fi
and when these lines are in a file http://hoge.com/hoge.sh,
I can do this, for instance,
wget http://hoge.com/hoge.sh
/bin/bash hoge.sh -f
but not
/bin/bash -f hoge.sh
I know the reason but I want to do like this,
wget -O - http://hoge.com/hoge.sh | /bin/bash
with -f option for hoge.sh not for /bin/bash
Are there any good ways to do this?
/bin/bash <(wget -O - http://hoge.com/hoge.sh) -f
worked. but this is only for bash users, right?
Using bash you can do
wget -O - http://hoge.com/hoge.sh | /bin/bash -s -- -f
as with -s commands are read from the standard input. This option allows the positional parameters to be set too.
It should work with other POSIX shells too.

running a pipe command with variable substitution on remote host

I'd to run a piped command with variable substitution on a remote host and redirect the output. Given that the login shell is csh, I have to used "bash -c". With help from users nlrc and jerdiggity, a command with no variable substitution can be formulated as:
localhost$ ssh -f -q remotehost 'bash -c "ls /var/tmp/ora_flist.sh|xargs -L1 cat >/var/tmp/1"'
but the single quote above will preclue using variable substitution, say, substituting ora_flist.sh for $filename. how can I accomplish that?
Thanks.
Something like this should work:
ssh -f -q remotehost 'bash -c "ls /var/tmp/ora_flist.sh|xargs -L1 cat >/var/tmp/1"'
So your problem was that you want the shell variable to be extended locally. Just leave it outside the single quotes, e.g.
ssh -f -q remotehost 'bash -c "ls '$filename' | xargs ..."'
Also very useful trick to avoid the quoting hell is to use heredoc, e.g.
ssh -f -q remotehost <<EOF
bash -c "ls $filename | xargs ... "
EOF

Resources