How do I use variable substitution in a remote ssh command when the variable value has spaces in it? - linux

I've got the following test script:
#!/bin/bash
ssh -o StrictHostKeyChecking=no root#192.168.1.10 'ls -l "aaa bbb.txt"'
domain="aaa bbb.txt"
ssh -o StrictHostKeyChecking=no root#192.168.1.10 \'ls -l "${domain}"\'
The first command without the $domain variable works fine. Returns:
-rw-rw-rw- 1 root root 7 Nov 21 22:49 aaa bbb.txt
What I can't figure out is the second command. Running it returns the following from the remote server: bash: ls -l aaa bbb.txt: command not found
If I leave off the escaped backticks (ssh -o StrictHostKeyChecking=no root#192.168.1.10 ls -l "${domain}") I get the following error:
ls: cannot access 'aaa': No such file or directory
ls: cannot access 'bbb.txt': No such file or directory
How can I use variable substitution with spaces in the variable value in a remote ssh command?
Thanks.

Related

Connect to two servers and get the data

I am writing a script to connect to server machine and get some data from that. My sequence of commands are as follows
ssh -tt user#server1 ssh -tt user#server2
cd dir1/dir2
ls -1t name* | head 1
the result from the last command should be printed after exit from the server
To run a command on the other sever, you need to use it as a parameter to ssh.
man ssh (abriviated with [...]):
Synopsis
ssh [...] destination [command]
[...]
If command is specified, it is executed on the remote host instead of a login shell.
To illustrate In the first step only the second command is converted to this form.
ssh -tt user#server1
ssh -tt user#server2 'cd dir1/dir2; ls -1t name* | head 1'
now the second one has to be quoted as well and used as parameter to the first login:
ssh -tt user#server1 "ssh -tt user#server2 'cd dir1/dir2; ls -1t name* | head 1'"
make sure to escape characters that are spacial in double quotes e.g. "\$"

why sh softlink to bash doesn't work? [duplicate]

I have a shell script which uses process substitution
The script is:
#!/bin/bash
while read line
do
echo "$line"
done < <( grep "^abcd$" file.txt )
When I run the script using sh file.sh I get the following output
$sh file.sh
file.sh: line 5: syntax error near unexpected token `<'
file.sh: line 5: `done < <( grep "^abcd$" file.txt )'
When I run the script using bash file.sh, the script works.
Interestingly, sh is a soft-link mapped to /bin/bash.
$ which bash
/bin/bash
$ which sh
/usr/bin/sh
$ ls -l /usr/bin/sh
lrwxrwxrwx 1 root root 9 Jul 23 2012 /usr/bin/sh -> /bin/bash
$ ls -l /bin/bash
-rwxr-xr-x 1 root root 648016 Jul 12 2012 /bin/bash
I tested to make sure symbolic links are being followed in my shell using the following:
$ ./a.out
hello world
$ ln -s a.out a.link
$ ./a.link
hello world
$ ls -l a.out
-rwx--x--x 1 xxxx xxxx 16614 Dec 27 19:53 a.out
$ ls -l a.link
lrwxrwxrwx 1 xxxx xxxx 5 May 14 14:12 a.link -> a.out
I am unable to understand why sh file.sh does not execute as /bin/bash file.sh since sh is a symbolic link to /bin/bash.
Any insights will be much appreciated. Thanks.
When invoked as sh, bash enters posix
mode after the startup files are read. Process substitution is not recognized in posix mode. According to posix, <(foo) should direct input from the file named (foo). (Well, that is, according to my reading of the standard. The grammar is ambiguous in many places.)
EDIT: From the bash manual:
The following list is what’s changed when ‘POSIX mode’ is in effect:
...
Process substitution is not available.

Bash: Running one command after another using string variable

I understand that running one command after another is done in bash using the following command
command1 && command2
or
command1; command2
or even
command1 & command2
I also understand that a command stored in a bash variable can be run by simply firing the variable as:
TestCommand="ls"
$TestCommand
Doing the above will list all the files in the directory and I have tested that it does.
But doing the same with multiple commands generates an error. Sample below:
TestCommand="ls && ls -l"
$TestCommand
ls: cannot access &&: No such file or directory
ls: cannot access ls: No such file or directory
My question is why is this happening and is there any workaround?
And before you bash me for doing something so stupid. The preceding is just to present the problem. I have a list of files in my directory and I am using sed to convert the list into a single executable string. Storing that string in a bash variable, I am trying to run it but failing.
When you put two command in a single string variable, it is executed as single command. so when you are using "$TestCommand" to execute two "ls" commands, it is executing only one(first) "ls" command. it considers && and ls(second) as argument of first ls command.
As your current working directory is not having any files named && and ls it is returning error :
ls: cannot access &&: No such file or directory
ls: cannot access ls: No such file or directory
So, basically your commands behaves like this
ls file1 file2 -l
and it will give you output like this if file1 and file2 exists:
HuntM#~/scripts$ ls file1 file2 -l
-rw-r--r-- 1 girishp staff 0 Dec 8 12:44 file1
-rw-r--r-- 1 girishp staff 0 Dec 8 12:44 file2
Now your solution:
You can create function OR one more script to execute 2 commands as below:
caller.sh
#!/bin/bash
myLs=`./myls.sh`
echo "$myLs"
myls.sh
#!/bin/bash
ls && ls -l

Remote SSH commands not working in Linux

Regardless of why, I am trying to write a script that will let me send a command to various addresses. There is a shared key for the user, so there is no need for logging in. But this isn't working.
So, the following will not work...
#!/bin/bash
ip=$1
shift
args="'$#'"
cmd="ssh user#$ip -C $args"
output=$($cmd)
If I execute it with the following:
./myscript.sh 10.0.1.2 /bin/ls -l /var
I get the error of "ls -l /var: No such file or directory"
If I run that command (ssh user#10.0.1.2 -C '/bin/ls -l /var'), it works fine.
What am I doing wrong? These are the same installs of RHEL6.
Apparently, the quotes were confusing bash. The following works...
ip=$1
shift
$(ssh -o ConnectTimeout=1 User#$ip "$#")

Shell script to compare remote directories

I have a shell script that I am using to compare directory contents. The script has to ssh to different servers to get a directory listing. When I run the script below, I am getting the contents of the server that I am logged into's /tmp directory listing and not that of the servers I am trying to ssh to. Could you please tell me what I am doing wrong?
The config file used in the script is as follows (called config.txt):
server1,server2,/tmp
The script is as follows
#!/bin/sh
CONFIGFILE="config.txt"
IFS=","
while read a b c
do
SERVER1=$a
SERVER2=$b
COMPDIR=$c
`ssh user#$SERVER1 'ls -l $COMPDIR'`| sed -n '1!p' >> server1.txt
`ssh user#$SERVER2 'ls -l $COMPDIR'`| sed -n '1!p' >> server2.txt
done < $CONFIGFILE
When I look at the outputs of server1.txt and server2.txt, they are both exactly the same - having the contents of /tmp of the server the script is running on (not server1 or 2). Doing the ssh +dir listing on command line works just fine. I am also getting the error "Pseudo-terminal will not be allocated because stdin is not a terminal". Adding the -t -t to the ssh command isnt helping either
Thank you
I have the back ticks in order to execute the command.
Backticks are not needed to execute a command - they are used to expand the standard output of the command into the command line. Certainly you don't want the output of your ssh commands to be interpreted as commands. Thus, it should work fine without the backticks:
ssh user#$SERVER1 "ls -l $COMPDIR" | sed -n '1!p' >>server1.txt
ssh user#$SERVER2 "ls -l $COMPDIR" | sed -n '1!p' >>server2.txt
(provided that double quotes to allow expansion of $COMPDIR are used).
first you need to generate keys to login to remote without keys
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub remote-host
then try to ssh without pass
ssh remote-host
then try to invoke in your script but first make sanity check
var1=$(ssh remote-host) die "Cannot connect to remote host" unless $var1;

Resources