linux 安装 nodejs,为什么环境变量 NODE_MAJOR 无法被填充?

我按照这里的 https://github.com/nodesource/distributions 方式在 ubuntu22.04 上安装 nodejs 和 npm

图片.png

但是遇到了问题,当我执行下面的命令

NODE_MAJOR=18 echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list

我发现 NODE_MAJOR 并没有填充

pon@T4GPU:~/code/me/reflex_example$ cat /etc/apt/sources.list.d/nodesource.list
deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_.x nodistro main

可以看到,结果不是 https://deb.nodesource.com/node_18.x 而是 https://deb.nodesource.com/node_.x

我用的是 bash

为什么把 NODE_MAJOR=18 加在命令开头却不行,理论上,这也是一种正确传递环境变量的方式之一?


加个分号也可以, 但是在使用 python 的时候,是可以不加 ;

pon@T4GPU:~/code/me/reflex_example$ NODE_MAJOR=18; echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list
deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main

难道是因为,不加分号,只对该 shell 的子进程可见,shell 本身不可见?


比如我写一个 python 程序

main.py

import os
print(os.environ['RUN_MODE'])

然后调用

pon@T4GPU:~/code/me/reflex_example$ python main.py 
Traceback (most recent call last):
  File "/home/pon/code/me/reflex_example/main.py", line 2, in <module>
    print(os.environ['RUN_MODE'])
          ~~~~~~~~~~^^^^^^^^^^^^
  File "<frozen os>", line 679, in __getitem__
KeyError: 'RUN_MODE'
pon@T4GPU:~/code/me/reflex_example$ RUN_MODE=prd python main.py 
prd

可以看到直接 python main.py 会报错,但是 RUN_MODE=prd python main.py 是正常的

阅读 1.5k
avatarAI BotBETA

这个问题出现的原因可能是因为在执行命令时,NODE_MAJOR 环境变量的值并没有正确地传递到 echo 命令中。要解决这个问题,您可以直接在 echo 命令中使用变量,而不需要将其存储在单独的变量中。

以下是修正后的命令:

NODE_MAJOR=18 echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list

在这个命令中,您可以直接使用 $NODE_MAJOR 来引用环境变量的值,而不需要将其存储在另一个变量中。通过这样的修改,您应该能够正确地填充 NODE_MAJOR 环境变量的值,并获得正确的源列表。

请注意,在执行这个命令之前,确保已经正确安装了 Node.js 和 npm,并且已经按照 https://github.com/nodesource/distributions 中的说明设置了 NODE_MAJOR 环境变量。

3 个回答
NODE_MAJOR=18 echo "deb ... https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main"

这里 $NODE_MAJOR 的替换是在当前的 bash 进程里完成的。而命令开始的 MAJOR=18 只影响新启动的 echo 进程。所以 $NODE_MAJOR 是替换不了的。


NODE_MAJOR=18; ... 里的 NODE_MAJOR=18 是一个独立的赋值语句,他会影响当前 shell 的环境。在其之后执行的所有进程都可以看到 NODE_MAJOR 的值。
(上面 NODE_MAJOR=18 echo ... 的里 NODE_MOJOR=18 是临时的,它只影响后面的 echo 。)


NODE_MOJOR=18 python ... ,这个例子里,python 进程已经可以看到 NODE_MAJOR=18 的值了。所以其内部是可以用它做替换的。

> export NODE_MAJOR=18
> echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_MAJOR.x nodistro main" | sudo tee /etc/apt/sources.list.d/nodesource.list

可能是因为 shell 认为这个NODE_MAJOR=18 echo "deb $NODE_MAJOR"命令是一条命令,执行这个命令的时候,NODE_MAJOR这个环境变量还不存在,所以是空的。

image.png

就是 shell 在解析命令的时候,在还没有执行 这行命令 的时候,就把当前这个shell的环境变量的值填充给了这个即将执行的命令了。在当前shell没有环境变量的时候,echo执行的就是 echo ''


用一个小程序来验证这个
这个程序执行后会打印环境变量和传入的参数。

package main

import (
    "fmt"
    "os"
)

func main() {
    // 打印环境变量
    fmt.Println("环境变量:")
    for _, env := range os.Environ() {
        fmt.Println(env)
    }

    // 检查是否传递了参数并打印参数
    args := os.Args[1:] // os.Args[0] 是程序名称,从索引 1 开始是传递的参数
    if len(args) > 0 {
        fmt.Println("传递的参数:")
        for _, arg := range args {
            fmt.Println(arg)
        }
    } else {
        fmt.Println("未传递任何参数。")
    }
}

执行 HHH=123456 ./main $HHH
image.png
image.png
可以看到 程序里面读取到了HHH这个环境变量,没有获取到参数,因为现在这个参数为空。
再次执行
image.png
这个时候结果是这样的:
image.png

就是在解析命令的时候,shell已经把当前的环境变量替换给echo了,echo拿到的就是“”,程序是能正常拿到环境变量的。


加了分号之后,分号之前的内容,相当于在当前会话设置了一个环境变量,分号之后是执行的另一个命令,这个分号其实和回车换行是一样的效果。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题