我想创建一个 makefile,其中目标和依赖项不是本地文件,而是位于某个 AWS/S3 存储桶中。
考虑以下示例,该示例只需将“data_raw”文件复制到“obj1”,然后复制到“obj2”(您需要将“bucket”编辑到您拥有的某个存储桶,并在运行之前创建一些“data_raw”文件):
# local, works fine
bucket = /tmp/test/
cp = cp
# remote, does not work
bucket = s3://bucket/test/
cp = s3cmd cp
all : $(bucket)obj2
$(bucket)obj2 : $(bucket)obj1
$(cp) $(bucket)obj1 $(bucket)obj2
$(bucket)obj1 :
$(cp) $(bucket)raw_data $(bucket)obj1
我遇到的错误是:
makefile:9: *** target pattern contains no `%'. Stop.
用于:
all : $(bucket)obj2
我怀疑 make 根本不理解远程 URI(“s3://xxx”)。
我能找到的所有示例/文档似乎都隐式引用本地文件来获取目标和依赖项。广泛的谷歌搜索只产生了一些关于为 s3 创建 ant 任务的看似未完成的想法 (http://code.google.com/p/awstasks/)。
这是在 Python 中运行多个复杂/错综复杂的 MapReduce 作业的背景下。
我宁愿使用 GNU make,但肯定会考虑替代方案。
我总是可以创建一些远程目标的光本地镜像,但肯定有更好的方法吗?
提前致谢!
尼克
一种有效的解决方法是在本地安装 S3 存储桶。
在Linux上,也许可以使用fuse/s3fs。这可能也适用于 MacOS,但安装起来似乎很麻烦。我转而使用商业软件transmit(单击“挂载为磁盘”)。这样,上面的例子对我来说是有用的:
bucket = /Volumes/s3.amazonaws.com/bucket/test/
cp = cp
在此示例中,我们使用“cp”,因为“s3cmd cp”拒绝本地 uri。在(我的)现实生活中的示例中,该命令将被一些需要实际 s3 输入/输出 uri 的 python map-reduce 脚本替换。
为了保持整洁,本地安装的文件可能应该有一个前缀变量(“/Volumes/s3.amazonaws.com/”)(用于 Make 测试存在性/最新性)和一个前缀变量(“s3://”) 让构建命令指向实际数据(数据将由 EC2 实例通过 MapReduce 进行处理,我们绝对不想在本地下载所有内容)。
请记住,S3 仅具有最终一致性。还要确保为了测试是否存在和最新性,整个文件不会在本地下载(在这种情况下,应该使用一些虚拟文件)。
希望有帮助。
如果有人有更直接的方法(无需本地安装),我很感兴趣。
尼克
我喜欢你正在寻找的东西。但如果这被内置到 makefile 和
make
本身中,我会感到惊讶;正如您正确指出的那样,“Linux”的方法是找到一种将 S3 作为文件系统挂载的方法。
但是,如果您要包含“make-like”,我会推荐来自 Ruby 宇宙的
rake
。自从我愤怒地使用它以来已经有一段时间了,但我记得它允许您编写自定义扩展,以便您的源和目标不需要位于本地文件系统上。
如果 Ruby 在我倾向于使用的系统上更流行一点(相当简单的 EC2 和 ECS 系统,没有管理员权限),我会将我的 make 文件切换为 rake 文件。