问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

如何在C语言中执行shell命令

发布网友 发布时间:2022-04-23 20:51

我来回答

5个回答

热心网友 时间:2023-08-24 00:05

题主可以使用 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 <stdio.h>
#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 <stdio.h>
#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 <stdio.h>
#include <unistd.h>

int main() {

    if (execlp("ls", "ls", "-l", NULL) == -1)
        perror("Error Executing Command.\n");
    return 0;
    
}


如果改用 execvp 来写的话就是


#include <stdio.h>
#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 <stdio.h>
#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 <stdio.h>
#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 这句话就会被输出到屏幕上。

热心网友 时间:2023-08-24 00:06

可以通过system函数,调用shell命令。
1 函数原型:
int system(const char *cmd);
2 功能:
调用cmd内容的系统命令,即shell命令。
3 头文件:
stdlib.h
4 举例:
system("ls");
打印当前工作目录下的文件。

热心网友 时间:2023-08-24 00:06

1、可以使用system函数调用。system("shell_command");可以实现在shell中调用shell_command的作用。
2、例如设置网卡IP为192.168.1.100,可以写作
system("ifconfig eth0 192.168.1.100");

热心网友 时间:2023-08-24 00:07

system 这个函数可以帮到你。 参数就一个 就是shell命令

热心网友 时间:2023-08-24 00:07

参数type可使用“r”代表读取,“w”代表写入。依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。此外,所有使...
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
人字梯有什么安全隐患吗 怎样激发青春期孩子的内驱力 如何激发青春期孩子的内驱力 ...小题1:移船相近邀相见,添酒回灯重开宴。 , &amp;n... L1和L2串联 电压表并联在L1两端 当L1断路后 电压表测的为什么就成了电源... L1和L2串联,用电压表测L1两端的电压,L2不亮时,电流表为什么测的是电源电... 电路上传连两个灯泡L1与L2电压表测L1电压,当L1短路与断路时电压表情况... 对方拖着不办离婚手续该怎么办 计算机一级电子表格怎么拿分 如何配置思源黑体为latex中文字体? 思源黑体字体怎么安装 C语言能否用在shell脚本 c语言如何调用需传入参数的shell脚本 口碑最好的老人手机是什么? 华为nova5换内外屏多少钱? 华为手机通讯录的根目录在哪 固态硬盘带缓存和不带缓存的区别 华为手机的通讯录,放在哪个文件夹里 华为手机的通讯录在哪里 华为手机默认联系人和短信储存在什么位置? 华为手机通讯录权限在哪里打开 华为手机上的联系人在哪个文件夹里,我想找到文件夹,把里面的联系人拷... 苹果手机截完屏怎么立马保存 vivo手机截完屏以后怎样局部截屏 截屏问题,截完屏,图片在手机上停留时间太长怎么解决? 买的鸡肉有点味道了,怎么处理味道 买的鸡肉,回来没有及时处理,几个小时后在弄,肉有点臭了,怎么办 超市买的一小块鸡肉,回来怎么处理,再炒菜用 每次买鸡肉都只会炖汤,鸡肉除了炖汤还可以怎么做? 买来的鸡胸肉怎么处理,才能够更加鲜嫩多汁? 面试老师问我 为什么考辅警怎么回答? 在c\c++程序里怎么执行shell脚本命令? 如何将c语言的变量传递给shell脚本使用 linux C编程中怎样调用shell命令 能将c语言的预计用在shell脚本中吗,它的执行需要经过编译链接吗,为什么 如何在C语言中调用shell命令 能将c语言的语句用在shell脚本吗他的执行需要经过编译链接吗为什么 在Linux C语言下,可执行的Shell脚本文件与编译之后的C可执行文件的区别有哪些 ? 在 shell脚本中调用一个C语言的可执行程序,如何将C程序中printf的字符保存成到文件中? 学习先锋事迹的感受短30字? 读了许振超的事迹后,你有何感想? 学习英雄模范主要事迹有什么感悟 求几篇学习 先进事迹 的 心得体会学习 *** 先进事迹心得体会 学习了 *** 同志的先进事迹 求一篇学习先进典型、增强团队执行力心得 学习先锋事迹的感受怎样写? 关于学习廖俊波同志的先进事迹心得体会 推荐几个hiphop的视频 学习黄文秀同志先进事迹心得体会01 hip-hop是什么舞蹈? ghetto style,它是hiphop舞蹈的一个什么风格? hiphop和breaking有什么区别,breaking不是属于hiphop吗?