前言
在这一章,我对Linux中有关shell较为深入的理解和环境变量方面知识的一个记录。同时,还将其中涉及到的链接文件方面的内容也一并记录下来。
链接文件
链接文件是Linux文件系统的一个优势。如果需要在系统中维护同一文件的两个或多个副本,可以使用单个物理副本加多个虚拟副本(链接)的方法代替创建多个物理副本。链接是目录中指向文件真实位置的占位符。在Linux中有两种类型的文件链接。
- 符号链接
- 硬链接
符号链接(软链接)
符号链接是一个实实在在的文件,该文件指向存放在虚拟目录结构中某个地方的另一个文件。这两个以符号方式链接在一起的文件批次的内容并不相同。
要为一个文件创建符号链接,原始文件必须事先存在。然后可以使用ln
命令以及-s
选项来创建符号链接。如下面的例子
$ ls -l test_file
-rw-rw-r--. 1 christine christine 74 Feb 29 15:50 test_file
$
$ ln -s test_file slink_test_file
$
$ ls -l *test_file
lrwxrwxrwx. 1 christine christine 9 Mar 4 09:46 slink_test_file -> test_file
-rw-rw-r--. 1 christine christine 74 Feb 29 15:50 test_file
$
在上面的例子中,符号链接文件名slink_test_file位于ln命令的第二个参数的位置。长列表(ls -l
)中显示的内容中,符号文件名后的箭头(->)符号表明该文件是链接到文件test_file的一个符号链接。
同时,这两个文件的大小明显不同。这其中的原因是这两个就是两个完全不同的文件。slink_test_file文件只是指向test_file文件而已。
硬链接
硬链接创建的是一个独立的虚拟文件,其中包含了原始文件的信息以及位置。但是,两者就根本而已是同一个文件
要想创建硬链接,原始文件也必须事先存在存在,只不过这次只用ln
命令时不需要加入额外的选择了,如下
ls -l *test_one
-rw-rw-r--. 1 christine christine 0 Feb 29 17:26 test_one
$
$ ln test_one hlink_test_one
$
$ ls -li *test_one
1415016 -rw-rw-r--. 2 christine christine 0 Feb 29 17:26 hlink_test_one
1415016 -rw-rw-r--. 2 christine christine 0 Feb 29 17:26 test_one
$
在上面的例子中,创建好硬链接文件之后,使用ls -li
命令显示了两个文件的inode编号以及长列表。可以看到两者共享同一个inode编号。同时两者的文件大小也是一模一样的。
只能对处于同一个存储设备的文件创建硬链接。要想在位于不同存储设备的文件之间创建链接,只能使用符号链接。
shell
shell不单单是CLI(命令行界面),而是一种复杂的交互式程序。输入命令并利用shell来运行脚本会出现一些既有趣又令人困惑的问题。搞清楚shell进程及其与系统之间的关系能够帮助你解决这些难题,或是完全避开它们。
shell 的类型
当你登录系统时,系统启动什么样的shell程序取决于你的个人用户配置。在/etc/passwd文件中,用户记录的第7个字段中列出了该用户的默认shell程序。只要用户登录某个虚拟控制台终端或是在GUI中启动终端仿真器,默认的shell程序就会启动。
通过which bash
可以找到bash shell的位置。当然也可以找到其余shell的位置。
在现代Linux系统中,/bin目录通常是/usr/bin/目录的符号链接。这就是为什么通常默认shell程序是/bin/bash,但bash shell程序实际位于/usr/bin/目录。
并不是非得使用默认的交互式shell。可以启动系统中拥有的任意一种shell。只需要输入其名称即可。但是在实际中,不会有任何提升或消息表明你当前使用的是哪种shell。使用echo $0
会显示当前shell的名称。
shell的父子关系
用户登录某个虚拟控制台终端或在GUI中运行终端仿真器时所启动的默认的交互式shel(登录shell)是一个父shell。到目前为止,都是由父shell提供CLI提示符并等待命令输入。
当你在CLI提示符处输入bash命令(或是其他shell程序名)时,会创建新的shell程序。这是一个子shell。子shell也拥有CLI提示符,同样会等待命令输入。如下图
在生成子shell进程时,只有部分父进程的环境被复制到了子shell环境中。这会对变量在内的一些东西造成影响。当然,子shell也可以继续生成其子shell。同时,我们可以使用exit
命令来退出子shell。
- 进程就是正在运行的程序。如bash shell是一个程序,当它运行的时候,就成了进程。
理解外部命令和内建命令
which
命令只可以查看外部命令程序所在的位置type
命令即可看外部命令也可以查看内建命令程序所在位置。
外部命令
外部命令(也可以称为文件系统命令)指的是存在于bash shell 之外的程序。也就是说,它并不属于shell程序的一部分。外部命令程序通常位于/bin、/usr/bin、/sbin目录中。
每当执行外部命令时,就会创建一个子进程。这种操作称为衍生。只要涉及进程衍生,就需要耗费时间和资源来设置新子进程的环境。因此,外部命令系统开销较高。
无论是衍生子进程还是创建子shell,都仍然可以通过信号与其互通,这一点无论是在使用命令行还是编写脚本时都极其有用。进程间以发送信号的方式彼此通信。
内建命令
与外部命令不同,内建命令无需子进程来执行。内建命令已经和shell编译成一体了,作为shell的组成部分存在,无需借助外部程序文件来执行。
Linux环境变量
Linux环境变量能帮你提升Linux shell 的使用体验。很多程序和脚本通过环境变量来获取系统信息、存储临时数据和配置信息。
bash shell 使用环境变量来存储shell会话和工作环境的相关信息。环境变量允许在内存中存储数据,以便shell中运行的程序或脚本能够访问到这些数据。这也是存储持久数据的一种简便的方法。bash shell 中有两种环境变量、
- 全局变量
- 局部变量。
全局变量对于shell会话和所有生成的子shell都是可见的。局部环境变量则是只对创建它的shell可见。一下几个命令为查看环境变量的命令
①env
:查看全局变量;
②printenv
:也是查看全局变量。与上一条命令不同的是其可以查看个别环境变量的值。
③set
:可以显示特定进程的所有环境变量,既包括局部变量、全局变量,也包括用户自定义变量。
可以看到没有直接能够直接查看局部变量的命令。下边是使用全局变量和局部变量的一些注意事项
- 两者本质都是变量,该变量是有值得。一般是一个字符串(如某一路劲)或者数值。在引用某个环境变量的时候,必须在该变量名前加上美元符号($)
- 创建用户自定义变量:如
my_var=Hello
.如果用于赋值的字符串包含空格,则必须使用单引号或双引号来界定字符串的起止。 - 系统变量用的都是大写字母,所以为了与其区分。我们自定义的变量,一般都使用小写字母即可。
- 创建全局环境变量的方法是先创建局部变脸,然后再将其导出到全局环境中。如:
export my_var="Hello World"
。同时,如果之后再子shell修改该全局变量的值并不会影响父shell中该变量的值。(甚至我们就无法再使用export 命令来改变父shell中全局变量的值
)。也就是说,在该例子的全局变量中,我们在子shell修改了这个值(全局中没有改变),之后再使用export
命令。在父shell中my_var的值还是“Hello World”
PATH环境变量
PATH环境变量定义了用于查找命令和程序的目录。
如下为在Ubuntu Linux系统中,PATH环境变量的内容如下:
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:
/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$
PATH中的目录之间以冒号分隔。上边输出显示共有9个目录,shell会在其中查找命令和程序。
如果命令或程序所在的位置没有包括在PATH变量中,那么在不使用绝对路径的情况下,shell是无法找到的。shell找不到指定的命令或程序时就会产生错误。
我们安装的应用程序的可执行文件目录有时不在PATH环境所包含的目录中。解决办法是保证PATH环境变量包含所有存在应用程序的目录。
&emsp为如何添加PATH环境变量,我们只需引用原来的PAHT值,添加冒号(😃,然后再使用绝对路径输入新目录即可:
$ ls /home/christine/Scripts/
myprog
$ echo $PATH
/home/christine/.local/bin:/home/christine/bin:/usr/local/bin:/usr/
bin:/usr/local/sbin:/usr/sbin
$
$ PATH=$PATH:/home/christine/Scripts
$
$ myprog
The factorial of 5 is 120
$
将上述目录加入PATH环境变量之后,就可以在虚拟目录结构的任意位置执行这个程序了。
如果希望程序位置也可用于在shell,则务必确保将修改之后的PATH环境变量导出。(全局)
ps
:对于如此修改的PATH环境变量只能持续到退出或重启系统。也就是说这种效果不会一直凑效的。(如果想永久修改,需要修改其中的文件)