读写process.env值是否同步?

时间:2017-08-21 05:35:22

标签: node.js asynchronous environment-variables

在Node.js中读取和编写环境变量是使用process.env object完成的。

例如:

  • process.env.foo评估为env var foo
  • process.env.bar = 'blah'env var bar的值设置为blah
  • delete process.env.baz删除环境变量baz

从试验和错误,以及缺少回调,我认为这些操作是同步的,但我没有找到它process.env documentation

Node {js中的env var访问是同步还是异步?

附录:为什么我认为这个问题不重要

评论之后:读取和编写环境变量可能意味着进程需要与操作系统通信,或执行某种阻塞I / O操作。

因此,有必要询问环境变量是否作为本地对象存储在内存中而没有任何同步,或者以阻塞方式发送到操作系统。

此外,实施可能因操作系统而异,官方文档也没有对非阻塞操作的承诺。

2 个答案:

答案 0 :(得分:2)

我认为“同步”/“异步”可能有点误导。

我想实际的问题是:阅读或写process.env贵吗?它是否使用操作系统执行阻止操作?

简短的回答是是的,它可能很昂贵。

有关更多背景信息及其对某些应用的影响程度,请参阅this GitHub issue。在2015年它已经stated that the documentation should be updated to make it clear that accessing process.env is slow但尚未发生。

您实际上可以看到implementation for process.env in the node.js source code显然任何访问都会调用functions defined from here onwards之一。

根据平台的不同,这可能会产生或多或少的影响。

在Windows上变得最为明显,因为您可以从外部查看进程的当前环境(在Linux中,/proc/.../environ文件将在使用{{1}更改环境时保留其原始内容})。

例如:

setenv

这将启动一个节点进程,该进程在当前进程的环境中创建一个node -e "process.env.TEST = '123'; setInterval(() => {}, 1000);"; 环境变量,然后永远等待。

现在我们可以打开Process Explorer或Process Hacker等工具,查看节点流程的环境:

enter image description here

瞧,变量就在那里。这证明另一种方式是写入TEST实际上访问操作系统。

此外,因为对象实际上查询来自OS的所有数据,这意味着它甚至与普通对象的行为不同。再一次,Windows示例(因为它最古怪):

  • Windows匹配不区分大小写的环境变量。

    process.env
  • Windows隐藏了以> process.env.TEST = '123' '123' > process.env.tEsT '123' 开头的环境变量,这些变量不能通过常规方式更改,也不能枚举。 node.js复制这些语义。 =变量特别代表特定驱动器中的当前目录(是的,Windows为每个驱动器存储它们)。

    =X:

现在,有人可能会认为(类似于我链接的GitHub问题中提出的那样)node.js应该只在实际对象中缓存> Object.keys(process.env).filter(k => k === '=Z:') [] > process.env['=Z:'] 'Z:\\' > process.env['=Z:'] = 'Z:\\Temp' 'Z:\\Temp' > process.env['=Z:'] 'Z:\\' > process.chdir('Z:\\Temp') undefined > process.env['=Z:'] 'Z:\\Temp' ,并且为子进程创建从缓存中读取环境宾语。由于以下原因,这是不可取的:

  • 他们需要复制底层平台的语义并重新实现它们。正如您在上面的Windows示例中所看到的,这在某些时候最终会拦截process.env并尝试自动更新受影响驱动器的相关chdir变量(然后它将无法正常工作)如果一个原生插件会改变当前目录),或者只为某些变量访问操作系统,那么就会产生疯狂和巨大的潜在错误。
  • 这会破坏从外部读取进程环境的应用程序(如Process Explorer),因为它们会看到不正确的值。
  • 如果本机模块从C ++代码访问其自身的环境变量,则会产生不一致,因为它们现在具有与缓存对象不同的状态。
  • 如果子进程是由本机模块启动的,则会导致子进程不继承正确的变量(出于与上述相同的原因)。

这也应该解释为什么在代码中执行=X:是个坏主意。首先,它会破坏Windows上的不区分大小写(并且您不可能知道某些其他模块所需的模块可能依赖于此),除此之外,它当然会导致如上所述的大量其他问题。 / p>

答案 1 :(得分:-1)

实际上,这是一个普通的对象,让你可以获得当前进程的环境变量,毕竟它们只是一些变量,可以为程序提供一些设置。在nodejs程序读取它们之后,Nodejs只为它们设置了一个普通对象。虽然文档没有写出来但是它写了这是一个对象并遵循以下内容:

  

可以修改此对象,但这样的修改不会   反映在Node.js进程之外。换句话说,   以下示例不起作用:

$ node -e 'process.env.foo = "bar"' && echo $foo
     

以下将:

process.env.foo = 'bar';
console.log(process.env.foo);
     

在process.env上分配属性会隐式地将值转换为字符串。

这足以解释你的问题。