从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)
,想想输入验证,如果你要传递它是一个可能受恶意用户影响的字符串。
答
第二个工作更好,因为第一个参数应该是命令名称。因此,MySQL从第二个参数开始读取。您应该使用命令名称(路径),而不是空字符串,但通常无关紧要。
您不能使用execv
重定向,因为这是一个shell功能,并且execv
不运行该shell。您可以执行/bin/sh
,并使用参数告诉它运行mysql
,或者您可以使用dup2
将stdin更改为任何您想要的值。
答
改为使用popen()
来启动mysql,然后自己将sql文件的内容写入进程。
这是合法的(但非常奇怪)告诉'mysql'程序它被称为'--user = root',但这不会被程序视为选项参数。它也是合法的(但是_rather_奇怪)不通过提供一个空字符串来告诉程序它被称为什么。如果程序查看它的名字来决定它应该做什么,这可能很重要。如果一个程序的设计根据它所调用的名称而有所不同,就会发生这种情况。 (考虑'cc'和'gcc',它们是指向同一个可执行文件的链接;'c89'和'c99'是简单的脚本,而不是指向'gcc'的链接。) – 2012-02-11 20:19:13