gsutil cp 管道在 docker 容器中作为 bash exec 命令失败

Posted

技术标签:

【中文标题】gsutil cp 管道在 docker 容器中作为 bash exec 命令失败【英文标题】:gsutil cp pipe fails in docker container as a bash exec command 【发布时间】:2020-09-24 08:18:15 【问题描述】:

我正在尝试在 cloud-sdk Linux 容器中运行一个 bash 脚本作为 ETL 管道的一部分,基本上是尝试使用 gsutilsed 来解决 Cloud SQL 导出 mysql csv 数据的方式的问题(空值被写成一个奇怪的、未封闭的引用工件,"N,需要在数据可以继续移动或解析之前将其删除。对于 Cloud SQL 团队来说,这一直是一个悬而未决的问题超过 2 年)。

命令是

gsutil cp gs://bucket/dir/file.csv - | sed 's/"N,/,/g' | gsutil cp - gs://bucket/dir/file.csv

还有错误: CommandException: cp: "gs://bucket/dir/file.csv" and "gs://bucket/dir/file.csv" are the same file - abort.

我也试过把管道分成两个步骤:

gsutil cp gs://bucket/dir/file.csv - | sed 's/"N,/,/g' > file.csv &&
gsutil cp file.csv gs://bucket/dir

但这也失败了,同样的错误,这对我来说毫无意义。第一个在 CLI 中运行直到完成,尽管进入 GCS 的文件有 0 个字节。第二个在 CLI 中可以正常工作,但在作为 Docker 容器执行的 bash 命令调用时就不行。

我所能想象的只是这两个命令同时运行,因此正试图同时访问同一个资源,但操作的顺序不应该是这种情况——除非 exec for容器不等待操作完成?

编辑:嗯,cp - 是一个流式处理,所以我想这会持续将输入通过管道传输到 sed 中,并且 sed 必须在某处写入,因此 sed 必须将输入直接流式传输回 gcs,尽管更改输出文件名并不能解决错误。并且 2 应该可以工作,除非 && 之后的第二个命令在 cp - 继续流式传输时执行(在此处更改输出文件名也不能解决问题)。

【问题讨论】:

【参考方案1】:

您可以尝试将文件复制到另一个存储桶:

gsutil cp gs://[SOURCE_BUCKET_NAME]/[SOURCE_OBJECT_NAME] gs://[DESTINATION_BUCKET_NAME]/[NAME_OF_COPY]

然后在文件中进行更改(在第二个存储桶中):

sed 's/"N,/,/g' gs://bucket/dir/file.csv

然后简单地删除旧文件并将新文件移动到第一个存储桶中:

gsutil mv gs://[SOURCE_BUCKET_NAME]/[SOURCE_OBJECT_NAME] gs://[DESTINATION_BUCKET_NAME]/[DESTINATION_OBJECT_NAME]

这是一个较长的过程,但您可以记住一些事情。

供您参考:https://cloud.google.com/storage/docs/renaming-copying-moving-objects

【讨论】:

但这并不能确定这些错误的原因,以及这些特定解决方案为何不起作用。有很多解决方法,包括放弃整个方法。

以上是关于gsutil cp 管道在 docker 容器中作为 bash exec 命令失败的主要内容,如果未能解决你的问题,请参考以下文章

如何让 gsutil 在 docker 容器中使用 gcloud 凭据

gsutil 实际需要哪些配置文件

Gsutil 同步与 cp -n

管道 gsutil 输出到文件

gsutil cp 失败 - “无法创建清单文件”

Docker命令之四:docker cp