SSH Remote Store Command Result In Variable [duplicate] - bash

This question already has answers here:
How to cat <<EOF >> a file containing code?
(5 answers)
Closed 7 years ago.
I'm trying to run a bash script that ssh's onto a remote host and stops the single docker container that is running.
#!/usr/bin/env bash
set -e
ssh <machine> <<EOF
container=$(docker ps | awk 'NR==2' | awk '{print $1;}')
docker stop $container
EOF
However, I get the following error:
stop.sh: line 4: docker: command not found
When I do this manually (ssh to the machine, run the commands) all is fine, but when trying to do so by means of a script I get the error. I guess that my command substitution syntax is incorrect and I've searched and tried all kinds of quotes etc but to no avail.
Can anyone point me to where I'm going wrong?

Use <<'EOF' (or <<\EOF -- quoting only the first character will have the same effect) when starting your heredoc to prevent its expansions from being evaluated locally.
BTW, personally, I'd write this a bit differently:
#!/bin/sh -e
ssh "$1" bash <<'EOF'
{ read; read container _; } < <(docker ps)
docker stop "$container"
EOF
The first read consumes the first line of docker ps output; the second extracts only the first column -- using bash builtins only.

Related

Sudo throws error while reading a file post changing the user [duplicate]

This question already has answers here:
When to wrap quotes around a shell variable?
(5 answers)
Escaping a dollar sign in Unix inside the cat command
(2 answers)
Useless use of cat?
(9 answers)
In a PHP / Apache / Linux context, why exactly is chmod 777 dangerous?
(4 answers)
Closed 3 years ago.
Logging into the shell as a normal user and I am hitting a DB and storing the output to a file. Then within the script and changing into root user(sudo su) and then trying to access the file. But am getting error.
pro=$(sqlplus <code goes here>)
echo $pro > pro.txt
chmod 777 pro.txt
sudo su <<Here
cat pro.txt
total=$(cat pro.txt|tr -cd ' \t' | wc -c)
echo $total
i=1
provide=$(cat pro.txt|awk -v var=$i '{print $var}')
Output received :
no output came for "echo $total"
last line get error as "bash: line 10: azure: command not found"
The same script got executed when i didnt get changed to root user.
It is not clear what you are trying to do or where the azure text is coming from; but my understanding is that the text comes from the output of the SQL command and then gets evaluated because you are not quoting it properly.
See When to wrap quotes around a shell variable? or simply submit your code to http://shellcheck.net/ before asking for human review.
The following attempts to fix the broken quoting, the incorrect permissions, and the multiple useless cats.
# Don't capture to a variable; simply write directly to a file
# This also coincidentally removes one instance of broken quoting
sqlplus <code goes here> >pro.txt
# Don't use insecure permissions
chmod 644 pro.txt
# Add missing Here terminator at the end; backslash causes code to be run by su
sudo su <<\Here
cat pro.txt
# Avoid useless cat
total=$(tr -cd ' \t' <pro.txt| wc -c)
# Fix quoting
echo "$total"
i=1
# Fix quoting and useless cat
provide=$(awk -v var="$i" '{print $var}' pro.txt)
# Add missing Here terminator
Here
This code doesn't do anything useful because the variables will be gone when the sudo su subshell exits, so there is probably more work to be done. Perhaps ask a new question where you explain what you hope to actually accomplish.
A particularly pesky problem was the lack of quoting around the here document terminator. Without it, the command substitutions would be executed by the current shell. Let me demonstrate:
sudo su <<Here
echo $(who am i)
Here
The output is you, not root, because the command substitution $(who am i) is evaluated by your current shell before sudo su runs. Quoting or backslashing the string after << disables this expansion, and passes the entire here document verbatim as standard input to sudo su. See also Escaping a dollar sign in Unix inside the cat command

Syntax error when using sudo to execute a script [duplicate]

This question already has answers here:
Difference between sh and Bash
(11 answers)
Closed 4 years ago.
I encounter a problem when launching a script using sudo, though I have no problem and the script works fine without sudo.
The Line is :
mapfile -t dataList< <( tac /tmp/result.log | grep 'Command' | cut -d" " -f1 )
The error is "Syntax error near the unexpected symbol " < ".
The sudo command is :
sudo -u victor /tmp/parse.sh
Thank you all for help...
Sounds like a different shell is executing your script, one which doesn't understand the used syntax.
Your script /tmp/parse.sh might lack the #!/bin/bash (or similar) in its head line, and a different shell (root's login shell?) might be used to execute it.
This could be fixed by adding the missing #! line in the script header (recommended), or by calling the shell explicitly:
sudo -u victor bash /tmp/parse.sh

Printing to console doesnt work when substituting variable within another variable in bash [duplicate]

