SSH – How to Send a HEREDOC Over SSH to a Remote Host from a Local Script?

cshio-redirectionssh

I essentially want to run a script on machine A which will SSH into machine B, execute commands on B, and return the output to machine A.

So I am creating a csh script to do this, hopefully, if it's possible.

For instance, this solution from this answer works from command line:

ssh user@host << 'ENDSSH'
ls -l
ENDSSH

I can verify it is running the ls on the remote and not locally.

However I want to be able to do this within the backticks, inside my csh script running locally. Would that be possible?

I know it is possible to SSH in and run a script that is on the remote, but that is not my case.

I have also heard it is possible to send a second script stored locally over the SSH (which I also have not figured out), but I like the idea of having all of the commands inside the original script, hence the HEREDOC.

I know it is a pretty particular question, but if there is a way, it would be very cool to know how.

Things that don't work

1)

`ssh user@host<<'ENDSSH'`
`echo "ls -l"`
`echo "ENDSSH"`

This gives the error:

stty: standard input: Invalid argument.
stty: standard input: Invalid argument.
Warning: Command not found

And then it runs ls -l locally, and then it tried to run ENDSSH locally and of course fails with command not found.

2)

`ssh user@host<<'ENDSSH'`
echo "ls -l"
echo "ENDSSH"

Same problem as above, except it only displays ls -l and ENDSSH as text. Makes sense…since the HEREDOC portion failed.

3) 3-5 aren't exactly what I asked about, but still trying just to get even the basic case working.

`ssh user@host ls-l` 

This returns total: Command not found.
Yeah, I have no clue where that's coming from.

4)

`cat ./test.csh | ssh user@host`

Also returns the same as attempt #1

5)

`cat ./test.csh | ssh -t user@host`

Same as #1 and 4.

I am beginning to exhaust other solutions from stackoverflow/Ubuntu/serverfault…etc. Most people ask about how to run their script on a remote from command line, not how to run commands on a remote from a locally running script.

Edit

Well I think I have part of the problem figured out. With case 3 from above for example, what happens is ls -l runs locally, and the first part of the output is then sent over SSH as a command.

I noticed this because I tried ssh user@host $CMD, with $CMD set to "whoami". The output was username: Command not found, and then I realized the total is from the ls output. Still not sure about how to solve this, though

Best Answer

If you wrap the entire command that you want executed inside backticks it's likely you'll get the correct solution. There are issues regarding the evaluation of variables and other interpolated elements, but I'll put those to one side for a moment.

However, I'm not entirely sure why you want anything in backticks. Your Question says you want to run a local script remotely. Your first example does this.

ssh -q user@host << ENDSSH
hostname
ls -l
id
ENDSSH

Perhaps you want to get the output of the remote execution into a variable? It doesn't say that anywhere in the Question, but you'd do it like this (bash)

RESULT=$(ssh user@host <<ENDSSH
hostname
id
ENDSSH
)
...
echo "$RESULT"

Or, since you mentioned csh, like this

set result = `ssh -q user@host` <<ENDSSH
hostname
id
ENDSSH
...
echo "$result"

Note that for the csh variant all output lines are concatenated together.

I see that you have reported an error, stty: standard input: Invalid argument. This is probably occurring because you have an stty command in your login script on the remote server. This should be wrapped in a test for an interactive shell. In bash you would do something like this:

if test -n "$PS1"
then
    # Interactive setup here
    stty ...
fi
Related Question