使用NSTask执行cd命令无输出,如何验证命令执行成功?
问题
我正尝试使用NSTask通过standardInput和standardOutput执行终端命令,ls、pwd等命令均可正常运行,但执行cd命令时standardOutput无任何输出。我清楚cd命令本身无显示响应,因此标准输出不会写入数据,但我需要判断该命令是否执行成功,以此更新UI。以下是我的代码,我使用NSFileHandleDataAvailableNotification读取输出,这对ping这类命令很有帮助:
-(void)setupTask { @autoreleasepool { // Commands are read from standard input: NSFileHandle *input = [NSFileHandle fileHandleWithStandardInput]; NSPipe *inPipe = [NSPipe new]; // pipe for shell input NSPipe *outPipe = [NSPipe new]; // pipe for shell output NSPipe *errorPipe = [NSPipe new]; task = [NSTask new]; [task setLaunchPath:@"/bin/sh"]; [task setStandardInput:inPipe]; [task setStandardOutput:outPipe]; [task setStandardError:errorPipe]; [task launch]; // Wait for standard input ... [input waitForDataInBackgroundAndNotify]; // ... and wait for shell output. [[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify]; [[errorPipe fileHandleForReading] waitForDataInBackgroundAndNotify]; // Wait asynchronously for standard input. // The block is executed as soon as some data is available on standard input. [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification object:input queue: [NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { NSData *inData = [input availableData]; if ([inData length] == 0) { // EOF on standard input. [[inPipe fileHandleForWriting] closeFile]; } else { // Read from standard input and write to shell input pipe. [[inPipe fileHandleForWriting] writeData:inData]; // Continue waiting for standard input. [input waitForDataInBackgroundAndNotify]; } }]; // Wait asynchronously for shell output. // The block is executed as soon as some data is available on the shell output pipe. [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification object:[outPipe fileHandleForReading] queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { // Read from shell output NSData *outData = [[outPipe fileHandleForReading] availableData]; if ([outData length] > 0) { NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding]; NSLog(@"Output: %@", outStr); } // Continue waiting for shell output. [[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify]; }]; [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification object:[errorPipe fileHandleForReading] queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) { // Read from shell output NSData *outData = [[errorPipe fileHandleForReading] availableData]; if ([outData length] > 0) { NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding]; NSLog(@"Error: %@", outStr); } // Continue waiting for shell output. [[errorPipe fileHandleForReading] waitForDataInBackgroundAndNotify]; }]; } } -(void)executeCommand:(NSString*)command { NSData* data = [command dataUsingEncoding:NSUTF8StringEncoding]; NSError* error; [[[task standardInput] fileHandleForWriting] writeData:data error:&error]; if (error != NULL) { NSLog(@"%@", [error localizedDescription]); } NSData* newLine = [@"\n" dataUsingEncoding:NSUTF8StringEncoding]; [[[task standardInput] fileHandleForWriting] writeData:newLine error:&error]; if (error != NULL) { NSLog(@"%@", [error localizedDescription]); } } -(void)runCommand { [self setupTask]; [self executeCommand:@"cd Users"]; }
解决方案
方法1:通过echo $?获取命令退出码
cd命令执行成功时退出码为0,失败则为非0值。可以在执行cd后紧接着执行echo $?,读取该输出即可判断cd是否成功:
[self executeCommand:@"cd Users && echo $?"];
在输出回调中,解析得到的数字,0表示成功,其他值表示失败。
方法2:监听错误输出(stderr)
cd命令执行失败时(比如目录不存在),会将错误信息输出到stderr。你的代码已经监听了errorPipe,当cd失败时,error回调会收到类似cd: Users: No such file or directory的信息,通过判断是否有错误输出即可得知命令执行失败。
方法3:执行cd后主动获取当前工作目录
在执行cd命令后,执行pwd命令,读取输出的目录路径,对比是否是目标目录,以此验证cd是否成功:
[self executeCommand:@"cd Users && pwd"];
如果输出的路径包含目标目录名,则说明cd成功。
内容的提问来源于stack exchange,提问作者prabhu
相关产品推荐
相关产品推荐

