Using SED in a ssh command on a remote node - bash

I wrote a script to ssh to some nodes and run a sed command inside the node. The script looks like
NODES="compute-0-3"
for i in $NODES
do
echo $i
ssh $i 'sed -i \'s/172.16.48.70/172.20.54.10/g\' /etc/hosts;'
done
However, the error is
unexpected EOF while looking for matching `''
syntax error: unexpected end of file
It seems that the character ' is not treated as the begining of a sed command.

I suggest to replace
ssh $i 'sed -i \'s/172.16.48.70/172.20.54.10/g\' /etc/hosts;'
by
ssh "$i" 'sed -i "s/172.16.48.70/172.20.54.10/g" /etc/hosts'
If you absolutely want to use single quotes:
ssh "$i" 'sed -i '"'"'s/172.16.48.70/172.20.54.10/g'"'"' /etc/hosts'

Related

OS version capture script - unexpected results when using awk

I have a small shell script as follows that I am using to login to multiple servers to capture whether the target server is using Redhat or Ubuntu as the OS version.
#!/bin/ksh
if [ -f $HOME/osver.report.txt ];then
rm -rf $HOME/osver.report.txt
fi
for x in `cat hostlist`
do
OSVER=$(ssh $USER#${x} "cat /etc/redhat-release 2>/dev/null || grep -i DISTRIB_DESCRIPTION /etc/lsb-release 2>/dev/null")
echo -e "$x \t\t $OSVER" >> osver.report.txt
done
The above script works, however, if I attempt to add in some awk as shown below and the server is a redhat server...my results in the osver.report.txt will only show the hostname and no OS version. I have played around with the quoting, but nothing seems to work.
OSVER=$(ssh $USER#${x} "cat /etc/redhat-release | awk {'print $1,$2,$6,$7'} 2>/dev/null || grep -i DISTRIB_DESCRIPTION /etc/lsb-release 2>/dev/null")
If I change the script as suggested to the following:
#!/bin/bash
if [ -f $HOME/osver.report.txt ];then
rm -rf $HOME/osver.report.txt
fi
for x in cat hostlist
do
OSVER=$(
ssh $USER#${x} bash << 'EOF'
awk '{print "$1,$2,$6,$7"}' /etc/redhat-release 2>/dev/null || grep -i DISTRIB_DESCRIPTION /etc/lsb-release 2>/dev/null
EOF
)
echo -e "$x \t\t $OSVER" >> osver.report.txt
done
Then I get the following errors:
./test.bash: line 9: unexpected EOF while looking for matching `)'
./test.bash: line 16: syntax error: unexpected end of file
You're suffering from a quoting problem. When you pass a quoted command to ssh, you effectively lose one level of quoting (as if you passed the same arguments to sh -c "..."). So the command that you're running on the remote host is actually:
cat /etc/redhat-release | awk '{print ,,,}' | grep -i DISTRIB_DESCRIPTION /etc/lsb-release
One way of resolving this is to pipe your script into a shell, rather than passing it as arguments:
OSVER=$(
ssh $USER#${x} bash <<'EOF'
awk '{print "$1,$2,$6,$7"}' /etc/redhat-release 2>/dev/null ||
grep -i DISTRIB_DESCRIPTION /etc/lsb-release 2>/dev/null
EOF
)
The use of <<'EOF' here inhibits any variable expansion in the here document...without that, expressions like $1 would be expanded locally.
A better solution would be to look into something like ansible which has built-in facilities for sshing to groups of hosts and collecting facts about them, including distribution version information.

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

Passing link parameters via sed

I'm trying to insert an image link into a file for a wiki on a remote server.
ssh root#10.10.10.1 "sed -i -e '1i'[^http://10.10.10.2/image.jpg^]'\'" /var/www/wiki/page
Works but I need to add the resize parameter after the file name but it doesn't work, how do I account for the spaces?
ssh root#10.10.10.1 "sed -i -e '1i'[^http://10.10.10.2/image.jpg height480 width=640^]'\'" /var/www/wiki/page
sed: can't read height480: No such file or directory
sed: can't read width=640^]\: No such file or directory
I'm not sure why you're quoting only the '1i'. You should quote the entire sed expression, if you have spaces in it. Try this:
ssh root#10.10.10.1 "sed -i -e '1i[^http://10.10.10.2/image.jpg height480 width=640^]'" /var/www/wiki/page
Better use heredoc here to avoid crazy escaping and other issues like spaces in command:
ssh -t -t root#10.10.10.1 <<'EOF'
sed -i '1i[^http://10.10.10.2/image.jpg height480 width=640^]' /var/www/wiki/page
exit
EOF

bash cat a file from a another server to a variable

i am trying to do a basic command of cat to a variable and it does not work..
lines="not working"
sshpass -p triltest ssh root#ILCFS 'cat /var/try/check ' > $lines
echo $lines
./script.sh: line 34: $lines: ambiguous redirect
not working
the file exists. can anyone help me please?
Use `command` or $(command). I.e.
lines=$(sshpass -p triltest ssh root#ILCFS 'cat /var/try/check ')
echo "$lines"

Deleting word from line on remote server

I am trying to delete a word from bash profile on remote server but the command never come out.
ssh -X test_server 'sed -e \'s/unalias ls//g\' -i .bash_profile' </dev/null
Not sure what i am doing wrong, Kindly assist.
It's not possible to nest single quotes in shell, switching to double quotes should give you the desired result. E.g.:
$ ssh somehost sh <<< 'echo "Xunalias lsX" | sed -e "s/unalias ls//"'
XX

Resources