【问题标题】:Using execv (C language) to run commands from a linux command prompt使用 execv(C 语言)从 linux 命令提示符运行命令
【发布时间】:2012-09-25 03:30:28
【问题描述】:

到目前为止,我唯一感到困惑的部分是如何使用第一个参数设置 execv 作为当前工作目录。我已经尝试了两个“。”和“~”,都没有对屏幕执行任何操作; “/”也一样。和“/~”。我对如何让 execv 运行这样的事情感到困惑:

$ ./prog ls -t -al

并让它在当前目录或与文件所在目录相同的目录中执行程序执行后的命令(存储在argv中)(根据使用者的不同而有所不同。)

我的代码:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

void main(int argc, char *argv[])
{
    int pid;
    int count = 0;
    char *argv2[argc+1];

    for(count = 0; count < argc-1; count++){
        argv2[count] = argv[count+1];
        printf("Argv2: %s\n", argv2[count]);  //just double checking
        argv2[argc-1] = NULL;
    }

    pid = fork();
    if(pid == 0){
        printf("Child's PID is %d. Parent's PID is %d\n", (int)getpid, (int)getppid());
        execv(".", argv2);       //<---- confused here
    }
    else{
        wait(pid);
        exit(0);
    }
}

一些示例输出:

$ ./prog ls -t -al
Argv2: ls
Argv2: -t
Argv2: -al
Child's PID is 19194. Parent's PID is 19193

【问题讨论】:

  • 我建议增加“编译器警告”的设置。它应该告诉你从 main 返回 int。在我的系统上,它还抱怨缺少#include 。并且 wait 将整数指针作为参数,而不是整数。

标签: c unix argv execv


【解决方案1】:
/* main() returns int */
int main(int argc, char *argv[])
{
        int pid;

        pid = fork();
        if(pid == 0){
                printf("Child's PID is %d. Parent's PID is %d\n"
                      , (int)getpid, (int)getppid());
                execv(argv[1], argv+1);
        }
        else{
        wait(NULL);
        exit(0);
        }

        return 0;
}

更新:execv() 需要可执行文件的绝对路径;对于当前目录中的文件,您必须构造该路径(例如通过 pwd())。如果您希望通过 $PATH 环境变量搜索可执行文件,可以使用 execvp(),它会为您完成所有搜索。

【讨论】:

    【解决方案2】:

    我猜 execv 是需要使用的。 execvp 更好,因为它会在你的 PATH 设置中查找命令。

    execv(".", argv2);       //<---- confused here
    

    ...

    #include <errno.h>
    #include <string.h>
    if ( execv(argv2[0],argv2) )
    {
        printf("execv failed with error %d %s\n",errno,strerror(errno));
        return 254;  
    }
    

    wait(pid);
    

    ...

    pid_t wait_status = wait(&pid);
    

    【讨论】:

      【解决方案3】:

      按照惯例,第一个参数应该指向与正在执行的文件关联的文件名。 你要执行ls,所以第一个参数应该是/bin/ls,也就是说代码是

      execv("/bin/ls", argv2);
      

      你可以试试

      【讨论】:

        【解决方案4】:

        execv() 的第一个参数不是要运行的目录,而是要执行的文件的路径。默认情况下,您的 exec 程序将在调用者当前目录的上下文中运行。

        【讨论】:

        • 好吧,我也试过用execv("/prog.c", argv2);运行它,但这也不起作用。我无法将文件的路径硬编码到程序中,因为路径会因运行代码的人而异。有什么建议么? (对不起,这太模棱两可了,我的教授不是一流的,如果你明白我的意思)。
        • 并且还尝试创建一个文件夹,然后创建子文件夹只是为了让它成为“/Lab1/Prog/”。还是什么都没有:/
        • /prog.c 不是相对路径 - 它是根目录中 prog.c 文件的完整路径。此外,execv 的第一个参数应该是可执行文件,而不是 c 源文件。我对你在这里想要做什么感到困惑。
        • @baelix execv("/prog.c", argv2);会尝试运行一个 .c 文件,这是没有意义的。根据您的实际描述和您发布的代码,您只需要执行 execv(argv2[0], argv2); 即可编译并运行您自己的程序,就像您已经提到的那样:./prog ls -t -al
        【解决方案5】:

        第一个参数是你要运行的程序的绝对路径;换句话说,您在终端中键入的命令的第一部分。您可以使用命令whereis 找到程序所在的位置。此外,execv 函数可以为您查找路径,这使您的代码更具可移植性。

        【讨论】:

          【解决方案6】:

          供您参考的代码示例:

          #include <stdio.h>
          
          int main() {
          
              int ret = fork();
              if(ret == 0)
              {
                      char *params[4]  = {"/bin/ls", "-l",0}; //cmd params filled
          
                      int res = execv( "/bin/ls" , params);  //parameters for cmd
                      //int res = execv( "/bin/ls" , NULL);  //this is fail case (when child-exit with -1 status can be seen)
                      printf("\n child exiting (%d) .. \n", res); //on successful execution of cmd, this exit never appears
                  }
                  else
                  {
                      waitpid(ret,1,0);
                      printf("parent exiting\n");
              }
          
              return 1;
           }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-08-01
            • 2010-11-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-01
            相关资源
            最近更新 更多