目的/やったこと
- Glue Python ShellからRDS for Oracleに接続するためにライブラリ
cx_Oracle
を使用する - Oracleに接続するためには(cx_Oracleを使用するためには)Oracle ClientのLibrary(
libclntsh.so
など)の読み込みが必要 - 対処方法のついての情報がいくつか発見したので、それを元に試していく
先にまとめ
- Oracle ClientのLibraryをzip化&S3にアップロードし、Glue Python Shell から参照できるようにした
- しかし、下記のエラーが発生し、対処法が特定できないためこの検証をストップした
- DatabaseError: Error while trying to retrieve text for error ORA-01804
- 2023/5/2 追記
- python-oracledbを使えばGlue Python ShellからでもOracleに接続できました!
- 詳しくは Glue Python Shellでpython-oracledbを使ってOracleへ接続 の記事に記載してます
- python-oracledbを使えばGlue Python ShellからでもOracleに接続できました!
試したことまとめ
- 参考サイトに記載されている手順に従いzipファイルを作成
- Oracle Client Libraryをダウンロード
- libclntsh.soのrename
- rpathの書き換え
- libaio.so.1の生成
- zipファイルをS3にアップロードし、glue の参照ライブラリ設定
Referenced files path
に設定 - Glue jobの処理に下記を追加
- zipファイルが配置されているpathを突き止める
- zipファイルを解凍
- cx_Oracleにclient libraryのpathを設定
- 正常に動作しなかったのでその他の方法を試した
- client libraryのversionを変更
cx_Oracle.init_oracle_client(lib_dir='/xxx/xxxx/')
を使用せずに、os.environ['ORACLE_HOME'] = '/tmp/oracle'
でlibのpathを設定する
- 結果エラーは変わらず断念
特にハマった箇所
rpathの書き換え
rpathとは wiki Rpath
rpathは、実行可能ファイルまたはライブラリにハードコードされた実行時検索パスを指定します。ダイナミックリンクローダーは、rpathを使用して必要なライブラリを検索します。 具体的には、共有ライブラリへのパスを実行可能ファイルのヘッダーにエンコードします
wikipedia.org/wiki/Rpath
ざっくり「参照する実行するファイルがどこに存在するかを設定しておくもの」ととりあえず認識しました
当初このrpathの書き換え作業をmac PCで実行していました(最終的にはCodeBuildで実行するようにした)
$brew install patchelf
$patchelf --set-rpath /tmp/libs/instantclient_21_9 libclntsh.so
ですが、正常にrpathが変更されたかを確認する術が不明でした
- いくつかのライブラリ(readelfなど)を使ってみたけど正常に動かなった
- さらにmacでは正常にrpathを書き換えられていない、との記事を見かけて更に不信感が募る
mac PCではなくAWS Cloud Shellで試そうとしたけど、oracle clientのzipをダウンロードして解凍する時点でDiskエラーが発生したためこちらも断念
その後、検証用に立てているEC2 instanceで試してなんとかrpathの設定ができた(rpathを書き換えたファイルをダウンロードするためにCloud ShellからSCPで接続して持ってきた)
最初からCodeBuildでやっておけばよかった….
libaio.so.1の生成
libaio.so.1を生成するために下記の手順が必要だったため、macで試したけどmake prefix=
の実行でエラーになったpwd
/usr install
なのでこちらもEC2で実行、後にCodeBuildで実行するようにした
glue の参照ライブラリが配置されるpathは実行毎に変わる
Reference file path で設定したファイルはGlue 実行時/tmp/glue-python-libs-xxxxx
に配置される
pathのxxxxx
の部分はランダム文字列で実行毎に違う値が入る
なので下記のような処理でどこに参照ファイル(今回はOracle ClientのLibrary)があるかを探す(面倒臭え..)
def get_referenced_filepath():
for dir_name in sys.path:
if dir_name.startswith('/tmp/glue-python-libs-'):
return dir_name
return ''
目的のzipを見つけた後、解凍する(面倒臭え..)
filename = 'instantclient-basic-linuxx64_patched.zip'
files = glob.glob(dir_name + "/" + filename)
with zipfile.ZipFile(files[0], 'r') as f:
Path(dir_name + '/tmp').mkdir()
f.extractall(dir_name + '/tmp')
感想
せっかく時間をとって調査したので、個人的につまった箇所を残しておきたく投稿しました
Stack Overflow unable-to-connect-oracle-database-using-cx-oracle-from-aws-glue の投稿を見つけた瞬間気持ちは「絶対Glue Python ShellからOracle繋げる!」気持ちになってしまい、諦めるタイミングが見極められず長々と奮闘してました
同じ境遇でなかなか諦めがつかない方にこの記事が見つかると良いな…
あと個人的に最近Cloud Shellに期待しがちになっていた…
Linuxコマンドの前処理が必要なケースで、サクッとlocalできなかったら、次はサクッとCodeBuildに移ろう…