Passing Bash Command Through SSH - Executing Variable Capture - bash

I am passing the following command straight through SSH:
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i /key/path server#111.111.111.111 'bash -s' << EOF
FPM_EXISTS=`ps aux | grep php-fpm`
if [ ! -z "$FPM_EXISTS" ]
then
echo "" | sudo -S service php5-fpm reload
fi
EOF
I get the following error:
[2015-02-25 22:45:23] local.INFO: bash: line 1: syntax error near unexpected token `('
bash: line 1: ` FPM_EXISTS=root 2378 0.0 0.9 342792 18692 ? Ss 17:41 0:04 php-fpm: master process (/etc/php5/fpm/php-fpm.conf)
It's like it is trying to execute the output of ps aux | grep php-fpm instead of just capturing git the variable. So, if I change the command to try to capture ls, it acts like it tries to execute that as well, of course returning "command not found" for each directory.
If I just paste the contents of the Bash script into a file and run it it works fine; however, I can't seem to figure out how to pass it through SSH.
Any ideas?

You need to wrap starting EOF in single quotes. Otherwise ps aux | grep php-fpm would get interpreted by the local shell.
The command should look like this:
ssh ... server#111.111.111.111 'bash -s' << 'EOF'
FPM_EXISTS=$(ps aux | grep php-fpm)
if [ ! -z "$FPM_EXISTS" ]
then
echo "" | sudo -S service php5-fpm reload
fi
EOF
Check this: http://tldp.org/LDP/abs/html/here-docs.html (Section 19.7)
Btw, I would encourage you to use $() instead of backticks consequently for command substitution because of the ability to nest them. You will have more fun, believe me. Check this for example: What is the benefit of using $() instead of backticks in shell scripts?

You should wrap the EOF in single quotes.
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i /key/path server#111.111.111.111 'bash -s' << 'EOF'
FPM_EXISTS=`ps aux | grep php-fpm`
if [ ! -z "$FPM_EXISTS" ]
then
echo "" | sudo -S service php5-fpm reload
fi
EOF

Related

How to run shell script via kubectl without interactive shell

I am trying to export a configuration from a service called keycloak by using shell script. To do that, export.sh will be run from the pipeline.
the script connects to k8s cluster and run the command in there.
So far, everything goes okay the export work perfectly.
But when I try to exit from the k8s cluster with exit and directly end the shell script. therefore it will move back to the pipeline host without staying in the remote machine.
Running the command from the pipeline
ssh -t ubuntu#example1.com 'bash' < export.sh
export.sh
#!/bin/bash
set -x
set -e
rm -rf /tmp/realm-export
if [ $(ps -ef | grep "keycloak.migration.action=export" | grep -v grep | wc -l) != 0 ]; then
echo "Another export is currently running"
exit 1
fi
kubectl -n keycloak exec -it keycloak-0 bash
mkdir /tmp/export
/opt/jboss/keycloak/bin/standalone.sh -Dkeycloak.migration.action=export -Dkeycloak.migration.provider=dir -Dkeycloak.migration.dir=/tmp/export -Dkeycloak.migration.usersExportStrategy=DIFFERENT_FILES -Djboss.socket.binding.port-offset=100
rm /tmp/export/master-*
exit
kubectl -n keycloak cp keycloak-0:/tmp/export /tmp/realm-export
exit
exit
scp ubuntu#example1.com:/tmp/realm-export/* ./configuration2/realms/
After the first exit the whole shell script stopped, the left commands doesn't work. it won't stay on ubuntu#example1.com.
Is there any solutions?
Run the commands inside without interactive shell using HEREDOC(EOF).
It's not EOF. It's 'EOF'. this prevents a variable expansion in the current shell.
But in the other script's /tmp/export/master-* will expand as you expect.
kubectl -n keycloak exec -it keycloak-0 bash <<'EOF'
<put your codes here, which you type interactively>
EOF
export.sh
#!/bin/bash
set -x
set -e
rm -rf /tmp/realm-export
if [ $(ps -ef | grep "keycloak.migration.action=export" | grep -v grep | wc -l) != 0 ]; then
echo "Another export is currently running"
exit 1
fi
# the suggested code.
kubectl -n keycloak exec -it keycloak-0 bash <<'EOF'
<put your codes here, which you type interactively>
EOF
mkdir /tmp/export
/opt/jboss/keycloak/bin/standalone.sh -Dkeycloak.migration.action=export -Dkeycloak.migration.provider=dir -Dkeycloak.migration.dir=/tmp/export -Dkeycloak.migration.usersExportStrategy=DIFFERENT_FILES -Djboss.socket.binding.port-offset=100
rm /tmp/export/master-*
kubectl -n keycloak cp keycloak-0:/tmp/export /tmp/realm-export
scp ubuntu#example1.com:/tmp/realm-export/* ./configuration2/realms/
Even if scp runs successfully or not, this code will exit.

