Tom*_*cky 1 command objective-c nstask nspipe
我想使用NSTask模拟终端运行命令.代码如下.它可以在循环中获得输入并返回过程输出.
int main(int argc, const char * argv[])
{
@autoreleasepool {
while (1) {
char str[80] = {0};
scanf("%s", str);
NSString *cmdstr = [NSString stringWithUTF8String:str];
NSTask *task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:[NSArray arrayWithObjects:@"-c", cmdstr, nil]];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
[task launch];
NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile];
[task waitUntilExit];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", string);
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:当循环结束时,运行环境恢复到初始化状态.例如,默认运行路径是/Users/apple,我运行cd /以更改路径/,然后运行pwd,它返回/Users/apple而不是/.
那么如何才能NSTask完全模拟终端呢?
cd并且pwd是shell 内置命令.如果您执行任务
/bin/sh -c "cd /"
Run Code Online (Sandbox Code Playgroud)
无法将更改的工作目录返回到调用进程.如果要设置变量,则存在同样的问题MYVAR=myvalue.
您可以尝试单独解析这些行并更新环境.但是像多行命令呢?
for file in *.txt
do
echo $file
done
Run Code Online (Sandbox Code Playgroud)
您无法通过将每行发送到单独的NSTask进程来模拟它.
你能做的唯一一件事就是启动一个单一的 /bin/sh与过程NSTask,并养活所有的输入线到该进程的标准输入.但是你不能readDataToEndOfFile用来读取输出,但你必须异步读取(使用[[pipe fileHandleForReading] waitForDataInBackgroundAndNotify]).
简而言之:您只能通过运行(单个)shell来模拟终端.
添加:也许您可以使用以下内容作为应用的起点.(我省略了所有错误检查.)
int main(int argc, const char * argv[])
{
@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
NSTask *task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setStandardInput:inPipe];
[task setStandardOutput:outPipe];
[task launch];
// Wait for standard input ...
[input waitForDataInBackgroundAndNotify];
// ... and wait for shell output.
[[outPipe 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:nil
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:nil
usingBlock:^(NSNotification *note)
{
// Read from shell output
NSData *outData = [[outPipe fileHandleForReading] availableData];
NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
NSLog(@"output: %@", outStr);
// Continue waiting for shell output.
[[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
}];
[task waitUntilExit];
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6164 次 |
| 最近记录: |