Reputation: 8699
I'm trying to execute this comamnd ps -ef | grep test
using NSTask but I can't get the | grep test to be included in the NSTask:
This is what I'm using currently to get the output of ps -ef into a string then I need to somehow get the pid of the process test
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);
Upvotes: 11
Views: 4705
Reputation: 2371
Piping is a feature provided by shells, such as /bin/sh
. You may try launching your command via such a shell:
/* ... */
[task setLaunchPath: @"/bin/sh"];
/* ... */
arguments = [NSArray arrayWithObjects: @"-c", @"ps -ef | grep test", nil];
However, if you let the user supply a value (instead of hard-coding e.g. test
), you are making the program susceptible to shell injection attacks, which are kind of like SQL injection. An alternative, which doesn't suffer from this problem, is to use a pipe object to connect the standard output of ps
with the standard input of 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. */
This uses built-in Foundation functionality to perform the same steps as the shell does when it encounters the |
character.
Finally as others have pointed out, the usage of grep
is overkill. Just add this to your code:
NSArray *lines = [string componentsSeparatedByString:@"\n"];
NSArray *filteredLines = [lines filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"SELF contains[c] 'test'"]];
Upvotes: 22
Reputation: 7272
You may need to call [task waitUntilExit] before you launch the task, so that the process can finish running before you read the output.
Upvotes: 0