我是 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 &
提前致谢!