SSH, Remote Commands and echo, oh my!

So, HostB has a SSH trust via pre-shared keys from HostA.

HostA> ssh HostB hostname
HostB

HostA> ssh HostB echo `hostname`
HostA

HostA> ssh HostB 'echo `hostname`'
`hostname`

HostA> ssh HostB "echo `hostname`"
HostA

HostA> ssh HostB echo $PS1
user@HostA:$PWD

HostA> ssh HostB 'echo $PS1'
$PS1

I'm at a loss for how to get these types of commands to run remotely. Echo seems to always interpret locally.

sshd_config is setup for PermitRootLogin forced-commands-only.

The authorized_keys is setup for command=$SSH_ORIGINAL_COMMAND ssh-dss <key> user@HostA

Just including that in case it's somehow causing my grief, though it seems more like quoting, trapping, etc.

The idea is this will be used on many systems to run a command, and it'd be nice to be able to prefix returns w/ a hostname for example.

Locally, I could run:

echo "`hostname`: `df -g /tmp|tail -1`"

and get

HostA : /dev/hd3 16.00 4.06 75% 7655 1% /tmp

So that way, if I script to run against a large amount of hosts, I get a hostname prefix for easy output reading.

Though the redirect also brings up another question.

If I do

HostA> ssh HostB cat /etc/passwd|grep user
user::100:100:<snip>

Is the grep happening remotely, or is the grep happening locally after the data is returned?

Thanks in advance for any insight you can offer.

Try this:

for server in "host1" host2" host3" ;

do
   ssh $server /usr/local/apache/bin/apachectl graceful
 done

Of course change the command to what ever you want. I am showing how to gracefully restart apache on the remote hosts. You can substitute that command with yours.

Jaysunn

Thanks for the reply.

Yes, I knew I could for loop commands, but the issue was trying to understand why echo is being interpreted locally.

What I've done in the mean time is write a sshpush wrapper that just pushes a script file remotely, executes it, then cleans it up afterwards.

It's not quite as nice IO wise, cause it takes a few scp/ssh commands to make it work, but it gets the job done. Can't seem to command stack via ssh delivered commands either:

ssh HostA hostname;hostname
Changes the remote hostname, and that's bad.

Where the expected output would be:
HostA
HostA

And yes, even if you trap the semi-colon, it just changes your hostname to \;

its because everything inside of the `'s are executed before leaving your host.

just do the ssh host command

risk@Heavyarms [164] --> ssh zhilliard@xxxxxxx hostname;hostname
zhilliard@xxxxxxx's password:
li27-239
Heavyarms
-(~/work/sun6kchassis/working)------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------(15:19 Mon Jul 20)
risk@Heavyarms [165] -->

This is because your system is resolving the variable before it sends the command so:

HostA# ssh HostB "echo $HOSTNAME"

is sending the command "echo HostA" to HostB, which it is doing. One thing you can do is put a backslash before the dollar sign:

HostA# ssh HostB "echo \$HOSTNAME"

This will send the command "echo $HOSTNAME" to HostB. This doesn't work with single quotes though. I got around it recently by doing this:

remotecmd=      "echo -n 'The hostname of this computer is ';
               echo \$HOSTNAME"
ssh HostB $remotecmd

which would return:

The hostname of this computer is HostB

or..

-bash-3.2$ ssh -l myid host2 "echo \`hostname\`"
host2
-bash-3.2$ hostname
host1
-bash-3.2$

why would you not just do ssh id@server hostname

[risks-macbook] ~ > hostname
risks-macbook
[risks-macbook] ~ > ssh risk@xxxx.com hostname
risk@xxxx.com's password: 
li27-239
[risks-macbook] ~ > ssh risk@xxxx.com hostname
risk@xxxx.com's password: 
li27-239
[risks-macbook] ~ > 

the topic is about "echo" running locally

Right.

And what happens if you use the example:

ssh HostB "echo \`hostname\`"

You get a literal return of:

`hostname`

Not HostB

why don't you try it first and see for yourself. The escape char is used to prevent "hostname" from being evaluated from the current system instead passed to the target host

Why are you echoing.... JUST RUN THE COMMAND.

ssh HostB hostname

it will ssh and then execute the command, I dont understand why this is hard?

#10 - I did try it myself, that wasn't theory I replied w/ there, that was the actual results.

#11 - Of course I can just execute hostname and be done. Hostname is just a simple return command to test it w/.

The question is why can you not send echo remotely. It's used in many processes. What if I just wanted to check a remote environment variable across a span of hosts, you would think you could ssh a "echo $PATH" for example and see the remote path, but that would just print the local path.

Hostname itself isn't the goal, it's just a easy targeted command to identify if your results are actually remote or local.

Mass change a user's password? ssh HostA "echo user:tmppass|chpasswd", etc. Lots of uses for echo.

I've moved to making a script and pushing it remotely for the time being, and that's working, I'm just trying to gain an understanding here.

yes, i do understand your problem. if you want to pass the command to the target host machine you need to passed it like a regular string since you're using ssh.

the single qoute will probably do it for you or double qoutes plus escape char.

-bash-3.2$ ssh -l testid xav10-m 'echo $HOME'
/root/home/testid
-bash-3.2$ pwd
/home/erm/testid

some more testing

-bash-3.2$ ssh -l testid xav10-m 'echo \$HOME'
$HOME
-bash-3.2$ ssh -l testid xav10-m "echo \$HOME"
/root/home/testid
-bash-3.2$ echo $HOME
/home/erm/testid
-bash-3.2$ ssh -l testid xav10-m "echo $HOME"
/home/erm/testid
-bash-3.2$

the last testing says something like "hostA, process this and passed it to hostB" whereas the first testing would mean "passed this literal string and let hostB do the rest."

hope this helps you