This question already has answers here:
Are shell scripts sensitive to encoding and line endings?
(14 answers)
Closed 4 years ago.
I am observing a weird issue where when I substitute a variable(A) within another variable(B) and print variable B , the console output is messed up.
docker_command="docker ps | grep consul | awk '{print \$1}'"
container_id=$(execute_command_on_host $IP $USER_NAME $USER_PASSWD "$docker_command")
echo "container_id: $container_id"
service_command="docker exec "$container_id" consul catalog services"
echo "service_command: $service_command"
#run script
Output:
container_id: 411d55019dba
consul catalog servicesommand: docker exec 411d55019dba
The last line of the output is messed up and sort of jumbled. But the same script if I run directy using the container_id then it works
container_id="411d55019dba"
service_command="docker exec "$container_id" consul catalog services"
echo "service_command: $service_command"
#run script
Output:
service_command: docker exec 411d55019dba consul catalog services
I feel I am missing out on something very simple. Would appreciate any help
I have tried the following and it worked for me.
docker_command="docker ps | awk '/consul/{print \$1}' | tr -d '\r\n'"
Line encoding seemed to be the issue

Obtain the last command executed by bash, inside a perl script [duplicate]

This question already has answers here:
What's the difference between Perl's backticks, system, and exec?
(5 answers)
How can I store Perl's system function output to a variable?
(8 answers)
Closed 5 years ago.
I would like to write a perl script that do something similar to what fc do. Indeed I want to edit programmatically the last command executed.
Something like this should work
perl -wle 'print system("/bin/bash", "-i", "-c", "history | tail -n 1")'
but system return the exit status of the command executed, not the stdout, that is what I want, while I'm not able to activate the history (-i flag) using back-tic, qx// or opening a pipe.
I know that using back-tic, qx// or opening a pipe it is simple to read the stdout of the command, but int this case how to use the builtin bash hisotry command properly?
Even using system and passing -i to bash, I'm not able to get the expected output from history | tail -n 1. Bi redirecting the output to a file I found its content empty.
perl -wle 'print system("/bin/bash", "-i", "-c", "history | tail -n 1 > /tmp/pippo")'
So am I forced to write the bash history on a file whit history -w and to read that file inside perl?
Use qx to capture shell command output. Read the ~/.bash_history file directly since you cannot capture the output of the shell builtin function history.
You may need to add history -a to your .bashrc file to get bash to write the history file after every command, or add history -w to your bash PROMPT_COMMAND. Other settings are covered nicely over at unix.stackexchange.com.
$ echo "foo"
foo
$ perl -e 'chomp(my $cmd = qx(tail -n 1 ~/.bash_history)); print "$cmd bar\n";'
echo "foo" bar

gnome terminal tabs open multiple ssh connections

I have a file with a list of servers:
SERVERS.TXT:
192.168.0.100
192.168.0.101
192.168.0.102
From a gnome terminal script, I want open a new terminal, with a tab for each server.
Here is what I tried:
gnome-terminal --profile=TabProfile `while read SERVER ; do echo "--tab -e 'ssh usr#$SERVER'"; done < SERVERS.TXT`
Here is the error:
Failed to parse arguments: Argument to "--command/-e" is not a valid command: Text ended before matching quote was found for '. (The text was ''ssh')
Tried removing the space after the -e
gnome-terminal --profile=TabProfile `while read SERVER ; do echo "--tab -e'ssh usr#$SERVER'"; done < SERVERS.TXT`
And I get a similar error:
Failed to parse arguments: Argument to "--command/-e" is not a valid command: Text ended before matching quote was found for '. (The text was 'usr#192.168.0.100'')
Obviously there is a parsing error since the the shell is trying to be helpful by using the spaces to predict and place delimiters. The server file is changed without notice and many different sets of servers need to be looked at.
I found this question while searching for an answer to the issue the OP had, but my issue was a little different. I knew the list of servers, they where not in a file.
Anyway, the other solutions posted did not work for me, but the following script does work, and is what I use to get around the "--command/-e" is not a valid command" error.
The script should be very easy change to suit any need:
#!/bin/sh
# Open a terminal to each of the servers
#
# The list of servers
LIST="server1.info server2.info server3.info server4.info"
cmdssh=`which ssh`
for s in $LIST
do
title=`echo -n "${s}" | sed 's/^\(.\)/\U\1/'`
args="${args} --tab --title=\"$title\" --command=\"${cmdssh} ${s}.com\""
done
tmpfile=`mktemp`
echo "gnome-terminal${args}" > $tmpfile
chmod 744 $tmpfile
. $tmpfile
rm $tmpfile
Now the big question is why does this work when run from a file, but not from within a script. Sure, the issue is about the escaping of the --command part, but everything I tried failed unless exported to a temp file.
I would try something like:
$ while read SERVER;do echo -n "--tab -e 'ssh usr#$SERVER' "; \
done < SERVERS.txt | xargs gnome-terminal --profile=TabProfile
This is to avoid any interpretation that the shell could do of the parameters (anything starting with a dash).
Because it is concatenating strings (using -n), it is necessary to add an space between them.
Is this a problem of parsing command-line options? Sometimes if you have one command sending arguments to another command, the first can get confused. The convention is to use a -- like so:
echo -- "--tab -e 'ssh usr#$SERVER'";
Try to type
eval
before gnome terminal command.
it should be something like this:
eval /usr/bin/gnome-terminal $xargs
worked for me!

Resources