【问题标题】:Python shell commands not executed from Google Cloud Functions未从 Google Cloud Functions 执行的 Python shell 命令
【发布时间】:2019-12-22 22:33:40
【问题描述】:

我正在尝试构建一个自动流程,将聚合数据从 BigQuery 传输到 redshift。看了很多我发现最好的方法是这样的:

BigQuery -> 导出到 Google 云存储 -> 使用 gsutil 传输到 S3 -> 从 CSV 复制到 Redshift 上的表中。

我把它做成了一个 python 脚本,在我的电脑上运行时似乎一切正常。

但是做了一些测试,我发现直接从 Cloud Shell 使用 gsutil 可以加快文件传输速度。好像亚马逊和谷歌有一些专门的数据管道什么的。

我正在尝试将传输过程移动到我将通过请求触发的谷歌云函数(在 python 中,但只要它有效,语言最终无关紧要)。使用子进程和操作系统。都没有奏效。 python 函数中的 Shell 命令似乎通常不起作用。

这是 Cloud Function 的代码,从 Cloud Shell 手动运行时可以完美运行:

import subprocess

def hello_world(request):
    data = subprocess.call('gsutil -m cp gs://bucket/file.csv s3://bucket/',shell=True)
    print(data)
    return 'Success!'

传输文件后,我将为插入 Redshift 表的 lambda 函数创建一些 S3 触发器。

我读到这个:How to Transfer data from Google cloud storage to S3 without any manual activity?

但是调度器对我没有多大意义?也许我做错了什么。我似乎可以提出要求?但这并不能解决shell命令不被执行的问题。

如果有更好的选择,我愿意接受。是否值得寻找相反的方法?在 AWS 上使用 Lambda 和 gsutil。

【问题讨论】:

  • “它不起作用”是什么意思?它是否引发了异常,是否返回了错误,您是否从子进程捕获了 stdout/stderr 输出并告诉了您一些有用的信息?除此之外,看看 boto3 - 你也许可以将它连接到 GCS 作为数据源,将 S3 作为数据接收器。
  • 函数执行了,什么也没发生。数据字段内的返回为 0。函数执行开始 0 函数执行耗时 180 毫秒,完成状态码:200

标签: python amazon-web-services amazon-s3 google-cloud-platform google-cloud-storage


【解决方案1】:

我了解到您想要构建一个自动流程,将聚合数据从 BigQuery 传输到 redshift。

很遗憾,Cloud Function 环境中不存在 gsutil。

云函数施加超时 [1]。此超时的最大值为 9 分钟。所以即使是gsutil在Cloud Function的环境下可用,复制大文件也可能会超过超时时间。

如果知道发生了哪个文件更改对您的情况至关重要,那么另一种方法是设置 Cloud Pub/Sub [2] 并向其中注册对象更改 [3]。

如果 AppEngine 或 Compute Engine 虚拟机订阅了此 Cloud Pub/Sub,当发生文件更改时,它们将收到一个指示此更改的事件。他们可以使用 Amazon 的 API [4](在 AppEngine 的情况下)或 gsutil-rsync(在 Compute Engine 的情况下)将文件更改同步到 Amazon S3。

如果知道发生了哪个文件更改对您的用例来说并不重要,那么在 Compute Engine 虚拟机中设置一个 cron 作业来运行 gsutil-rsync 可以实现相同的目标。

请注意,来自云存储的传出网络带宽会产生费用 [5]。您可以设置预算提醒 [6] 以避免因同步大文件而被多收费用。

[1]https://cloud.google.com/functions/docs/concepts/exec#timeout

[2]https://cloud.google.com/storage/docs/pubsub-notifications

[3]https://cloud.google.com/storage/docs/reporting-changes

[4]https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html

[5]https://cloud.google.com/storage/pricing#network-egress

[6]https://cloud.google.com/billing/docs/how-to/budgets

【讨论】:

  • 我将其标记为答案,因为它主要是我最终所做的。我用 Jenkins(在 AWS 端)创建了一个虚拟机。安装了 gsutil 并获得了组织级别的服务帐户 JSON,因此它可以访问所有项目。从那时起,jenkins 脚本只需将表作为 CSV 导出到 GCS,在 VM 上运行 gsutil 并将文件放在 lambda 触发器正在等待的 S3 上。
【解决方案2】:

谷歌云功能是沙盒的,你不能执行 shell 命令。而且,你绝对不知道gsutil是否安装,版本,....这是serverless的“美”!

但是,有两种选择:

  1. 使用 Google Python 库执行 API 调用。如果未实现,请使用 Discovery API。看起来很复杂,但可以工作......看看第二个解决方案
  2. 看看 Cloud Run。根据需要打包您的容器,安装 gcloud SDK,您可以按原样执行您的流程。我为此写了article,您可以找到将函数转换为容器的基础。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 2011-06-15
    • 2018-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多