无法使用 AWS Glue 中的 cx_oracle 连接 Oracle 数据库

2023-12-02

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

数据库错误:DPI-1047:无法找到 64 位 Oracle 客户端库:“libclntsh.so:无法打开共享对象文件:没有这样的文件或目录”。看https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html求助

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

我已经尝试过这个计算器question并尝试使用 s3 url 设置 rpath 但没有成功。任何想法都会有帮助


Credits

这个答案是一个汇编this and this评论中围绕前者进行了大量讨论。信用为rpath修补解决方案交给@harjeet-singh,他是上述答案的原作者,libaio致@good-will,但这些解决方案仍然有一些步骤让人们感到困惑,所以这就是为什么我将在这里将所有内容合并为一个逐步的答案。

背景

为了使用以下命令连接到 Oracle 数据库cx-Oracle从 Python shell AWS Glue 作业中,我们需要将 Oracle 客户端库与其捆绑在一起。此外,库必须使用正确的补丁rpath为了正确加载,因为在 Glue 运行时我们只有文件系统写访问权限/tmp,这就是我们的档案所在的位置,但是cx-Oracle无法知道这一点,并且默认情况下需要不同的目录。还有LD_LIBRARY_PATHhack 无法实现,因为我们无法控制 Glue 作业的启动方式。

分步指南

  1. 下载适用于 x86-64 Linux 的 Instant Client Basic ZIP 包:here。本指南使用版本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-Oracle: libclntsh.so)。这样做是因为无论动态加载这些库,显然都不会解析符号链接。也许将来会,但我必须这样做才能让它发挥作用。
cd instantclient_21_5/
find . -type l -name "libclntsh.so*" -delete
mv libclntsh.so.21.1 libclntsh.so

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

数据库错误:DPI-1047:无法找到 64 位 Oracle 客户端库:“libsomething.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. Put 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

Note:您可能想检查一下较新版本的libaio如果有的话。 6. 压缩存档

cd ..
zip -T -r instantclient-basic-linuxx64_patched.zip instantclient_21_5/
  1. 下载cx-Oracle wheel
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 to 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. 配置您的 Glue 作业

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

  • 将 S3 URL 放入“引用文件路径”配置参数中
  • 将 S3 URL 放入cx-Oracle“Python库路径”配置参数中的wheel
  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 配置您的作业。

希望任何读过这篇文章的人都能在第一次尝试时就做对,因为我确实没有做到。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法使用 AWS Glue 中的 cx_oracle 连接 Oracle 数据库 的相关文章

