Need help automating SSH commands using SU

Mar 24, 2011 at 5:33 PM

Hello,

I am trying to automate a series of commands for a remote *nix device.  Because of the nature of this device, I do not have the ability to login as the root user.
In addition, the utility we are tyring to run for data collection requires the use of the "su" command.

Here is an example of the commands the way they look in a shell such as PUTTY:

admin@device1:~$ su

Password:

bash-3.1# su -

root@device1:~#  /usr/app/bin/{command here}

Diagnostics : Version 1.0

2011-Mar-23 22:27:53.131 Shell: list users

USER1
USER2
USER3
USER4

2011-Mar-23 22:27:53.131 Shell: list users user1

USERNAME
EMAIL
ETC

2011-Mar-23 22:27:53.131 Shell: exit

What I basically need to be able to do is automate that process, such that the user is logged in and the su command is run.  Then, we run the {command} to access the diagnostics application.  Once inside the diagnostics application, we would run another series of commands such as "List Users", then output all that data, make decisions, then send the next command such as "list users user1". 

Any help would be greatly appreciated.

Coordinator
Mar 24, 2011 at 6:30 PM

Hi,

 

Well in theory it is possible to automate everything the question is which approach will work.

So as simple as executing the command it will not work since it doesnt keep session between command execution.

So if you cannot create a script on the server that will do the job for you or provide everything you need to do in one command line then you can try different approiach.

I created this as an option for future development and to see since I was curious what will happend but I think it might help in your case.

I thought once of a way to provide an input stream and to use this input stream as an input for a shell. Mostly it works but I didnt take it any further.

            using (var ssh = new SshClient(connectionInfo))
            {
                ssh.Connect();
                var input = new MemoryStream(Encoding.ASCII.GetBytes("sudo ufw status\r\nPassword\r\n"));
                //var input = Console.OpenStandardInput();
                var shell = ssh.CreateShell(inputConsole.OutConsole.Out"xterm"8024800600"");
                shell.Stopped += delegate(object senderEventArgs e)
                {
                    Console.WriteLine("\nDisconnected...");
                };
                shell.Start();
                Thread.Sleep(1000 * 1000);
                shell.Stop();
            }

This is how I use it in my case.

You can replace inputs and then you will have simple telnet client.

Stopped event will be fired when shell is finished, usually when you call "exit" command.

 

Let me know if you have any more question or have some ideas on how and where to take this Shell implementation further.

Also, you  would need to get latest version that I just checked in since I had an error when printing out results back.

 

Hope it helps,

Thanks,

Oleg

Mar 24, 2011 at 7:09 PM

Thanks Oleg,

I saw your same approach earlier on one of the other posts, however I couldn't get this to work.  I will try getting latest, but my question is - how would I send the commands if I want it automated.
This approach seems to be designed to provide a 'terminal' type of interface.  I need this to be an interactive approach where my application can send a command, listen, make a decision, then send another command.

Looking for your reply.

Coordinator
Mar 24, 2011 at 7:15 PM

Unfortunalty I dont thing it will be possible,

At least at the momen, or may be I dont know how to achive that.

The reason is that SSH protocol.

To perform different task in SSH you open channels by issueing differnt channel requests.

One that I am using to run commands only run one command at a time, and this is protocol restrication, as far as I know.

Another possibility is to open shell channel, this is what I did in the example above, but then there is no way to capture the output result, at least not the easy one.

Of course its possible to analyze output and then to do something as a response but that will be messy.

I was trying to see if I can open a channel as a SU account but couldnt find a way around that, at least not so far :(

 

Mar 24, 2011 at 8:03 PM

Is it possible to just send a series of commands, without analyzing the output until the end?

Coordinator
Mar 24, 2011 at 8:27 PM

yes,

in fact you can execute as many commands as you want, as long as it one command execution, so for example you do this:

var cmd = s.CreateCommand(string.Format("echo aaaaaa;sleep 60s;exit 16"));
as long as you separate them by ";"

 

Oleg

Mar 24, 2011 at 8:54 PM

Ok, I tried your suggestion, however it now errors with an ExitStatus of 0 but the Result object is throwing a NullReferenceException.

Where should the "output" of the commands be stored?

Coordinator
Mar 29, 2011 at 7:21 PM

Sorry for late response, was out for the weekend.

Command output is stored in Result property.

If you need to access output as a stream you can use OutputStream. If additional output is available, for example, debug info, then you can access it using ExtendedOutputStream property.

 

Let me know if you have any more questions.

 

Thanks,

Oleg

Jun 6, 2012 at 10:51 PM

Not sure if this helps, i process the following to run commands as su and echo the password in using  -S

.CreateCommand ( string.Format ( "echo {0} | sudo -S {1}" , sudoPassword , command ) );

 

//Here is an example i use this to simulate network failure on a system for testing some code

.CreateCommand ( "echo sudoPassword | sudo -S ifdown eth0;sleep 10s;sudo ifup eth0;" );