oracle / node-oracledb

Oracle Database driver for Node.js maintained by Oracle Corp.
http://oracle.github.io/node-oracledb/
Other
2.24k stars 1.07k forks source link

Azure Linux Functions Error: DPI-1047 Cannot locate a 64-bit Oracle Client library #1611

Closed damienwebdev closed 2 weeks ago

damienwebdev commented 9 months ago
  1. What versions are you using?
damien@DESKTOP-N7ABP4H:~/project$ npm ls oracledb
mono@0.0.0 /home/damien/project
└── oracledb@6.1.0

Give your database version - 11g

{
  "platform": "linux",
  "version": "v18.16.0",
  "arch": "x64",
  "oracleVersion": "6.1.0",
  "clientVersion": "21.4.0.0.0"
}
  1. Is it an error or a hang or a crash? Error.

  2. What error(s) or behavior you are seeing?

Error: DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory".

func start

  1. Include a runnable Node.js script that shows the problem.
import * as fs from 'fs';
import * as oracledb from 'oracledb';

module.exports = async function (context: any, req: any) {
    context.log('This is a new function.');
    oracledb.initOracleClient();
    context.res = {
        // status: 200, /* Defaults to 200 */
        body: {
            "platform": process.platform,
            "version": process.version,
            "arch": process.arch,
            "oracleVersion": oracledb.versionString,
            "clientVersion": oracledb.oracleClientVersionString,
        }
    };
    return context;
}

Locally, I can get this to work with a local.settings.json like:

   {
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "ORACLE_DATABASE_NAME": "",
    "ORACLE_DATABASE_HOST": "",
    "ORACLE_DATABASE_USER": "",
    "ORACLE_DATABASE_SERVICE": "",
    "ORACLE_DATABASE_PASSWORD": "",
    "ORACLE_DATABASE_PORT": "1521",
    "LD_LIBRARY_PATH": "/home/damien/path/to/client",
    "DPI_DEBUG_LEVEL": 64
  }
}

