[TOC]
# 环境变量及配置相关命令
> Shell脚本的命令常常会使用到`环境变量`进行信息传递,因此非常有必要对`环境变量`知识做个基础了解。
- `环境变量`相关命令 : `export`、`env`、`set`
- 重要的`环境变量`: `PATH`、`HOME`、`RANDOM`
- 环境变量配置文件: `/etc/profile`、`~/.bash_profile`、`~/.bashrc`
## 环境变量相关命令
- `export` : Bash保留关键词,用于导出当前Shell环境变量的`name`变量到后续执行的命令的环境中,如果没有指定`name`或设置了`-p`参数将打印输出当前Shell的`所有被导出`的变量名称和变量值。用法:`export -fn [name[=word]]`或`export -p`。常用在`多个子脚本之间`的环境变量信息传递。
- `env` : 独立系统命令,在`重建`的Shell环境中运行命令程序,如果无任何参数则打印输出当前环境变量信息,用法:`env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]` 。
- `set` : Bash内建命令,用于设置`Shell`的`属性`,注意到这个并不是用来设置环境变量的命令,但是无参数时可以输出显示当前`Shell`的所有变量名称和变量值信息,比`export`输出内容更多(包含没有被导出的变量)。
示例,您可以预测一下执行下面脚本后的输出结果:
```sh
#!/bin/bash
name="Bob"
echo "Hello $name"
sh -c 'echo "Hello $name"'
env name="Jim" echo "Hello $name"
env name="Jim" sh -c 'echo Hello $name'
echo "Hello $name"
export name="Tom"
echo "Hello $name"
sh -c 'echo "Hello $name"'
env sh -c 'echo Hello $name'
```
执行输出结果:
```sh
$ sh ./a.sh
Hello Bob
Hello
Hello Bob
Hello Jim
Hello Bob
Hello Tom
Hello Tom
Hello Tom
```
跟您预测的结果一致么? 我们来分析一下。
第一条命令`name="Bob"`是在`a.sh`脚本内部设置环境变量`name`,但生效范围仅限当前的脚本中,
第二条命令`echo "Hello $name"`,`name`变量值为"Bob",输出结果为"Hello Bob"。
第三条命令`sh -c 'echo "Hello $name"'`是在新建的子Shell环境中执行`'echo "Hello $name"'`命令,您可能注意到了这里命令两边用了单引号,目的防止在`a.sh`脚本执行子shell进程的参数传递时对`name`变量进行解析,应该将`name`放到子Shell中进行解析,因此输出结果是`Hello `,因为子Shell中并没有设置`name`环境变量。
第四条命令`env name="Jim" echo "Hello $name"`,虽然设置了`name`变量,但是由于`没有使用单引号`括起来导致在`env`命令新生成的Shell环境中执行的命令是`echo "Hello Bob"`,而不是`echo "Hello $name"`,因此输出结果分别为"Hello Bob"。
第五条命令`env name="Jim" sh -c 'echo Hello $name`解决了上一条命令的问题,因此输出结果为"Hello Jim"。
第六条命令`echo "Hello $name"`的目的是用来说明`env`命令内设置的环境变量不会对当前Shell脚本的环境变量产生影响,输出结果为"Hello Bob"。
第七条命令`export name="Tom"`,导出了`name`变量,这意味着此命令之后生成的其他子Shell的环境变量中会携带`name`变量,因此最后的三条命令输出的都是"Hello Tom"。
如果您在以后编写脚本时还会遇到此类环境变量显示不正确或者与预期不符合时,您可以回来再仔细的想一想上面的示例,相信会帮到您的。
### set使用介绍
> 由于`set`命令在`Shell`脚本中可以改变脚本的执行结果和状态,对于编写、调试脚本都比较重要,所以单独的说明一下。
使用方法: `set [--abefhkmnptuvxBCHP] [-o option] [arg ...]`
常用的参数:
- `-a` : `-o allexport`自动将设置的变量导出,相当于默认每个变量都使用了`export`进行导出。
- `-e` : `-o errexit`当脚本中的命令执行返回结果为非0值时,脚本立即退出。也就是执行错误后不再继续向下执行,避免更多的错误结果。
- `-n` : `-o noexec`只读取命令,并不执行。常用于语法检测,通常使用`sh -n script.sh`方法检查脚本语法正确性。
- `-u` : `-o nounset`遇到未定义的变量时报错退出执行,而不是默默的忽略继续执行。
- `-v` : `-o verbose`在读取输入的同时打印出来。
- `-x` : `-o xtrace`跟踪调试脚本,并显示 `PS4` 的值。通常使用`sh -x script.sh`作为`调试`查看脚本执行过程中变量值的真实情况。
- `-o vi`: 使用`vi`样式的命令行编辑操作方式,如果你比较喜欢使用`vi`的操作方式就可以这样设置了。
- `-o emacs`: 使用`emacs`样式的命令行编辑操作方式,这是`Bash`的默认方式。
>值得说的是,当我们想要`关闭`某个选项时,可以把减号`-`替换成加号`+`执行一下就可以了,例如`set +x`就可以关闭`xtrace`跟踪调试功能。这样我们就可以非常灵活的使用这些`shell`属性了。
## 重要的环境变量
- `PATH` : 定义了Shell中执行的命令的搜索路径列表。目录之间用冒号(`:`)分割,格式如“/path/to/bin1:/path/to/bin2:.:/usr/bin”,当执行`ls`时会按先后顺序逐个查找$PATH变量中的目录,找到后停止继续查找,如果找不到会提示命令找不到"ls: command not found"。
- `HOME` : 当前用户的个人目录;内建命令 `cd` 的默认参数。在执行波浪线(`~`)扩展时也用到这个变量。
- `RANDOM`: 每次引用这个参数时,都会产生一个 0 到 32767 之间的随机整数。可以通过向 `RANDOM` 赋值来初始化随机数序列。如果取消了 RANDOM 的定义,它就失去了特殊的意义,即使后来重新定义它。
- `HISTFILE`: 保存命令历史的文件名。默认值是`~/.bash_history`。如果取消定义,在交互式 shell 退出时 命令历史将不会保存。
- `HISTFILESIZE`: 历史文件中包含的最大行数。 默认值是 500。
- `PS1` : 交互终端光标前的提示符串设置的变量。 默认值是 `\s-\v\$ `。设置方法可以在`man bash`文档中的`PROMPTING`小节找到详细说明。
- `PS2` : 这个参数的值同 PS1 一起被扩展,用作次提示符字符串。默认值是 `> `。
- `PS3` : 这个参数的值被用作内建命令 select 的提示符。
- `PS4` : 跟踪`shell`脚本或者交互界面执行过程的细节前缀提示符,`PS4`的第一个字符会被复制多次,来指示 indirection 的`层数`。默认值是加号后携带一个空格`+ `。
`PATH`变量在Shell中是非常重要的,比如配置JAVA开发环境,我们将`JDK环境`保存路径为 /prod/jdk ,如果想要在shell中可以直接使用`java`命令,做法是在 PATH 变量中添加 /prod/jdk/bin 目录即可,但是为了保证这个配置以后也一直有效,就可以将`export PATH=/prod/jdk/bin:$PATH`添加到 ~/.bashrc 环境变量文件中。
## 环境变量配置文件
> 在Linux系统中,每个进程都有其各自的环境变量设置。 缺省情况下, 当一个进程被创建时, 除了创建过程中的明确更改外,它继承了其父进程的绝大部分环境设置。
Linux系统的环境变量设置是通过一些默认(疑问1?)的文件定义的,下面是我们经常使用的默认`Bash`环境变量设置文件。
- `/etc/profile` : 系统范围的初始化文件,登录 shell 会执行它,登录桌面时执行一次。
- `~/.bash_profile` : 个人初始化文件,登录 shell 会执行它,登录桌面时执行一次。
- `~/.bashrc` : 个人的每个交互式 shell 启动时执行的文件,每次打开新窗口会执行一次。
- `~/.bash_logout` : 个人的登录 shell 清理文件,当一个登录 `shell` 退出时会执行一次。
- `~/.inputrc` : 个人的 `readline` 初始化文件。
**修改后的环境变量文件如何生效呢?**
这要依赖我们修改的是哪个配置文件,比如`/etc/profile`被修改后会在下次重新登录时生效,而`~/.bashrc`在我们打开新的`shell`终端窗口时就会生效。
知道了不同环境变量文件的作用,就不会**随意乱修改**配置文件,导致在不应该修改的位置修改了,看似有效实则扩大了影响的范围,有可能会对服务器上运行的其他应用造成错误影响。
当然我们可以通过`手动`执行配置文件来立即生效,方法如下:
- `. ~/.bashrc` : 注意文件前面有个点符号(`.`),在`当前shell环境`中执行 `~/.bashrc` 中的命令。
- `source ~/.bashrc`: 读取并在`当前shell环境`中执行 `~/.bashrc` 中的命令,返回最后一个命令的返回状态。
通常以上两种方式常常会在脚本中见到,这样可以帮助脚本执行时保证能够提供脚本需要的环境变量信息,例如使用`cron`调度脚本时或者远程`ssh`执行脚本时。
疑问1: 默认的文件是谁执行的?
答案: 是我们的默认Shell执行的,也就是 grep `whoami` /etc/passwd 中配置的默认shell的默认环境变量文件。
疑问2: 如何知道有哪些默认环境变量文件呢?
答案: 查看`man bash`文档,在最后有`Files`一节内容,列举出了相关文件及作用信息,例如我们修改了默认shell为/usr/bin/zsh,那么每次打开新Terminal窗口执行的默认的环境变量文件就变成了`~/.zshrc`。与之对应的默认环境变量文件如下:
$ZDOTDIR/.zshenv
$ZDOTDIR/.zprofile
$ZDOTDIR/.zshrc
$ZDOTDIR/.zlogin
$ZDOTDIR/.zlogout
关于环境变量文件内容就介绍到这里。
---
~END~
- 前言
- 第一章 开始吧
- 1.0 选择适合你的Linux发行版
- 1.1 开始制作启动U盘
- 1.2 安装你的第一个Linux操作系统
- 1.3 安装Linux系统后要做的事情
- 1.4 什么是root用户
- 1.5 Linux下使用终端执行Shell命令
- 1.6 Linux软件安装方法介绍
- 1.7 Linux常用软件推荐
- *安装Manjaro发行版系统
- *安装Manjaro后要做的配置工作
- Flatpak安装软件方法
- 为什么Linux系统普及成都落后于Windows和MacOS?
- 第二章 Linux上的基础命令
- 2.0 环境变量及配置相关命令
- 2.1 文件及目录操作相关命令
- 2.2 文本处理相关命令
- 2.3 进程任务管理相关命令
- 2.4 用户管理相关命令
- 第三章 开发环境的部署
- 3.0 学习Shell编程
- 3.1 环境变量配置实例_如何配置JDK环境
- Python编程环境
- C语言编程环境
- 第四章 深入理解Linux系统
- 关于Linux不得不说的CopyLeft