随机推荐

  • 如何使用 Jupyter + SparkR 和自定义 R 安装

    我正在使用 Dockerized 映像和 Jupyter Notebook 以及 SparkR 内核 当我创建 SparkR 笔记本时 它使用 Microsoft R 3 3 2 安装 而不是普通的 CRAN R 安装 3 2 3 我使用的
  • 沿着旋转路径附加影片剪辑(通过 AS3)

    我该怎么办 沿着路径 其他影片剪辑 附加影片剪辑 例如 脚步声 这将在一次附加一个影片剪辑的时间间隔内 我需要旋转 即脚步应该根据路径方向旋转 Thanks 1 创建坐标数组 这是你的路 您可以通过多种方法来实际创建数组 但结果应该与此类似
  • java do while循环在满足条件后继续循环

    我是一名新的java程序员 我正在编写一个程序 为3台打印机设置3个型号 如果用户输入错误的值 我希望它继续询问用户型号 我让它工作 但前提是用户输入的第一个值是 3 台打印机之一的编号 如果第一个值不是可能的值之一并且第二个输入是 则它仍
  • 如何在Android中使用dimens.xml?

    当我设计布局时 由于可维护性主题 我将所有维度集中在 dimens xml 中 我的问题是这是否正确 最好的做法是什么 关于这方面的信息很少 什么都没有 我知道将布局的所有字符串集中在 strings xml 上 将颜色集中在 color
  • Python正则表达式搜索十六进制字节

    我正在尝试在二进制文件中搜索一系列十六进制值 但是 我遇到了一些无法完全解决的问题 1 我不知道如何搜索整个文件并返回所有匹配项 目前 我的 f seek 只达到了我认为可能的值 这不好 2 我想以十进制或十六进制形式返回可能匹配的偏移量
  • 未签名的APK无法安装

    我正在尝试将我的应用程序分发给一些人进行测试 我已经直接从 eclipse 将它安装在我的 Desire 上 并且运行良好 要创建 APK 文件 我选择 导出未签名的应用程序包 直接从eclipse 然后创建一个APK文件 我通过电子邮件将
  • Android:如何以编程方式从 url 将图像设置为 imageview

    我有一个来自我的 REST API 的图像 URL 现在我想在加载活动时将其设置为图像视图 下面是我如何从其余 api 获取 bean 然后从中获取 URL Message message new Message String imageU
  • UWP 窗口放置

    我正在 Visual Studio 2015 RC 中创建 net UWP 应用程序 我使用以下代码成功设置了窗口大小 ApplicationView GetForCurrentView TryResizeView New Size wid
  • 分割文件 - Java/Linux

    我有一个包含近 2 5 亿个字符的大文件 现在 我想将其分成几个部分 每个部分包含 3000 万个字符 因此前 8 部分将包含 3000 万个字符 最后一部分将包含 1000 万个字符 另一点是 我想在下一部分的开头包含每个文件的最后 10
  • 如何通过 ZF2 FormElementManager 将 Doctrine ObjectManager 传递到表单

    我想在 ZF2 中创建自定义表单元素 这需要 FormElementManager 我目前在表单创建中使用 Doctrine Hydrator 如下所示本教程 在此方法中 在控制器中创建一个 ObjectManager 对象 并在实例化时将
  • 基于 R 中的值进行迭代和分配的函数

    我正在编写一个函数 该函数迭代一个帐户列表 每个帐户都有一个关联的值 并为该帐户分配名称列表中的一个名称 名称列表将具有关联的值 我希望分配的名称是具有最小值的名称 name totalvalue Jeff 54 Christy 43 Ma
  • Adobe flash cs6 输出窗口在 .exe 文件中执行 Filesteam 操作时自动关闭,但在 Flash 调试模式下工作正常

    我在用Adobe Flash CS6用于创建桌面应用程序 在该应用程序中我使用闪存文件系统文件流保存文本文件 我不想使用文件参考因为我不想显示保存对话框 当我在导出的文件中调用 new FileStream 时 swf or exe文件后
  • 使用 URL 中的 ID 从 mySQL 选择数据

    我有一个包含列的表 GroupID GroupName GroupDesc Overs 1 Test Group Description Yes 我有一个名为 list php 的页面 它当前为组表 上图 中数据库中的每一行创建 URL 该
  • 如何中断 Scanner.nextline() 调用

    SO 上有很多关于中断读取 system in 的线程 但我在这里寻找的是一些关于如何最好地编码我想要实现的目标的建议 我有一个getlogin 需要执行以下操作的方法 要求用户输入所需的登录环境详细信息 如果 6 秒后用户没有输入有效值
  • 从 Android 应用程序中的 Sqlite 数据库读取数据。

    我正在尝试从数据库读取数据 我将数据库导入到sqlite手动 现在只想在 android 应用程序中建立连接 并希望读取行并将其显示在文本字段中 但是我使用的代码要么每次都创建新数据库 要么在该数据库中再次创建表 我出现运行时错误 我的代码
  • 像 € 这样的 Html 实体在 CSV 转换中不会转换为其符号

    我使用过 CSV 解析器http code google com p parsecsv for php 将我的报告导出为 PHP 中的 CSV 我已显示销售总额 euro XXXX XX 在浏览器以及Excel 导出后 中 显示为欧元符号
  • 使用 JavaScript 淡出 Mp3 歌曲

    我正在尝试创建一个嵌入了一些 JavaScript 的 HTML 文件 该文件允许我按下按钮并开始淡出歌曲 我已经设法让它工作 以便它播放歌曲 这是一个开始 但我一直在尝试使用第二个功能来尝试降低音量并在该功能上设置延迟 有人可以帮忙吗
  • WPF C# Web浏览器滚动到顶部菜单

    我有一个网格 里面有菜单和滚动查看器 在滚动查看器中 我有一个带有另一个网格的组框和一个网络浏览器元素 现在 当我使窗口小于网络浏览器内容的内容并在滚动查看器中向下滚动时 问题就出现了 所有内容都有边距 因此它位于顶部菜单下方 但网络浏览器
  • 需要在java中以某种方式识别本地机器

    我试图找出应用程序正在运行的本地计算机的名称 或唯一标识特定计算机的其他方式 我一直在用这个 String hostname java net InetAddress getLocalHost getHostName 效果很好 但我碰巧在分
  • 无法使用 AWS Glue 中的 cx_oracle 连接 Oracle 数据库

    我正在尝试使用 cx oracle 从 AWSglue 连接 Oracle 数据库 但收到此错误消息 数据库错误 DPI 1047 无法找到 64 位 Oracle 客户端库 libclntsh so 无法打开共享对象文件 没有这样的文件或