我試圖通過system()
啓動外部應用程序 - 例如,system("ls")
。我想捕獲它的輸出,所以我可以將它發送到另一個函數進行進一步處理。在C/C++中做這件事的最好方法是什麼?以最佳方式從系統()命令捕獲stdout
回答
我不完全確定它可能在標準C中,因爲兩個不同的進程通常不共享內存空間。我能想到的最簡單的方法是讓第二個程序將其輸出重定向到一個文本文件(程序名> textfile.txt),然後讀取該文本文件以進行處理。但是,這可能不是最好的方法。
編輯:誤讀爲想將輸出傳遞給另一個程序,而不是另一個函數。 popen()幾乎肯定是你想要的。
系統爲您提供對shell的完全訪問權限。如果你想繼續使用它,你可以通過系統(「ls> tempfile.txt」)將其輸出重定向到一個臨時文件,但選擇一個安全的臨時文件是一件痛苦的事情。或者,你甚至可以通過另一個程序重定向它:system(「ls | otherprogram」);
有些人可能會推薦popen()命令。這是你想要的,如果你能處理輸出自己:
FILE *output = popen("ls", "r");
,這將給你一個文件指針,你可以用下面的命令對輸出它讀取。您可以使用pipe()調用創建一個與fork()組合的連接,以創建新的進程,dup2()更改它們的標準輸入和輸出,exec()運行新的程序,並在主程序中等待()以等待它們。這只是設置管道很像殼。有關詳細信息和示例,請參閱pipe()手冊頁。
在Windows中,不是使用system(),而是使用CreateProcess,將輸出重定向到管道並連接到管道。
我猜這也是可能的一些POSIX的方式?
從POPEN手冊:
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
FILE * stream = popen(const char * command,const char * type); – Arpith 2013-08-26 12:25:24
我想補充說這隻適用於Posix系統。在我的Windows 7版本中,沒有popen功能,但是有一個可用的_popen。 – user1505520 2014-07-30 20:25:39
嘗試POPEN()函數。它執行一個命令,如system(),但將輸出導向一個新文件。返回一個指向流的指針。
FILE *lsofFile_p = popen("lsof", "r");
if (!lsofFile_p)
{
return -1;
}
char buffer[1024];
char *line_p = fgets(buffer, sizeof(buffer), lsofFile_p);
pclose(lsofFile_p);
功能popen()
和pclose()
可能是你在找什麼。
查看glibc manual的示例。
函數popen()
等沒有重定向stderr等;我爲此寫了popen3()
。
其實,我只是檢查和:
POPEN是有問題的,因爲該過程分叉。所以如果你需要等待shell命令執行,那麼你就有可能錯過它。就我而言,我的程序在管道開始工作之前就已經關閉了。
我結束了使用系統在linux上使用tar命令調用。來自系統的返回值是焦油的結果。
所以:如果需要返回值,則不是沒不僅沒有必要使用POPEN,它可能不會做你想做的。
問題要求捕獲*輸出*,而不是*退出代碼*。所以我不認爲你提到的問題出現了。 – 2014-12-21 16:41:50
本頁內容:capture_the_output_of_a_child_process_in_c描述了使用popen與使用fork/exec/dup2/STDOUT_FILENO方法的限制。我的問題capturing tshark output with popen。
而且我猜測,這種限制可能是我的問題:
它返回,而不是原始的文件描述符,這 不適合異步處理輸出stdio流。
如果我有另一種方法的解決方案,我會回到這個答案。
最有效的方法是直接用stdout
文件描述符,繞過FILE
流:
pid_t popen2(const char *command, int * infp, int * outfp)
{
int p_stdin[2], p_stdout[2];
pid_t pid;
if (pipe(p_stdin) == -1)
return -1;
if (pipe(p_stdout) == -1) {
close(p_stdin[0]);
close(p_stdin[1]);
return -1;
}
pid = fork();
if (pid < 0) {
close(p_stdin[0]);
close(p_stdin[1]);
close(p_stdout[0]);
close(p_stdout[1]);
return pid;
} else if (pid == 0) {
close(p_stdin[1]);
dup2(p_stdin[0], 0);
close(p_stdout[0]);
dup2(p_stdout[1], 1);
dup2(::open("/dev/null", O_WRONLY), 2);
/// Close all other descriptors for the safety sake.
for (int i = 3; i < 4096; ++i) {
::close(i);
}
setsid();
execl("/bin/sh", "sh", "-c", command, NULL);
_exit(1);
}
close(p_stdin[0]);
close(p_stdout[1]);
if (infp == NULL) {
close(p_stdin[1]);
} else {
*infp = p_stdin[1];
}
if (outfp == NULL) {
close(p_stdout[0]);
} else {
*outfp = p_stdout[0];
}
return pid;
}
從孩子使用popen2()
讀輸出是這樣的:
int child_stdout = -1;
pid_t child_pid = popen2("ls", 0, &child_stdout);
if (!child_pid) {
handle_error();
}
char buff[128];
ssize_t bytes_read = read(child_stdout, buff, sizeof(buff));
爲了寫和閱讀:
int child_stdin = -1;
int child_stdout = -1;
pid_t child_pid = popen2("grep 123", &child_stdin, &child_stdout);
if (!child_pid) {
handle_error();
}
const char text = "1\n2\n123\n3";
ssize_t bytes_written = write(child_stdin, text, sizeof(text) - 1);
char buff[128];
ssize_t bytes_read = read(child_stdout, buff, sizeof(buff));
- 1. 如何從Perl腳本捕獲系統命令的stdin和stdout?
- 2. 最佳方式命令
- 3. 爲命令式程序員學習球拍宏系統的最佳方式
- 4. 製作「hashtag」系統的最佳方式
- 5. 獲取當前操作系統的最佳方式是什麼?
- 6. 如何以異步方式在Perl中運行系統命令?
- 7. 從多個外部系統構建DataMart的最佳方式?
- 8. 命令歷史記錄系統的最佳途徑
- 9. MATLAB系統命令
- 10. 系統命令bash
- 11. PHP - 最佳登錄系統方法
- 12. 錯誤捕獲最佳方法
- 13. 從javascript/jquery執行系統命令
- 14. 從mysql執行系統命令
- 15. 從ArcGIS地圖發出系統命令
- 16. Ruby從系統命令返回(sox)
- 17. 系統命令無法從程序
- 18. Quest系統最佳設計
- 19. Rails 3創建帖子評論系統的最佳方式
- 20. 什麼是學習Windows生態系統的最佳方式?
- 21. 實現Web 2.0導航系統的最佳方式
- 22. 是卡桑德拉建立報告系統的最佳方式
- 23. 實現實時IP白名單系統的最佳方式
- 24. MySQL:創建訪問系統的最佳方式是什麼?
- 25. 處理評級系統的最佳方式
- 26. Maven - 引用系統路徑上目錄的最佳方式
- 27. 在Clojure捕獲系統/出
- 28. 捕獲系統信息
- 29. 捕獲的Perl系統()
- 30. 斯卡拉系統命令從命令行
你最好是什麼意思?從我的回答中,我會說最優的可能取決於每種情況。 fork/exec/dup2/STDOUT_FILENO方法可能適用於特殊情況。 – nephewtom 2014-10-03 10:43:47