道阻且長,行則將至,埋頭苦干,不鳴則已,一鳴驚人!加油,騷年!
文章目錄
- 1 參考資料
- 2 使用說明
- 2.1 應用場景
- 2.2 擴展性
- 2.3 測驗環境
- 2.3.1 Ubuntu
- 2.3.2 工程代碼
- 3 函式原型
- 4 函式封裝
- 5 實際測驗
- 6 總結
祝大家新年快樂,身體健康,作業順利,牛年大吉!
1 參考資料
1、【c/c++】如何呼叫【linux】shell命令列命令并獲取命令列的輸出內容(https://blog.csdn.net/youngstar70/article/details/70305687)
2 使用說明
2.1 應用場景
最近在實際程式開發中,需要通程序式執行 shell 命令,并獲取命令輸出內容,但是系統自帶的 system 只能回傳命令執行成功與否,不能捕獲命令輸出,
基于此,需要實作的需求有:
- 可以執行 shell 命令;
- 可以獲取命令輸出內容;
2.2 擴展性
由于應用場景本就廣泛,因此擴展性較好,
此函式可以執行任意命令,并捕獲命令輸出結果,
實際使用程序中可以把此函式作為最底層介面,然后層層封裝,實作自己想要的功能,
2.3 測驗環境
2.3.1 Ubuntu
找到此方法時,我首先在 Ubuntu 中進行了測驗,環境如下:
- 系統版本:Ubuntu 14.04.1 LTS
- 系統版本詳細資訊如下
zhaoc@ubuntu14:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 14.04.1 LTS
Release: 14.04
Codename: trusty
- 系統內核版本如下
zhaoc@ubuntu14:~$ uname -a
Linux ubuntu14 3.13.0-32-generic #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
- gcc 版本如下
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)
2.3.2 工程代碼
隨后又放到工程代碼中測驗,環境如下:
- 系統內核版本如下
[root]#uname -a
Linux itl 4.4.207+ #24 PREEMPT Fri Jan 29 18:09:37 CST 2021 armv5tejl GNU/Linux
- gcc 版本如下
gcc version 4.8.3 20140320 (prerelease) (Sourcery CodeBench Lite 2014.05-29)
- 使用 C++ 標準:C++11
3 函式原型
根據參考資料,優化后的函式原型如下
#include <stdio.h>
#include <string.h>
#define CMD_RESULT_BUF_SIZE 1024
/*
* cmd:待執行命令
* result:命令輸出結果
* 函式回傳:0 成功;-1 失敗;
*/
int ExecuteCMD(const char *cmd, char *result)
{
int iRet = -1;
char buf_ps[CMD_RESULT_BUF_SIZE];
char ps[CMD_RESULT_BUF_SIZE] = {0};
FILE *ptr;
strcpy(ps, cmd);
if((ptr = popen(ps, "r")) != NULL)
{
while(fgets(buf_ps, sizeof(buf_ps), ptr) != NULL)
{
strcat(result, buf_ps);
if(strlen(result) > CMD_RESULT_BUF_SIZE)
{
break;
}
}
pclose(ptr);
ptr = NULL;
iRet = 0; // 處理成功
}
else
{
printf("popen %s error\n", ps);
iRet = -1; // 處理失敗
}
return iRet;
}
查看原始碼中的 popen() 、pclose() 函式原型定義如下:
#if (defined __USE_POSIX2 || defined __USE_SVID || defined __USE_BSD || \
defined __USE_MISC)
/* Create a new stream connected to a pipe running the given command.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern FILE *popen (const char *__command, const char *__modes) __wur;
/* Close a stream opened by popen and return the status of its child.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern int pclose (FILE *__stream);
#endif
查看原始碼中的 fgets() 函式原型如下:
/* Get a newline-terminated string of finite length from STREAM.
This function is a possible cancellation point and therefore not
marked with __THROW. */
extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
__wur;
4 函式封裝
介面 ExecuteCMD() 對于基礎的使用已經夠了,但是輸出結果是 char * 型別的,在 C++ 中實際使用起來不是很方便,為什么不直接轉換為 string 型別呢?
如果轉換為 string 型別,就可以使用 C++ 標準庫中的介面函式進行操作了,
于是簡單封裝了一下,此處的行內函式實際不一定會生效,
/*
* 輸入: 執行命令
* 輸出: 命令執行結果字串
*/
__inline std::string SystemWithResult(const char *cmd)
{
char cBuf[CMD_RESULT_BUF_SIZE] = {0};
string sCmdResult;
ExecuteCMD(cmd, cBuf);
sCmdResult = string(cBuf); // char * 轉換為 string 型別
printf("CMD Result: \n%s\n", sCmdResult.c_str());
return sCmdResult;
}
5 實際測驗
使用 ExecuteCMD() 函式,進行測驗,測驗代碼如下:
#include <stdio.h>
#include <string.h>
#define CMD_RESULT_BUF_SIZE 1024
/*
* cmd:待執行命令
* result:命令輸出結果
* 函式回傳:0 成功;-1 失敗;
*/
int ExecuteCMD(const char *cmd, char *result)
{
int iRet = -1;
char buf_ps[CMD_RESULT_BUF_SIZE];
char ps[CMD_RESULT_BUF_SIZE] = {0};
FILE *ptr;
strcpy(ps, cmd);
if((ptr = popen(ps, "r")) != NULL)
{
while(fgets(buf_ps, sizeof(buf_ps), ptr) != NULL)
{
strcat(result, buf_ps);
if(strlen(result) > CMD_RESULT_BUF_SIZE)
{
break;
}
}
pclose(ptr);
ptr = NULL;
iRet = 0; // 處理成功
}
else
{
printf("popen %s error\n", ps);
iRet = -1; // 處理失敗
}
return iRet;
}
int main()
{
char result[CMD_RESULT_BUF_SIZE]={0};
ExecuteCMD("ls -l", result);
printf("This is an example\n\n");
printf("%s", result);
printf("\n\nThis is end\n");
return 0;
}
編譯運行結果如下
zhaoc@ubuntu14:~/test/11-shellCmdTest$ gcc test1.c
zhaoc@ubuntu14:~/test/11-shellCmdTest$
zhaoc@ubuntu14:~/test/11-shellCmdTest$
zhaoc@ubuntu14:~/test/11-shellCmdTest$ ./a.out
This is an example
總用量 16
-rwxrwxr-x 1 zhaoc zhaoc 8968 2月 2 19:27 a.out
-rwxr--r-- 1 zhaoc zhaoc 1095 2月 2 19:27 test1.c
This is end
zhaoc@ubuntu14:~/test/11-shellCmdTest$
6 總結
學會了一個車輪,很開心,并且通過后續介面封裝,可擴展性也很好,重點還是 C 語言自己的庫函式使用,比如 popen() 、pclose() 、fgets() 等,
如果文章內容有誤,麻煩評論/私信多多指教!如果覺得文章內容還不錯,記得一鍵四連哦(點贊、收藏、留言、關注),如果您能點個關注,那就是對我最大的鼓勵,也將是我創作的動力,謝謝您嘞!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/261835.html
標籤:其他
