如何在C语言中执行shell命令
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在C语言中执行shell命令相关的知识,希望对你有一定的参考价值。
题主可以使用 exec 系列函数。这系列函数定义在 unistd.h 头文件中,所以使用前请包含这个头文件。这系列函数共有五个,
execl, execlp, execv, execvp, execle其中常用的是前四个。前四个函数的原型为:
int execl(const char *path, const char *arg, ...);int execlp(const char *file, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
这四个函数的主要差别就在于参数的类型和用不用输入命令的绝对路径上。
以路径形式来分,凡是函数名中带 p 的(execlp,execvp)都只需要提供命令的名,函数会自动在当前的环境变量 $PATH 中查找命令的路径。而不带 p 的(execl,execv)必须要提供命令的绝对路径,否则函数会找不到这个命令的位置。这里以 execl 和 execlp 为例,以下运行
ls -l命令的代码:
#include <unistd.h>
int main()
// exec 系列函数出错时会返回 -1,平常返回 0,所以可以
// 据此来打印错误信息
// 第一个 ls 是命令的名称,execlp 函数会自动在 $PATH
// 中寻找这个命令。
// 后面一个 ls 是要在 shell 中输入的第一个参数
//(也就是命令名称本身)
// 使用 NULL 作为参数结尾标记是 exec 系列函数的要求。
if (execlp("ls", "ls", "-l", NULL) == -1)
perror("Error Executing Command.\\n");
return 0;
在 shell 中运行这个 C 程序会输出
和你直接在 shell 中写 ls -l 的效果是一样的。然而,如果你使用不带 p 的 execl, 那么这样写就会报错。
#include <unistd.h>
int main()
// execl 只接受命令的绝对路径,所以必须输入完整的
// 路径 /bin/ls,即
// if (execl("/bin/ls", "ls", "-l", NULL) == -1)
if (execl("ls", "ls", "-l", NULL) == -1)
perror("Error Executing Command.\\n");
return 0;
输出结果为:
以参数类型来分,凡是函数名中带 l 的(execl,execlp)都需要把系统命令的参数全部传递给函数,而凡是函数名中带 v 的(execv,execvp)都需要把系统命令的参数统一放在一个数组里,然后把这个数组传递给函数。
比如刚才这个
#include <unistd.h>
int main()
if (execlp("ls", "ls", "-l", NULL) == -1)
perror("Error Executing Command.\\n");
return 0;
如果改用 execvp 来写的话就是
#include <unistd.h>
int main()
// 这个字符串数组存有所有参数(包括命令名本身和
// 最后的 NULL)
char * argv[] = "ls", "-l", NULL;
// 这里只需将命令名称和参数数组传递给 execvp 函数即可,
// 无需将参数一个个传递。同样函数会自动在 $PATH
// 中查找命令
if (execvp("ls", argv) == -1)
perror("Error Executing Command.\\n");
return 0;
运行结果同样和直接写 ls -l 的效果相同。
execv 和 execvp 的区别也在于是否必须输入绝对路径,就不赘述了。
要注意的一点是,如果执行成功,exec 系列函数开启的新进程会完全代替当前的进程,也就是说当前进程会消失。所以一般会将 exec 和 fork 连用,先 fork 出一个子进程,然后在这个子进程中使用 exec 运行别的程序,防止父进程被 exec 覆盖。比如刚才的代码稍微改一下
#include <unistd.h>
int main()
char * argv[] = "ls", "-l", NULL;
if (execvp("ls", argv) == -1)
perror("Error Executing Command.\\n");
// 加入一个 printf 语句
printf("Main process is still running.\\n");
return 0;
运行后并不会出现 Main process is still running 这句话,因为 exec 后 main 函数执行产生的进程已经被 ls 命令产生的进程完全覆盖了,所以 exec 函数以下的语句是完全不会执行的。这时就可以使用 fork 来新建一个子进程,在子进程中执行 exec 函数。
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
int r;
// fork() 大于零,父进程
if ((r = fork()) > 0)
int status;
if (wait(&status) != -1)
// 等待子进程退出
if(WIFEXITED(status))
printf("Main process is still running.\\n");
return 0;
// fork () 等于零,子进程。子进程中运行 exec
else if (r == 0)
char * argv[] = "ls", "-l", NULL;
if (execvp("ls", argv) == -1)
perror("Error Executing Command.\\n");
return 0;
// fork() 小于零,出错
else
perror("Fork");
return 0;
这样运行结果就变成了
Main process is still running 这句话就会被输出到屏幕上。
参考技术A 可以通过system函数,调用shell命令。1 函数原型:
int system(const char *cmd);
2 功能:
调用cmd内容的系统命令,即shell命令。
3 头文件:
stdlib.h
4 举例:
system("ls");
打印当前工作目录下的文件。 参考技术B 1、可以使用system函数调用。system("shell_command");可以实现在shell中调用shell_command的作用。
2、例如设置网卡IP为192.168.1.100,可以写作
system("ifconfig eth0 192.168.1.100"); 参考技术C system 这个函数可以帮到你。 参数就一个 就是shell命令 参考技术D 参数type可使用“r”代表读取,“w”代表写入。依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。此外,所有使...
如何在shell脚本中,判断一个基本命令执行是不是成功
每一条基本命令执行后都有一个返回码,该返回码是用$?表示,执行成功的返回码是0,例如:if [ $? -ne 0 ];then
上一命令执行失败时的操作
else
上一命令执行成功时的操作
fi 参考技术A echo $? # 0:正确执行;非0表示其它错误 参考技术B 看看你的用户的默认shell是什么
就是/etc/password的最后一列
root:x:0:0:root:/root:/bin/bash
然后在shell脚本第一行就写上什么shell
#!/bin/bash 参考技术C 输入 mkdir /home/testuser 通过返回结果,我可以看到执行是否成功
但是如果这个mkdir在脚本中,我如何知道 mkdir 是否执行成功?
因为我这里需要有个判断,如果成功了,我就做A事;如果没有成功,我就做B事
以上是关于如何在C语言中执行shell命令的主要内容,如果未能解决你的问题,请参考以下文章