【问题标题】:Get result from shell script objective-c从shell脚本objective-c获取结果
【发布时间】:2009-11-29 18:33:34
【问题描述】:

我想从文件或从 Objective-C 字符串(在代码中)运行 shell 脚本。我还希望将 shell 脚本的结果存储到一个变量中。我不希望将 shell 脚本拆分为参数(例如运行时的 setLaunchPath)。例如:运行这个 shell 脚本 "mount_webdav idisk.mac.com/mac_username /Volumes/mac_username" 而不是 "/bin/mount_webdav" 然后是参数。有没有办法做到这一点?我现在正在使用 NSTask,但是当我尝试使用它时,它给我带来了一些错误。这是提出的代码:

(一些.m文件)

 NSString *doshellscript(NSString *cmd_launch_path, NSString *first_cmd_pt) {

 NSTask *task = [[NSTask alloc] init]; // Make a new task

 [task setLaunchPath: cmd_launch_path]; // Tell which command we are running

 [task setArguments: [NSArray arrayWithObjects: first_cmd_pt, nil]];

 [task setArguments: first_cmd_pt];

 NSPipe *pipe = [NSPipe pipe];

 [task setStandardOutput: pipe];

 [task launch];

  NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile];

  NSString *string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];

  [task release]; //Release the task into the world, thus destroying it.

  return string;
}


NSString *mount_idisk(NSString *mac_username) {

 doshellscript(@"/bin/mkdir", [@"/Volumes/" stringByAppendingString:mac_username]);

 NSString *path_tmp = [mac_username stringByAppendingString: @"/ /Volumes/"];

 NSString *idisk_path = [path_tmp stringByAppendingString:mac_username];

 //NSLog(@"%@", [@" http://idisk.mac.com/" stringByAppendingString: idisk_path]);

 NSString *finished_path = [@"http://idisk.mac.com/" stringByAppendingString: idisk_path];

 doshellscript(@"/sbin/mount_webdav", finished_path);
}

... 这是我用来运行它的行: mount_idisk("username");

【问题讨论】:

    标签: objective-c shell scripting nsstring


    【解决方案1】:

    没有办法将整个命令行传递给 NSTask。

    有充分的理由;如果您正在进行任何类型的字符串组合,那么这样做会充满安全漏洞。您的字符串组合代码必须完全了解解析 shell 命令行的所有规则,并且必须转义所有可能导致任意命令执行的字符组合。

    system() C API 允许您执行任意命令,但没有直接捕获输出的机制。向您的命令行添加一些东西会很容易将输出发送到您稍后阅读的临时文件中,但是这样做只会增加更多的安全漏洞,而不仅仅是将整个命令行作为单个字符串传递。

    等等...看起来你有一个简单的错误:

    [task setArguments: [NSArray arrayWithObjects: first_cmd_pt, nil]];
    [task setArguments: first_cmd_pt];
    

    为什么要设置然后重新设置任务的参数?

    鉴于您的 mount_idisk() 函数有效地将各个参数组合在一起并将它们连接到一个字符串中,您为什么不简单地将所有参数填充到 NSArray 并修改 doshellscript() 以将数组作为第二个参数;参数数组?


    您没有正确创建参数数组。

    即:

    NSArray *finished_path = [NSArray arrayWithObjects:@"http://idisk.mac.com/", mac_username, @"/ /Volumes/", mac_username, nil];
    

    该行正在创建一个包含 4 个对象的数组,这些对象随后在 doshellscript() 函数中被视为 4 个单独的参数,而不是您需要的两个参数。

    可能是这样的:

    NSString *mobileMeUserURL = [@"http://idisk.mac.com/" stringByAppendingString: mac_username];
    NSString *localMountPath = [ @"/ /Volumes/" stringByAppendingString:  mac_username];
    NSArray *arguments = [NSArray arrayWithObjects: mobileMeUserURL, localMountPath, nil];
    

    【讨论】:

    • @bbum:你是说用NSTask一次只能运行一个命令?
    • @GitSyncApp 正确。 NSTask 允许外部执行单个命令。创建多个实例,每个命令一个。如果您需要在进程之间进行任何类型的管道,请将 shell 脚本写入临时文件并执行。
    • @bbum: 调用一个shellscript,然后调用多个命令呢?
    • @bbum:我想出了一种方法:将每个命令作为参数从 NSTask 传递给 .sh 文件。 .sh 文件循环并调用每个命令,瞧:来自 NSTask 的多个命令调用。
    • @GitSyncApp 对;每个 NSTask 一个命令....该命令的作用是任意的。 :)
    猜你喜欢
    • 1970-01-01
    • 2012-09-18
    • 2013-01-03
    • 2015-08-18
    • 1970-01-01
    • 2011-08-28
    • 1970-01-01
    • 2011-02-22
    相关资源
    最近更新 更多