当我使用命令及其参数调用execvp
时,有时该命令是不合法的。
例如,如果我使用分叉的 SON 进程在我的 shell(bash shell)中执行此操作:
$ ls ffdfdfd
则输出为:
$ ls: cannot access ffdfdfd: No such file or directory
现在,我想将该确切的消息传递给文件。我尝试过perror
,这样:
void directErrors(char * arg)
{
perror(arg); // execute the problem to screen
// now execute the problem to file
FILE* myFile = fopen("errors.log", "a");
if(myFile == NULL)
{
perror("fopen");
exit(-1);
}
fprintf(myFile, "%s: %sn", arg, strerror(errno));
fclose(myFile);
}
但它所做的只是编写该命令X
失败。
如何定向execvp
调用后获得的确切输出?
在我的代码中,我像这样调用execvp
:
executeCurrentCommand = execvp(*(arg)[0], *arg);
请记住,exec
的工作原理是将程序完全替换为您正在执行的程序。 因此,您在 exec() 调用后编写的任何代码都不会运行:
execvp(cmd, args);
/* This code is never reached. */
exec
调用返回的唯一方法是,如果您尝试调用的命令无法运行:例如,如果您尝试执行不存在的文件或没有执行权限的文件。
在您的情况下,命令 ( ls
) 确实存在,因此 exec 确实成功了...这意味着它之后的任何代码都不会运行。 ls
命令将像往常一样向 stderr 生成错误消息。
如果你想捕捉ls
的输出,你必须更加花哨。 例如,您可以打开一个文件以附加到日志文件,然后使用 dup()
将其复制为 stderr 文件描述符,然后执行 exec 调用。 新进程将继承该设置,ls
发送到 stderr 的所有输出都将追加到日志中。 如果你想同时捕获标准输出和标准,请将它们都删除。 这就是外壳等的做法。
顺便说一句,使用*(arg)[0]
对我来说看起来很奇怪:你为什么要使用它? 更合理的是(*arg)[0]
(我认为)。