Shell 基础
- Shell 基础
- 查看可用的 Shell
- 判断当前 Shell 类型
- 变量
- 环境变量
- 查看环境变量
- 临时环境变量
- 永久环境变量
- PATH 变量
- 自定义变量
- 特殊赋值(双引号、单引号、反撇号)
- 预定义变量
- bashrc
Shell 基础
Shell 是一个用 C 语言编写的程序,相当于是一个翻译,把我们在计算机上的操作或我们的命令,翻译为计算机可识别的二进制命令,传递给内核(Kernal),以便调用计算机硬件执行相关的操作;同时,计算机执行完命令后,再通过Shell翻译成自然语言,呈现在我们面前。
Linux 中的各种命令其实都是独立的应用程序,通过操作系统提供的接口和 Kernal 进行交互,从实现某种操作。
【具体内部和操作系统相关,这里不在过多说明。】
简单来说,Shell 就是一种命令行解释器,它接受用户输入的命令,并将其转换为操作系统可以执行的指令。它不仅仅是一个简单的命令行界面,还是一个功能强大的脚本编程环境,可以编写自动化任务和复杂的工作流程。
Shell是用户和Linux(或者更准确的说,是用户和Linux内核)之间的接口程序。你在提示符下输入的每个命令都由 Shell 先解释然后传给Linux内核。
Shell 是一个命令语言解释器(command-language interpreter)。拥有自己内建的 Shell 命令集。此外,Shell 也能被系统中其他有效的Linux 实用程序和应用程序(utilities and application programs)所调用。
不论何时你键入一个命令,它都被 Linux Shell 所解释。一些命令,比如打印当前工作目录命令(pwd),是包含在Linux bash 内部的(就象DOS的内部命令)。其他命令,比如拷贝命令(cp)和移动命令(rm),是存在于文件系统中某个目录下的单独的程序。而对用户来说,你不知道(或者可能不关心)一个命令是建立在 Shell 内部还是一个单独的程序,因为使用方法都是一样的。
一般情况下,Linux 中的命令的按照如下顺序执行:
- 以相对/绝对路径执行指令,例如“ /bin/ls ”或“ ./ls ”;
- 由
alias
找到该指令来执行; - 由 bash 内置的 (builtin) 指令来执行;
- 通过
$PATH
这个变量的顺序搜寻到的第一个指令来执行。
查看可用的 Shell
由于早年的 Unix 年代,发展者众,所以由于 Shell 依据发展者的不同就有许多的版本,如 Bourne SHell (sh) 、C SHell、K SHell、 TCSH 等。
每一种 Shell 都各有其特点了,大多数 Linux 使用的默认版本为 “ Bourne Again SHell (简称 BASH) ”,这个 Shell 是 Bourne Shell 的增强版本。
在 Linux 系统中,使用 cat /etc/shells
可以查看查看当前系统中可用的 Shell 。
不同类型的 Shell 的语法及其包含的命令会有一定的不同,除非有特别说明,否则后续使用的命令都是 BASH 中命令。
Tips:
第一个流行的 shell 是由 Steven Bourne 发展出来的,为了纪念他所以就称为 Bourne shell ,或直接简称为 sh !而后来另一个广为流传的 shell 是由柏克莱大学的 Bill Joy 设计依附于 BSD 版的 Unix 系统中的shell ,这个 Shell 的语法有点类似 C 语言,所以才得名为 C shell ,简称为 csh。
判断当前 Shell 类型
Linux 中判断当前 Shell 的类型的方法有很多,部分方法如下所述。
方法1:
通过环境变量 SHELL
来查看:
echo $SHELL
方法2:
在 Terminal 输入命令 ps
,查看当前运行的 shell 是什么。如下图所示,有一个进程是 csh,说明当前 shell 的类型是 csh。
变量
变量是 bash 环境中非常重要的一个内容。
Linux 是多用户多任务的环境,每个人登陆系统都能取得一个 bash shell, 每个人都能够使用 bash 下达 mail 这个指令来收受“自
己”的邮件等等。问题是, bash 是如何得知你的邮件信箱是哪个文件? 这就需要“变量”的帮助。
变量,简单的说,就是让某一个特定字串代表不固定的内容。
我们每个帐号的邮件信箱默认是以 MAIL 这个变量来进行存取的, 当 dmtsai 这个使用者登陆时,他便会取得 MAIL 这个变量,而这个变量的内容其实就是 /var/spool/mail/dmtsai, 那如果 vbird 登陆呢?他取得的 MAIL 这个变量的内容其实就是/var/spool/mail/vbird 。 而我们使用信件读取指令 mail 来读取自己的邮件信箱时,该程序可以直接读取 MAIL 这个变量的内容, 就能够自动的分辨出信箱的归属。
在 Linux Shell 中,变量主要有两大类:环境(系统)变量和用户定义变量。
每种类型的变量依据作用域不同,又分为全局变量和局部变量。全局变量作用在整个 Shell 会话及其子 Shell,局部变量作用在定义它们的进程及其子进程内。
环境变量属于全局变量,它在任何的 Shell 中都可以使用。
环境变量
Linux是一个多用户的操作系统。多用户意味着每个用户登录系统后,都有自己专用的运行环境。而这个环境是由一组变量所定义,这组变量被称为环境变量。用户可以对自己的环境变量进行修改以达到对环境的要求。
一些常用的环境变量及其作用:
-
HOME
用户的主工作目录,即为用户登录到Linux系统中时的默认目录。
-
PATH
PATH
变量用于设置可执行程序的默认搜索路径。当我们输入一个指令时,Shell 会先检查命令是否是系统内部命令,如果不是则会再去检查此命令是否是一个应用程序,Shell会试着从
PATH
指定的路径下寻找这些应用程序。PATH
变量中可以指定多条路径,不同的路径使用:
进行区分。# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
在 IC 的环境下,如果安装了一些 EDA 工具,这些 EDA 工具的启动程序的所在的路径就要放到
PATH
中,这样才能在 Terminal 中使用dc_shell, vcs, verdi
等直接启动 EDA 工具。 -
HISTSIZE
保存历史命令的条数。我们输入的指令都会被系统保存下来,这个环境变量记录的就是保持指令的条数。一般为1000。
历史命令是被保存在内存中的,当退出或者登录shell时,会自动保存或读取我们可以通过
history
命令来查看。可以使用符号!
执行指定序号的历史命令。例如,要执行第2个历史命令,则输入!2
。 -
LOGNAME、USER、HOSTNAME
登录名、用户名和主机名。
-
SHELL
当前使用的默认 Shell 解释器的名称。
-
PS1
BASH 解释器的提示符。
【C shell 中 PS1 对应的变量名称为 prompt】CentOS 默认的 PS1 为
[\u@\h \W]$
,在终端对应的提示信息为:[dmtsai@study ~]$
查看环境变量
echo
命令可以显示某个具体的环境变量的值,可用于快速检查一个变量的修改是否生效。
env
显示当前 shell 环境下的所有环境变量及其值。
BASH 中不只有环境变量,还有一些与 BASH的操作接口有关的变量,以及用户自己定义的变量。set
会显示当前 shell 的所有变量。
临时环境变量
环境变量和用户自定义变量之间的差异主要是“该变量是否会被子程序所继续引用”。
当你登陆 Linux 并取得一个 bash 之后,你的 bash 就是一个独立的程序,这个程序的识别使用的是一个称为程序识别码,被称为 PID 的就是。 接下来你在这个 bash 下面所下达的任何指令都是由这个 bash 所衍生出来的,那些被下达的指令就被称为子程序。
使用 export
命令将一个自定义变量变成环境变量,从而可以让该变量的值继续存在于子程序。
该命令设定的环境变量仅在当前窗口生效,关闭窗口或新建其他窗口,无法查看到之前设置的临时环境变量
export
命令也可以临时设置改变环境变量的值,相当于是给变量一个新的值,然后把之前的值覆盖了。
永久环境变量
使用 export
命令指定的环境变量仅在当前 Shell 及其子 Shell 中生效,如果像让变量永久生效,可以将其放到环境变量配置文件中。
在 Linux 系统中,环境变量的全局配置文件为 /etc/profile,在此文件中定义的变量作用于所有用户。除此之外,每个用户还有自己的独立配置文件(~/.bash_profile
, ~/.profile
,~/.bashrc
等)。在这些文件中设置好环境变量之后,重新登录或者使用 source
命令之后,变量才能生效。
-
/etc/profile
用于设置系统级的环境变量和启动程序,在这个文件下配置会对所有用户生效。当用户第一次登录时,该文件被执行,并从/etc/profile.d目录的配置文件中搜集shell的设置.
一般用户不会对环境变量的全局配置文件进行修改,主要是对用户个人的配置文件进行修改。
-
~/.bash_profile & ~/.profile
在登录 Shell 时加载的配置文件。当你通过图形界面登录、通过SSH远程连接到系统或通过终端登录时,这些文件中的设置就会生效。
~/.profile
作用于所有类型的 Shell,而~/.bash_profile
只作用于 BASH Shell。 -
.bashrc
~/.profile
和~/.bash_profile
文件只会在用户登录的时候读取一次,而.bashrc
在每次打开新的终端窗口或标签时都会读取。.bashrc
仅作用于 BASH Shell,C Shell 中与之对应的文件是.cshrc
/etc/bashrc
中的配置作用于所有用户,而~/.bashrc
中的配置仅作用于当前用户。.bashrc
文件会在 bash shell 调用另一个bash shell时读取,也就是在shell中再键入bash命令启动一个新shell时就会去读该文件。这样可有效分离登录和子shell所需的环境。但一般 来说都会在.bash_profile
里调用.bashrc
脚本以便统一配置用户环境。
PATH 变量
PATH
变量用于设置可执行程序的默认搜索路径。当仅指定文件名称来执行命令程序时,Linux 系统将在 PATH 变量指定的目录范围查找对应的可执行文件,如果找不到则会提示“command not found”。
示例:
[root@localhost ~]# test.sh
bash: test.sh: Command not found.
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# pwd
/root
由于 test.sh 不在 PATH
目录中,所以系统无法识别这个命令,需要使用绝对路径来执行该脚本。
将脚本目录加入 PATH
方法一:将脚本的目录临时加入 PATH
[root@localhost ~]# PATH="$PATH:/root"
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root
[root@localhost ~]# test.sh
hello world
方法二:将你自己写的脚本放到 PATH 中的某一个目录
[root@localhost ~]# mv test.sh /usr/local/bin/
[root@localhost ~]# test.sh
hello world
自定义变量
在 Bash 中,定义变量非常简单,不像其他高级编程语言(如 C/C++、Java 等)那么复杂。在定义一个新变量时,一般不需要提前声明,只需直接指定变量名称并赋值即可。
格式:
name=value
Notes
- 变量名需以字母或下划线开头,名称中不能包含特殊字符。
- 等号两边不能有空格。
- 新定义的变量只在当前的 Shell 环境中有效,因此称为局部变量。当进入子程序或新的子 Shell 环境时,局部变量将无法再使用。
特殊赋值(双引号、单引号、反撇号)
双引号主要起界定字符串的作用,特别是当要赋值的内容中包含空格时,必须以双引号括起来。其他情况下双引号通常可以省略。
当要赋值的内容中包含 $、"、\
等具有特殊含义的字符时,应使用单引号括起来。在单引号的范围内,将无法引用其他变量的值,任何字符均作为普通字符看待,输入什么就显示什么。
test=123
echo "$test" # 输出:123
echo '$test' # 输出:$test
反撇号主要用于命令替换,允许将执行某个命令的屏幕输出结果赋值给变量。反撇号括起来的范围内必须是能够执行的命令行,否则将会出错。
time=`date +%T`
使用反撇号难以在一行命令中实现嵌套命令替换操作,这时可以改用 $() 来代替反撇号操作,以解决嵌套的问题。
ls -lh `which useradd`
# or
rpm -qc $(rpm -qf $(which useradd))
预定义变量
预定义变量是由 Bash 程序预先定义好的一类特殊变量,用户只能使用预定义变量,而不能创建新的预定义变量,也不能直接为预定义变量赋值。预定义变量使用 $
符号和另一个符号组合表示。
$#
:表示命令行中位置参数的个数。$*
:表示所有位置参数的内容,这些内容当做一个整体。$@
:表示列出所有位置参数,但是是以单个的形式列出。$?
:表示前一条命令执行后的返回状态,返回值为 0 表示执行正确,返回任何非 0 值均表示执行出现异常。$0
:表示当前执行的脚本或程序的名称。$$
:表示返回当前进程的进程号。$!
:返回最后一个后台进程的进程号。
bashrc
作为配置文件,bashrc
等文件不只是用于设置变量,还可以用于配置其他内容。
在 bashrc
文件中,#
表示的是注释。
1. 配置别名,简化指令
当我们想把一些常用的指令以及相关指令参数,定制为更加精简的指令,就可以用 alias
为命令设置别名。
alias ll = "ls -lha"
2. 配置函数,定制指令过程
除了缩短命名,也可以用bash函数组合多个命令到一个操作,这些命令大多遵循以下语法。
# Syntax 1
function function_name {
command1
<^>command2</^>
# Syntax 2
function_name () {
command_1
command_2
}
# Syntax 3
function_name () { commmand1; command2; }
示例:
下面的命令组合了 mkdir
和 cd
命令,输入md folder_name
会在你的工作目录创建一个名为"folder_name"的目录并且进入其中。
md () {
mkdir -p $1
cd $1
}
# or
md () { mkdir -p $1; cd $1;}
3. 设置变量
在原来PATH的后面继续添加了新的路径:
# Syntax 1
PATH=$PATH:new_path
export PATH
# Syntax 2
export PATH=$PATH:new_path
export
是让变量可以作用域子 Shell。
示例:
user@pc:~$ echo 'VAL_TS="hello, no export"' >> ~/.bashrc #添加非export变量赋值到.bashrc
user@pc:~$ source ~/.bashrc #使.bashrc生效
user@pc:~$ echo $VAL_TS #输出变量 VAL_TS 值
#结果
hello, no export
user@pc:~$ echo 'echo "val is :" $VAL_TS' > test.sh #添加脚本语句到脚本 test.sh
user@pc:~$ ./test.sh #执行脚本 test.sh
#结果
val is : #脚本中并没有变量值
user@pc:~$ echo 'export EX_VAL_TS="hello, export"' >> ~/.bashrc #添加export变量赋值
user@pc:~$ source ~/.bashrc #使.bashrc生效
user@pc:~$ echo $EX_VAL_TS #输出变量 EX_VAL_TS 值
#结果
hello, export
user@pc:~$ echo 'echo "export val is :$EX_VAL_TS' >> test.sh #添加脚本语句到脚本
user@pc:~$ ./test.sh #执行脚本 test.sh
#结果
export val is :hello, export #脚本中获取到了变量值