本文总结了四种linux下的启动子进程执行命令行的方法
基于c++/c,包含qt下的qprocess的使用
linux方法,windows大同小异,请自行验证
----------------------------------------------------------------------------------------------------------------------------
1、system,执行命令行
system()是C标准库中提供的一个函数,它可以在Linux/Unix系统中执行另一个命令或者程序。system()函数将要执行的命令作为参数传入,并且会创建一个子进程来运行这个命令,然后等待这个子进程结束并返回。
system()函数如下:
int system(const char* command);
其中command参数是要执行的命令或者程序。当command不为NULL时,system()函数会调用shell来解释执行该命令或者程序,否则不执行任何操作。
在qt中使用方法示例如下:
QString strCMD="df -h";
system(strCMD.toLatin1().data());
system()函数的返回值有以下3种情况:
如果调用失败,则返回与目标平台相关的非零错误代码;
如果command为NULL,则返回0;
如果调用成功,则返回被调用进程的退出状态。
system()函数适用于一些简单的命令行交互场景,例如启动另一个程序、改变环境变量等。由于system()函数是同步阻塞式的,执行时间较长的命令可能会导致UI界面卡死,因此在GUI程序中应该避免频繁使用system()函数。
2、使用fork()函数创建子进程,再在子进程中使用exec()函数来执行另一程序
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
pid_t pid = fork();
if (pid < 0) { // 子进程创建失败
perror("fork");
exit(1);
} else if (pid == 0) { // 子进程
execlp("/bin/ls", "ls", "-l", NULL); //参数:路径,命令,参数
perror("execlp"); // 如果执行失败,则输出错误信息
exit(1);
} else { // 父进程
wait(nullptr); // 等待子进程结束
printf("process child finished");
exit(0);
}
}
3、shell命令行,执行命令行并获得执行结果--推荐
在shell终端中执行相应的命令行指令,使用类似于system()
的函数来执行命令,并将其输出捕获到当前程序中.
#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
int main() {
string command = "ls -la";
FILE* fp = popen(command.c_str(), "r");
if (!fp) {
cerr << "Failed";
return -1;
}
char buffer[1024] = {0};
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
cout << buffer;
}
pclose(fp);
return 0;
}
4、posix_spawn()
、vfork()等系统库函数、
安全性和可靠性高
使用Linux系统库提供的函数来创建并执行进程
#include <iostream>
#include <vector>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
int main() {
pid_t pid = vfork(); // 创建子进程
if (pid == -1) { // 如果失败,则退出
perror("fork");
exit(1);
} else if (pid == 0) { // 子进程
vector<char*> args{const_cast<char*>("ls"), const_cast<char*>("-la"), nullptr};
// execvp()函数把args传入新的进程中并执行命令
execvp(args[0], &args[0]);
_exit(127); // 如果执行失败,则退出,并输出错误信息
} else { // 父进程
int status;
waitpid(pid, &status, 0); // 等待子进程结束
if (!WIFEXITED(status)) { // 子进程未正常退出
cerr << "Child process terminated abnormally." << endl;
} else if (WEXITSTATUS(status) != 0) { // 子进程返回了非0状态码
cerr << "Child process returned error code: " << WEXITSTATUS(status) << endl;
} else {
cout << "Child process finished." << endl;
}
}
return 0;
}
5、QProcess用法
5.1 使用start()函数来启动进程:这是一种最简单的启动进程方式。调用start()函数并传入要执行的程序名称和参数即可启动一个新的进程。
QProcess process;
process.start("ls", QStringList() << "-l");
5.2 使用startDetached()函数来启动进程:与start()函数类似,但不需要等待进程完成并返回。可以将该函数作为静态方法调用,因此无需实例化QProcess对象即可启动新进程。
QProcess::startDetached("ping", QStringList() << "-c" << "5" << "www.baidu.com");
5.3 在构造函数中设置命令行参数:在创建QProcess对象时,可将要执行的命令及其参数一起传入构造函数中,这样可以省略掉start()函数的调用。
QProcess process(nullptr);
QStringList args = {"-l"};
process.start("ls", args);
5.4 重定向进程的标准输入和输出:通过设置QProcess对象的标准输入、标准输出和标准错误设备,可以实现对进程I/O流的重定向,使得后续能够获取进程的输出结果或者将某些数据发送给进程。
QProcess process;
process.setStandardOutputFile("output.txt"); // 指定标准输出的设备为文件
process.start("ls", QStringList() << "-lR" << "/"); // 启动进程并重定向标准输出
if (process.waitForFinished()) {
QByteArray output = process.readAllStandardOutput();
qDebug() << output; // 输出读取到的数据
}