likes
comments
collection
share

Linux 环境变量

作者站长头像
站长
· 阅读数 43

最近阅读了一些linux相关的书籍、文章以及文档,想结合自己的理解来讲解一下linux的环境变量。

本文的参考内容如下,感兴趣的小伙伴也可以阅读原文:

我的日常开发环境如下:

  • 操作系统:macos
  • shell: zsh

变量

linux中的变量有如下俩类:

  • shell变量(局部变量): 只能在当前shell中使用
  • 环境变量(全局变量): 可以传递变量到子shell

可以通过以下俩种方式来查看定义的变量:

  • printenv : 没有参数时列出所有的环境变量,有参数时列出参数对应的环境变量
  • echo: 显示对应的shell变量或环境变量

shell变量

在终端中可以直接通过name=value的形式来创建变量:

# 等号左右俩边不能有空格
name=value

可以通过echo $<variable name>来查看刚才定义的变量:

echo $name
# value

printenv <variable name>可以查看定义的环境变量:

# 由于name不是环境变量,输出内容为空
printenv name

通过这种方式定义的变量只能在当前进程中使用,而无法在子进程中使用。

为了验证上述文字,使用bash命令在终端中再创建一个子进程,可以看到,此时再次执行echo $name不会输出任何内容:

➜  ~ bash

bash-3.2$ echo $name

bash-3.2$

环境变量

想要让变量能在子进程中也使用,需要通过export来定义变量:

export name1=value1

查看定义的环境变量:

➜  ~ printenv name1
value1
➜  ~ echo $name1
value1

此时,我们在子进程中也能访问到定义的变量:

bash

bash-3.2$ printenv name1
value1
bash-3.2$ echo $name1
value1

但是当重新开启一个终端后,shell 变量和环境变量都会失效无法访问。为了能让变量永久的在所有终端中生效,需要修改配置文件 ,这个会在之后进行详细介绍。

内置环境变量

操作系统中有许多内置的环境变量,执行printenv可以查看这些变量:

# some environment variables
TERM_SESSION_ID=w0t0p0:D35D538F-01B7-407D-AC61-476CD68AE6E7
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.1Goz8bCjVc/Listeners
LC_TERMINAL_VERSION=3.4.16
COLORFGBG=7;0
ITERM_PROFILE=Default
XPC_FLAGS=0x0
SHELL=/bin/zsh
__CFBundleIdentifier=com.googlecode.iterm2
LC_CTYPE=UTF-8
TERM_PROGRAM_VERSION=3.4.16
TERM_PROGRAM=iTerm.app
LC_TERMINAL=iTerm2
COLORTERM=truecolor
COMMAND_MODE=unix2003
PATH=/Users/username/Library/pnpm:/Users/username/.bun/bin:/Users/username/.nvm/versions/node/v16.14.2/bin:/opt/homebrew/bin:/opt/homebrew/sbin:/Users/username/bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/username/.yarn/bin

需要注意的是PATH变量,PATH中定义了由:分割的目录列表,当用户在终端执行一个命令如ls时,会在PATH 中定义的目录下进行查找,找到对应的文件然后执行。

作为前端开发者,以我们经常用到的npm为例:

Linux 环境变量

可以看到npm所在目录存在于PATH对应的目录列表中,所以我们才可以通过终端来执行npm命令。其它的终端中的可执行命令,也是如此。

Node.js中的环境变量(wait approve)

Node.js中可以通过process.env来访问以及修改环境变量:

// 访问环境变量
console.log('mock', process.env.MOCK)

// 设置环境变量
process.env.MOCK = '22222'

需要注意的是,Node.js在创建子进程的时候环境变量默认和父进程相同:

import { spawn } from 'node:child_process'

console.log('mock', process.env.MOCK)

process.env.MOCK = '22222'

const childProcess = spawn('sh', ['-c', 'echo $MOCK'], { stdio: 'inherit' })
childProcess.on('error', (err) => {
  console.error(err)
})

执行上述代码MOCK=true npx tsx index.ts,输出如下:

mock true
22222

Shell 初始化文件

当我们每次打开终端后,shell便会从初始化文件中读取一系列配置,如环境变量、别名等。常见的shell初始化文件如下:

文件内容
/etc/profile应用到所有用户的全局配置
/etc/bashrc应用到所有用户的全局配置(专用于bash
~/.zshrc用户个人的zsh配置

通过cat ~/.zshrc命令,可以查看配置文件中的内容。下面展示的是我电脑中配置文件里的一些代码:

# If you come from bash you might have to change your $PATH.
export PATH=$HOME/bin:/usr/local/bin:$PATH

# Path to your oh-my-zsh installation.
export ZSH="$HOME/.oh-my-zsh"

# Set name of the theme to load --- if set to "random", it will
# load a random theme each time oh-my-zsh is loaded, in which case,
# to know which specific one was loaded, run: echo $RANDOM_THEME
# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes
ZSH_THEME="robbyrussell"

alias cat="pygmentize -g"

可以看到,在配置文件中可以进行设置环境变量、设置别名等一系列操作。

修改配置文件

当然,配置文件也可以修改来实现一些用户自定义的内容。我们可以通过vim命令,在命令行中直接修改配置文件

vim ~/.zshrc

比如,我们在配置文件中增加一个新的环境变量

# ... some other code
export A=test

需要注意的是,这样添加的内容只会在下次重新启动终端,再次读取配置文件时才会生效。为了让配置立即生效,要记得执行如下命令:

source ~/.zshrc
# 或者 . ~/.zshrc, 俩者作用完全相同

执行printenv A来查看是否成功添加环境变量:

Linux 环境变量

npm执行scripts中的cli命令

vite为例,在启动项目时需要在package.jsonscripts中配置{dev: "vite"}命令,然后在终端执行npm run devnpm 便会执行scriptsdev对应的vite命令。

vite命令在执行时,Node.js会将其环境变量PATH设置为node_modules/.bin,即会在node_modules/.bin 中查找可以执行的vite文件。其实现代码如下:

// npm-run-dev.ts
import { spawn } from 'node:child_process'
import { fileURLToPath } from 'node:url'
import process from 'node:process'
import path from 'node:path'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
// 核心:通过spawn执行 sh -c -- vite 命令,并将根目录下的./node_modules/.bin添加到环境变量中
// PATH和cwd要根据自已的目录结构来决定
const PATH = `${path.resolve(__dirname, '../../../', './node_modules/.bin')}:${
  process.env.PATH
}`
const ls = spawn('sh', ['-c', '--', 'vite'], {
  env: { PATH },
  cwd: path.resolve(__dirname, '../../../playground/vue-jsx'),
  stdio: 'inherit'
})

ls.on('close', (code) => {
  console.log(`child process exited with code ${code}`)
})
ls.on('error', (err) => {
  console.log('err', err)
})

上述代码其实就是通过spawn命令中的env来指定命令执行时的环境变量,从而能够直接运行本地安装的cli 。最终node_modules/.bin/vite在执行时,执行真正的vite源代码。

使用tsx执行上述代码,便可以实现与npm run dev一样的效果。

结语

以下是文中涉及到的linux命令:

学习linux的相关知识,帮助我进一步深入理解了Node.jscli的运行和调试过程,也让自己能更熟练的使用前端以及开发cli工具。

以上就是我对linux环境变量的一些理解,希望这些知识也能对你有所帮助。

转载自:https://juejin.cn/post/7162788361328361502
评论
请登录