2

I am writing a bash shell script that runs on a jump server. This has one parameter, which represents a string to be searched for. This parameter is worked into a `-surrounded command (command substitution) which does a grep for the search parameter in a bunch of files in a directory and pipes the result to wc -l. That is then worked into a quoted string which is passed as a command parameter:

ssh server "[grep command]"

That ssh command is executed in a loop that loops through all the servers we want to check.

Getting all the quoting right so that each element is not evaluated until its proper time was a major pain but I've almost got this crazy thing working.

Everything gets passed down to the proper server by ssh but when the command runs on the server, the result is

bash: /bin/echo "26520 instances of [xyz]": No such file or directory

The 26520 is the result of successfully running /bin/grep xyz /path/to/logfiles/*access*|wc -l

which was passed through as part of the command via ssh:

ssh server [command]

if I actually ssh to one of the remote servers and run

$ /bin/echo "26490 instances of [xyz]"
26520 instances of [xyz]

bash, of course has no problem.

if I actually ssh to one of the remote servers and run

$ /bin/echo "`/bin/grep xyz /path/to/logfiles/*access*|wc -l` instances of [xyz]"
26520 instances of [xyz]

bash also has no problem.

But when the command comes through ssh it has this problem - even though the grep command was executed and produced the correct result

bash: /bin/echo "26520 instances of [xyz]": No such file or directory

What exactly is bash objecting to and how may I get around this?

UPDATE: to simplify, I find I can replicate the problem by a one-line command line on the local server, abstracting away all the complications arising from scripts, variable substitutions etc.

$ ssh {remoteserver} "echo `/bin/grep xyz /path/to/logfiles/*access*|wc -l`"
grep: /path/to/logfiles/*access*: No such file or directory
26520

Again, bash is complaining about no such file (it exists nonetheless) and then going ahead and running the grep command and printing the correct result.

I have actually solved the problem now by rewriting my script to write all the commands for the remote servers to a file on the local server, after resolving the command line params, then piping the contents of the file to ssh:

echo ... > commandfile
cat commandfile | ssh -T ${SERVER}

I'd also tried the <

But I'd still like to know what bash was objecting to.

  • how can we reproduce your problem? I see a lot of text and that there is something wrong passed to bash, but without actual code, it is hard to guess what is wrong there. – Jakuje Feb 25 '17 at 19:13
  • Gave a more reproducible example. – Steve Cohen Feb 25 '17 at 19:32
  • That is different error then what was above. – Jakuje Feb 25 '17 at 19:45
1

Running

ssh {remoteserver} "echo `/bin/grep xyz /path/to/logfiles/*access*|wc -l`"

leads to running the subcommand on your local computer, not the remote one. It can be simply verified using

$ ssh host "echo `hostname`"
the local hostname

if you want to run the subcommand on the remote server, use apostrophes

$ ssh host 'echo `hostname`'
the remote hostname

but the error in the update is different then the original one ...

  • You're right, about my second example. In my original example the command was running on the remote server and printing the correct result even though it was complaining about it. I think in my first example it was running the command locally producing the error, but also shipping it to the remote server where it ran correctly. In any event my solution of writing all the commands out to disk and then piping its content out to the remote over ssh is probably the cleanest solution. – Steve Cohen Feb 25 '17 at 20:07
0
ssh server "[grep command]"

Variable and command substitutions ($variable, $(command), `command`) are performed inside double quotes, so if any $ or ` appears in [grep command], it's performed by the local shell before invoking ssh. Then, once the substitutions have been performed (running the grep command locally), ssh is called, to echo a string on the remote host.

Put the command to execute on the remote host in single quotes (i.e. apostrophes):

ssh server '[grep command]'

For simplicity, don't include any single quotes in the command. If you really need a single quote, you can include it as '\'' (single quote, backslash, single quote, single quote).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.