英文:
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'm trying to connect to my university's Oracle DB. I wrote a simple backend that is working on my Windows machine but I can'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('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() {
// 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("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();
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'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 "listen to port 5000" 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 'console.log(process.arch)'` to verify I'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'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: "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)". 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: "/my/instant_client_directory"}).
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'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'm following the link and trying to find how to install Oracle Client libraries.
I'm following the instructions [here][3] but I'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'm not where to move instantclient_19_8 so that it's accessible. I tried moving `instantclient_19_8` to `/Users/brian` but that didn'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: "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)". 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: "/my/instant_client_directory"}).
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'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'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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论