无法以正确的方式执行其他程序
Can't exec other programs in a proper way
我正在尝试从我自己的程序中执行另一个程序,但我不明白一些事情。所以我写了这段代码:
void run() {
cout << "##Run" << endl;
pid_t process_id = fork();
if (process_id == 0) {
char* args[] = { "sudo", "ls", "-l" };
auto i = execvp("sudo", args);
cout << "#Result: " << i << endl;
return;
} else if (process_id < 0) {
throw std::runtime_error("fork() failed");
} else if (process_id > 0) {
wait(&process_id);
}
return;
}
void run_decorator() {
cout << "###Run decorator: " << endl;
run();
}
int main() {
run();
run_decorator();
return 0;
}
输出为
##Run
total 88
-rwxr-xr-x 1 bezik bezik 77560 Nov 29 19:53 colors
-rwxr-xr-x 1 bezik bezik 63 Nov 26 21:45 compile
drwxr-xr-x 2 bezik bezik 4096 Nov 26 20:46 headers
drwxr-xr-x 2 bezik bezik 4096 Nov 23 00:48 sources
###Run decorator:
##Run
#Result: -1
谁能给我解释一下,为什么从 run_decorator() 函数调用时 execvp 失败?
仔细阅读 execvp(3) 的文档。它说 execl
等...:
The first argument, by convention, should point to
the filename associated with the file being executed. The list of
arguments must be terminated by a null pointer, and, since these are
variadic functions, this pointer must be cast (char *) NULL
.
关于execvp
:
The array of pointers must be terminated by a null pointer.
所以你应该编码:
char* args[] = { "sudo", "ls", "-l", NULL };
execvp("sudo", args);
顺便说一句,execvp
根本不 return, 除了 失败。调用后无需保留其结果。
但是您需要在 execvp
return 时(这只会在失败时发生)显示一些错误消息。我建议:
perror("execvp");
exit(EXIT_FAILURE);
你可以找到有效的调用参数,在那种情况下,_exit(2) instead of exit(3). I still prefer exit
(because it would flush the stdio buffers and run atexit(3)-注册的处理程序)。
Can someone please explain to me, why execvp
failed
是的,errno(3). Which is used by perror(3)。
不要忘记仔细阅读每个使用函数的文档。对于系统调用(在 syscalls(2)) and standard C library functions (see intro(3) 中列出),您通常应该处理失败情况(通常使用 errno
,至少通过 perror
然后 exit
)
我不明白你为什么需要 sudo
和 ls
。在少数情况下这可能有用,因为大多数时候你的 working directory is listable (then sudo
is useless), and in that case you could even use opendir(3), readdir(3) with stat(2)(所以不需要 fork
然后 execvp
/bin/ls
程序)。
另请阅读 setuid techniques in execve(2) and credentials(7) (and setreuid(2)). See this(您可以使用自己的 setuid 程序避免 sudo
)。
顺便说一句,你应该编译 with all warnings and debug info (g++ -Wall -Wextra -g
with GCC) and use the debugger gdb
(and perhaps strace(1) and valgrind(1)).
我正在尝试从我自己的程序中执行另一个程序,但我不明白一些事情。所以我写了这段代码:
void run() {
cout << "##Run" << endl;
pid_t process_id = fork();
if (process_id == 0) {
char* args[] = { "sudo", "ls", "-l" };
auto i = execvp("sudo", args);
cout << "#Result: " << i << endl;
return;
} else if (process_id < 0) {
throw std::runtime_error("fork() failed");
} else if (process_id > 0) {
wait(&process_id);
}
return;
}
void run_decorator() {
cout << "###Run decorator: " << endl;
run();
}
int main() {
run();
run_decorator();
return 0;
}
输出为
##Run
total 88
-rwxr-xr-x 1 bezik bezik 77560 Nov 29 19:53 colors
-rwxr-xr-x 1 bezik bezik 63 Nov 26 21:45 compile
drwxr-xr-x 2 bezik bezik 4096 Nov 26 20:46 headers
drwxr-xr-x 2 bezik bezik 4096 Nov 23 00:48 sources
###Run decorator:
##Run
#Result: -1
谁能给我解释一下,为什么从 run_decorator() 函数调用时 execvp 失败?
仔细阅读 execvp(3) 的文档。它说 execl
等...:
The first argument, by convention, should point to the filename associated with the file being executed. The list of arguments must be terminated by a null pointer, and, since these are variadic functions, this pointer must be cast
(char *) NULL
.
关于execvp
:
The array of pointers must be terminated by a null pointer.
所以你应该编码:
char* args[] = { "sudo", "ls", "-l", NULL };
execvp("sudo", args);
顺便说一句,execvp
根本不 return, 除了 失败。调用后无需保留其结果。
但是您需要在 execvp
return 时(这只会在失败时发生)显示一些错误消息。我建议:
perror("execvp");
exit(EXIT_FAILURE);
你可以找到有效的调用参数,在那种情况下,_exit(2) instead of exit(3). I still prefer exit
(because it would flush the stdio buffers and run atexit(3)-注册的处理程序)。
Can someone please explain to me, why
execvp
failed
是的,errno(3). Which is used by perror(3)。
不要忘记仔细阅读每个使用函数的文档。对于系统调用(在 syscalls(2)) and standard C library functions (see intro(3) 中列出),您通常应该处理失败情况(通常使用 errno
,至少通过 perror
然后 exit
)
我不明白你为什么需要 sudo
和 ls
。在少数情况下这可能有用,因为大多数时候你的 working directory is listable (then sudo
is useless), and in that case you could even use opendir(3), readdir(3) with stat(2)(所以不需要 fork
然后 execvp
/bin/ls
程序)。
另请阅读 setuid techniques in execve(2) and credentials(7) (and setreuid(2)). See this(您可以使用自己的 setuid 程序避免 sudo
)。
顺便说一句,你应该编译 with all warnings and debug info (g++ -Wall -Wextra -g
with GCC) and use the debugger gdb
(and perhaps strace(1) and valgrind(1)).