Archived Forum Post

Index of archived forum posts

Question:

ssh commands not executed

Dec 10 '12 at 12:10

i would like to use the ssh project in order to send and receive commandsoutputs from my linux machine. commands such as ls, pwd etc' are working well but custom commands not being executed... for example "cd mydir". i use the code as in the ssh example:

            SshClient sshClient = new SshClient();

            sshClient.Connect("mymachine", "user", "password");

            sshClient.Send("cd mydir");

            sshClient.Recieve();

public void Send(string command)
{
    //  Open a session channel.  (It is possible to have multiple
    //  session channels open simultaneously.)
    _channelNum = _ssh.OpenSessionChannel();
    if (_channelNum < 0)
    {
        Console.WriteLine(_ssh.LastErrorText);
        return;
    }

    bool success = _ssh.SendReqExec(_channelNum, command + "\r\n");
    if (success != true)
    {
        Console.WriteLine(_ssh.LastErrorText);
        return;
    }

    int n;
    int pollTimeoutMs;
    pollTimeoutMs = 2000;
    n = _ssh.ChannelReadAndPoll(_channelNum, pollTimeoutMs);
    if (n < 0)
    {
        Console.WriteLine(_ssh.LastErrorText);
        return;
    }

    //  Close the channel:
    success = _ssh.ChannelSendClose(_channelNum);
    if (success != true)
    {
        Console.WriteLine(_ssh.LastErrorText);
        return;
    }
}

public void Recieve()
{
    //  Perhaps we did not receive all of the commands output.
    //  To make sure,  call ChannelReceiveToClose to accumulate any remaining
    //  output until the server's corresponding "channel close" is received.
    bool success = _ssh.ChannelReceiveToClose(_channelNum);
    if (success != true)
    {
        Console.WriteLine(_ssh.LastErrorText);
        return;
    }

    //  Let's pickup the accumulated output of the command:
    string cmdOutput;
    cmdOutput = _ssh.GetReceivedText(_channelNum, "ansi");
    if (cmdOutput == null)
    {
        Console.WriteLine(_ssh.LastErrorText);
        return;
    }

    //  Display the remote shell's command output:
    string text = string.Empty;
    text += cmdOutput + "\r\n";

    Console.Write(text);
}

the output is always as followed: ksh[1]: cd: mydir : [No such file or directory]

what am i missing ?


Answer

Have you tried

sshClient.Send("pwd");
or
sshClient.Send("ls");
instead of the "cd mydir"? Most likely issue is that you are in another directory then you think you are. I don't know about SshClient but CkSftp (which I believe is based upon CkSsh) doesn't support the notion of a "current directory" and you always need to specify full paths.


Answer

