Boost.Process 从不同工作目录启动 Docker 为何报错?
数据小许
结论
若要让程序不依赖当前工作目录,可以先用 boost::process::search_path("docker") 从 PATH 中查找 Docker 可执行文件,再将程序路径和参数分别传给 boost::process::system。Boost.Process 1.74 文档说明,单个字符串参数会按命令行处理;也支持传入可执行文件路径和独立参数,并通过 search_path 查找可执行文件。Boost.Process 1.74 教程
#include <boost/process.hpp>
int main()
{
namespace bp = boost::process;
const auto docker = bp::search_path("docker");
if (docker.empty()) {
return 127; // PATH 中没有找到 docker
}
return bp::system(docker, "run", "--detach", "--rm", "3151172cc781");
}
为什么这样写
报错中的 execve failed: Permission denied 表示操作系统拒绝执行尝试启动的文件。现有日志没有显示实际尝试执行的路径,因此无法确认是哪个路径或权限设置造成了差异。仅凭这段日志,也无法判断 Docker 或镜像本身是否有问题。
search_path 会按当前进程的 PATH 查找名为 docker 的可执行文件,并返回其路径。将该路径作为可执行文件传入,再把 run、--detach、--rm 和镜像 ID 分别作为参数传入,可以避免依赖相对路径和当前目录进行命令解析。Boost.Process 1.74 教程
检查仍然报错时的路径和权限
如果调用仍然失败,可以分别在两个工作目录下检查程序运行时的 PATH 和 Docker 路径:
command -v docker
ls -l "$(command -v docker)"
也可以运行 strace -f -e execve build/test,查看进程实际尝试执行的路径。检查两个启动环境中的 PATH 是否相同,并确认找到的文件具有执行权限。终端中的 PATH 和工作目录可能与启动 C++ 程序时使用的环境不同。
注意事项
bp::system会等待子进程结束,并返回其退出码;上例将这个退出码作为main的返回值。- 如果
search_path找不到docker,它会返回空路径,因此代码会先检查这一情况。 - 如果部署环境固定,也可以直接使用 Docker 的绝对路径。具体路径应以该环境中
command -v docker的结果为准。
备注:内容仅供参考。
