“sh -c”不接受额外参数的问题,UNIX,使用execve()

时间:2011-12-04 02:06:10

标签: bash unix arguments sh execve

我正试图找出如何正确使用sh -cbash -c

我可以轻松地运行一个简单的命令,如"sh -c ls"而无需参数。

当我试图添加参数时,问题出现了。 要做ls -ltga,我必须这样做:

sh -c "ls -ltga"

这不是一个大问题,除了我试图编写自己的小shell程序, 当我使用execve时,我尝试:

Argument #:  string
         0:  sh
         1:  -c
         2:  "ls
         3:  -ltga"

它给了我一个错误,说它在找到下一个'"'之前达到了EOF

我也试过了:

         0:  sh
         1:  -c
         2:  "ls -ltga"

它返回给我说它找不到名为"ls -ltga"

的文件/脚本

有人知道我做错了吗?

2 个答案:

答案 0 :(得分:3)

你不应该在execve()的参数中加注引号。它应该像这样调用:

char *args = { "sh", "-c", "ls -ltga", 0};
execve("/bin/sh", args);

execve()的第一个参数必须是可执行文件的路径(通常是完整路径)。

答案 1 :(得分:0)

shell期望的符号是sh -c "command plus arguments"。所以,你作为“解决方法”所做的事实上是shell要求的。

另一种方法是使用execvp()来运行ls

char *args[] = { "ls", "-lgta", 0 };
execvp(args[0], args);
fprintf(stderr, "Oops: failed to find 'ls'\n");
exit(1);

  

我还需要能够运行带有正则表达式的命令,例如"rm *.c",但是无法在execve()内运行(大多数情况下),所以我试图通过将整个命令集传递给“sh -c”。有什么想法吗?

如果你想要元字符扩展,你必须调用shell来执行它(或者编写相同的代码来执行它 - 这是可能的,并且对于标准POSIX函数来说并不太困难)。

要运行“rm *.c”,请使用:

char *args[] = { "/bin/sh", "-c", "rm *.c", 0 };
execv(args[0], args);

或者,如果你有一个环境,你需要专门传递(我认为它由envp指出):

char *args[] = { "/bin/sh", "-c", "rm *.c", 0 };
execve(args[0], args, envp);

exec*函数调用后不要忘记错误处理;它可能会失败。