1. 关键词 关键词:
C++ 系统调用 system popen 跨平台
应用场景:
希望直接调用操作系统的某些命令,并获取命令的返回值。
2. sysutil.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #pragma once #include <cstdint> #include <string> namespace cutl{ bool system (const std::string &cmd) ; bool callcmd (const std::string &cmd, std::string &result) ; }
不需要返回值时,可以直接使用system, 需要获取返回值时,可以调用callcmd。
3. sysutil.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include <map> #include <iostream> #include <strutil.h> #include <cstdlib> #include "sysutil.h" #include "inner/logger.h" #include "inner/system_util.h" #include "inner/filesystem.h" namespace cutl{ bool system (const std::string &cmd) { return call_system (cmd); } bool callcmd (const std::string &cmd, std::string &result) { constexpr int MAX_CMD_BUF_LEN = 1024 ; FILE *fp = pipline_open (cmd); if (fp == NULL ) { CUTL_ERROR ("pipline_open error for cmd:" + cmd); return false ; } char buffer[MAX_CMD_BUF_LEN] = {0 }; char *res = fgets (buffer, sizeof (buffer), fp); if (res == NULL ) { CUTL_ERROR ("read result error for cmd:" + cmd); if (pipline_close (fp) != 0 ) { CUTL_ERROR ("pipline_close error for cmd:" + cmd); } return false ; } if (pipline_close (fp) != 0 ) { CUTL_ERROR ("pipline_close error for cmd:" + cmd); } result = strip (std::string (buffer)); return true ; } }
3.1. system_util_unix.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #if defined(_WIN32) || defined(__WIN32__) #else #include "system_util.h" #include "inner/logger.h" namespace cutl{ bool call_system (const std::string &cmd) { if (cmd.empty ()) { CUTL_ERROR ("cmd is empty!" ); return false ; } pid_t status; status = std::system (cmd.c_str ()); if (-1 == status) { CUTL_ERROR ("system error!" ); return false ; } if (!WIFEXITED (status)) { CUTL_ERROR ("exit status:" + std::to_string (WEXITSTATUS (status))); return false ; } if (0 != WEXITSTATUS (status)) { CUTL_ERROR ("run shell script fail, script exit code:" + std::to_string (WEXITSTATUS (status))); return false ; } return true ; } FILE *pipline_open (const std::string &cmd) { return popen (cmd.c_str (), "r" ); } int pipline_close (FILE *stream) { return pclose (stream); } } #endif
3.2. system_util_win.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #if defined(_WIN32) || defined(__WIN32__) #include <cstdlib> #include "system_util.h" #include "inner/logger.h" namespace cutl{ bool call_system (const std::string &cmd) { if (cmd.empty ()) { CUTL_ERROR ("cmd is empty!" ); return false ; } int ret = system (cmd.c_str ()); if (ret != 0 ) { CUTL_ERROR (std::string ("system failure, error" ) + strerror (errno)); return false ; } return true ; } FILE *pipline_open (const std::string &cmd) { return _popen(cmd.c_str (), "r" ); } int pipline_close (FILE *stream) { return _pclose(stream); } } #endif
4. 测试代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include "common.hpp" #include "sysutil.h" void TestSystemCall () { PrintSubTitle ("TestSystemCall" ); bool ret = cutl::system ("echo hello" ); std::cout << "system call 'echo hello', return: " << ret << std::endl; auto cmd = "cmake --version" ; std::string result_text; ret = cutl::callcmd (cmd, result_text); std::cout << "callcmd " << cmd << ", return: " << ret << std::endl; std::cout << "callcmd " << cmd << ", result text: " << result_text << std::endl; }
5. 运行结果 1 2 3 4 5 -------------------------------------------TestSystemCall------------------------------------------- hello system call 'echo hello' , return : 1 callcmd cmake --version, return : 1 callcmd cmake --version, result text: cmake version 3.28.3
6. 源码地址 更多详细代码,请查看本人写的C++ 通用工具库: common_util , 本项目已开源,代码简洁,且有详细的文档和Demo。