繁体   English   中英

如何捕获shell命令的输出?

[英]How do I capture output from a shell command?

可可新手警告!

我发现以下shell命令是确定进程是否正在运行的好方法(1 =正在运行,0 =未运行):

if [ $(ps -Ac | egrep -o 'ProcessName') ]; then echo 1; else echo 0; fi;

我可以使用“ system”命令将其合并到Cocoa中:

system("if [ $(ps -Ac | egrep -o 'Finder') ]; then echo 1; else echo 0; fi;");

但是,输出定向到运行日志,我无法弄清楚如何在我的Cocoa代码中捕获结果(1或0)。

我尝试使用NSTask实现此目标,如下所示:

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:[NSArray arrayWithObject:@"if [ $(ps -Ac | egrep -o 'Finder') ]; then echo 1; else echo 0; fi;"]];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
[task launch];
NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile];
[task waitUntilExit];
[task release];
NSString *output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog (@"%@", output);
[output release];

但是,这会生成以下错误消息:

如果[$(ps -Ac | egrep -o'Finder')]; 然后回声1; 否则回显0; fi ;:没有这样的文件或目录

您能告诉我如何正确实现此shell命令,以允许我捕获代码中的输出(1或0)吗? (我知道确定进程是否正在运行的其他方法,但我的问题的部分原因是学习如何在Cocoa中总体上实现Shell脚本。)

非常感谢您对这个问题的帮助。

你这样做是错的。 与其问“我如何运行外部过程来执行X”,不如问“我如何编写代码来执行X”。

您无需使用外部脚本即可获取进程列表。 通常,出于性能和安全性方面的考虑,应始终尝试使用API​​而不是启动外部任务。

在这种情况下,您需要的API是sysctl C接口。

JongAm Park已编写了一个Objective-C包装器,用于使用sysctl获取正在运行的进程的列表。 在他的帖子的评论中也有一些要点。

另外,您可以通过查看ps命令的源代码来了解Apple的工作方式

Rob,感谢您提供有关尽可能在代码中使用直接解决方案的一般指导。 我浏览了JongAm Park的sysctl包装和苹果的ps源代码。 合并将花费一些时间,但是我现在知道在哪里可以找到获取过程列表的直接解决方案。

Shellter和Tripleee,谢谢您有关与Shell命令交互的建议。 根据您的建议,我有三种工作方法(!):

方法1使用system命令的返回码(不需要egrep -o ):

BOOL processIsRunning = system("ps -Ac | grep 'ProcessName' > /dev/null") == 0;

方法2将NSTask与shell -c选项一起使用(请注意-c而不是-e ):

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:[NSArray arrayWithObjects:@"-c",@"ps -Ac | grep 'ProcessName'",nil]];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
[task launch];
NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile];
[task waitUntilExit];
[task release];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
BOOL processIsRunning = [result length] > 0;

方法3还将NSTask与shell -c选项一起使用,但是在这种情况下,要执行的命令是具有其自身-c选项的另一个shell(这是我经过反复尝试才能发现的将if结构合并的唯一方法。在命令要执行的;当然,它是当前的问题矫枉过正方式 ):

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:[NSArray arrayWithObjects:@"-c",@"/bin/sh -c 'if [ \"$(ps -Ac | egrep -o 'ProcessName')\" = \"ProcessName\" ]; then echo 1; else echo 0; fi;'",nil]];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
[task launch];
NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile];
[task waitUntilExit];
[task release];
NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
BOOL processIsRunning = [result intValue] == 1;

谢谢大家的帮助。

这是一个根本不涉及可可的一般答案:

如果要从system()获取输出,请不要使用system() ,请使用popen()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM