微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 AWS Lambda 上而不是在 EC2 问题我尝试过的我的猜测

如何解决在 AWS Lambda 上而不是在 EC2 问题我尝试过的我的猜测

问题

我一直尝试在 AWS Lambda 上使用 Firefox 运行 Selenium,但在 AWS Lambda 上运行我的代码时一直收到以下错误。但是,当我在 EC2 实例上运行时,Dockerfile 按预期成功运行(访问 google.com)。我正在运行 Firefox 60.9.0 ESR、Selenium 3.141.0、python3.8 和 Geckodriver 29。

Traceback (most recent call last):
  File "/var/task/app.py",line 21,in handler
    res = test.testGet()
  File "/var/task/test.py",line 39,in testGet
    driver = create_session_proxy("placeholder")
  File "/var/task/test.py",line 27,in create_session_proxy
    driver = webdriver.Firefox(profile,firefox_binary=firefox_path,executable_path=geckodriver_path,service_log_path=geckolog_path)
  File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/firefox/webdriver.py",line 170,in __init__
    RemoteWebDriver.__init__(
  File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py",line 157,in __init__
    self.start_session(capabilities,browser_profile)
  File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py",line 252,in start_session
    response = self.execute(Command.NEW_SESSION,parameters)
  File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/remote/webdriver.py",line 321,in execute
    self.error_handler.check_response(response)
  File "/var/lang/lib/python3.8/site-packages/selenium/webdriver/remote/errorhandler.py",line 242,in check_response
    raise exception_class(message,screen,stacktrace)
selenium.common.exceptions.WebDriverException: Message: Process unexpectedly closed with status signal

...

Duration: 2534.59 ms    Billed Duration: 3615 ms    Memory Size: 4096 MB    Max Memory Used: 419 MB Init Duration: 1079.94 ms

在我的 geckodriver 日志中,这是输出。有趣的是,有时我会在一次运行中多次收到此错误,但并非总是如此。

1626910798772\tgeckodriver\tINFO\tListening on 127.0.0.1:40439
1626910798785\tmozrunner::runner\tINFO\tRunning command: \"/tmp/firefox/firefox-bin\" \"--marionette\" \"-foreground\" \"-no-remote\" \"-profile\" \"/tmp/rust_mozprofileFhPiVM\"
ExceptionHandler::GenerateDump cloned child 30
ExceptionHandler::WaitForContinueSignal waiting for continue signal...
ExceptionHandler::SendContinueSignaltochild sent continue signal to child

这是我的 Dockerfile 的样子:

FROM public.ecr.aws/lambda/python:3.8

yum update -y

# Create function directory
workdir /app

# Install the function's dependencies
copY requirements.txt  .
RUN  pip install -r requirements.txt
RUN  yum -y install Xvfb
RUN  yum -y install gtk3
RUN  yum -y install dbus-glib

# copy handler function (from the local app directory)
copY  . ${LAMBDA_TASK_ROOT}

# Overwrite the command by providing a different command directly in the template.
CMD ["app.handler"]

这是 test.py 的代码

from selenium import webdriver
from selenium.webdriver.firefox.options import Options
import time
import random
import pickle
from selenium.webdriver.common.proxy import Proxy,ProxyType
from selenium.webdriver.support.ui import webdriverwait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys

def create_session_proxy(ip_address):
    options = Options()
    options.headless = True
    profile = webdriver.FirefoxProfile()

    # Creates webdriver
    LAMBDA_TASK_ROOT = os.environ.get('LAMBDA_TASK_ROOT')
    geckodriver_path = '/tmp/geckodriver'
    geckolog_path = '/tmp/geckodriver.log'
    firefox_path = '/tmp/firefox/firefox-bin'
    driver = webdriver.Firefox(profile,service_log_path=geckolog_path)
    time.sleep(2)
    driver.get('https://google.com')

    return driver


def testGet():
    display = display(visible=0,size=(1024,768))
    display.start()

    driver = create_session_proxy("placeholder")
    time.sleep(2)
    source = driver.page_source
    driver.close()

    return source

app.py 的代码(入口点):

import sys
import test
import os
import shutil
import time
import traceback

def handler(event,context):
    # Moves files into tmp to run
    start = time.time()
    LAMBDA_TASK_ROOT = os.environ.get('LAMBDA_TASK_ROOT')
    if not os.path.isfile("/tmp/geckodriver"):
        shutil.copy(LAMBDA_TASK_ROOT + "/geckodriver","/tmp/")
    if not os.path.isfile("/tmp/geckodriver.log"):
        shutil.copy(LAMBDA_TASK_ROOT + "/geckodriver.log","/tmp/")
    if not os.path.isdir("/tmp/firefox/"):
        shutil.copytree(LAMBDA_TASK_ROOT + "/firefox/","/tmp/firefox/")
    print("Time elapsed:",time.time() - start)

    try:
        res = test.testGet()
    except:
        traceback.print_exc()
        error_log_text = open('/tmp/geckodriver.log').read()
        return error_log_text
    return 'Hello from AWS Lambda using Python' + sys.version + '!' + res

我尝试过的

  • 在 Firefox 版本 66.0.5、52.9.0ESR 和 60.0.1ESR 上运行(没有区别)
  • 改变 geckodriver 版本(17.0 和 29.0)和 Selenium 版本(没有区别)
  • 使用 firefox/firefox 和 firefox/firefox-bin 作为可执行文件(没有区别)

我知道 Lambda 会在重新启动时删除 /tmp 文件夹,并且除了 /tmp 之外,文件系统是只读的(在 Lambda 上)。我正在将 Firefox 和 Geckodriver 可执行文件复制到 /tmp,因此问题与无法找到这两个文件无关。

我还在为 Firefox 和 Geckodriver 使用 Linux 64 位版本,所以这不是问题。

我的猜测

我应该注意,虽然我知道基础知识,但我对 Docker 并不是很有经验。

我的主要想法是,它是在 Lambda 的幕后发生的事情,并且它可能与 pyvirtualdisplay(运行 Firefox 需要它)有关。不过,其他人已经成功地在 Lambda 上运行 Selenium,所以我不确定这就是问题所在。对于pyvirtualdisplay,我安装在requirements.txt中,所以安装了,但是我想知道EC2上是否设置了一些认情况下不在Lambda上的环境变量。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?