无法使用来自 AWS Glue 的 cx_oracle 连接 oracle 数据库
Unable to connect oracle database using cx_oracle from AWS Glue
我正在尝试使用 cx_oracle 从 AWS glue 连接 oracle 数据库,但我收到此错误消息
DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory". See https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html for help
我尝试按照文档下载 so 文件并将其存储在已使用 --extra-files 参数链接到 Glue 的 S3 中,但仍然收到相同的错误消息
我已经尝试过这个 Whosebug question 并且还尝试使用 s3 url 设置 rpath 但没有成功。任何想法都会有帮助
学分
这个答案是 this and this 的汇编,并且在评论中围绕前者进行了大量讨论。 rpath
补丁解决方案归功于上述答案的原作者 @harjeet-singh,libaio
归功于@good-will,但围绕这些问题仍有一些步骤令人困惑的解决方案,这就是为什么我要在此处将所有内容合并为一个 step-by-step 答案。
背景
为了使用 cx-Oracle
从 Python shell AWS Glue 作业连接到 Oracle 数据库,我们需要将 oracle 客户端库与其捆绑在一起。此外,库必须使用正确的 rpath
进行修补才能正确加载,因为在 Glue 运行时中,我们只有 /tmp
的文件系统写入权限,这是我们的存档所在的位置,但是 cx-Oracle
不知道这一点,默认情况下需要一个不同的目录。 LD_LIBRARY_PATH
hack 无法实施,因为我们无法控制 Glue 作业的启动方式。
Step-By-Step指南
- 从 here 下载适用于 x86-64 Linux 的即时客户端基本 ZIP 包。本指南使用版本 21.5.0.0.0
wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip
- 解压缩存档
unzip instantclient-basic-linuxx64.zip
- 从存档中删除符号链接并将它们指向的文件(在本例中
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
如果在完成整个指南和运行你的工作后,你仍然对像
这样的库有问题,那么对其他带有符号链接的文件执行相同的操作
DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libsomething.so: cannot open shared object file: No such file or directory"
- 修补
rpath
以指向我们将在 Glue 作业中使用的静态目录
例如,如果您的存档名为 instant-client-basic-linux.x64-21.5.0.0.0
,并且它包含一个名为 instantclient_21_5
的文件夹,其中包含所有库。当作业运行时,该存档将在 /tmp
下的随机目录中可用(更多内容见下文。我们需要在这些目录之一中找到我们的存档并将其解压缩到 [=24 下的静态目录中=],例如 /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
- 将
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/
- 下载
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
- 上传存档并
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
- 配置您的 Glue 作业
我假设您的粘合作业已经创建,我们将对其进行配置。
- 将 S3 URL 放入“引用文件路径”配置参数中的存档
- 将S3URL放到“Python库路径”配置参数
cx-Oracle
轮
- 向粘合作业添加一些代码以设置库。
此代码必须在使用
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 步配置您的作业。
希望任何读过这篇文章的人都能在第一次尝试时就做对,因为我确实没有。
我正在尝试使用 cx_oracle 从 AWS glue 连接 oracle 数据库,但我收到此错误消息
DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory". See https://cx-oracle.readthedocs.io/en/latest/user_guide/installation.html for help
我尝试按照文档下载 so 文件并将其存储在已使用 --extra-files 参数链接到 Glue 的 S3 中,但仍然收到相同的错误消息
我已经尝试过这个 Whosebug question 并且还尝试使用 s3 url 设置 rpath 但没有成功。任何想法都会有帮助
学分
这个答案是 this and this 的汇编,并且在评论中围绕前者进行了大量讨论。 rpath
补丁解决方案归功于上述答案的原作者 @harjeet-singh,libaio
归功于@good-will,但围绕这些问题仍有一些步骤令人困惑的解决方案,这就是为什么我要在此处将所有内容合并为一个 step-by-step 答案。
背景
为了使用 cx-Oracle
从 Python shell AWS Glue 作业连接到 Oracle 数据库,我们需要将 oracle 客户端库与其捆绑在一起。此外,库必须使用正确的 rpath
进行修补才能正确加载,因为在 Glue 运行时中,我们只有 /tmp
的文件系统写入权限,这是我们的存档所在的位置,但是 cx-Oracle
不知道这一点,默认情况下需要一个不同的目录。 LD_LIBRARY_PATH
hack 无法实施,因为我们无法控制 Glue 作业的启动方式。
Step-By-Step指南
- 从 here 下载适用于 x86-64 Linux 的即时客户端基本 ZIP 包。本指南使用版本 21.5.0.0.0
wget https://download.oracle.com/otn_software/linux/instantclient/instantclient-basic-linuxx64.zip
- 解压缩存档
unzip instantclient-basic-linuxx64.zip
- 从存档中删除符号链接并将它们指向的文件(在本例中
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
如果在完成整个指南和运行你的工作后,你仍然对像
这样的库有问题,那么对其他带有符号链接的文件执行相同的操作DatabaseError: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libsomething.so: cannot open shared object file: No such file or directory"
- 修补
rpath
以指向我们将在 Glue 作业中使用的静态目录 例如,如果您的存档名为instant-client-basic-linux.x64-21.5.0.0.0
,并且它包含一个名为instantclient_21_5
的文件夹,其中包含所有库。当作业运行时,该存档将在/tmp
下的随机目录中可用(更多内容见下文。我们需要在这些目录之一中找到我们的存档并将其解压缩到 [=24 下的静态目录中=],例如/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
- 将
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/
- 下载
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
- 上传存档并
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
- 配置您的 Glue 作业
我假设您的粘合作业已经创建,我们将对其进行配置。
- 将 S3 URL 放入“引用文件路径”配置参数中的存档
- 将S3URL放到“Python库路径”配置参数
cx-Oracle
轮
- 向粘合作业添加一些代码以设置库。
此代码必须在使用
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 步配置您的作业。
希望任何读过这篇文章的人都能在第一次尝试时就做对,因为我确实没有。