我正在尝试使用this answer中的技术通过SSH在远程计算机上运行命令,并收集输出。这是我的代码:
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);
...
运行此代码会在我的Xcode控制台中生成此代码:
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:
在控制台中运行whereis ssh
会显示/usr/bin/ssh
- 正是我期望的那样。似乎我的arguments
数组中的第一个参数由于某种原因被用作命令。我已经尝试将其更改为:
arguments = [NSArray arrayWithObjects:@"ssh", @"validusername:192.168.0.15", @"-t 'ps -C mpg123'", nil];
但是这会显示在控制台中:
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:
所以似乎第一个值是使用 - 除非它是我想要的值。有什么想法吗?
答案 0 :(得分:2)
您应该更改创建参数的方式,以便传递给ssh
:
NSArray *arguments;
arguments = [NSArray arrayWithObjects:@"validusername:192.168.0.15", @"-t", @"ps -C mpg123", nil];
你遇到的问题是你提供了一个参数列表,如果通过shell作为命令传递,那么这些参数看起来还可以。例如,您引用了ps
命令。但是,由于您遇到了错误,我推断出启动任务的API是直接启动它,而不使用shell。当一个人不应该传递对shell有利的参数时,这是一个常见的错误(我有时会自己做出来)。因此,当事情失败时,仔细检查是一件好事:这个API是否通过shell启动我的可执行文件。
我还认为你必须使用validusername@192.168.0.15
而不是validusername:192.168.0.15
,但是你在评论中提到你已经使用过它并没有区别。我提到这一点是为了完整,以防其他读者感到有必要指出这一点。