Linux fork/exec 到同一目录中的应用程序
Posted
技术标签:
【中文标题】Linux fork/exec 到同一目录中的应用程序【英文标题】:Linux fork/exec to application in same directory 【发布时间】:2011-02-08 15:29:01 【问题描述】:是否有exec
变体会使用当前应用程序目录来定位目标程序?
我正在使用 C++ 和 Qt 来实现“最后一搏”错误报告系统。使用Google Breakpad,我可以创建一个小型转储并直接执行到处理程序。因为我的应用程序处于不稳定状态,我只想使用最少的依赖项来分叉并启动一个单独的错误处理过程。错误报告应用程序将部署在与应用程序可执行文件相同的目录中。
我对@987654323@ 和exec
选项非常陌生,并且在搜索路径中找不到包含当前应用程序目录的exec
选项。这是我目前所拥有的:
static bool dumpCallback(const char* /*dump_path*/,
const char* /*minidump_id*/,
void* /*context*/,
bool succeeded)
pid_t pid = fork();
if (pid == 0)
// This is what I would *like* to work.
const char* error_reporter_path = "error_reporter";
// This works, but requires hard-coding the entire path, which seems lame,
// and really isn't an option, given our deployment model.
//
// const char* error_reporter_path = "/path/to/app/error_reporter";
// This also works, but I don't like the dependency on QApplication at this
// point, since the application is unstable.
//
// const char* error_reporter_path =
// QString("%1/%2")
// .arg(QApplication::applicationDirPath())
// .arg("error_reporter").toLatin1().constData();
execlp(error_reporter_path,
error_reporter_path,
(char *) 0);
return succeeded;
关于使用fork
和exec
的最佳实践的任何其他建议也将不胜感激;这是我第一次使用它们。在这一点上,我只关心 Linux(Ubuntu、Fedora);稍后我将研究其他操作系统的处理程序。
【问题讨论】:
【参考方案1】:你要求的其实很简单:
pid_t pid = fork();
if (pid == 0)
const char* error_reporter_path = "./error_reporter";
execl(error_reporter_path,
error_reporter_path,
(char *) 0);
_exit(127);
else
return pid != -1;
但它不会做你想做的事。 当前工作目录不一定与包含当前可执行文件的目录相同——事实上,几乎在所有情况下都不会。
我建议您将error_reporter_path
设为全局变量,并在main
的开头使用您的“选项2”代码对其进行初始化
QString("%1/%2")
.arg(QApplication::applicationDirPath())
.arg("error_reporter").toLatin1().constData();
QString
对象(不仅仅是它的constData
)必须在程序的整个生命周期内都存在,但这应该不是问题。请注意,您应该转换为 UTF-8,而不是 Latin1(我猜 QString
使用宽字符?)
【讨论】:
【参考方案2】:我认为你有两个选择:
-
添加“.”到 $PATH。
将
getcwd()
的结果添加到可执行文件名称中。
【讨论】:
【参考方案3】:您应该在程序启动时构建您的助手可执行文件的路径,并将其保存在某处(在全局或静态变量中)。如果您只需要在 Linux 上运行,您可以通过读取 /proc/self/exe 来获取可执行文件的位置。像这样的:
// Locate helper binary next to the current binary.
char self_path[PATH_MAX];
if (readlink("/proc/self/exe", self_path, sizeof(self_path) - 1) == -1)
exit(1);
string helper_path(self_path);
size_t pos = helper_path.rfind('/');
if (pos == string::npos)
exit(1);
helper_path.erase(pos + 1);
helper_path += "helper";
摘自此处的完整工作示例:http://code.google.com/p/google-breakpad/source/browse/trunk/src/client/linux/minidump_writer/linux_dumper_unittest.cc#92
【讨论】:
【参考方案4】:在任何情况下都不要添加“。”到 $PATH !!
1234563然后你必须考虑如何处理结果文件名中的符号链接。即使在那之后,您也永远无法确定 argv[0] 是否设置为用于执行程序的命令选项 3:
在您的可执行文件中硬编码完整的文件名,但使用配置脚本来设置文件名。 (您使用的是配置脚本,对吗?)
选项 4;
不要调用 exec。您不必在分叉后调用 exec 。假装你刚刚进入“main”,当你的错误报告完成后调用“exit”。
【讨论】:
感谢您的回答;你能详细说明一下:(选项1)如果我添加“。”会发生什么坏事到 $PATH? (选项 3)不,不使用配置脚本;您能否添加指向您最喜欢的文章的链接,其中概述了业务线应用程序的好处和实施? (选项4)对不起,不明白。为什么我在调用fork
之后还要假装进入main
?
当前工作目录及其内容由运行程序的人控制。因此,如果您 exec
当前工作目录中具有固定名称的程序 - 无论您如何操作;添加“。”到 $PATH 只是最明显的——你将你的程序拥有的任何额外特权交给其他人控制的程序。 -- 你实际上并不想要当前的工作目录。您将它与包含可执行文件的目录混淆了。看我的回答。
@Dave:关于为什么将当前目录“.
”添加到您的$PATH
环境变量是一个安全漏洞的其他说明,请参见此处:fixunix.com/unix/88657-whats-wrong-having-my-path.html。以上是关于Linux fork/exec 到同一目录中的应用程序的主要内容,如果未能解决你的问题,请参考以下文章
Linux下进程的创建(system(); fork(); exec*())
Terraform 资源 AWS LAMBDA GO 错误:“fork/exec /var/task/main:没有这样的文件或目录”