1

I am trying to execute a bash shell script from Windows on a remote Linux machine.

I am using c# and the SSH.Net library.

The scripts live on the windows box and cannot be installed on the Linux machine. I read in the script using 'File.ReadAllText(...)' which loads in the script as string. Using SSH.Net I then execute the script on Linux:

        SshCommand cmd;
        using (var client = new SshClient(ConnectionInfo))
        {
            client.Connect();
            cmd = client.CreateCommand(string.Format("sh -x -s < {0}", script));                 
            cmd.Execute();
            client.Disconnect();
        }
        return cmd.ExitStatus;

This works when the script doesn't have any parameters. But if I need to pass in some arguments the following executes the script but the params are missing:

     cmd = client.CreateCommand(string.Format("sh -x -s p={0} < {1}", parameterString, script));

The sample script is:

#!/bin/bash
# check-user-is-not-root.sh

echo "Currently running $0 script"
echo "This Parameter Count is       [$#]"
echo "All Parameters            [$@]"

The output is:

Currently running bash script
This Parameter Count is     [0]
All Parameters          []

Update

For now I am using curl (like in the approved answer here:).

cmd = client.CreateCommand(string.Format("curl http://10.10.11.11/{0} | bash -s {1}", scriptName, args))

But I still think there must be a way to read in a bash script with arguments and run it across ssh on a remote Linux box.

Any help would be greatly appreciated.

Community
  • 1
  • 1
ozczecho
  • 8,649
  • 8
  • 36
  • 42

2 Answers2

1

Perhaps you are better off running ssh user@host 'command; another; more' or if you really have to use an explicit sh, something like ssh user@host "sh -c 'command; another; more'". That should also save you from putting the script in a temporary file.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • The scripts are pre-baked. They might be long. The c# app I am writing will be running these scripts with changing arguments on a remote linux box using ssh. My app will then analyse the results received. I am able to execute the script without any args, but if I pass in any command line arguments - they are ignored. – ozczecho Aug 22 '11 at 13:00
  • Curiously, at least on OSX, you have to combine `sh -c` and `-s` to get positional parameters. `sh -c 'echo $1' -s bar` produces `bar` but without the `-s` you get nothing. – tripleee Aug 22 '11 at 13:12
  • While there may be a limit on the command length, if you cannot store the scripts on the remote box, this is the way to go. Storing the scripts in `/tmp` and then executing them is hardly a sane or safe way to cope with this policy. – tripleee Aug 22 '11 at 13:16
  • I ended up using curl (like in the approved answer here: http://stackoverflow.com/questions/4642915/passing-parameters-to-bash-when-executing-a-script-fetched-by-curl). But I still think there must be a way to read in a bash script with arguments and run it across ssh on a remote Linux box. – ozczecho Aug 22 '11 at 22:58
  • I went down the /tmp dir way. Thanks everyone for looking into this. – ozczecho Aug 23 '11 at 05:15
0

I've done a little trouble-shooting, entirely off a linux box. I think that the I think that your problem is 'p='.

I put your test script in /tmp/script, and ran the following:

$ ssh 192.168.2.3 sh -s foo bar baz < /tmp/script
Currently running sh script
This Parameter Count is       [3]
All Parameters            [foo bar baz]

I also tried

$ ssh 192.168.2.3 sh -s p=foo bar baz < /tmp/script
Currently running sh script
This Parameter Count is       [3]
All Parameters            [p=foo bar baz]

... so I'm not entirely sure why you're seeing a parameter count of 0, you should be seeing at least 'p=' as a parameter. It looks like you're trying to specify the argument list using 'p=' but that's not necessary. Give it a try without that, and see what happens.

To be clear, '/tmp/script' is stored on my local linux box, not on the remote machine. Anything sent to the standard input of the ssh command will be sent to the remote machine and processed as its standard input of the command being executed, so I could have just as easily used the command

$ cat /tmp/script | ssh 192.168.2.3 sh -s foo bar baz
Barton Chittenden
  • 4,238
  • 2
  • 27
  • 46
  • Yeah that works, but thats because the script exists as a file on the linux box. In my scenario I will be storing the scripts in windows and using ssh to execute them on linux. The script variable in my code refers to the script content, not the script file name. – ozczecho Aug 22 '11 at 04:52
  • ... sorta. The '-s' argument to sh indicates that the script should come from stdin. – Barton Chittenden Aug 22 '11 at 12:55
  • 1
    In the command "ssh 192.168.2.3 sh -s foo bar baz < /tmp/script", only 'sh -s foo bar baz' is interpreted remotely. If you can generate that part as using string.Format, you should be home free... anything after '-s' will be interpreted as arguments to the script that you pass in via stdin. – Barton Chittenden Aug 22 '11 at 13:01