补充
-
shell解释器是可以手动开启的,可以开启多个shell、也可以开启子shell
-
最明显的感觉就是当你新开启一个shell后,你刚才执行的历史命令调用不出来
-
使用bash命令可以打开一个新的bash,查看pstree结果中的sshd部分
[root@localhost ~]# pstree
systemd─┬─NetworkManager───2*[{NetworkManager}]
├─rsyslogd───2*[{rsyslogd}]
├─sshd───sshd───sshd───bash───pstree
├─systemd───(sd-pam)[root@localhost ~]# bash
[root@localhost ~]# pstree
systemd─┬─NetworkManager───2*[{NetworkManager}]├─rsyslogd───2*[{rsyslogd}] ├─sshd───sshd───sshd───bash───bash───pstree
一、大括号、小括号
- {}:定义了命令在本bash中运行
- ():定义了命令在子bash中运行,脱离当前变量环境
注:父bash定义的环境变量能够被子bash继承,但子不传父,且没法继承局部变量
[root@localhost ~]# name=lisi
[root@localhost ~]# bash
[root@localhost ~]# echo $name
[root@localhost ~]# exit
exit
[root@localhost ~]# (echo $name)
lisi
#虽然bash和(echo $name)都会创建子Shell,但它们的创建时机和方式有本质区别,这导致了行为的不同
[root@localhost ~]# (name=zhangsan;echo $name)
zhangsan
[root@localhost ~]# echo $name
lisi
#虽然在小括号的子bash中修改了变量值,但不会影响到父bash
{}和()的区别
相同:都是把一串命令放在括号里,并且命令之间用;隔开
不同
-
()执行命令时需要重开一个子bash去执行,{}在当前shell执行
-
()命令最后可以不加分号,但{}命令最后不加分好则无法正确执行
-
()里各命令和括号之间可以没有空格,{}第一个命令和左括号之间必须有一个空格
#{ } 执行命令时,就在本shell中进行
[root@localhost ~]# { name=wangwu;echo name;} wangwu [root@localhost ~]# echo name
wangwu
二、shell变量
- 变量:即可变的量(变量包含字母、数字、下划线,但数字不能作开头)
- 声明变量:变量名=值(字符串、常量、命令结果、变量的值,等号两边不能有空格)
- 调用变量:echo $变量名
注:变量是有类型的,默认是字符串
#可以把一个现有变量的值作为变量值赋给变量
$ lujing="$PATH"
$ echo $lujing
#可以把一个命令的结果作为变量值赋给变量
$ shijian=`date`
或:shijian=$(date)
$ echo $shijian
#调用变量值时,为了保证不与后面的字符(字母、数字、下划线)被误判成新的变量名,需要加花括号
进行分隔
$ shijian="$(date)"
$ echo "now time is $shijian ma?"
now time is 2023年 09月 15日 星期五 00:19:48 CST ma?
$ echo "nowtimeis$shijianma?"
nowtimeis?
$ echo "nowtimeis${shijian}ma?"
nowtimeis2023年 09月 15日 星期五 00:19:48 CSTma?
#变量是可以叠加的
$ a=10;b=20
$ echo $a+$b -- 10+20
变量的分类
- 自定义变量:由用户自由定义变量的名和值
- 环境变量:保存的值是和系统操作环境相关的数据(一般为系统预先设定)
- 预定义变量:bash中已经 定义好的变量,变量名不能自定义,作用也是固定的
- 位置参数变量:用来向脚本中传递参数或数据的,变量名不能自定义,作用是固定的
注:set命令会将当前定义好的变量都给列出来
自定义变量
-
增:名=值
-
删:unset 名
-
改:名=新值
-
查:echo $变量名
[root@localhost ~]# shijian=(date) #增 [root@localhost ~]# echo shijian
2025年 08月 25日 星期一 18:44:16 CST
[root@localhost ~]# set | grep shijian #查
shijian='2025年 08月 25日 星期一 18:44:16 CST'
[root@localhost ~]# unset shijian #删
[root@localhost ~]# set | grep shijian
_=shijian
[root@localhost ~]# echo $shijian[root@localhost ~]#
注:用echo输出,无论是没有变量还是有变量但值为空,输出结果是一样的;因此要用set做区分
[root@localhost ~]# echo $nnn
[root@localhost ~]# shijian=
[root@localhost ~]# echo $shijian
[root@localhost ~]# set | grep nnn
[root@localhost ~]# set | grep shijian
shijian=
[root@localhost ~]#
set命令
-
set -u:提示未定义的变量,开启校验模式(或set | grep 变量名,查找)
-
set -x:执行命令前先打印出来(bash -x可以起到相同的效果)
-
set +u:可以取消校验变量名的模式
[root@localhost ~]# set -u
[root@localhost ~]# echo nnn #调用没有声明的变量时会报错 -bash: nnn:未绑定的变量 [root@localhost ~]# echo shijian[root@localhost ~]# set -x
++ printf '\033]0;%s@%s:%s\007' root localhost '~'
[root@localhost ~]# echo "nihao"- echo nihao
nihao
++ printf '\033]0;%s@%s:%s\007' root localhost '~'
[root@localhost ~]# set +u +x
#调试脚本时,可以在脚本中写入set -x,每次运行脚本(bash 脚本名)都会先打印
[root@localhost ~]# cat for1.sh
#!/bin/bash
set -x
for i in 1 2 3 4
do
echo $i
done
#也可以有问题时打印一次,bash -x 脚本名
- echo nihao
环境变量
- 定义:export 变量名=值
备注:环境变量一般都大写,但一般很少自定义环境变量,都是使用系统设置好的
-
增:export 名=值(名大写)或名=值 && export 名
-
删:unset 名
-
改:名=新值
-
查:set查看所有变量(普通或环境)或env
#增
[root@localhost ~]# SIZE=1000
[root@localhost ~]# export SIZE
或
[root@localhost ~]# export SIZE=1000
#查
[root@localhost ~]# set | grep SIZE
HISTFILESIZE=1000
HISTSIZE=1000
SIZE=1000
_=SIZE=1000
或
[root@localhost ~]# env | grep SIZE
HISTSIZE=1000
SIZE=1000
#删
[root@localhost ~]# unset SIZE
[root@localhost ~]# env | grep SIZE
HISTSIZE=1000
[root@localhost ~]#
1.PATH:存放命令路径
#系统中的环境变量
#PATH变量:系统命令存放路径
[root@localhost ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
#问题:将一个系统外部命令使用命令名就可以执行
方法一:可以考虑把自己写的脚本放入PATH对应的目录内
[root@localhost bik.d]# bash prin.sh
Bash
also
a
of
[root@localhost bik.d]# cp -a prin.sh /usr/bin/
[root@localhost ~]# chmod +x /usr/bin/prin.sh
[root@localhost ~]# prin.sh
Bash
also
a
of
[root@localhost ~]#
方法二:修改PATH变量的值,将我们存放脚本的目录叠加到PATH变量中
[root@localhost ~]# rm -rf /usr/bin/prin.sh
[root@localhost ~]# echo $PATH
/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
[root@localhost ~]# PATH=$PATH:/root/bik.d
[root@localhost ~]# echo $PATH
/root/.local/bin:/root/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bik.d
[root@localhost ~]# chmod +x /root/bik.d/prin.sh
[root@localhost ~]# prin.sh
Bash
also
a
of
[root@localhost ~]#
#永久设置PATH变量:
单用户生效:~/.bash_profile
所有用户生效:/etc/profile
PATH=$PATH:/root/bik.d #在末行写入命令,保存退出后重载
#相关的配置文件(顺序执行):
/etc/profile => ~/.bash_profile => ~/.bashrc => /etc/bashrc
#修改/etc路径下的配置文件将会应用到整个系统,属于系统级的配置
#修改用户目录下的.bashrc则只是限制在用户应用上,属于用户级设置
2.PS1:命令提示符设置
[root@localhost ~]# echo $PS1
[\u@\h \W]\$
-
\u:显示当前用户名
-
\h:显示简写主机名。如默认主机名"localhost",全名是"localhost.localdomain"
-
\W:显示当前所在目录的最后一个目录
-
\:提示符。如果是root提示符为"#",如果是普通用户提示符为""
-
\H:显示完整的主机名。如默认主机名"localhost.localdomain"
-
\d:显示日期,格式为"星期月日"Ø
-
\t:显示24小时制时间,格式为"HH:MM:SS"
-
\T:显示12小时制时间,格式为"HH:MM:SS"
-
\A:显示24小时制时间,格式为"HH:MM"
-
\@:显示12小时制时间,格式为"HH:MM am/pm"
-
\v:显示Bash的版本信息
-
\w:显示当前所在目录的完整名称
-
\#:执行的第几个命令
[root@localhost ~]# echo $PS1
[\u@\h \W]$
[root@localhost ~]# PS1='[\u@\H \w]'
[root@localhost ~]cd bik.d/
[root@localhost ~/bik.d]
注:跟系统环境相关的变量,但env命令查不到;自定义PS1时需要使用单引号,否则不生效
永久设置:vim /etc/bashrc
3.LANG:系统语系变量
查:localectl list-locales------查看Linux支持的所有语系
改:localectl set-locale LANG=en_US(退出当前终端后生效)或cat /etc/locale.conf
永久修改:vim /etc/locale.conf
预定义变量
-
$?:判断命令是否正确执行
-
:当前进程的进程号(PID)
[root@19:52 ~]# echo $$
878
[root@19:53 ~]# echo $![root@19:53 ~]# top &
[1] 1304
[root@19:53 ~]# echo $!
1304
位置参数变量
作用:根据调用脚本时传入参数值的位置,进行变量赋值或取值
- n:n可以是0,1,2,3....,但是10以后要加大括号,0是脚本名
- \*/@:取所有的值
区别:\*取值是一个整体;@取的每一个值都是可以分开的
实验:编写一个test.sh脚本,输出位置参数

[root@20:01 ~]# bash test.sh 1 2 3 4 5 6 7 8 9 10
$0的值是:test.sh
$1的值是:1
$2的值是:2
$10的值是:10
注:$n按顺序取值,但是十以及十以后的值需要加大括号,否则
[root@20:03 ~]# bash test.sh 1 2 3 4 5 6 7 8 9 abs
$0的值是:test.sh
$1的值是:1
$2的值是:2
$10的值是:10

[root@20:05 ~]# bash test.sh 1 2 3 4 5 6 7 8 9 abs
$0的值是:test.sh
$1的值是:1
$2的值是:2
$10的值是:abs
\*和@取值:在test.sh中写入命令

[root@20:08 ~]# bash test.sh 1 2 3 4 5 6 7 8 9 abs
$0的值是:test.sh
$1的值是:1
$2的值是:2
$10的值是:abs
$*的值是1 2 3 4 5 6 7 8 9 abs
$@的值是1 2 3 4 5 6 7 8 9 abs
测试两者的不同,用for循环