node-oracledb 在 M1 Mac 上

huangapple go评论44阅读模式
英文:

node-oracledb on M1 Mac

问题

我正在尝试连接到我的大学的 Oracle 数据库。我编写了一个简单的后端,在我的 Windows 机器上可以工作,但是在我的 M1 Mac 上无法工作。您可以在 [这里][1] 找到我的存储库,以下是其中的核心部分:

    const express = require('express');
    const oracledb = require('oracledb');
    if (process.platform === 'darwin') {
        try {
          console.log("Success");
          oracledb.initOracleClient({libDir: process.env.HOME + '/Downloads/instantclient_19_8'});
        } catch (err) {
          console.log("Failure");
          console.error('Whoops!');
          console.error(err);
          process.exit(1);
        }
    }
    const dotenv = require('dotenv');
    const app = express();
    const PORT = 5000;
    dotenv.config();
    var cors = require('cors');
    app.use(cors());
    app.use(express.json());

    app.listen(PORT, () => {console.log(`listen to port ${PORT}`);})

    database_initialized = false

    async function init_database() {
        // 以下内容应该被包裹在 try/catch 语句中
    	await oracledb.createPool({
            user: process.env.USER_NAME,
            password: process.env.DB_PASSWORD,
            connectionString: process.env.CONNECTION_STRING
        });
        console.log("Successfully created connection pool");
        database_initialized = true
    }

    app.get('/', (req,res) => {
        res.send('Hello world!');
    });

    app.get('/get-customers', (req,res) => {
        async function fetchDataCustomers(){
            try {
                const connection = await oracledb.getConnection();

                oracledb.outFormat = oracledb.OUT_FORMAT_ARRAY;

                const query = process.env.QUERY_STR;;

                const result = await connection.execute(query);
                console.log("Completed request");
                
                try {
                    await connection.close();
                }
                catch (err) {
                    console.log("Encountered an error closing a connection in the connection pool.");
                }
                
                return result;
            } catch (error) {
                return error;
            }
        }

        fetchDataCustomers().then(dbRes => {
            res.send(dbRes);
        })
        .catch(err => {
            res.send(err);
        })
    })

    init_database();

我找到了一个好心的人提供了[详细说明][2],关于如何使用 Rosetta 切换到 x64 版本的 nvm,但是我的 `oracledb.createPool()` 函数在我的 M1 Mac 上似乎无法工作(在我的 Windows 机器上是可以工作的)。也就是说 try 块失败并转到 catch 块,并打印出 "listen to port 5000",然后重复打印控制台日志消息。终端上没有其他错误消息。

在我的 M1 Mac 上,我遵循了链接中的说明,并运行了 `nvm use intel` 和 `node -e 'console.log(process.arch)'` 来验证我使用的是 `x64`。在两台机器上,我可以运行以下命令:
- `npm init -y`
- `npm i --save express`
- `npm i --save-dev nodemon dotenv oracledb cors`
- 然后运行 `node server.js` 来测试连接。

在我的 Windows 机器上,我可以连接,然后可以检查我创建的端点(未包含在此处,但可以在我上面链接的 GitHub 存储库中看到)。在我的 M1 Mac 上,我只收到在 catch 块中的消息,告诉我遇到了错误。我想要能够从我的 M1 Mac 连接到 Oracle 数据库,但似乎我还没有技能可以自己解决这个问题。任何帮助将不胜感激。

更新:
将 `oracledb.createPool()` 从 try/catch 语句中移出后,我得到了以下内容:

    listen to port 5000
    (node:47913) UnhandledPromiseRejectionWarning: Error: DPI-1047: 无法定位 64 位 Oracle Client 库: "dlopen(libclntsh.dylib, 0x0001): tried: 'libclntsh.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OSlibclntsh.dylib' (no such file), '/usr/local/lib/libclntsh.dylib' (errno=62), '/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/libclntsh.dylib' (no such file), '/usr/lib/libclntsh.dylib' (no such file, not in dyld cache), 'libclntsh.dylib' (no such file), '/usr/local/lib/libclntsh.dylib' (errno=62), '/usr/lib/libclntsh.dylib' (no such file, not in dyld cache)'。请参阅 https://oracle.github.io/node-oracledb/INSTALL.html 以获取帮助
    Node-oracledb 安装说明: https://oracle.github.io/node-oracledb/INSTALL.html
    您必须在 /usr/local/lib 中具有 64 位 Oracle Instant Client Basic 或 Basic Light 包库,或通过调用 oracledb.initOracleClient({libDir: "/my/instant_client_directory"}) 进行设置。
    可以从 https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html 下载 Oracle Instant Client。

        at processTicksAndRejections (internal/process/task_queues.js:95:5)
        at async init_database (/Users/my-name/workspaces/node-oracle-test-project/back-end/server.js:30:5)
    (使用 `node --trace-warnings ...` 显示警告的创建位置)
    (node:47913) UnhandledPromiseRejectionWarning: 未处理的 promise 拒绝。这个错误要么是在 async 函数中抛出而没有 catch 块来处理,要么是一个未被 .catch() 处理的拒绝的 promise。要终止未处理的 promise 拒绝的 Node 进程,使用 CLI 标志 `--unhandled-rejections=strict`(参见 https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode)。 (rejection id: 2)
    (node:47913) [DEP0018] DeprecationWarning: 未处理的 promise 拒绝已被弃用。将来,未处理的 promise 拒绝将以非零退出代码终止 Node.js 进程