Execute command with multiple layers of quoting via ssh

I want to execute a docker command on a remote server. The problem is I don't know to escape multiple quotes.
ret=$(ssh root#server "docker exec nginx bash -c 'cat /etc/nginx/nginx.conf | grep 'ServerName' | cut -d '|' -f1'")
I get
bash: -f1: command not found
There's little need to execute so much on the remote host. The file you want to search isn't likely that big: just pipe the entire thing down via ssh to a local awk process:
ret=$(ssh root#server "docker exec nginx cat /etc/nginx/nginx.conf" |
awk -F'|' '/ServerName/ {print $1}')
Wrap your parameter string with N calls to "$(printf "%q" ...)", for N recursive calls .
ssh root#server "docker exec nginx bash -c 'cat /etc/nginx/nginx.conf | grep ServerName | cut -d | -f1'"
How may recursive calls the above line has? I don't wish to set up docker just for the test, so I may have one of the following wrong:
ssh - certainly counts
docker - ??
ngix - ??
bash - certainly counts
If there are four, then you need four calls to "$(printf "%q "str")", don't forget to add all those " marks
ssh root#server docker exec nginx bash -c "$(printf "%q" "$(printf "%q" "$(printf "%q" "$(printf "%q" "cat /etc/nginx/nginx.conf | grep ServerName | cut -d | -f1")")")")"
Explanation: ssh parses the string like bash -c does, stripping one level of quotes. docker and nginx may also each parse the string (or not). Finally, bash -c parses whatever the previous levels have parsed, and removes the final level of quotes. exec does not parse the strings, it simply passes them verbatim to the next level.
Another solution is to put the line, that you want bash to execute, into a script. Then you can simply invoke the script without all this quoting insanity.
#!/bin/bash
< /etc/nginx/nginx.conf grep ServerName | cut -d | -f1
Consider using here-document :
ret="$(ssh root#server << 'EOF'
docker exec nginx bash -c "grep 'ServerName' /etc/nginx/nginx.conf | cut -d '|' -f1"
EOF
)"
echo "$ret"
Or, simpler as suggested by #MichaelVeksler :
ret="$(ssh root#server docker exec -i nginx bash << 'EOF'
grep 'ServerName' /etc/nginx/nginx.conf | cut -d '|' -f1
EOF
)"
echo "$ret"

Execute command in variable with bash through ssh

I face an issue while sending a command to a local variables in ssh. Actually my variable doesn't receive the expected execution of the coding instructions.
If someone has an idea about the good syntax to be applied...
ssh -T $HR_HST -l $HR_USR -q -o StrictHostKeyChecking=no <<END_SSH_0
HermesShowCmd="sfe in;fname=$INPUT_WPPComOutFile;node=$Node;format=1" #ok
$HermesFolder/hcl \$HermesShowCmd >> $HR_LOG/$HRM_LOG #ok
HermesStatus=`$HermesFolder/hcl "$HermesShowCmd" | grep "Taken: \.\.\." | wc -l` #KO... variable not updated...
echo "$(date) --HermesStatus=\$HermesStatus" >> $HR_LOG/$HRM_LOG
END_SSH_0

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

Running script through command

I'm trying to decode my password through a script while it's being run but it seems like the script is being run with a literal and the password is not processed. Is there a better way of doing this?
#!/bin/bash
MYENC="Tk9UX1RIQVRfU1RVUElEX0xPTAo="
rdesktop -u FOO -d mgmt -p 'echo $(echo $MYENC) | base64 --decode' 192.0.0.0
I also tried to just pass in a variable but that failed as well.
Try this instead:
#!/bin/bash
MYENC="Tk9UX1RIQVRfU1RVUElEX0xPTAo="
rdesktop -u FOO -d mgmt -p $(echo $MYENC | base64 --decode) 192.0.0.0
Note that I wrapped the juicy stuff echo...base64... in $(...). This is called "command substitution" - basically you're telling bash that you want the code inside the $(...) to be executed before the rest of the line, with the result substituted in its place. More info here: http://www.tldp.org/LDP/abs/html/commandsub.html
Or this
#!/bin/bash
MYENC="Tk9UX1RIQVRfU1RVUElEX0xPTAo="
rdesktop -u FOO -d mgmt -p $(base64 --decode <<< "$MYENC") 192.0.0.0

Resources