Мы недавно столкнулись с точно такой же проблемой. После обновления до AWS Lambda Node v10.x с Node v8.x chrome и chromedriver перестали работать. Короче говоря, основная причина заключается в том, что Lambda Node 10.x работает на Amazon Linux 2 против Lambda Node v8, которая работает на Amazon Linux. В Amazon Linux 2 отсутствует ряд пакетов по сравнению с его предшественником, что делает его более легковесным, но в то же время затрудняет настройку среды выполнения. Прежде чем я расскажу вам, как решить эту проблему, позвольте мне сначала выделить несколько полезных ссылок, которые помогли мне найти правильный набор двоичных файлов, которые я также должен был включить в свой пакет развертывания lambda.
Просто помните! Чтобы решить эту проблему, нужно выяснить, какие двоичные файлы отсутствуют в пакете развертывания Lambda, и добавить их.
- Как использовать собственные двоичные пакеты Amazon Linux в пакете развертывания AWS Lambda. Как только вы узнаете, что в вашей среде Lambda отсутствуют некоторые двоичные файлы, эта ссылка от AWS поможет вам включить их в ваш пакет. Для своих целей я использовал EC2 Amazon Linux 64 bit AMI для загрузки пакетов и их распаковки. Далее следуют подробности ... https://aws.amazon.com/premiumsupport/knowledge-center/lambda-linux-binary-package
- Помимо двоичных файлов, отсутствующих в Amazon Linux 2, также не установлены шрифты. Эта ссылка расскажет вам, как установить шрифты на AWS Lamda. Одной из причин, по которой Chrome не запускается на Lambda, является отсутствие шрифтов. https://forums.aws.amazon.com/thread.jspa?messageID=776307
- Это хороший поток вопросов на github, который научил меня, что порядок путей в переменной среды LD_LIBRARY_PATH имеет значение. Это переменная окружения, которая содержит пути, в которых находятся ваши двоичные файлы. https://github.com/alixaxel/chrome-aws-lambda/issues/37
- Теперь это изменит правила игры. Без удивительного док-контейнера lambci, созданного, чтобы имитировать AWS Lambda настолько близко, насколько это возможно, я бы никогда не понял этого. После того, как мы попробовали все что угодно между сервером Amazon Linux 2 EC2 и AWS Lambda, это превратилось в мою площадку, где я мог очень быстро выполнять различные пакеты. https://hub.docker.com/r/lambci/lambda/
- Запуск произвольных исполняемых файлов в AWS Lambda. Несколько полезных ссылок, если вы хотите запустить исполняемый файл прямо в lambda и посмотреть, как он себя ведет. Сообщения об ошибках, которые вы видите из пакета selenium-webdriver, на самом деле не обнаруживают реальной ошибки, которую выдает Chrome или chromedriver. Попытка напрямую запустить chrome или chromedriver в док-контейнере lambci - вот как мне удалось отладить это и выяснить, какие двоичные файлы отсутствовали. https://aws.amazon.com/blogs/compute/running-executables-in-aws-lambda/
Итак, вот что вам нужно сделать:
- Запустить 64-битный сервер Amazon Linux 2. Достаточно t3.micro.
- SSH к машине и установить rmpdevtools:
sudo yum install -y yum-utils rpmdevtools
- Создать временный каталог для загрузки отсутствующих пакетов:
cd /tmp
mkdir lib
cd lib
- Загрузка пакетов RPM, отсутствующих в узле AWS Lambda v10.x:
yumdownloader --resolve GConf2 glibc glib2 libblkid libffi libgcc libmount libsepol libstdc++ libuuid pcre zlib libselinux dbus-glib mozjs17 polkit polkit-pkla-compat libX11 libX11-common libXau libxcb fontconfig expat fontpackages-filesystem freetype stix-fonts gnu-free-sans-fonts fontpackages-filesystem gnu-free-fonts-common nss nspr nss-softokn nss-softokn-freebl nss-util dbus-libs audit-libs bzip2-libs cracklib elfutils-libelf elfutils-libs libattr libcap libcap-ng libcrypt libdb libgcc libgcrypt libgpg-error libsepol lz4 pam systemd-libs xz-libs mesa-libOSMesa-devel mesa-libOSMesa mesa-libglapi sqlite
- Извлечение пакетов RPM:
rpmdev-extract *rpm
- Создать временное местоположение для копирования двоичных файлов из извлеченных артефактов RPM:
sudo mkdir -p /var/task
sudo chown ec2-user:ec2-user /var/task
cd /var/task
mkdir lib
mkdir fonts
- Скопируйте извлеченные двоичные файлы в новое временное расположение:
/bin/cp /tmp/lib/*/usr/lib64/* /var/task/lib
/bin/cp /tmp/lib/*/lib64/* /var/task/lib
/bin/cp /tmp/lib/*/usr/share/fonts/*/*.ttf /var/task/fonts
- Zip артефакты:
zip -r ./lib.zip ./*
- Загрузите их с сервера извлекитеzip и включите ваш лямбда-обработчик. На этом этапе у вас должна быть очень похожая структура, подобная той, что была у вас с несколькими бинарными файлами в вашей папке lib и новой папкой шрифтов.
- Включите следующий файл конфигурации "fonts.conf" в ваш / var /папка task / fonts:
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/var/task/fonts/</dir>
<cachedir>/tmp/fonts-cache/</cachedir>
<config></config>
</fontconfig>
Добавьте следующий фрагмент кода в ваш лямбда-обработчик. Это установит правильный порядок включаемых путей для переменной среды LD_LIBRARY_PATH, а также установит FONTCONFIG_PATH в новый каталог / var / task / fonts.
process.env.FONTCONFIG_PATH = `${process.env.LAMBDA_TASK_ROOT}/fonts`;
if (process.env.LD_LIBRARY_PATH.startsWith("/var/task/lib:") !== true) {
process.env.LD_LIBRARY_PATH = [...new Set(["/var/task/lib", ...process.env.LD_LIBRARY_PATH.split(':')])].join(':');
}
Скачать локально изображение lambci / lambda.
docker pull lambci/lambda
Отладьте ваш lamda-обработчик, запустив образ lambci следующим образом:
docker run --rm -v "$THE_LOCAL_DIR_OF_YOUR_UNCOMPRESSED_LAMDA_PACKAGE":/var/task lambci/lambda:nodejs10.x index.handler
Итерируйте шаги с 7 по 14, пока не получите работу с контейнером lambci. С указанными RPM-пакетами это должно работать, но если это не так, вы можете локально отлаживать происходящее, пытаясь запустить chrome в вашей лямбде следующим образом:
const childProcess = require('child_process');
childProcess.execFileSync(`${process.env.LAMBDA_TASK_ROOT}/lib/chrome`);
Этотрудоемкий процесс, но в конце концов все, что вы делаете, это просто добавляете еще несколько двоичных файлов в ваш пакет и 3 строки кода в своем обработчике для обновления переменных среды lib и fonts.
На всякий случай, добавив ниже также используемые нами хромированные флаги:
const defaultChromeFlags = [
"--headless",
"--disable-gpu",
"--window-size=1280x1024",
"--no-sandbox",
"--user-data-dir=/tmp/user-data",
"--hide-scrollbars",
"--enable-logging",
"--v=99",
"--single-process",
"--data-path=/tmp/data-path",
"--ignore-certificate-errors",
"--homedir=/tmp",
"--disk-cache-dir=/tmp/cache-dir"
];
Удачи!