我正在尝试使用NSTask执行此comamnd ps -ef | grep test
,但我无法得到grep test包含在NSTask中:
这就是我目前用来将ps -ef的输出变成字符串然后我需要以某种方式得到过程测试的pid
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/ps"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: @"-ef", 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 (@"got\n%@", string);
答案 0 :(得分:18)
管道是shell提供的功能,例如/bin/sh
。您可以尝试通过这样的shell启动命令:
/* ... */
[task setLaunchPath: @"/bin/sh"];
/* ... */
arguments = [NSArray arrayWithObjects: @"-c", @"ps -ef | grep test", nil];
但是,如果你让用户提供一个值(而不是硬编码,例如test
),你就会使程序容易受到shell注入攻击,这有点像SQL注入。另一个没有遇到此问题的方法是使用管道对象将ps
的标准输出与grep
的标准输入连接起来:
NSTask *psTask = [[NSTask alloc] init];
NSTask *grepTask = [[NSTask alloc] init];
[psTask setLaunchPath: @"/bin/ps"];
[grepTask setLaunchPath: @"/bin/grep"];
[psTask setArguments: [NSArray arrayWithObjects: @"-ef", nil]];
[grepTask setArguments: [NSArray arrayWithObjects: @"test", nil]];
/* ps ==> grep */
NSPipe *pipeBetween = [NSPipe pipe];
[psTask setStandardOutput: pipeBetween];
[grepTask setStandardInput: pipeBetween];
/* grep ==> me */
NSPipe *pipeToMe = [NSPipe pipe];
[grepTask setStandardOutput: pipeToMe];
NSFileHandle *grepOutput = [pipeToMe fileHandleForReading];
[psTask launch];
[grepTask launch];
NSData *data = [grepOutput readDataToEndOfFile];
/* etc. */
这使用内置的Foundation功能来执行shell遇到|
字符时所执行的相同步骤。
最后正如其他人所指出的那样,使用grep
是过度的。只需将其添加到您的代码中:
NSArray *lines = [string componentsSeparatedByString:@"\n"];
NSArray *filteredLines = [lines filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"SELF contains[c] 'test'"]];
答案 1 :(得分:0)
您可能需要在启动任务之前调用[task waitUntilExit],以便在读取输出之前该过程可以完成运行。