从execv运行mysql导入

问题描述:

pid_t childPid = fork(); 
if (childPid == (pid_t) 0)//zero success 
{ 
    const char *path = "/usr/local/mysql/bin/mysql"; 
    //doesn't work 
    //char * const parmList[] = {"--user=root", "test_db", NULL}; 
    //does work 
    char * const parmList[] = {"", "--user=root", "test_db", NULL}; 
    execv(path, parmList); 
    printf("ERROR:\tFork failed.\n"); 
} 
else if (childPid < (pid_t) 0)// -1 failure 
{ 
    /* The fork failed. */ 
    printf("ERROR:\tFork failed.\n"); 
    return EXIT_FAILURE; 
} 
else 
{ 
    while (true) { 
     //stay alive 
     sleep(1); 
    } 
} 
printf("done"); 
exit(0); 

我无法通过使用execv导入sql转储。你可以看到我无法使用第一个paramList登录,但第二个工作正常。无论如何,如果我添加到参数列表:从execv运行mysql导入

char * const parmList[] = {"", "--user=root", "test_db", "<", "/Users/joelsaltzman/Desktop/dump.sql", NULL}; 

输出显示命令行参数的mysql帮助,就像我输入错误的东西。 有谁知道如何让这个工作?

第一paramList是不正确的,因为第一个元素应该是你要执行程序的文件名:

的参数argv的是字符数组的指针,以null结尾的字符串。应用程序应确保该数组的最后一个成员是空指针。这些字符串将构成可用于新过程映像的参数列表 。 argv [0]中的值应该指向与其中一个exec函数启动的进程关联的文件名。

<输入重定向不起作用,因为这不是内核(它调用使用execv)的功能,但通常的Unix外壳。图书馆电话system是你正在寻找的。 (这也只是使用来自exec - 家庭电话,但拨打您的命令,那么这将支持<壳。)

请务必阅读手册页system(3),想想输入验证,如果你要传递它是一个可能受恶意用户影响的字符串。

+0

这是合法的(但非常奇怪)告诉'mysql'程序它被称为'--user = root',但这不会被程序视为选项参数。它也是合法的(但是_rather_奇怪)不通过提供一个空字符串来告诉程序它被称为什么。如果程序查看它的名字来决定它应该做什么,这可能很重要。如果一个程序的设计根据它所调用的名称而有所不同,就会发生这种情况。 (考虑'cc'和'gcc',它们是指向同一个可执行文件的链接;'c89'和'c99'是简单的脚本,而不是指向'gcc'的链接。) – 2012-02-11 20:19:13

第二个工作更好,因为第一个参数应该是命令名称。因此,MySQL从第二个参数开始读取。您应该使用命令名称(路径),而不是空字符串,但通常无关紧要。

您不能使用execv重定向,因为这是一个shell功能,并且execv不运行该shell。您可以执行/bin/sh,并使用参数告诉它运行mysql,或者您可以使用dup2将stdin更改为任何您想要的值。

改为使用popen()来启动mysql,然后自己将sql文件的内容写入进程。