<details>
<summary>英文:</summary>

I&#39;m trying to connect to my university&#39;s Oracle DB. I wrote a simple backend that is working on my Windows machine but I can&#39;t get it working on my M1 Mac. You can find my repo [here][1] and here is the core of it,

    const express = require(&#39;express&#39;);
    const oracledb = require(&#39;oracledb&#39;);
    if (process.platform === &#39;darwin&#39;) {
        try {
          console.log(&quot;Success&quot;);
          oracledb.initOracleClient({libDir: process.env.HOME + &#39;/Downloads/instantclient_19_8&#39;});
        } catch (err) {
          console.log(&quot;Failure&quot;);
          console.error(&#39;Whoops!&#39;);
          console.error(err);
          process.exit(1);
        }
    }
    const dotenv = require(&#39;dotenv&#39;);
    const app = express();
    const PORT = 5000;
    dotenv.config();
    var cors = require(&#39;cors&#39;);
    app.use(cors());
    app.use(express.json());
    
    app.listen(PORT, ()=&gt;{console.log(`listen to port ${PORT}`);})
    
    database_initialized = false
    
    async function init_database() {
        // The following should be wrapped in a try/catch
    	await oracledb.createPool({
            user: process.env.USER_NAME,
            password: process.env.DB_PASSWORD,
            connectionString: process.env.CONNECTION_STRING
        });
        console.log(&quot;Successfully created connection pool&quot;);
        database_initialized = true
    }
    
    app.get(&#39;/&#39;, (req,res) =&gt; {
        res.send(&#39;Hello world!&#39;);
    });
    
    app.get(&#39;/get-customers&#39;, (req,res) =&gt; {
        async function fetchDataCustomers(){
            try {
                const connection = await oracledb.getConnection();
    
                oracledb.outFormat = oracledb.OUT_FORMAT_ARRAY;
    
                const query = process.env.QUERY_STR;;
    
                const result = await connection.execute(query);
                console.log(&quot;Completed request&quot;);
                
                try {
                    await connection.close();
                }
                catch (err) {
                    console.log(&quot;Encountered an error closing a connection in the connection pool.&quot;);
                }
                
                return result;
            } catch (error) {
                return error;
            }
        }
    
        fetchDataCustomers().then(dbRes =&gt; {
            res.send(dbRes);
        })
        .catch(err =&gt; {
            res.send(err);
        })
    })
    
    init_database();

I found someone who was nice enough to provide [detailed instructions][2] on using Rosetta to switch to the x64 version nvm, but my `oracledb.createPool()` function doesn&#39;t seems to be working on my M1 Mac (this works on my Windows machine). By that I mean the try block fails and drops to the catch block and prints &quot;listen to port 5000&quot; followed by repeatedly printing the console.log message. There are no other errors messages printed to the terminal.

On my M1 Mac, I follow the linked instructions and run `nvm use intel` and `node -e &#39;console.log(process.arch)&#39;` to verify I&#39;m using `x64`. On both machines, I can then run:
- `npm init -y`
- `npm i --save express`
- `npm i --save-dev nodemon dotenv oracledb cors`
- and `node server.js` to test the connection.

On my Windows machine, I connect and can then go on to check the endpoint I created (not included here but can be seen in the github repo I linked above). On my M1 Mac, I just get the message in the catch block telling me that an error was encountered. I want to be able to connect to an Oracle DB from my M1 Mac but it seems I don&#39;t yet have the skills to figure it out on my own. Any help would be appreciated.

Update:
After pulling `oracledb.createPool()` out of the try/catch I got the following:

    listen to port 5000
    (node:47913) UnhandledPromiseRejectionWarning: Error: DPI-1047: Cannot locate a 64-bit Oracle Client library: &quot;dlopen(libclntsh.dylib, 0x0001): tried: &#39;libclntsh.dylib&#39; (no such file), &#39;/System/Volumes/Preboot/Cryptexes/OSlibclntsh.dylib&#39; (no such file), &#39;/usr/local/lib/libclntsh.dylib&#39; (errno=62), &#39;/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/libclntsh.dylib&#39; (no such file), &#39;/usr/lib/libclntsh.dylib&#39; (no such file, not in dyld cache), &#39;libclntsh.dylib&#39; (no such file), &#39;/usr/local/lib/libclntsh.dylib&#39; (errno=62), &#39;/usr/lib/libclntsh.dylib&#39; (no such file, not in dyld cache)&quot;. See https://oracle.github.io/node-oracledb/INSTALL.html for help
    Node-oracledb installation instructions: https://oracle.github.io/node-oracledb/INSTALL.html
    You must have the 64-bit Oracle Instant Client Basic or Basic Light package libraries in
    /usr/local/lib or set by calling oracledb.initOracleClient({libDir: &quot;/my/instant_client_directory&quot;}).
    Oracle Instant Client can be downloaded from https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html
    
        at processTicksAndRejections (internal/process/task_queues.js:95:5)
        at async init_database (/Users/my-name/workspaces/node-oracle-test-project/back-end/server.js:30:5)
    (Use `node --trace-warnings ...` to show where the warning was created)
    (node:47913) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
    (node:47913) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

I then re-ran `npm install oracledb` and I&#39;m getting 

    oracledb ********************************************************************************
    oracledb ** Node-oracledb 5.5.0 installed in Node.js 19.3.0 (darwin, x64)
    oracledb **
    oracledb ** To use node-oracledb:
    oracledb ** - Oracle Client libraries (64-bit) must be available.
    oracledb ** - Follow the installation instructions:
    oracledb **   https://oracle.github.io/node-oracledb/INSTALL.html#instosx
    oracledb ********************************************************************************

So I&#39;m following the link and trying to find how to install Oracle Client libraries.

I&#39;m following the instructions [here][3] but I&#39;m not sure how to proceed. I ran `/Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru/install_ic.sh` as it says but I&#39;m not where to move instantclient_19_8 so that it&#39;s accessible. I tried moving `instantclient_19_8` to `/Users/brian` but that didn&#39;t resolve the error message.

I found [this][4] and added the suggested conditional to my code. Getting a new error.

    (node:51947) UnhandledPromiseRejectionWarning: Error: ORA-24415: Missing or null username.
        at async init_database (/Users/brian/workspaces/node-oracle-test-project/back-end/server.js:42:5)
    (Use `node --trace-warnings ...` to show where the warning was created)
    (node:51947) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
    (node:51947) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Is there a solution? Will I just resolve one error to be greeted by another? Am I just wasting my time?


  [1]: https://github.com/GoonerBrian/node-oracledb-on-m1-mac
  [2]: https://gist.github.com/LeZuse/bf838718ff2689c5fc035c5a6825a11c
  [3]: https://node-oracledb.readthedocs.io/en/latest/user_guide/installation.html#manual-installation
  [4]: https://blogs.oracle.com/opal/post/avoiding-the-dpi-1047-error-with-nodejs-node-oracledb-5-on-macos-and-windows


</details>


# 答案1
**得分**: 1

将`oracledb.createPool()`从try/catch块中移出后,我得到以下信息:

```plaintext
监听端口5000
(node:47913)UnhandledPromiseRejectionWarning: 错误:DPI-1047:无法定位64位Oracle客户端库:"dlopen(libclntsh.dylib,0x0001):尝试过:'libclntsh.dylib'(没有此文件),'/System/Volumes/Preboot/Cryptexes/OSlibclntsh.dylib'(没有此文件),'/usr/local/lib/libclntsh.dylib'(errno=62),'/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/libclntsh.dylib'(没有此文件),'/usr/lib/libclntsh.dylib'(没有此文件,在dyld缓存中),'libclntsh.dylib'(没有此文件),'/usr/local/lib/libclntsh.dylib'(errno=62),'/usr/lib/libclntsh.dylib'(没有此文件,在dyld缓存中)。请参阅https://oracle.github.io/node-oracledb/INSTALL.html以获取帮助
Node-oracledb安装说明:https://oracle.github.io/node-oracledb/INSTALL.html
您必须在/usr/local/lib中拥有64位Oracle Instant Client Basic或Basic Light包库,或通过调用oracledb.initOracleClient({libDir: "/my/instant_client_directory"})进行设置。
Oracle Instant Client可以从https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html下载

在processTicksAndRejections(internal/process/task_queues.js:95:5)处
async init_database(/Users/my-name/workspaces/node-oracle-test-project/back-end/server.js:30:5)
(使用`node --trace-warnings ...`以显示警告的创建位置)
(node:47913)UnhandledPromiseRejectionWarning:未处理的Promise拒绝。此错误要么是在没有catch块的情况下在async函数内抛出的,要么是未使用.catch()处理的拒绝的Promise。要在未处理的Promise拒绝时终止Node进程,请使用CLI标志`--unhandled-rejections=strict`(请参见https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode)。(拒绝ID:2)
(node:47913)[DEP0018] DeprecationWarning:未处理的Promise拒绝已弃用。将来,未处理的Promise拒绝将以非零退出代码终止Node.js进程。

然后,我重新运行了npm install oracledb,得到以下信息:

oracledb ********************************************************************************
oracledb ** Node-oracledb 5.5.0已安装在Node.js 19.3.0(darwin,x64)中
oracledb **
oracledb ** 要使用node-oracledb:
oracledb ** - 必须可用64位Oracle客户端库。
oracledb ** - 遵循安装说明:
oracledb **   https://oracle.github.io/node-oracledb/INSTALL.html#instosx
oracledb ********************************************************************************

我按照这里的说明安装了Instant Client,但实际上发现这里更容易跟随(因为我在认为我得到所需内容后停止阅读文档)。有一个问题,我需要解决如何从我的.env文件中获取我的凭据,但我认为这超出了我的原始帖子的范围。只要process.env值是硬编码的,这将起作用(我知道。解决这个问题是下一步)。我将更新我在原始帖子中链接的GitHub存储库,希望其他人会觉得比我容易。

更新:.env问题最终是我存储位置的问题。在我的Windows机器上,我可以将它放在父目录(与我的.gitignore并列)中,但在我的Mac上,我必须将它放在back-end目录中。


<details>
<summary>英文:</summary>
After pulling oracledb.createPool() out of the try/catch I got the following:
listen to port 5000
(node:47913) UnhandledPromiseRejectionWarning: Error: DPI-1047: Cannot locate a 64-bit Oracle Client library: &quot;dlopen(libclntsh.dylib, 0x0001): tried: &#39;libclntsh.dylib&#39; (no such file), &#39;/System/Volumes/Preboot/Cryptexes/OSlibclntsh.dylib&#39; (no such file), &#39;/usr/local/lib/libclntsh.dylib&#39; (errno=62), &#39;/System/Volumes/Preboot/Cryptexes/OS/usr/local/lib/libclntsh.dylib&#39; (no such file), &#39;/usr/lib/libclntsh.dylib&#39; (no such file, not in dyld cache), &#39;libclntsh.dylib&#39; (no such file), &#39;/usr/local/lib/libclntsh.dylib&#39; (errno=62), &#39;/usr/lib/libclntsh.dylib&#39; (no such file, not in dyld cache)&quot;. See https://oracle.github.io/node-oracledb/INSTALL.html for help
Node-oracledb installation instructions: https://oracle.github.io/node-oracledb/INSTALL.html
You must have the 64-bit Oracle Instant Client Basic or Basic Light package libraries in
/usr/local/lib or set by calling oracledb.initOracleClient({libDir: &quot;/my/instant_client_directory&quot;}).
Oracle Instant Client can be downloaded from https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html
at processTicksAndRejections (internal/process/task_queues.js:95:5)
at async init_database (/Users/my-name/workspaces/node-oracle-test-project/back-end/server.js:30:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:47913) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:47913) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I then re-ran npm install oracledb and I&#39;m got
oracledb ********************************************************************************
oracledb ** Node-oracledb 5.5.0 installed in Node.js 19.3.0 (darwin, x64)
oracledb **
oracledb ** To use node-oracledb:
oracledb ** - Oracle Client libraries (64-bit) must be available.
oracledb ** - Follow the installation instructions:
oracledb **   https://oracle.github.io/node-oracledb/INSTALL.html#instosx
oracledb ********************************************************************************
I followed the instructions [here][1] to install Instant Client but actually found [this][2] to easier to follow (because I stopped reading the doc once I thought I got what I needed). There is an issue with getting my credentials from my `.env` that I need to figure out but I&#39;d consider that to be out of scope to my original post. This will work so long as the `process.env` values are hard coded. (I know. Fixing that is the next step.) I will update the GitHub repo I linked in the original post and hopefully others will find things easier than I did.
Update: The `.env` issue turned out to be an issue with where I was storing it. On my Windows machine I was able to put it in the parent directory (sibling to my `.gitignore`) but on my Mac I had to put it in the `back-end` directory.
[1]: https://node-oracledb.readthedocs.io/en/latest/user_guide/installation.html#install-the-free-oracle-instant-client-basic-package
[2]: https://blogs.oracle.com/opal/post/avoiding-the-dpi-1047-error-with-nodejs-node-oracledb-5-on-macos-and-windows
</details>

huangapple
  • 本文由 发表于 2023年2月6日 04:39:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75355354.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定