However, when I tried the exact same setup in Azure Functions (I confirmed the instantclient's *.so are uploaded correctly to the right location both via manual inspection and via a script like:

import * as fs from 'fs';

console.log(process.env['LD_LIBRARY_PATH']);
const files = fs.readdirSync(process.env['LD_LIBRARY_PATH'] ?? process.cwd());
console.log(files);

For clarity, for me, my settings across the envs in question are:

LD_LIBRARY_PATH - Azure Functions (locally):  /home/damien/projects/dist/packages/project/oracle-instant-client
Instaclient Location - Azure Functions (locally): /home/damien/projects/dist/packages/project/oracle-instant-client

== Version 1
LD_LIBRARY_PATH - Azure Functions (PaaS): /home/site/wwwroot/oracle-instant-client
Instaclient Location - Azure Functions (PaaS): /home/site/wwwroot/oracle-instant-client

== Version 2 via a file mount
LD_LIBRARY_PATH - Azure Functions (PaaS): /opt/oracle-instant-client
Instaclient Location - Azure Functions (PaaS): /opt/oracle-instant-client

I tried the debug setting DPI_DEBUG_LEVEL: 64 and locally I see a successful load:

[2023-10-08T20:02:01.414Z] ODPI [26713] 2023-10-08 16:02:01.412: ODPI-C 5.0.0
[2023-10-08T20:02:01.414Z] ODPI [26713] 2023-10-08 16:02:01.412: debugging messages initialized at level 64
[2023-10-08T20:02:01.414Z] ODPI [26713] 2023-10-08 16:02:01.412: Context Parameters:
[2023-10-08T20:02:01.414Z] ODPI [26713] 2023-10-08 16:02:01.412: Environment Variables:
[2023-10-08T20:02:01.415Z] ODPI [26713] 2023-10-08 16:02:01.412:     LD_LIBRARY_PATH => "/home/damien/project/dist/packages/oracle-instant-client"
[2023-10-08T20:02:01.415Z] ODPI [26713] 2023-10-08 16:02:01.412: check module directory
[2023-10-08T20:02:01.415Z] ODPI [26713] 2023-10-08 16:02:01.412: module name is /home/damien/project/dist/packages/esg-read-api/build/Release/oracledb-6.1.0-linux-x64.node
[2023-10-08T20:02:01.415Z] ODPI [26713] 2023-10-08 16:02:01.412: load in dir /home/damien/project/dist/packages/esg-read-api/build/Release
[2023-10-08T20:02:01.415Z] ODPI [26713] 2023-10-08 16:02:01.412: load with name /home/damien/project/dist/packages/esg-read-api/build/Release/libclntsh.so
[2023-10-08T20:02:01.416Z] ODPI [26713] 2023-10-08 16:02:01.412: load by OS failure: /home/damien/project/dist/packages/esg-read-api/build/Release/libclntsh.so: cannot open shared object file: No such file or directory
[2023-10-08T20:02:01.416Z] ODPI [26713] 2023-10-08 16:02:01.412: load with OS search heuristics
[2023-10-08T20:02:01.416Z] ODPI [26713] 2023-10-08 16:02:01.412: load with name libclntsh.so
[2023-10-08T20:02:01.421Z] ODPI [26713] 2023-10-08 16:02:01.421: load by OS successful
[2023-10-08T20:02:01.421Z] ODPI [26713] 2023-10-08 16:02:01.421: validating loaded library

However, comparing that with the Azure Function logs with debugging enabled gives me:

"ODPI [00088] 2023-10-08 20:24:31.060: ODPI-C 5.0.0"
"ODPI [00088] 2023-10-08 20:24:31.061: debugging messages initialized at level 64"
"ODPI [00088] 2023-10-08 20:24:31.062: Context Parameters:"
"ODPI [00088] 2023-10-08 20:24:31.062: Environment Variables:"
"ODPI [00088] 2023-10-08 20:24:31.062:     LD_LIBRARY_PATH => ""/opt/oracle-instant-client"""
"ODPI [00088] 2023-10-08 20:24:31.062: check module directory"
"ODPI [00088] 2023-10-08 20:24:31.062: module name is /home/site/wwwroot/build/Release/oracledb-6.1.0-linux-x64.node"
"ODPI [00088] 2023-10-08 20:24:31.062: load in dir /home/site/wwwroot/build/Release"
"ODPI [00088] 2023-10-08 20:24:31.062: load with name /home/site/wwwroot/build/Release/libclntsh.so"
"ODPI [00088] 2023-10-08 20:24:31.063: load by OS failure: /home/site/wwwroot/build/Release/libclntsh.so: cannot open shared object file: No such file or directory"
"ODPI [00088] 2023-10-08 20:24:31.063: load with OS search heuristics"
"ODPI [00088] 2023-10-08 20:24:31.063: load with name libclntsh.so"
"ODPI [00088] 2023-10-08 20:24:31.063: load by OS failure: libclntsh.so: cannot open shared object file: No such file or directory"
"ODPI [00088] 2023-10-08 20:24:31.063: load with name libclntsh.so.19.1"
"ODPI [00088] 2023-10-08 20:24:31.063: load by OS failure: libclntsh.so.19.1: cannot open shared object file: No such file or directory"
"ODPI [00088] 2023-10-08 20:24:31.063: load with name libclntsh.so.18.1"
"ODPI [00088] 2023-10-08 20:24:31.063: load by OS failure: libclntsh.so.18.1: cannot open shared object file: No such file or directory"
"ODPI [00088] 2023-10-08 20:24:31.064: load with name libclntsh.so.12.1"
"ODPI [00088] 2023-10-08 20:24:31.064: load by OS failure: libclntsh.so.12.1: cannot open shared object file: No such file or directory"
"ODPI [00088] 2023-10-08 20:24:31.064: load with name libclntsh.so.11.1"
"ODPI [00088] 2023-10-08 20:24:31.064: load by OS failure: libclntsh.so.11.1: cannot open shared object file: No such file or directory"
"ODPI [00088] 2023-10-08 20:24:31.064: load with name libclntsh.so.20.1"
"ODPI [00088] 2023-10-08 20:24:31.064: load by OS failure: libclntsh.so.20.1: cannot open shared object file: No such file or directory"
"ODPI [00088] 2023-10-08 20:24:31.065: load with name libclntsh.so.21.1"
"ODPI [00088] 2023-10-08 20:24:31.065: load by OS failure: libclntsh.so.21.1: cannot open shared object file: No such file or directory"

I also created https://github.com/Azure/azure-functions-core-tools/issues/1620#issuecomment-1752126509 as this may be on the Azure side, but I'm not 100% sure the internals of the v6 binaries.

Unfortunately, at this point, I didn't know where to look further. It feels as though:

  1. There's a mystical lookup function included in the pre-compiled binaries that I don't understand that excludes my directory on Azure functions.
  2. Azure functions filesystem operates "differently" in a way that I do not understand.
  3. true === false results in true
sharadraju commented 9 months ago

Thanks for reporting this. Based on the logs, it seems that the underlying ODPI-C library does not pickup the LD_LIBRARY_PATH for fetching libclntsh.so, when called through Azure functions.

We will investigate this and get back to you.

sudarshan12s commented 9 months ago

If all the files are confirmed to be at the path set in LD_LIBRARY_PATH, then it most likely looks to be some permissions or settings issue in the Function stack.

damienwebdev commented 9 months ago

I would assume so. I wound up just spinning up a docker container based upon mcr.microsoft.com/azure-functions/node:4-node18 that does actually function properly with the LD_LIBRARY_PATH. I suspect that this is something specific to Azure functions, but depending on whether or not the team cares to support the Azure Functions model, you may or may not want to investigate it further.

I can provide any further information you may need, but my C is weak at best and I got to LoadLibrary in the ODPI and then gave up as I don't know what that function does internally.

sudarshan12s commented 9 months ago

LoadLibrary is an windows API called by ODPI. GetLastError is dumped in odpi code. I think any application doing dlopen seems to have some permissions/setting issue. Can we also run under Linux which uses dlopen

Does thin mode work for your application? I mean If you remove oracledb.initOracleClient(); call from your application, driver runs in thin mode.

damienwebdev commented 9 months ago

I can't use thin mode as I am targeting an Oracle 11g database.

I did try to connect and I received a specific error saying that the thin client wasn't supported for the database I was connecting to.

anthony-tuininga commented 9 months ago

@damienwebdev Note the extra quotes around the value of LD_LIBRARY_PATH used in Azure compared to the one locally. It looks like the value of the environment variable includes the quotes -- which shouldn't be happening. Can you remove those quotes and try again?

damienwebdev commented 9 months ago

Those extra quotes are just from the log file escaper. They don't exist at runtime.

flash4174 commented 3 months ago

I strugle with the same issue. Any solution? I can only use thick mode Azure deployment, but can't run because of the missing instant oracle client. If I install it with ssh then the new deployment removes it from /oracle directory.

Azure web app -> Linux plan

sharadraju commented 2 months ago

@flash4174 Can you tell, what is the new deployment that removes Oracle Instant Client from the /oracle directory?

Are you saying that installing node-oracledb via npm removes Oracle Instant Client from the oracle?

flash4174 commented 2 months ago

@sharadraju I install Oracle Instant Client with ssh with wget and unzip to /oracle folder

Then I redeploy my site with local git and after that if I check the folder with ssh, it not exist.

Does the oracledb library should have the instant client by default?

sharadraju commented 2 months ago

Thanks @flash4174 for the explanation. When you redeploy your site, there may be other modules that could have erased the /oracle directory. Node-oracledb will not remove the /oracle directory and as of version 6.0 does not require Oracle Instant Client to get started.

If you want to use Thick mode, Oracle Instant Client is required.

I would suggest that you raise this issue with Azure. See https://github.com/oracle/node-oracledb/issues/1611#issuecomment-1753909473 for the OP's comments on Azure functions.

sharadraju commented 2 weeks ago

Closing this issue as it is an install issue with Azure, over which node-oracledb has no control.