NodeJS 为什么我不能更新节点js中的env变量

qgelzfjb  于 2023-06-29  发布在  Node.js
关注(0)|答案(3)|浏览(158)

我想在node js中更新我的env变量,但我无法更新它的env变量,我尝试使用console.log(process.env.DB_HOST),但仍然得到旧值,这里我添加了我的整个代码,任何人都可以看看它,并帮助我解决这个问题,

function exec_api() { 
    return new Promise(async function (resolve) {
        const execSync = require('child_process').exec;
        //let child_process_obj = execSync('DB_HOST='+process.env.UNITTEST_DB_HOST+' DB_DATABASE='+process.env.UNITTEST_DB_DATABASE+'  DB_USERNAME='+process.env.UNITTEST_DB_USERNAME+' DB_PASSWORD='+process.env.UNITTEST_DB_PASSWORD+'  PORT='+process.env.UNITTEST_SERVICE_PORT+' ./node_modules/.bin/nodemon main.js'); 
        await execSync('export DB_HOST=' + process.env.UNITTEST_DB_HOST);
        await execSync('export DB_DATABASE=' + process.env.UNITTEST_DB_DATABASE);
        await execSync('export DB_USERNAME=' + process.env.UNITTEST_DB_USERNAME);
        await execSync('export DB_PASSWORD=' + process.env.UNITTEST_DB_PASSWORD);
        await execSync('export PORT=' + process.env.UNITTEST_API_BACKEND_PORT);
        let child_process_obj = await execSync('node main.js');
        unittest_api_backend_process_id = child_process_obj.pid;
        resolve(true);
    });
}
k7fdbhmy

k7fdbhmy1#

TLDR:修改process.env即可

要更改、添加或删除环境变量,请使用process.env。下面是测试代码,展示了这是如何工作的:
main.js中:

console.log(process.env.DB_DATABASE);

exec.js中:

const execSync = require ('child_process').execSync;

process.env.DB_DATABASE = 'foo'; // this is ALL you need to do

console.log(execSync('node main.js').toString('utf8'));

使用上面的两个文件,如果您运行node exec.js,您将看到foo在控制台中打印出来。这是从main.js打印的,它继承了exec.js的环境。
所以你需要在代码中做的就是:
我想在node js中更新我的env变量,但我无法更新其env变量,我尝试了console.log(process.env.DB_HOST),但仍然得到旧值,在这里我添加了我的整个代码,任何人都可以看看它,并帮助我解决这个问题,

function exec_api() { 
    return new Promise(function (resolve) {
        const exec = require('child_process').exec;

        // The following is node.js equivalent of bash "export":
        process.env.DB_HOST = process.env.UNITTEST_DB_HOST;
        process.env.DB_DATABASE = process.env.UNITTEST_DB_DATABASE;
        process.env.DB_USERNAME = process.env.UNITTEST_DB_USERNAME;
        process.env.DB_PASSWORD = process.env.UNITTEST_DB_PASSWORD;
        process.env.PORT = process.env.UNITTEST_SERVICE_PORT;

        let child_process_obj = exec('node main.js', {
            stdio: ['inherit', 'inherit', 'inherit']
        });

        unittest_api_backend_process_id = child_process_obj.pid;

        resolve(true);
    });
}

注意,如果你想在main.js结束时返回promise,你需要做:

function exec_api() { 
    return new Promise(function (resolve) {
        const exec = require('child_process').exec;

        // The following is node.js equivalent of bash "export":
        process.env.DB_HOST = process.env.UNITTEST_DB_HOST;
        process.env.DB_DATABASE = process.env.UNITTEST_DB_DATABASE;
        process.env.DB_USERNAME = process.env.UNITTEST_DB_USERNAME;
        process.env.DB_PASSWORD = process.env.UNITTEST_DB_PASSWORD;
        process.env.PORT = process.env.UNITTEST_SERVICE_PORT;

        let child_process_obj = exec('node main.js', {
            stdio: ['inherit', 'inherit', 'inherit']
        });

        unittest_api_backend_process_id = child_process_obj.pid;

        child_process_obj.on('exit', () => resolve(true));

        // ^^^ Cannot use `await` as the API is not promise based
        //     but event based instead.
    });
}

说来话长:为什么export不工作

在unixen上,环境变量,实际上,整个环境包括当前工作目录,根目录(可以通过chroot更改)等。不是贝壳的特征。它们是过程的特征。
我们可能熟悉一些shell为子进程设置环境变量的export语法,但这就是shell的语法。它与环境变量本身无关。例如,C/C++不使用export,而是使用setenv()函数来设置环境变量(实际上,在内部,bash/sh/ksh等在实现export时就是这样做的)。
在node.js中,阅读和设置环境变量的机制是通过process.env

为什么让shell做不了

这不仅仅是node.js的问题。它在bash中也不起作用:
Inexporter.sh

#! /bin/bash

export DB_DATABASE=$1

exec.sh中:

#! /bin/bash

./exporter.sh foo
echo $DB_DATABASE ;# does not print "foo"

这是unixen的一个核心安全特性:不允许其他用户干扰您的进程。在环境的情况下,此策略的实施方式是只有父进程可以设置子进程的环境。子进程不允许设置父进程的环境。假设子进程属于父进程,所以你应该被允许对程序做你想做的事情--但是由于父进程(你)不属于子进程,所以子进程不被允许扰乱父进程的环境。
这就是为什么尝试使用export不起作用的原因。它实际上可以工作(变量确实是在子shell中创建的),但不允许更改其父进程(node.js进程)的环境。

v8wbuo2f

v8wbuo2f2#

在终端中使用export时,它会指示shell设置环境变量。
当您从代码中调用exec时,您并没有运行这样的shell,原因是提取每个命令的输出将成为一个挑战。
这使得export成为一个被忽略的命令。
你可以通过向execSync传递一个option对象来解决这个问题:

execSync('node main.js', {
    env: {
        DB_HOST: 'localhost',
         // More envs...
    }
}
vfh0ocws

vfh0ocws3#

如果您使用.env文件存储端口;那我就有个办法
1.复制.env文件中的内容
1.现在,删除.env文件。
1.创建新的.env并粘贴内容。
1.现在运行(npm install dotenv
1.运行服务器

相关问题