The SendReqExec command is equivalent to doing an "rexec" (http://linux.die.net/man/1/rexec).

It's not the same as establishing a remote shell as in this example: http://www.example-code.com/vcpp/ssh_remote_command.asp

A remote shell SSH session is where a remote shell is established. The output received back to the SSH client includes the command prompt. Commands are sent one after the other just as they are typed, with a "\n" or "\r\n" terminating the command, and the command output is received back along with the next command prompt. It's the equivalent of a shell session where the SSH client (your app) is the human at the keyboard. (see the detailed answer to this Chilkat forum post: http://www.chilkatforum.com/questions/1272/how-to-get-the-full-output-of-an-ssh-command )

A remote command is entirely different. It's a single command sent without "\n" or "\r\n" because it's not the equivalent of being the human at the keyboard. You send the command, such as "ls", and get the response, which does not include the shell prompt. You can only do a single rexec (i.e. SendReqExec) in a session channel. To execute the next rexec, you would close the session channel, open a new one, and issue the next rexec. There is no "state". It wouldn't makes sense to "cd" to a directory in one rexec, and then do another rexec assuming you are now in that directory. A "cd" only makes sense if you are in a remote shell. If the rexec command produces no output, such as a "cd" command would output nothing, then there is no output to receive. It still executed the command remotely, but for no reason.


Answer

right now i open a new session for every command what probably causes to loose my last execution... 1st command: 1. cd mydir 2nd command: ll --> list the root dir...


Answer

Here's a C# example:

Chilkat.Ssh ssh = new Chilkat.Ssh();

// Any string automatically begins a fully-functional 30-day trial. bool success; success = ssh.UnlockComponent("30-day trial"); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// My prompt includes the current working directory. // Your prompt will be different. MAKE SURE TO CHANGE THIS... string myPrompt; myPrompt = "chilkat@ubuntu:~/workspace$";

// Connect to an SSH server: string hostname; int port;

// Hostname may be an IP address or hostname: hostname = "www.some-ssh-server.com"; port = 22;

success = ssh.Connect(hostname,port); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Wait a max of 15 seconds when reading responses.. ssh.IdleTimeoutMs = 15000;

// Authenticate using login/password: success = ssh.AuthenticatePw("myLogin","myPassword"); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Open a session channel. (It is possible to have multiple // session channels open simultaneously.) int channelNum; channelNum = ssh.OpenSessionChannel(); if (channelNum < 0) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

string termType; termType = "dumb"; int widthInChars; widthInChars = 120; int heightInChars; heightInChars = 40; // Use 0 for pixWidth and pixHeight when the dimensions // are set in number-of-chars. int pixWidth; pixWidth = 0; int pixHeight; pixHeight = 0; success = ssh.SendReqPty(channelNum,termType,widthInChars,heightInChars,pixWidth,pixHeight); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Start a shell on the channel: success = ssh.SendReqShell(channelNum); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Run the 1st command in the remote shell, which will be to // "cd" to a subdirectory. success = ssh.ChannelSendString(channelNum,"cd workspacen","ansi"); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Read the response until we get the shell prompt (assuming it's successful) success = ssh.ChannelReceiveUntilMatch(channelNum,myPrompt,"ansi",true); if (success != true) { // Check the last-error information and the session log... textBox1.Text += ssh.LastErrorText + "rn"; textBox1.Text += ssh.SessionLog + "rn"; // Check to see what was received. textBox1.Text += ssh.GetReceivedText(channelNum,"ansi") + "rn"; return; }

// Display what we've received so far. This clears // the internal receive buffer, which is important. // After we send the command, we'll be reading until // the next command prompt. If the command prompt // is already in the internal receive buffer, we'll think we're // already finished... textBox1.Text += ssh.GetReceivedText(channelNum,"ansi") + "rn";

// Run the 2nd command in the remote shell, which will be // to "ls" the directory. success = ssh.ChannelSendString(channelNum,"lsn","ansi"); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Read the response until we get the shell prompt (assuming it's successful) success = ssh.ChannelReceiveUntilMatch(channelNum,myPrompt,"ansi",true); if (success != true) { // Check the last-error information and the session log... textBox1.Text += ssh.LastErrorText + "rn"; textBox1.Text += ssh.SessionLog + "rn"; // Check to see what was received. textBox1.Text += ssh.GetReceivedText(channelNum,"ansi") + "rn"; return; }

// Display what we've received so far. textBox1.Text += ssh.GetReceivedText(channelNum,"ansi") + "rn";

// Start the final command in the remote shell. This example // will send a "ls -l" command to retrieve the long format directory listing. success = ssh.ChannelSendString(channelNum,"ls -ln","ansi"); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Send an EOF. This tells the server that no more data will // be sent on this channel. The channel remains open, and // the SSH client may still receive output on this channel. success = ssh.ChannelSendEof(channelNum); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Read whatever output may already be available on the // SSH connection. ChannelReadAndPoll returns the number of bytes // that are available in the channel's internal buffer that // are ready to be "picked up" by calling GetReceivedText // or GetReceivedData. // A return value of -1 indicates failure. // A return value of -2 indicates a failure via timeout.

// The ChannelReadAndPoll method waits // for data to arrive on the connection usingi the IdleTimeoutMs // property setting. Once the first data arrives, it continues // reading but instead uses the pollTimeoutMs passed in the 2nd argument: // A return value of -2 indicates a timeout where no data is received. int n; int pollTimeoutMs; pollTimeoutMs = 2000; n = ssh.ChannelReadAndPoll(channelNum,pollTimeoutMs); if (n < 0) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Close the channel: success = ssh.ChannelSendClose(channelNum); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Perhaps we did not receive all of the commands output. // To make sure, call ChannelReceiveToClose to accumulate any remaining // output until the server's corresponding "channel close" is received. success = ssh.ChannelReceiveToClose(channelNum); if (success != true) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Let's pickup the accumulated output of the command: string cmdOutput; cmdOutput = ssh.GetReceivedText(channelNum,"ansi"); if (cmdOutput == null ) { textBox1.Text += ssh.LastErrorText + "rn"; return; }

// Display the remote shell's command output: textBox1.Text += cmdOutput + "rn";

// Disconnect ssh.Disconnect();