软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 编程语言 -> linux下如何用c语言调用shell命令 -> 正文阅读

[编程语言]linux下如何用c语言调用shell命令


C程序调用shell脚本共有三种法子 :system()、popen()、exec系列数call_exec1.c ,
system() 不用你自己去产生进程,它已经封装了,直接加入自己的命令
exec 需要你自己 fork 进程,然后exec 自己的命令

popen() 也可以实现执行你的命令,比system 开销小


方法一、system()的使用,我直接上代码吧

 
int system(const char *command);



我在/home/book/shell新建一个test.sh文件如下:


<span style="font-size:18px;"><span style="font-size:18px;">#!bin/bash
echo $HOME
echo "the is test!"</span></span>

test.c文件如下:


<span style="font-size:18px;"><span style="font-size:18px;">#include<stdlib.h>
  
int   main()
{
  system("bash /home/book/shell/test.sh"); /* chmod +x test.sh ,路径前面要加上bash */
  return 0;  
}</span></span>



执行如下命令来编译:
<span style="font-size:18px;">gcc test.c -o test
</span>


测试命令:
<span style="font-size:18px;">./test</span>

结果如下:

<span style="font-size:18px;">/root
the is test!</span>


方法二:popen() 会调用fork()产生 子历程,然后从子历程中调用/bin/sh -c来履行 参数command的指令。参数type可应用 “r”代表读取,“w”代表写入。遵循此type值,popen()会建立 管道连到子历程的标准 输出设备 或标准 输入设备 ,然后返回一个文件指针。随后历程便可利用 此文件指针来读取子历程的输出设备 或是写入到子历程的标准 输入设备 中。此外,所有应用 文 件指针(FILE*)操作的函数也都可以应用 ,除了fclose()以外。
 
    返回值:若成功 则返回文件指针,否则返回NULL,差错 原因存于errno中。注意:在编写具SUID/SGID权限的程序时请尽量避免应用 popen(),popen()会继承环境变量,通过环境变量可能会造成系统安全的问题


FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);

其他不用改变我们直接修改test.c文件:

#include<stdio.h>
int  main()
{
    char buffer[80];
     FILE  *fp=popen("bash /home/book/shell/test.sh","r");
     fgets(buffer,sizeof(buffer),fp);
     printf("%s",buffer);
     pclose(fp);
return 0;
}



方法三:exec函数簇  (我不太懂,copy别人的,也没有验证,习惯方法一)
需要注意的是exec并不是1个函数, 其实它只是一组函数的统称, 它包括下面6个函数:


#include <unistd.h>  
  
int execl(const char *path, const char *arg, ...);  
  
int execlp(const char *file, const char *arg, ...);  
  
int execle(const char *path, const char *arg, ..., char *const envp[]);  
  
int execv(const char *path, char *const argv[]);  
  
int execvp(const char *file, char *const argv[]);  
  
