linuxc执行cmd命令
linuxc执行cmd命令详细介绍
在 Linux C 中执行系统命令(CMD)通常有多种方法,以下是常用的几种方式及其示例:
一、使用
system 函数(最简单)
功能
直接通过 shell 执行命令字符串,适用于简单场景(如执行脚本、简单命令)。
函数原型
c
command
返回值
- 命令执行成功:返回 shell 的退出状态(通过
WEXITSTATUS宏解析)。 - 失败或调用错误:返回
-1(此时errno会被设置)。
示例代码
c
status
status
status
status
注意事项
- 会启动一个 shell 进程(
/bin/sh -c),可能存在 命令注入风险(避免直接拼接用户输入的字符串)。 - 无法获取命令的输出流(如标准输出 / 错误),只能获取退出状态。
二、使用
popen 函数(获取命令输出 / 输入)
功能
通过管道(pipe)执行命令,可读取命令的输出("r" 模式)或向命令输入数据("w" 模式)。
函数原型
c
FILE command type
FILE stream
返回值
popen:成功返回文件流指针,失败返回NULL(errno被设置)。pclose:返回命令的退出状态(同system,通过WEXITSTATUS解析)。
示例:读取命令输出(如
ls -l 的结果)
c
FILE fp
buffer
fp
fp
buffer buffer fp
buffer
status fp
status
status
status
示例:向命令输入数据(如通过
grep 过滤)
c
FILE fpfp
fp
注意事项
- 适用于需要处理命令的 标准输出 / 输入 的场景(如管道数据)。
- 只能单向通信(读或写),不能同时读写。
- 命令执行完毕后必须调用
pclose释放资源。
三、使用
fork +
exec 族函数(更底层、更灵活)
功能
手动创建子进程,在子进程中执行命令,适合需要精细控制进程的场景(如不通过 shell、自定义参数)。
核心函数
fork():创建子进程(父进程返回子进程 PID,子进程返回 0,失败返回 -1)。execvp():在子进程中执行命令(常用,自动搜索PATH路径)。
示例代码:执行
ls -l(不通过 shell)
c
pid
pid
pid
argv
argv argv
status
pid status
status
status
示例:通过 shell 执行带管道的命令(如
ls -l | grep txt)
需显式调用 sh -c:
c
argvargv
注意事项
- 不通过 shell 时:命令参数需拆分为数组(如
ls -l拆为{"ls", "-l", NULL}),不能包含 shell 语法(如管道、重定向)。 - 通过 shell 时:需以
sh -c "命令字符串"的形式传递参数,此时存在命令注入风险。 - 父进程必须调用
wait或waitpid回收子进程资源,避免僵尸进程。
四、总结:适用场景对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
system |
简单易用 | 有 shell 开销,无法处理 IO | 简单命令执行(无需处理输出) |
popen |
可读写命令 IO | 单向通信,需处理文件流 | 需要获取命令输出 / 输入 |
fork+exec |
底层控制,无 shell 中间层 | 代码复杂,需手动管理进程 | 高性能要求,自定义参数处理 |
五、安全提示
- 避免直接拼接用户输入到命令字符串中(防止命令注入,如使用
popen或exec时校验参数)。 - 对不可信的输入,优先使用
fork+exec且不通过 shell(直接指定程序路径和参数数组)。
根据需求选择合适的方法,简单场景用 system,需处理 IO 用 popen,需要精细控制用 fork+exec。