1

我是 Objective-C 和 Cocoa 的新开发者。我需要从 Xcode/Cocoa 应用程序运行/停止/重新启动 Apache 和 Mysql,但我不知道哪个是最佳做法:使用 NSTask、使用 NSAppleScript 还是应该使用什么?

无论如何,我认为我需要管理员权限。

也许有人可以帮助我如何或从哪里开始使用最佳实践。

下面是我已经尝试过的一点:

我还看到了本教程: http: //www.michaelvobrien.com/blog/2009/07/authorizationexecutewithprivileges-a-simple-example/但是从 OS 10.6 开始不推荐使用 AuthorizationExecuteWithPrivileges 方法。

我尝试了几种在 stackoverflow.com 上找到的方法,但没有任何结果。

我尝试的一种方法是使用 TasksController 类中的以下方法:

- (BOOL) runProcessAsAdministrator:(NSString*)scriptPath
                 withArguments:(NSArray *)arguments
                        output:(NSString **)output
              errorDescription:(NSString **)errorDescription {

NSLog(@"runProcessAsAdministrator called!");

NSString * allArgs = [arguments componentsJoinedByString:@" "];
NSString * fullScript = [NSString stringWithFormat:@"%@ %@", scriptPath, allArgs];

NSDictionary *errorInfo = [NSDictionary new];
NSString *script =  [NSString stringWithFormat:@"do shell script \"sudo %@\" with administrator privileges", fullScript];

NSLog(@"shell script path: %@",script);

NSAppleScript *appleScript = [[NSAppleScript new] initWithSource:script];
NSAppleEventDescriptor * eventResult = [appleScript executeAndReturnError:&errorInfo];

// Check errorInfo
if (! eventResult)
{
    // Describe common errors
    *errorDescription = nil;
    if ([errorInfo valueForKey:NSAppleScriptErrorNumber])
    {
        NSNumber * errorNumber = (NSNumber *)[errorInfo valueForKey:NSAppleScriptErrorNumber];
        if ([errorNumber intValue] == -128)
            *errorDescription = @"The administrator password is required to do this.";
    }

    // Set error message from provided message
    if (*errorDescription == nil)
    {
        if ([errorInfo valueForKey:NSAppleScriptErrorMessage])
            *errorDescription =  (NSString *)[errorInfo valueForKey:NSAppleScriptErrorMessage];
    }

    return NO;
}
else
{
    // Set output to the AppleScript's output
    *output = [eventResult stringValue];

    return YES;
}
}

调用如下:

 TasksController *tasks = [[TasksController alloc] init];
            NSString * output = nil;
            NSString * processErrorDescription = nil;
            BOOL success = [tasks runProcessAsAdministrator:@"/Applications/MyAPP/Library/bin/httpd"
                                              withArguments:[NSArray arrayWithObjects:@"-f /Applications/MyAPP/conf/apache/MyAPP-httpd.conf", @"-k start", nil]
                                              output:&output
                                              errorDescription:&processErrorDescription
                                              ];


            if (!success) // Process failed to run
            {

                // ...look at errorDescription

                    [_lblStatus setStringValue:@"  Apache could not be started!"];
                    [_txtLogs setStringValue:processErrorDescription];
                    NSLog(@"%@",output);
                    NSLog(@"%@",processErrorDescription);


            }
            else
            {

                // ...process output

                    [_lblStatus setStringValue:@"  Hurray Apache running!!"];
                    [_txtLogs setStringValue:output];

            }

当我尝试上述方法时,应用程序会弹出一个小窗口,询问管理员密码,但在引入 pass 后,它会尝试运行,我在控制台中收到以下消息:

dyld: DYLD_ environment variables being ignored because main executable (/usr/libexec/security_authtrampoline) is setuid or setgid  

我也尝试使用以下方法但没有成功:

-(NSString*)runCommand:(NSString*)commandToRun
{
    NSTask *task;
    task = [[NSTask alloc] init];
    [task setLaunchPath: @"/bin/sh"];

    NSArray *arguments = [NSArray arrayWithObjects:
                          @"-c" ,
                          [NSString stringWithFormat:@"%@", commandToRun],
                          nil];
    NSLog(@"run command: %@",commandToRun);
    [task setArguments: arguments];

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

    NSFileHandle *file;
    file = [pipe fileHandleForReading];

    [task launch];

    NSData *data;
    data = [file readDataToEndOfFile];

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

}





-(void) runScript:(NSString*)scriptName
{
    NSTask *task;
    task = [[NSTask alloc] init];

    [task setLaunchPath: @"/bin/sh"];

    NSArray *arguments;
    NSString* newpath = [NSString stringWithFormat:@"'%@'/%@",[[NSBundle mainBundle] resourcePath], scriptName];


    NSLog(@"shell script path: %@",newpath);
    arguments = [NSArray arrayWithObjects:newpath, 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 (@"script returned:\n%@", string);
}

对于最后一种方法,我的 Supporting Files 文件夹中有 ShellScript 文件夹,其中包含 startMysql.sh、startApache.sh 等脚本...

startMysql.sh 示例:

# /bin/sh
/Applications/MyAPP/Library/bin/mysqld_safe --port=8889 --socket=/Applications/MyAPP/tmp/mysql/mysql.sock --lower_case_table_names=0 --pid-file=/Applications/MyAPP/tmp/mysql/mysql.pid --log-error=/Applications/MyAPP/logs/mysql_error_log &

提前致谢!

4

0 回答 0