int execve(const char *path, char *const argv[], char *const envp[]; 

可以见到这6个函数名字不同, 而且他们用于接受的参数也不同.
       实际上他们的功能都是差不多的, 因为要用于接受不同的参数所以要用不同的名字区分它们, 毕竟c语言没有函数重载的功能嘛..  
 
       但是实际上它们的命名是有规律的:
       exec[l or v][p][e]
       exec函数里的参数可以分成3个部分,      执行文件部分,     命令参数部分,   环境变量部分.
        例如我要执行1个命令   ls -l /home/gateman  
        执行文件部分就是  "/usr/bin/ls"
        命令参赛部分就是 "ls","-l","/home/gateman",NULL              见到是以ls开头 每1个空格都必须分开成2个部分, 而且以NULL结尾的啊.
        环境变量部分, 这是1个数组,最后的元素必须是NULL 例如  char * env[] = {"PATH=/home/gateman", "USER=lei", "STATUS=testing", NULL};
        
        好了说下命名规则:
        e后续,  参数必须带环境变量部分,   环境变零部分参数会成为执行exec函数期间的环境变量, 比较少用
        l 后续,   命令参数部分必须以"," 相隔, 最后1个命令参数必须是NULL
        v 后续,   命令参数部分必须是1个以NULL结尾的字符串指针数组的头部指针.         例如char * pstr就是1个字符串的指针, char * pstr[] 就是数组了, 分别指向各个字符串.
        p后续,   执行文件部分可以不带路径, exec函数会在$PATH中找
          
         还有1个注意的是, exec函数会取代执行它的进程,  也就是说, 一旦exec函数执行成功, 它就不会返回了, 进程结束.   但是如果exec函数执行失败, 它会返回失败的信息,  而且进程继续执行后面的代码!


       通常exec会放在fork() 函数的子进程部分, 来替代子进程执行啦, 执行成功后子程序就会消失,  但是执行失败的话, 必须用exit()函数来让子进程退出!
       下面是各个例子:

2.1  execv 函数


[cpp] view plain copy
 [img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/ico_fork.svg
  1. int childpid;  
  2. int i;  
  3.   
  4. if (fork() == 0){  
  5.     //child process  
  6.     char * execv_str[] = {"echo""executed by execv",NULL};  
  7.     if (execv("/usr/bin/echo",execv_str) <0 ){  
  8.         perror("error on exec");  
  9.         exit(0);  
  10.     }  
  11. }else{  
  12.     //parent process  
  13.     wait(&childpid);  
  14.     printf("execv done\n\n");  
  15. }  

注意字符串指针数组的定义和赋值

2.2  execvp 函数


[cpp] view plain copy
 [img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/ico_fork.svg
  1. if (fork() == 0){  
  2.     //child process  
  3.     char * execvp_str[] = {"echo""executed by execvp",">>""~/abc.txt",NULL};  
  4.     if (execvp("echo",execvp_str) <0 ){  
  5.         perror("error on exec");  
  6.         exit(0);  
  7.     }  
  8. }else{  
  9.     //parent process  
  10.     wait(&childpid);  
  11.     printf("execvp done\n\n");  
  12. }  



2.3 execve 函数


[cpp] view plain copy
 [img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/ico_fork.svg
  1. if (fork() == 0){  
  2.     //child process  
  3.     char * execve_str[] = {"env",NULL};  
  4.     char * env[] = {"PATH=/tmp""USER=lei""STATUS=testing", NULL};  
  5.     if (execve("/usr/bin/env",execve_str,env) <0 ){  
  6.         perror("error on exec");  
  7.         exit(0);  
  8.     }  
  9. }else{  
  10.     //parent process  
  11.     wait(&childpid);  
  12.     printf("execve done\n\n");  
  13. }  





2.4 execl 函数


[cpp] view plain copy
 [img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/ico_fork.svg
  1. if (fork() == 0){  
  2.     //child process  
  3.     if (execl("/usr/bin/echo","echo","executed by execl" ,NULL) <0 ){  
  4.         perror("error on exec");  
  5.         exit(0);  
  6.     }  
  7. }else{  
  8.     //parent process  
  9.     wait(&childpid);  
  10.     printf("execv done\n\n");  
  11. }  



2.5 execlp 函数


 
[cpp] view plain copy
 [img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/ico_fork.svg
  1. if (fork() == 0){  
  2.     //child process  
  3.     if (execlp("echo","echo","executed by execlp" ,NULL) <0 ){  
  4.         perror("error on exec");  
  5.         exit(0);  
  6.     }  
  7. }else{  
  8.     //parent process  
  9.     wait(&childpid);  
  10.     printf("execlp done\n\n");  
  11. }  




2.6 execle 函数


[cpp] view plain copy
 [img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/CODE_ico.png[img]http://blog.csdn.net/qq_21792169/article/details/51045846/https:/code.csdn.net/assets/ico_fork.svg
  1. if (fork() == 0){  
  2.     //child process  
  3.     char * env[] = {"PATH=/home/gateman""USER=lei""STATUS=testing", NULL};  
  4.     if (execle("/usr/bin/env","env",NULL,env) <0){  
  5.         perror("error on exec");  
  6.         exit(0);  
  7.     }  
  8. }else{  
  9.     //parent process  
  10.     wait(&childpid);  
  11.     printf("execle done\n\n");  
  12. }  





......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-03 20:43:25  
编程语言 最新文章
Java面试题(1)
ReactiveX序列——RxSwift
C++STL之ACM相关知识大全
c++中vector向量几种情况的总结(向量指针,
SSH框架整合demo
JAX
UVA
curl备忘(1)
C#机房重构——万事开头难(二)
OJ刷题
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年1日历
2018-1-16 17:23:04
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --