簡體   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