Strange issue of output via NSPipe when execute shell command using NSTask

436 views Asked by At

Here is my codes. When I set myCmd=@"cd /\nls -l\n" or myCmd=@"ls -l\n", it's no problem. However, when I set myCmd=@"cd /\n", program is dead in the line if ((output =[[outPipe fileHandleForReading] availableData]) && [output length]) and there is nothing debug info output.

I don't know if the "cd /" cmd is different with other shell command. Could you give me some advice?

NSData *inputData = [myCmd dataUsingEncoding:NSUTF8StringEncoding];
NSPipe *inPipe = [NSPipe pipe];
NSFileHandle *fh = [inPipe fileHandleForWriting];
[fh writeData: inputData];
NSPipe *outPipe = [NSPipe pipe];
//NSPipe *errPipe = [NSPipe pipe];
NSTask *task = [[NSTask alloc] init];
[task setStandardInput:inPipe];
[task setStandardOutput:outPipe];
[task setStandardError:outPipe];
[task setLaunchPath:@"/bin/sh"];
NSArray *args = [NSArray arrayWithObject:@"-s"];
[task setArguments:args];

[task launch];

NSData *output;
NSString *string;

if ((output =[[outPipe fileHandleForReading] availableData]) && [output length]) 
{
    string = [[NSString alloc] initWithFormat:@"%.s", [output bytes]];
}
NSLog(@"%@", string);
1

There are 1 answers

2
JeremyP On BEST ANSWER

I don't know if the cd / cmd is different with other shell command.

It's different fromm ls -l in that it doesn't write any output. Your program is probably blocked in the call to -availableData.


Unfortunately, I don't have time to try out any ideas but here are some things you might try.

  • You can try starting the task, then sending the data down the input pipe, then closing the input pipe. When the task sees the end of input, it will close the output pipe which means that your call to -availableData will return with end of file.

  • You could read the output asynchronously using the run loop. This is more flexible in that you don't have to send all the commands at once. You still need to close the input when you are done.

  • You could read the output in an NSOperation, which effectively puts it on a different thread. Again, you still need to close the input pipe when you are done.

I should point out, by the way, that sending cd to a shell as the last thing you do is a pointless operation. The next thing that happens is that the shell exits and the cd results are lost. If your objective is to change the directory in the current process, look at [NSFilemanager changeCurrentDirectoryPath:]