NSTask 中断不起作用 - Cocoa Objective C

问题描述 投票:0回答:1

我正在使用 NSTask 来像终端一样执行 shell 命令。我想在 root 级别运行该命令,因此我将 sh 切换到 root 用户。这工作正常,直到我想中断正在运行的进程(如 ping 命令)。下面是我的代码,

#import "ViewController.h"

@interface ViewController()
{
    NSTask* task;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupTask];
    [self executeCommand:@"sudo -S -i"];
    [self executeCommand:@"password"];

    [self executeCommand:@"ping www.google.com"];
    [self performSelector:@selector(terminateTask) withObject:nil afterDelay:3];
}

-(void)setupTask {
    @autoreleasepool {
        
        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];
        
        
        // ... and wait for shell output.
        [[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
        [[errorPipe fileHandleForReading] 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:nil
                                                      usingBlock:^(NSNotification *note)
         {
            // Read from shell output
            NSData *outData = [[outPipe fileHandleForReading] availableData];
            if ([outData length] > 0) {
                NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
                
                if ([outStr isEqualToString:@"Password:"]) {
                    NSLog(@"Password asked");
                    [[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
                } else {
                    NSLog(@"output: %@", outStr);
                }
                // Continue waiting for shell output.
            }
            [[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
        }];
    }
}

-(void)executeCommand:(NSString*)command {
    [task resume];
    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)terminateTask {
    [task interrupt];
}

@end

如何在根模式下运行命令并处理中断、挂起等信号?

objective-c cocoa sh interrupt nstask
1个回答
0
投票

显然,

sudo -i
命令打开了另一个bash,因此信号没有被传递。我已经在根级别启动了我的应用程序,因此 bash 默认情况下将在根级别启动,我不必手动更改为 sudo。使用
sudo -i
的另一个缺点是用户可以使用
exit
命令退出 sudo 模式,这是我不想要的。因此,从根级别启动 bash 是正确的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.