0

I am using SSH to communicate with a condor server and need to call commands for custom control (i.e. condor_submit, condor_make, condor_q, etc.). Having downloaded and successfully integrated libSSH in my Xcode project (yes, I'm using Mac OS), I found that the functions provided do not support custom commands. The tutorial stated that this will execute commands on the host:


rc = ssh_channel_request_exec(channel, "ls -l");
if (rc != SSH_OK) {
  ssh_channel_close(channel);
  ssh_channel_free(channel);
  return rc;
}

Source

Yet when I replace the "ls -l" with let's say "condor_q", the command doesn't seem to execute. I managed to fix this by using an interactive shell session like so:


// Create channel

rc = ssh_channel_request_pty(channel);
if (rc != SSH_OK) return rc;
rc = ssh_channel_change_pty_size(channel, 84, 20);
if (rc != SSH_OK) return rc;
rc = ssh_channel_request_shell(channel);

std::string commandString = "condor_q";
char buffer[512];
int bytesRead, bytesWrittenToConsole;
std::string string;

while (ssh_channel_is_open(channel) && !ssh_channel_is_eof(channel)) {
    // _nonblocking
    bytesRead = ssh_channel_read_nonblocking(channel, buffer, sizeof(buffer), 0);
    if (bytesRead < 0) {
        rc = SSH_ERROR;
        break;
    }
    if (bytesRead > 0) {
        for (int i = 0; i < bytesRead; i++) {
            string.push_back(buffer[i]);
        }
        bytesWrittenToConsole = write(1, buffer, bytesRead);
        if (string.find("$") != std::string::npos) {

            if (commandString.length() > 0) {
                ssh_channel_write(channel, commandString.c_str(), commandString.length());
                ssh_channel_write(channel, "\n", 1);
            } else {
                break;
            }
            commandString.clear();
            string.clear();
        }
    }
}

// Distroy channel

So my question, is there an easier way to send custom commands via SSH rather than having to "fake-send" the command?

Thanks

Max

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
Max Z.
  • 801
  • 1
  • 9
  • 25

2 Answers2

1

Custom commands generally dump into the stderr buffer.

For this reason if you use custom commands try using channel read as follows:

rc = ssh_channel_read(channel, buffer, sizeof(buffer), 1);

Note the 0 -> 1 change on the last function attribute. This attribute tells the read to read from the stderr on the channel where some of the information might be being dumped instead.

Try it out.

Edwin
  • 797
  • 2
  • 14
  • 23
-2

rc = ssh_channel_request_exec(channel, "ls -l");

The successful return code tells you that the command has been successfully sent to the server but not that it has been successfully executed. You need to wait and check the exit code or wait for output.

Did you read:

http://api.libssh.org/stable/libssh_tutor_command.html

and look at examples/exec.c in the source code?

asn
  • 798
  • 9
  • 17
  • The example file contains code pretty similar to their tutorial code, so that is no major help :( Still, you mentioned that I need to wait for an output, yet when running a loop that would continuously read the ssh channel, nothing would ever be returned. Also, have you checked the source I posted beneath my code? That's the same link that you posted ;) – Max Z. Nov 12 '12 at 15:54
  • As I told you to be sure that it successfully has been executed you have to check the exit code. The return code of ssh_channel_request_exec() tells you that it has been successfully transmitted to the server. The server tells you if it has successfully executed it with the exit code. Often an interactive shell is better with your own protocol like: ls && echo OK || echo KO – asn Dec 13 '12 at 18:37