无法从AWS Glue使用CX_ORACLE连接Oracle数据库

2022-05-28 00:00:00 amazon-web-services aws-glue oracle

我正在尝试使用cx_oracle从AWS GLue连接Oracle数据库,但收到此错误消息

数据库错误:DPI-1047:找不到64位Oracle客户端库:";libclntsh.so:无法打开共享对象文件:没有这样的文件或目录。有关帮助,请参阅https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html

我尝试按照文档下载so文件,并将其存储在S3中,该文件已使用--Extra-Files参数链接到Glue,但仍收到相同的错误信息

我已经尝试了这个堆栈溢出question,并尝试使用S3url设置rPath,但没有成功。任何想法都会很有帮助


解决方案

学分

这个答案是this和this的汇编,以及评论中围绕前者的大量讨论。rpath修补解决方案的功劳归功于@Harjeet-Singh,他是上述答案的原始作者,libaio归功于@Good-Will,但围绕这些解决方案仍然有一些步骤让人感到困惑,所以这就是为什么我将在这里将所有内容汇总到一个逐步的答案中。

背景

为了使用cx-Oracle从一个Python外壳AWS Glue作业连接到Oracle数据库,我们需要将Oracle客户端库与它捆绑在一起。此外,库必须使用正确的rpath打补丁才能正确加载,因为在Glue运行时,我们只有/tmp的文件系统写访问权限,这是我们的归档所在的位置,但cx-Oracle不知道这一点,并且默认情况下需要一个不同的目录。无法实施LD_LIBRARY_PATH黑客攻击,因为我们无法控制如何启动粘合作业。

分步指南

  1. 从here下载适用于x86-64 Linux的即时客户端基本ZIP包。本指南使用版本21.5.0.0.0
wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip
  1. 解压缩存档
unzip instantclient-basic-linuxx64.zip 
  1. 从存档中删除符号链接,并将它们指向的文件(在本例中libclntsh.so.21.1移动到您使用cx-Oraclelibclntsh.so时要查找的文件)。这样做是因为无论动态加载这些库的是什么,显然都不能解析符号链接。也许将来会这样,但我不得不这样做才能让它发挥作用。
cd instantclient_21_5/
find . -type l -name "libclntsh.so*" -delete
mv libclntsh.so.21.1 libclntsh.so

如果在完成整个指南并运行您的作业后,库仍然有问题,请使用符号链接对其他文件执行相同的操作

数据库错误:DPI-1047:找不到64位Oracle客户端库:&qot;libomething.so:无法打开共享对象文件:没有这样的文件或目录

  1. 修补rpath以指向我们将从Glue作业内部使用的静态目录 例如,如果您的存档名为instant-client-basic-linux.x64-21.5.0.0.0,并且它包含一个名为instantclient_21_5的文件夹,其中包含所有库。当作业运行时,该存档将在/tmp下的随机目录中可用(下面将详细介绍)。我们需要在其中一个目录中找到我们的归档文件,并将其解压缩到/tmp下的静态目录中,例如/tmp/libs。因此,您的rpath将是/tmp/libs/instant-client-basic-linux.x64-21.5.0.0.0/instantclient_21_5,因为它位于客户端库的绝对路径中。
sudo apt-get update
sudo apt-get install patchelf -y
patchelf --set-rpath /tmp/libs/instant-client-basic-linux.x64-21.5.0.0.0/instantclient_21_5 libclntsh.so
  1. libaio.so.1放入档案
cd ..
wget https://src.fedoraproject.org/lookaside/pkgs/libaio/libaio-0.3.110.tar.gz/2a35602e43778383e2f4907a4ca39ab8/libaio-0.3.110.tar.gz
tar xzvf libaio-0.3.110.tar.gz
cd libaio-0.3.110
make prefix=`pwd`/usr install 
find ./usr/lib/ -type l -name "libclntsh.so*" -delete
mv ./usr/lib/libaio.so.1.0.1 ../instantclient_21_5/libaio.so.1

注意:您可能需要检查libaio的更新版本(如果有)。 6.压缩存档

cd ..
zip -T -r instantclient-basic-linuxx64_patched.zip instantclient_21_5/
  1. 下载cx-Oracle滚轮
wget https://files.pythonhosted.org/packages/a9/b7/c2d0223fb4f1013b090cf82f3ce56f36f33b79a48f9c33b36717c2977b04/cx_Oracle-8.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
  1. 上传档案和cx-Oracle到S3
aws s3 cp instantclient-basic-linuxx64_patched.zip s3://<mybucket>/glue_libs
aws s3 cp cx_Oracle-8.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl s3://<mybucket>/glue_libs
  1. 配置您的粘合作业

我假定您的粘合作业已创建,我们将只对其进行配置。

  • 将S3 URL放入";引用的文件路径&配置参数中
  • 将S3 URL放到配置参数中的cx-Oracle滚轮中
  1. 在粘合作业中添加一些代码以设置库。 此代码必须在使用cx-Oracle之前执行。可以在导入后、使用前执行。
迭代/tmp中的随机目录,找到您创建的归档文件并将其解压缩到我们之前在rpath中设置的静态目录中。然后初始化cx-Oracle客户端,您就可以开始了。 下面是一个实现示例:

import zipfile

from pathlib import Path

import cx_Oracle

filename = 'instantclient-basic-linuxx64_patched.zip'
oracle_archive = next(Path('./tmp').glob(f'**/{filename}'))
with zipfile.ZipFile(oracle_archive, 'r') as f:
    Path('./tmp/libs').mkdir()
    f.extractall('./tmp/libs')

cx_Oracle.init_oracle_client(lib_dir=f'/tmp/libs/{filename}/instantclient_21_5')

TLDR

在您的Linux计算机上运行此命令(在末尾替换您的存储桶名称):

wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip
unzip instantclient-basic-linuxx64.zip
cd instantclient_21_5/
find . -type l -name "libclntsh.so*" -delete
mv libclntsh.so.21.1 libclntsh.so
sudo apt-get update
sudo apt-get install patchelf -y
patchelf --set-rpath /tmp/libs/instant-client-basic-linux.x64-21.5.0.0.0/instantclient_21_5 instantclient_21_5/libclntsh.so
cd ..
wget https://src.fedoraproject.org/lookaside/pkgs/libaio/libaio-0.3.110.tar.gz/2a35602e43778383e2f4907a4ca39ab8/libaio-0.3.110.tar.gz
tar xzvf libaio-0.3.110.tar.gz
cd libaio-0.3.110
make prefix=`pwd`/usr install 
find ./usr/lib/ -type l -name "libclntsh.so*" -delete
mv ./usr/lib/libaio.so.1.0.1 ../instantclient_21_5/libaio.so.1
cd ..
zip -T -r instantclient-basic-linuxx64_patched.zip instantclient_21_5/
wget https://files.pythonhosted.org/packages/a9/b7/c2d0223fb4f1013b090cf82f3ce56f36f33b79a48f9c33b36717c2977b04/cx_Oracle-8.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl
aws s3 cp instantclient-basic-linuxx64_patched.zip s3://<mybucket>/glue_libs/
aws s3 cp cx_Oracle-8.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl s3://<mybucket>/glue_libs/

按照上面的步骤9和10配置您的作业。

希望任何阅读本文的人在第一次尝试时都能正确理解,因为我肯定没有。

相关文章