-1

I'm trying to use the techniques from this answer to run a command on a remote machine over SSH, and collect the output. This is my code:

dispatch_async(dispatch_queue_create("closet ping", NULL), ^{
    NSTask *task;
    task = [[NSTask alloc] init];
    [task setLaunchPath: @"/usr/bin/ssh"];

    NSArray *arguments;
    arguments = [NSArray arrayWithObjects:@"validusername:192.168.0.15", @"-t 'ps -C mpg123'", nil];
    [task setArguments: arguments];

    NSPipe *pipe;
    pipe = [NSPipe pipe];
    [task setStandardOutput: pipe];

    NSFileHandle *file;
    file = [pipe fileHandleForReading];

    [task launch];

    NSData *data;
    data = [file readDataToEndOfFile];

    NSString *string;
    string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
    NSLog (@"ping returned:\n%@", string);

    ...

Running this code produces this in my Xcode console:

parker:192.168.0.15: illegal option --  
usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
           [-D [bind_address:]port] [-e escape_char] [-F configfile]
           [-I pkcs11] [-i identity_file]
           [-L [bind_address:]port:host:hostport]
           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
           [-R [bind_address:]port:host:hostport] [-S ctl_path]
           [-W host:port] [-w local_tun[:remote_tun]]
           [user@]hostname [command]
2014-04-15 13:09:56.640 NetworkBoard[26148:8443] ping returned:

Running whereis ssh in the console shows /usr/bin/ssh - exactly where I would expect it to be. It seems like the first argument in my arguments array gets used as the command for some reason. I've tried changing it to this:

arguments = [NSArray arrayWithObjects:@"ssh", @"validusername:192.168.0.15", @"-t 'ps -C mpg123'", nil];

But then this is shown in the console:

ssh: Could not resolve hostname ssh: nodename nor servname provided, or not known
2014-04-15 13:11:48.574 NetworkBoard[26280:2103] ping returned:

So it seems that the first value is used - unless it's the value I want to be used. Any ideas?

Community
  • 1
  • 1
Undo
  • 25,519
  • 37
  • 106
  • 129
  • I know squat about Cocoa and OS X but on a Linux machine you'd have to pass `validusername@192.168.0.15` with a `@`, not a `:`. Also, the 2nd `arguments = ...` you tried suggests to me that the `ssh` you've put at the start is extraneous. It would be like typing `ssh ssh...` at the command line. The `ssh` command interprets this `ssh` as a hostname and fails to resolve it. I have to say I'm puzzled by the `--` error you get in your first try. – Louis Apr 15 '14 at 19:23
  • @Louis I should have put that I've tried the conventional `user@host` method, still doesn't work. It puzzles me too... – Undo Apr 15 '14 at 19:25
  • Did you try separating `@"-t 'ps -C mpg123'"` into two arguments? Something like `@"-t", @"ps -C mpg123"`. – Louis Apr 15 '14 at 19:32
  • Wow, that worked @Louis. Go ahead and post it as an answer! – Undo Apr 15 '14 at 19:33
  • Please double check my syntax. As I said, that's not an environment I've ever worked with. I was able to figure it out from experience in other contexts. – Louis Apr 15 '14 at 19:39
  • Yeah, it's fine. Copy-pasting it works. Thanks again! – Undo Apr 15 '14 at 19:40

1 Answers1

2

You should change the way you create the arguments to pass to ssh to this:

NSArray *arguments;
arguments = [NSArray arrayWithObjects:@"validusername:192.168.0.15", @"-t", @"ps -C mpg123", nil];

The problem you were facing is that you were giving a list of arguments that would look okay if passed as a command through the shell. You were quoting the ps command, for instance. But with the error you were getting, I deduced that the API that was launching your task was launching it directly, without using a shell. Passing arguments that are good for a shell when one should not, is a common mistake (that I've made myself sometimes). So when things fail, that's a good thing to double check: is this API launching my executable through a shell or not.

I also thought was that you'd have to use validusername@192.168.0.15 instead of validusername:192.168.0.15 but you mentioned in a comment that you've used that and it made no difference. I'm mentioning this for completeness in case other readers would feel compelled to point this out.

Louis
  • 146,715
  • 28
  • 274
  • 320