1

I'm using Plink to connect ssh with C#. But when I send the command to server, Plink sends the command before it is logged-in. Therefore some commands does not work.

I send command from outside and these codes are,

cd /ssh/fd/
./myscript.sh

You can kindly find below the example code;

void connect()
{
     ProcessStartInfo psi = new ProcessStartInfo()
     {
         FileName = Application.StartupPath + @"\_Components\plink.exe",
         Arguments = String.Format("-ssh -hostkey {3} {0}@{1} -pw {2}", Users, Host, Password, Hostkey),
         RedirectStandardError = true,
         RedirectStandardOutput = true,
         RedirectStandardInput = true,
         UseShellExecute = false,
         CreateNoWindow = true
     };

     Process p = Process.Start(psi);
     m_objLock = new Object();
     m_blnDoRead = true;
     AsyncReadFeedback(p.StandardOutput);
     AsyncReadFeedback(p.StandardError);
     StreamWriter strw = p.StandardInput;
     string[] lstCommands = commandList.ToArray();

     foreach (string cmd in lstCommands)
     {
         strw.WriteLine(cmd);
     }

     strw.WriteLine("exit");
     p.WaitForExit();

     return m_szFeedback;
}

private String m_szFeedback;
private Object m_objLock;
private Boolean m_blnDoRead;

public void AsyncReadFeedback(StreamReader strr)
{
    Thread trdr = new Thread(new ParameterizedThreadStart(__ctReadFeedback));
    trdr.Start(strr);
}

private void __ctReadFeedback(Object objStreamReader)
{
    StreamReader strr = (StreamReader)objStreamReader;
    string line;
    while (!strr.EndOfStream && m_blnDoRead)
    {
        line = strr.ReadLine();
        lock (m_objLock) { m_szFeedback += line + "\r\n"; }
    }
}

This is the output:

Feedback from: xxx.xx.xxx.xx
cd /ssh/fd/

Last successful login:       Thu Nov 19 12:45:42 EET 2015 xxxxxxxxxxxxx  
Last authentication failure: Fri Dec 18 19:40:55 EET 2015 xxxxxxxxxxxxxxx
Last login: Thu Nov 19 12:45:42 2015 from xxxxxxxxxxx

(c)Copyright 1983-2006 Hewlett-Packard Development Company, L.P.
(c)Copyright 1979, 1980, 1983, 1985-1993 The Regents of the Univ. of California
(c)Copyright 1980, 1984, 1986 Novell, Inc.
(c)Copyright 1986-2000 Sun Microsystems, Inc.
(c)Copyright 1985, 1986, 1988 Massachusetts Institute of Technology
(c)Copyright 1989-1993  The Open Software Foundation, Inc.
(c)Copyright 1990 Motorola, Inc.
(c)Copyright 1990, 1991, 1992 Cornell University
(c)Copyright 1989-1991 The University of Maryland
(c)Copyright 1988 Carnegie Mellon University
(c)Copyright 1991-2006 Mentat Inc.
(c)Copyright 1996 Morning Star Technologies, Inc.
(c)Copyright 1996 Progressive Systems, Inc.

Confidential computer software. Valid license from HP required for
possession, use or copying.  Consistent with FAR 12.211 and 12.212,
Commercial Computer Software, Computer Software Documentation, and
Technical Data for Commercial Items are licensed to the U.S. Government
under vendor's standard commercial license.

You have mail.
./myscript.sh

exit

LANG has been set to C, but you can choose from C or ja_JP.SJIS or ja_JP.eucJP or ja_JP.utf8

hknnzb11:/home/def : ./myscript
-bash: ./myscript.sh: No such file or directory
hknnzb11:/home/def : 
hknnzb11:/home/def : exit
logout
logout
Using username "def".

I think it is the synchronization problem but I do not know how can I solve this.

You can kindle find the SSH.NET example which I tried.

using (var client = new SshClient(Host, Users, Password))
{
    client.Connect();
    var cmd = client.RunCommand("cd /ssh/fd/ ; ./myscript.sh");
    MessageBox.Show(cmd.Result);
    client.Disconnect();
}

Thanks.

1 Answers1

0

It's more a problem of your SSH server than your code.

Anyway, you should better use the -m command-line switch to provide the commands script to the Plink. The difference is that the commands specified by the -m are executed in the "exec" channel in a more controlled way, then in the "shell" channel you are using, when redirecting the input.


Even better though, is to use a native C# library for executing the commands in the "exec" channel:

E.g. using the SSH.NET:

using (var client = new SshClient(Host, Users, Password))
{
    client.Connect();
    client.RunCommand("cd /ssh/fd/ ; ./myscript.sh");
    client.Disconnect();
}

Credit: C# send a simple SSH command


If the above does not work, it's a bug in the SSH server.

All you can do to workaround it, is waiting few seconds before sending the commands. For this you need to keep using the "shell" channel, as in your original code.

In the "exec" channel (my solutions), you cannot delay the commands. The server itself should execute the commands only once the session is completely initialized.

Community
  • 1
  • 1
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • Actually, I tried SSH.NET but the problem continues. I think if I can send the command after login successfully, it will be solved. Is there any code to wait process to login ? –  Oct 19 '15 at 12:20
  • Yes, it occured the same problem. –  Oct 19 '15 at 12:23
  • Can you show us your SSH.NET code? Edit it into your question. – Martin Prikryl Oct 19 '15 at 12:24
  • I added the codes, I run that codes but it is not return any result. I must get the response from running script. Thanks. –  Oct 19 '15 at 19:07
  • What if you replace the `myscript.sh` with some simple command like `ls`. Do you get the results? – Martin Prikryl Oct 20 '15 at 05:46
  • Yes sometimes I get but sometimes not. –  Oct 20 '15 at 08:03
  • Well, it seems like the server does not behave correctly. – Martin Prikryl Oct 20 '15 at 08:16
  • When I try to login server via putty, after login process, it writes some text on the putty screen. But it is writing slowly. I think the problem is that. How can I keep waiting my commands to finished login process before sending commands ? –  Oct 20 '15 at 10:41
  • The SSH server should do it for you. If it does not, it's not your fault. There's no magical trick to workaround it. All you can do to workaround it is wait few seconds before sending the commands. – Martin Prikryl Oct 20 '15 at 10:50
  • Thanks for your help. –  Oct 20 '15 at 12:14