zoukankan      html  css  js  c++  java
  • linux 调用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 
     
     在CODE上查看代码片派生到我的代码片
    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 ");  
    15. }  

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

    2.2  execvp 函数

    [cpp] view plain copy 
     
     在CODE上查看代码片派生到我的代码片
    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 ");  
    12. }  

    2.3 execve 函数

    [cpp] view plain copy 
     
     在CODE上查看代码片派生到我的代码片
    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 ");  
    13. }  

    2.4 execl 函数

    [cpp] view plain copy 
     
     在CODE上查看代码片派生到我的代码片
    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 ");  
    11. }  

    2.5 execlp 函数

    [cpp] view plain copy 
     
     在CODE上查看代码片派生到我的代码片
    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 ");  
    11. }  



    2.6 execle 函数

    [cpp] view plain copy 
     
     在CODE上查看代码片派生到我的代码片
      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 ");  
      12. }  
  • 相关阅读:
    Android 2.2 r1 API 中文文档系列(11) —— RadioButton
    Android API 中文 (15) —— GridView
    Android 中文 API (16) —— AnalogClock
    Android2.2 API 中文文档系列(7) —— ImageButton
    Android2.2 API 中文文档系列(6) —— ImageView
    Android 2.2 r1 API 中文文档系列(12) —— Button
    Android2.2 API 中文文档系列(8) —— QuickContactBadge
    [Android1.5]TextView跑马灯效果
    [Android1.5]ActivityManager: [1] Killed am start n
    Android API 中文(14) —— ViewStub
  • 原文地址:https://www.cnblogs.com/plwing/p/13578575.html
Copyright © 2011-2022 走看看