自动化运维脚本之shell简介
conputer resources:计算机资源
kernel:内核
shell:命令解释器
programs:程序
utilities:实用工具
tools:工具
一个完整的计算机包括硬件与软件。软件又分系统软件与应用软件。负责对硬件进行 管理与操作的是系统软件的内核 (kernel) 部分,用户是无法和内核打交道的,用户只能通 过应用程序或部分系统软件发出指令,这些指令会被翻译并传给内核。在Linux内核的系统 下,可以通过shell和内核进行沟通,从而达到使用计算机资源的目的。
每当用ssh工具远程连接到系统时,或在服务器前输入密码后。那个跳动的光标就是一 个shell。shell是指命令解释器,为用户和操作系统之间通信提供的一种接口。
shell不光是命令解释器,还是一种编程工具,称为脚本语言。与编译型语言 (C/C++, java等) 不同,脚本语言又称为解释型语言,这种经过语言的特点在于经过编写后不需要做 任何编译就可以运行。
目前redhat和centos发行版中默认有多种shell,可以在/etc/shells文件中进行查看:
在Linux中/bin/bash是Linux默认的shell,那么bash shell就是我们要重点学习的部分。
一、echo命令
[root@localhost ~]# echo [选项] [输出内容]
子选项:-e:支持反斜线控制的字符转换。
-n:取消输出后行末的换行符号即内容输出后不换行。
例:
[root@localhost ~]# echo "Linux-BEIJING-YUN"
Linux-BEIJING-YUN
[root@localhost ~]# echo -n "Linux-BEIJING-YUN"
Linux-BEIJING-YUN[root@localhost ~]#
(如果加入了-n选项,输出内容结束后,不会换行而是直接显示新行执行命令的最前面)
在echo命令中如果使用了“-e”选项,则可以支持控制字符,如下表所示:
控制字符 |
作用 |
\\ |
输出\本身 |
\a |
输出警告音 |
\b |
退格键,也就是向左删除键 |
\f |
换页符 |
\n |
换行符 |
\t |
制表符 (TAB键) |
例:
[root@localhost ~]# echo -e "\\ \a"
\
音。
[root@localhost ~]# echo -e "ab\bc"
ac
#这个输出会输出\。同时也有提示
#只输出了ac,因为在b右侧有\b。所
以只能输出ac。反斜线b后要有字符或空格否则不生效。
[root@localhost ~]# echo -e "a\tb\tc\nd\te\tf"
a b c
d e f #加入了制表符和换行符,所以输出
会按照加入的格式进行输出。
echo命令还可以进行一些颜色上的输出:
[root@localhost ~]# echo -e "\e[1;31m abcd \e[0m"
abcd #这条命令会把abcd按照红色输出。 \e[1是标准格式,代表颜色输出开始,\e[0m代表颜色输出结束。31m定义字体颜色是红色。 echo能够识别的颜色如下:30m=黑色,31m=红色,32m=绿色,33m=黄色,34m=蓝色,35m=洋 红,36m=青色,37m=白色。以上这些数字+10就会变成底色。比如41m就是把字体底色变成红 色。
[root@localhost ~]# echo -e "\e[5;1;31m abcd \e[0m" #加上数字5为输出字符串闪
。
二、shell脚本的执行方式:
shell脚本执行:
[root@localhost ~]# chmod 755 hello.sh
[root@localhost ~]# /root/hello.sh
[root@localhost ~]# ./hello.sh
#脚本要赋予执行权限才能正常执行,执行方式有以上两种。
[root@localhost ~]# chmod -x hello.sh
[root@localhost ~]# /root/hello.sh
-bash: /root/hello.sh: 权限不够
[root@localhost ~]# . hello.sh
[root@localhost ~]# bash ./hello.sh
#当没有执行权限的时候,可以通过bash 【脚本】或 . 【脚本】的方式来执行脚本。
EOF的脚本使用方式:
[root@localhost ~]# vim p.sh #写入以下内容
#!/bin/bash
cat <<efo
========================
1.mysql
2.httpd
3.oracle
=======================
efo
[root@localhost ~]# chmod +x
[root@localhost ~]# p.sh #查看效果
也可以使用cat << EOF 结合重定向将多行数据追加到某个文件当中:
cat << EOF > /test.txt
1
22
333
EOF
三、bash的主要功能有如下几点:
1.history:历史命令功能,可以用上下箭头来找到之前执行过的命令,系统默认情况下会 记录1000条历史命令。这些历史命令会被记录在~/.bash_history,但记录的是上次登录以 前所执行过的命令,而当前执行的命令都会被暂时存放在内存中,当成功注销系统后,这些 历史命令才会记录到~/.bash_history中去。
history 【子选项】
子选项:-c 清空历史命令
-w 把缓存中的历史命令写入历史命令的保存文件中。如果不手工指定历 史文件保存文件,则放入默认历史命令保存文件,~/.bash_history
历史命令的调用:
使用“ ↑ ↓ ”箭头调用以前的历史命令。
使用“!n”重复执行第n条历史命令。
使用“!! ”重复执行上一条命令。
使用“!字符串”重复执行最后一条以该字符串开头的命令。
使用“!$”重复上一条命令的最后一个参数。例:
(比如,用cat命令查看/etc/fstab文件。此时想要编辑/etc/fstab文件就可以用!$命令)
(打开的就是/etc/fstab) (还有个操作技巧,就是在cat /etc/fstab之后。输入vim然后 按下esc键,松开后按.即可把之前命令的执行对象调用出来)
2.补全功能:此功能可以自动补全文件或命令。只要输入命令或文件的开头几个字母然后按 TAB键,系统就会自动补齐命令或文件名。并且,输入的字符越多补齐的范围越小,就越精 确。拥有这样的功能不单能让用户在操作时能提高速度,而且也能提高准确性。因为,如果 要用一个命令或要修改一个配置文件的时候,用TAB不能补全出来,那么就说明这个命令不 存在或者文件不存在。
在Centos7当中增强了补全功能,不仅仅能够补全命令。还可以补全命令之后的选项,启动 服务的服务名称等。
3.别名功能:很多最早接触Linux的工作人员习惯于用vi编辑文件,但vim比vi功能更加强 大。比如vim提供了语法校验与颜色显示功能。对于熟悉了vi命令的工作人员来说alias别名 功能可以在不影响原有工作习惯的情况下使用vim带来的便利。具体操作如下:
(直接用alias查看系统中已经定义好的别名)
(定义别名的格式为:alias 别名=原命令)
接下来我们继续进行一个小实验:
(我们定义一个别名ls=cd,当我们照常想用ls查看/etc/内容时。结果是将我们的所在位置
切换成了/etc/中。由此可见,别名不能随意设置。但......)
(我们也不是一点办法都没有,比如可以用命令的绝对路径来执行命令)
(unalias ls 关闭ls的别名、unalias -a 关闭所有别名)
Bash命令执行的顺序:
第一顺位执行的是用绝对或相对路径执行的命令。
第二顺执行别名。
第三顺位执行bash的内部命令。比如:cd、pwd等。
第四顺位执行按照$PATH环境变量定义的目录查找顺序找到的第一个命令。echo $PATH 用alias设置的别名都是临时生效的,重启后失效。如果想让别名永久生效需要修改环境变 量配置文件~/.bashrc文件。如果想让别名对所有用户生效,需要修改/etc/bashrc配置文 件。
补充:脚本执行方式:
1、脚本加入可执行权限,使用绝对路径或相对路径执行
2、bash执行,bash/脚本路径 可以在脚本没有可执行权限时执行
3、source执行,source/脚本路径 1、可以在脚本没有可执行权限时执行(source=.可以用.代替source1 比如./脚本路径)2、source执行相当于把脚本当中的语句拿到当前执行。
hash命令:
Linux系统下会有一个hash表,最初开机时这个hash表为空,每当执行过一条外部命令hash 表都会记录下命令的绝对路径 (因为外部命令会通过PATH“环境变量”去找命令的绝对路径) 而hash表会记录下所使用命令的路径,相当于一个缓存。也就是说,在执行外部命令的 时候,会首先去查找hash表,如果有响应的路径就不必去查找PATH。而在使用hash命令之后 会显示两列内容信息,其中hits表示为“开机后命令执行次数” 。command为“查找到命令 的绝对路径位置”。
为验证hash命令可以使用hash命令手工添加一条hash记录,然后再去执行响应的命令查看效 果即可:
[root@localhost ~]# hash -p /bin/touch mkdir
#-p添加缓存记录,指定/bin/touch命令为mkdir命令执行时路径。
[root@localhost ~]# mkdir test1
[root@localhost ~]# ll test1 #查看文件属性,就会发现mkdir创建test为文件而不是
目录。
[root@localhost ~]# hash -r #清空hash缓存记录。
4.bash常用快捷键
快捷键 |
作用 |
CTRL+a |
把光标移动到命令行开头。 |
CTRL+e |
把光标移动到行尾。 |
CTRL+c |
强制终止当前命令。 |
CTRL+l |
清屏,相当于clear命令。 |
CTRL+u |
删除或剪切光标之前的内容。 |
CTRL+k |
删除或剪切光标之后的内容。 |
CTRL+y |
粘贴CTRL+u或CTRL+k剪切的内容。 |
CTRL+r |
在历史命令中搜索。按下CTRL+r之后,就会出现搜索界面。只要输入搜索内 容,就会从历史命令中索搜。 |
CTRL+d |
退出当前终端。 |
CTRL+z |
暂停并放入后台。 (jobs命令查看挂起的进程。bg %N使第N个任务放入后 台。 fg %N使第N个任务在前台运行。) |
CTRL+s |
暂停屏幕输出。 |
CTRL+q |
恢复屏幕输出。 |
5.输入输出重定向
bash的标准输入输出:
设备 |
设备文件名 |
文件描述符 |
类型 |
键盘 |
/dev/stdin |
0 |
标准输入 |
显示器 |
/dev/stdout |
1 |
标准输出 |
显示器 |
/dev/stderr |
2 |
标准错误输出 |
输出重定向:
类型 |
符号 |
作用 |
标准输出重定向 |
命令 > 文件 |
以覆盖的方式,把命令的正确输 出输出到 指定的文件或设备中。 |
命令 >> 文件 |
以追加的方式,把命令的正确输 出输出到 指定的文件或设备中。 |
|
标准错误输出重定向 |
错误命令 2> 文件 |
以覆盖的方式,把命令的错误输 出输出到 指定的文件或设备中。 |
错误命令 2>> 文件 |
以追加的方式,把命令的错误输 出输出到 指定的文件或设备中。 |
|
正确输出和错误输出同 时 保存 |
命令 > 文件 2>&1 |
以覆盖的方式,把正确输出和错 误输出都 保存到同一个文件当中。 |
命令 >> 文件 2>&1 |
以追加的方式,把正确输出和错 误输出都 保存到同一个文件当中。 |
|
命令 &>文件 |
以覆盖的方式,把正确输出和错 误输出都 保存到同一个文件当中。 |
|
命令 &>>文件 |
以追加的方式,把正确输出和错 误输出都 保存到同一个文件当中。 |
|
命令>>文件1 2>>文件2 |
把正确的输出追加到文件1中,把 错误的 输出追加到文件2中。 |
tee命令功能:读取标准输入的数据,并将其内容输出成文件。
语法:tee [-a][--help][--version][文件...]
参数:
-a 内容追加到给定的文件而非覆盖
--help 帮助信息
tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成
文件
例1:将磁盘使用的信息写入文件(覆盖式)
[root@localhost ~]# df -h | tee disk.log
例2:将文件系统使用的信息追加到文件
[root@localhost ~]# df -h | tee -a disk.log
注: 可以使用来记录日志
输入重定向:wc或at命令
at 11:00 </root/test.txt 把这个文件里的命令给at并且十一点执行
命令:wc 统计指定文件中的行数,单词数,字数,并将统计结果显示输出。
选项
文件名
选项: -c 统计字数(字符)
-w 统计单词数(字符串,由空白、跳格或换行字符分隔的字符串。)
-l 统计行数
实例:
6.grep字符串过滤:
1) grep行提取命令
格式:grep 子选项 ”关键词“ 文件名
选项:-A数字 #列出符合条件的行,并连续列出后续n行。
-B数字 #列出符合条件的行,并连续列出前面n行。
-c #统计符合条件的字符串行数
-i #忽略大小写
-n #输出行号
-v #反向查找 (取反)
-o #只列出关键字
- - color=auto #搜索出的关键词高亮显示
7.通配符:用于shell命令行,或shell脚本中。正则用于字符串处理。
通配符 |
作用 |
? |
匹配任意一个字符。 |
* |
匹配0个或任意多个字符,可以匹配任何内容。 |
[] |
匹配中括号内任意一个字符。如:[abc]代表一定匹配一个字符,或a或b或c |
[-] |
匹配中括号内任意一个字符,-代表一个范围。如:[a-z]代表匹配一个小写 字 母。 |
[^] |
逻辑非,表示匹配不是中括号内的一个字符。如:[^0-9]代表匹配一个不是 数字的字符。 |
实例:
(我们在目录下创建abc、abcd、012、0abc文件。ls *查看所有文件。)
(? 匹配了任意一个字符,所以找到了0abc 不能匹配abc因为?不能匹配空)
(匹配任何以数字开头的文件)
(匹配不以数字开头的文件)
bash中其他特殊符号:
符号 |
作用 |
'' |
单引号。在单引号中所有的特殊符号,如“$”和”` ”反引号都没有特殊含义。 |
"" |
双引号。在双引号中特殊符号都没有特殊含义。但是“$”“ · ”“和”\“是例 外, 拥有调用变量、引用命令和转义符的特殊含义。 |
`` |
反引号。反引号括起来的内容是系统命令,在bash中会先执行它。和$()作用一样。 更推荐使用$()因为,反引号容易和单引号混淆。 |
$() |
和反引号作用一样,用来引用系统命令。 |
() |
用于一串命令执行时, () 中的命令会在子shell中运行。 |
{} |
用于一串命令执行时, {}中的命令会在当前shell中执行。也可以用于变量变形与替 换。 |
[] |
用于变量测试。 |
# |
在shell脚本中,#开头的行代表注释。 |
$ |
用于调用变量的值,如果需要调用变量name的值需要用$name的方式得到变量的值。 |
\ |
转义符,跟在\之后的特殊符号将失去特殊含义,变为普通字符。如\$将输出“$” 符号,而不是当做变量引用。 |
例:
1) 单引号和双引号
(定义变量name=hb,首先输出时用单引号。使$符变为没有特殊含义。然后,用双引号输 出。调用了变量name的值。)
(首先用反引号输出date,会被识别成系统命令执行成功。但是,如果在外边加上单引号那 么反引号就失去了特殊含义只是变成了一个普通符号输出。)
2) 反引号
(如果用echo直接跟ls那么只会输出ls,并不会执行ls这个命令。只有我们用反引号或者 $()把ls括起来时命令才能正确引用系统命令。)
3) 小括号、中括号和大括号
介绍小括号和花括号之前先要解释一个概念,那就是父shell和子shell。在我们的bash中,
是可以调用新的bash的,比如:
打开一个新的bash
通过pstree命令查看进程数
发现在原有的基础上又开启了个新的bash。
结合父shell和子shell我们来解释花括号和小括号的区别。如果是用于一串命令的执行,那 么花括号和小括号的区别在于:
()执行一串命令时,需要重新开一个子shell进行执行
{}执行一串命令时,在当前shell执行
()和{}都是把一串命令放在括号里,并且命令之间用;号隔开
()在命令最后可以不加分号
{}在命令最后不用分号不能正确执行
{}的第一个命令和左括号之间必须要有一个空格
()里的各命令和括号之间可以没有空格
例:
(首先我们定义变量name=hb,然后在小括号里定义name=rs并输出查看。再用echo输出变量 name显示仍然为hb。因为()里的内容是在一个新的shell里进行定义的,所以并不会影响父
shell的变量。)
(然后,我们用花括号继续做相同的操作。name还是hb。用花括号定义变量name=rs。因为 花括号是在父shell直接更改了之前的name变量。所以echo $name时变成了rs。)
Shell基础2
Bash的变量
用某个特定字符串代表不固定的内容就是变量。
在shell中定义变量的格式为:
name=[value]
如果value没有指定,变量将被赋值为空字符串。变量定义时需要遵守的规定有:
1)变量名称可以由字母、数字和下划线组成,但不能以数字开头。
2)在bash中,变量的默认类型都是字符串型。如果要进行数值运算,则必须修改指定变量类型为数值型。
3)变量用等号连接值,等号左右两边不能有空格。
4)变量的值如果有空格,需要使用单引号或双引号包括。
其中双引号括起来的内容“$” “\” “`”(反引号)都拥有特殊含义,而单引号括起来的内容都是普通字符。
5)在变量的值中,可以使用\转义符。
6)如果需要增加变量的值,那么可以进行变量值的叠加,不过变量需要用双引号包含"$变量名"或用${变量名}包含变量名。(补充:在原有的基础之上增加了内容,例:PATH=$PATH:/root/)
例:
7) 如果是把命令的结果作为变量值赋予变量,则需要使用反引号或$()包含命令。
例:
(把test的变量设置为date的值,unset是关闭变量的命令。)
8) 在字符串中调用变量的值,需要加花括号。
[root@localhost test]# a=1
[root@localhost test]# echo "a${a}b2c3d4"
a1b2c3d4
9) 变量名建议大写,便于区分。
2.变量的分类:
用户自定义变量:这种变量是最常见的变量,由用户自由定义变量命名和变量的值。
环境变量:在bash中预设了很多环境变量,在工作中我们可以直接调用这些变量。
环境变量的变量名可以自由定义,但一般对系统起作用的环境变量名是系统预先设定好的。
比如当前用户ID号 (UID) 、当前用户家目录 (HOME) 、前一个工作目录 (OLDPWD) 执行cd -相当于执行了 OLDPWD的变量、还有最常用的PATH。
这里我们重点解释一下PATH变量,在Linux系统中,我们输入cd可以切换目录。
Linux系统是通过PATH变量来搜索命令的,系统会按照PATH变量里目录的顺序查找该命令,如果所有目录都没找到命令,则提示命令未找 到 (排除别名的情况下) 。
位置参数变量:这种变量主要是用来向脚本当中传递参数或数据的,变量名不能自定义,变量作用是固定的。
预定义变量:是bash中已经定义好的变量,变量名不能自定义,变量作用也是固定的。
(上列截图中分别演示了:变量名不能以数字开头:在等号的两边不能有空格:变量的值如果有空格则要使用引号包含)
2) 变量调用:
(定义变量name,输出变量name的值)
3) 变量查看:
命令:set :显示系统中已经存在的shell变量,以及设置shell变量的新变量值。
set 【选项】
子选项:
-u:如果设定此选项,调用未声明的变量时会有提示 (-u开启,+u关闭) 。
-x:如果设定此选项,在命令执行之前,会把命令先输出一次 (-x开启,+x关闭) 。
例:
(用set命令,然后用grep命令找出name行。如果直接用set命令,会查询系统中所有变量,包含用户自定义变量和环境变量)
(file是没定义过变量的,因此用echo输出的时候,输出结果为空。但如果我们定义一个变量为空的话。那么就会和未定义变量混淆。 所以我们用set -u命令。命令执行后,如果确实没有定义变量的话那么就会报错) (如果想关闭此功能用set +u命令)
(如果设定了-x选项,会在每个命令执行之前,先把命令输出一次。)
变量删除:unset 变量名。补充:删除变量名后用set | grep 变量会发现看见 _=变量
环境变量:
1) 环境变量设置与删除:
(以上截图中,首先声明了变量age=18.然后用export命令声明为环境变量。之后用env命令找到age=18。证明环境变量声明成功。然后 用【unset 变量名】格式删除变量。再次查找发现未找到age相关环境变量。) (env和set的区别是,set命令可以查看所有变量,而env 命令只能查看环境变量。) (还可以使用export age=18的方式在声明环境变量的同时赋值,两种赋值方式都会在env和set中找到赋值变量,命令执行结果并无差别。
2) 系统默认环境变量:
[root@localhost ~]# env
HOSTNAME=localhost.localdomain |
#主机名 |
TERM=xterm |
#终端环境 |
SHELL=/bin/bash |
#当前shell |
HISTSIZE=1000 |
#历史命令条数 |
SSH_CLIENT=192.168.21.251 2761 22 |
#当前操作环境。用ssh连接,这里标记了客户端IP。 |
QTDIR=/usr/lib64/qt-3.3 |
#环境变量相关配置 |
QTINC=/usr/lib64/qt-3.3/include |
#环境变量相关配置 |
SSH_TTY=/dev/pts/1 |
#ssh连接的终端是pts/1 |
USER=root |
#当前登录的用户 |
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;0
pf=01;36: #颜色相关设置
MAIL=/var/spool/mail/root #用户邮箱PATH=/usr/lib64/qt3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin #PATH变量,系统查找命令的路径
PWD=/root #当前用户所在目录
LANG=zh_CN.UTF-8 #语系
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass #SSH相关配置
HISTCONTROL=ignoredups #此条目会删除历史命令中的重复命令连续重复的命令,在历史命令中
只会识别成一条。
SHLVL=1 #当前在第一层shell中。
HOME=/root #当前用户家目录
LOGNAME=root #当前用户名称
QTLIB=/usr/lib64/qt-3.3/lib #桌面相关环境变量
CVS_RSH=ssh #远程连接方式
SSH_CONNECTION=192.168.21.251 2761 192.168.21.44 22
#SSH连接的客户端IP和端口
LESSOPEN=|/usr/bin/lesspipe.sh %s#压缩包过滤相关环境变量
G_BROKEN_FILENAMES=1 #让GTK2使用LOCALES中的编码方式处理文件名
_=/bin/env #上次使用命令的最后一个参数或命令本身
env命令可以查询到所有的环境变量。
可是还有一些变量虽然不是环境变量,却是和bash操作接口相关的变量。
这些变量只能用set命令来查看了。
下面我们列出set中重要内容:
[root@localhost ~]# set
BASH=/bin/bash #bash的位置
BASH_VERSINFO=([0]="4" [1]="1" [2]="2" [3]="1" [4]="release" [5]="x86_64-redhat-linux-gnu") #bash的版本
BASH_VERSION='4.1.2(1)-release' #bahs版本
COLORS=/etc/DIR_COLORS #颜色记录文件
HISTFILE=/root/.bash_history #历史文件保存位置
HISTFILESIZE=1000 #在文件中记录的历史命令最大条数
HISTSIZE=1000 #在缓存中记录的历史命令最大条数
HOME=/root #家目录位置
HOSTNAME=localhost.localdomain #主机名
HOSTTYPE=x86_64 #主机类型
ID=0 #用户ID
IFS=$' \t\n' #内部域分隔符
LANG=zh_CN.UTF-8 #语系环境
LESSOPEN='|/usr/bin/lesspipe.sh %s' #压缩包过滤相关环境变量
LINES=35
LOGNAME=root
MACHTYPE=x86_64-redhat-linux-gnu #软件类型是i386兼容类型
MAIL=/var/spool/mail/root #邮箱位置
MAILCHECK=60 #每60秒去扫描新邮件
PATH=/usr/lib64/qt3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PPID=2543 |
#父shell的PID |
PS1='[\u@\h \W]\$ ' |
#命令提示符 |
PS2='> ' |
#如果第一行命令没有输入完成,第二行命令的提示符 |
PS4='+ ' |
#“set -x"用来修改跟踪输出的前缀。 (Shell脚本中使用select时的提示符) |
PWD=/root |
#当前所在目录 |
UID=0 |
#当前用户的UID |
PATH变量:系统查找命令的路径
查询PATH环境变量的值:
[root@localhost lib]# echo $PATH
/usr/lib64/qt3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PATH变量的值是用:分割的路径,这些路径就是系统查找命令的路径。就是说当我们输入了一个命令后,如果没写路径,系统就会到PATH变量定义的路径中去寻找是否有可执行的程序。如果没有写入路径,则会返回“命令没有发现”的错误。
那么也就就是说我们把自己的脚本拷贝到PATH变量定义的路径中,我们自己定义脚本也可以不输入路径而直接运行!
[root@localhost ~]# vim hb.sh
[root@localhost ~]# chmod 755 hb.sh
[root@localhost ~]# cp /root/hb.sh /bin/
[root@localhost ~]# cd /tmp/
[root@localhost tmp]# hb.sh
ROUSHANN!!
(在上面实验中,我创建了一个hb.sh的脚本。然后赋予权限,复制到/bin/。切换目录之后,仍然能直接执行脚本。说明cp的方式
可以直接将脚本添加至环境变量中。)
那么接下来,我们用变量叠加的方法试着修改PATH变量的值。达到相同的效果。(删除之前/bin/hb.sh)
[root@localhost tmp]# rm -rf /bin/hb.sh
[root@localhost tmp]# PATH="$PATH":/root/
[root@localhost tmp]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/root/
[root@localhost tmp]# hb.sh
ROUSHANN!!
(首先删除了之前复制进/bin/目录的脚本。然后用变量叠加的方式在PATH中添加了/root/目录。接下来执行hb.sh成功。)
当然,我们这种定义PATH变量的方式只是临时生效,一旦重启或注销就会消失,如果想要永久生效,需要写入环境变量配置文件,我们在之后的课程中会详细介绍。
PS1变量:命令提示符设置
PS1变量是用来定义命令行提示符的,看可以按照我们自己的需求来定义自己喜欢的提示符PS1支持的选项有:
\d:显示日期,格式为“星期 月 日”
\H:显示完整的主机名。如默认主机名:localhost.localdomain
\h:显示简写主机名。默认为:localhost
\T:显示12小时制时间,格式为HH:MM:SS
\t:显示24小时制时间,格式为HH:MM:SS
\A:显示24小时制时间,格式为HH:MM
\@:显示12小时制时间,格式为HH:MM am/pm
\u:显示当前用户名
\v:显示Bash的版本信息
\W:显示当前所在目录的最后一个目录
\w:显示当前所在目录的完整路径
\#:执行的第几个命令
\$:提示符。如果是root会显示提示符为“#”如果是普通用户会显示提示符为“$”
选项应用实例:
[root@localhost ~]# echo $PS1
[\u@\h \W]\$
[root@localhost ~]# PS1='[\u@\t \w]\$'
[root@22:52:10 ~]#cd /usr/local/src/
[root@22:52:21 /usr/local/src]#
(修改提示符为用户名@当前时间 当前所在目录完整路径)
这里需要注意:PS1变量的值要用单引号包含,否则设置不生效。
[root@22:52:21 /usr/local/src]#PS1='[\u@\@ \h \# \W]\$'
[root@11:04 下午 localhost 29 src]#
(\@:时间格式是HH:MM: am/pm 、#:会显示执行了多少个命令)
LANG语系变量
LANG变量定义了Linux系统的主语系环境,这个变量的默认值是:
[root@localhost ~]#echo $LANG
zh_CN.UTF-8
(因为我们安装Linux时,选择的是中文安装。所以,默认的主语系变量是“zh_CH.UTF-8”)
我们可以用locale命令查询Linux中支持的语系数量:
因为Linux系统支持语系众多,我们直接统计数量即可:
[root@localhost src]#locale -a | wc -l
735
Linux系统支持那么多语系,想要查看当前所有语系可以用locale命令查看:
[root@localhost ~]#locale
LANG=zh_CN.UTF-8
LC_IDENTIFICATION="zh_CN.UTF-8"
LC_ALL=
Linux中文支持问题:不是说我们定义了语系为中文语系,如:zh_CN.UTF-8就可以显示中文了。要分情况而定。如果在图形界面
中,或者用远程连接工具时,只要设置正确的语系就可以正常显示中文。当然,如果远程连接工具有可能也需要进行语系环境配置。如
果强行更改LANG变量,那么最终结果会让原有格式变成乱码:
位置参数变量:
位置参数变量 |
作用 |
$n |
n为数字 ,$0代表命令本身 ,$1-$9代表第一到第九个参数 ,十以上的参数要用 大括号包含例 ${10} |
$* |
这个变量代表命令行中所有的参数 ,$*把所有的参数看成一个整体。 |
$@ |
这个变量代表命令行中所有参数 ,不过$@把每个参数区分对待 |
$# |
这个变量代表命令行中所有参数的个数。 |
补充:$*和$@的区别是在接收键盘输入read定义for循环的时候把“”加上。例:for i in“$*”或“$@”,这样输出的话$*是全部输入的为一个整体输出,而$@是一个一个输出的,for循环是需要把输出的值写在命令行后面执行的。例:./for.sh 1 2 3 4.....
首先,我们演示一下$n的作用:
#!/bin/bash
echo "$0"
echo "$1"
echo "$2"
echo "$3"
(写一个脚本)
[root@localhost ~]#chmod +x chanshu.sh
[root@localhost ~]#./chanshu.sh 11 22 33
./chanshu.sh
11
22
33
(执行脚本,发现$0输出了命令的本身 $1输出了第一个数字11 $2输出了第二个数字22 $3输出了第三个数字33)
看起来这个位置参数变量并没有什么用处,但是可以实现简单的运算功能:
#!/bin/bash
aa=$1
bb=$2
cc=$((aa+bb))
echo "jieguoshi:$cc"
(编写了qiuhe.sh脚本)
[root@localhost ~]#chmod 755 qiuhe.sh
[root@localhost ~]#./qiuhe.sh 11 22
jieguoshi:33
(赋予执行权限,然后进行测试。脚本成功的计算出了11+22的和。位置参数变量的意义在于可以把值传进脚本,然后进行计算。)
[root@localhost ~]# cat canshu4.sh
#!/bin/bash
echo "$*" #首先我们编写了一个脚本,脚本分别输出$*、$@、$#。
echo "$@"
echo "$#"
[root@localhost ~]# chmod 755 canshu4.sh
[root@localhost ~]# ./canshu4.sh aa bb cc
aa bb cc
aa bb cc
3
(我们看到,$*和$@输出的结果相同似乎并没有什么区别。而$#输出了参数的个数是正确的。)
查看$*、$#区别的脚本。
[root@localhost ~]# cat canshuan3.sh
#!/bin/bash
for i in "$*" #定义for循环,in后边有几个值,for会循环多少次。$*要用双引号括起来。
do #每次循环都会把in后边的值赋予变量。
echo "$i" #shell把$*中的所有参数看成一个整体,所以这个for循环只会循环一次。
done #打印$i的值。
for a in "$@" #in后边的有几个值for就会循环几次,每次都把赋值给变量a
do #可是shell中把$@中的每个参数都看成是独立的,所以$@中有几个参数,就会循环几次。
echo "$a" #输出变量a的值。
done
echo "$#" $#输出了参数的个数。
[root@localhost ~]# chmod 755 canshuan3.sh
[root@localhost ~]# ./canshuan3.sh a b c d
a b c d
a
b
c
d
4
(解释一下上边的脚本输出内容:
因为$*会把所有参数看成一个整体,所以只输出了a b c d。
因为$@会把变量中的参数分别对待,结合for循环。
所以会分别输出,a b c d四个字母。而$#会算出命令行中参数的个数,我们输入了abcd,4个参数。)
预定义变量 |
作用 |
$? |
最后一次执行命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行。如 果这个变量的值为非0,则证明上一个命令不正确执行。 |
$$ |
当前进程的进程号 (PID) |
$! |
后台运行的最后一个进程的进程号 (PID) |
演示$?预定义变量:
[root@localhost tmp]# ls #执行命令ls,执行成功。
keyring-xS41Gf orbit-gdm pulse-VtQdCFNyTe9r
keyring-ZPERjY pulse-9ubbx0KGoo8T virtual-root.pPc6Ff #查看了/tmp下的内容。
[root@localhost tmp]# echo $? #执行echo $?
0 #返回值0说明命令执行功。
[root@localhost tmp]# lss #输入一个不存在的命令。
-bash: lss: command not found #报错,显示命令不存在。
[root@localhost tmp]# echo $? #执行echo $?
127 #非0命令执行不成功
(在命令执行成功后echo $?的返回值统一为0。当命令执行不成功值返回值为非0。具体数值为编程人员定义。)
演示$$预定义变量效果:
[root@localhost ~]# vim dangqian.sh #首先写一个脚本,dangqian.sh
[root@localhost ~]# chmod 755 dangqian.sh #赋予执行权限。
[root@localhost ~]# cat dangqian.sh #查看脚本内容。
#!/bin/bash #echo $$输出了脚本的进程号。
echo "$$"
[root@localhost ~]# ./dangqian.sh
2073 #脚本运行时进程号。
(也可以直接在命令行中输出echo $$返回的进程号就是当前bash的进程号。可以通过ps aux验证。)
演示$!预定义效果:
[root@localhost ~]# top & #把top命令放入后台执行
[1] 1967 #显示了top命令的进程号为1967
[root@localhost ~]# ps aux #用top命令查看top进程和进程号
[root@localhost ~]# echo $! #用echo $!命令查看进程号
1967
接收键盘输入:
命令格式:read 【选项】 【变量名】
子选项:
-p “提示信息”:等待read输入时,输出提示信息。
-t 秒数:read命令会一直等待用户输入,使用此选项可以指定等待时间。
-n 字符数:read命令只接受指定的字符数量,然后就会执行。
-s 隐藏输入内容,适用于机密信息的输入。
变量名:变量命名可以自定义,如果不指定变量名,会把输入保存入默认变量REPLY
如果只提供一个变量名,则整个输入行赋予该变量。
如果提供了一个以上的变量名,则输入行分为若干字,一个接一个地赋予各个变量,而命令行上的最后一个变量取得剩余所有字。
补充:-t是默认时间到了不会换行,-n设置字符数输入完了也是不会换行的。要想体现到换行需要在中间设置一行echo“”就可以换行。
例:
read -t 3 -n 2 -p "请输入值: " a1
echo""
echo "变量a1的值是:$a1"
read命令实例演示:
[root@localhost ~]# cat xx.sh #编写一个名为xx.sh的脚本
#!/bin/bash
read -t 30 -p "请输入姓名:" name #等待30秒,提示信息为“姓名..”,赋予变量”
name“read -t 30 -s -p "请输入年龄:" age #等待30秒,隐藏输入内容提示信息为“年龄..”变量age
echo -e "" #输入一个空行,没有的话在当前格式默认不换行。
read -t 30 -n 1 -p "请输入性别:" sex #等待30秒,提示信息为性别..,字符数1,变量sex
echo -e "" #输入一个空行,没有的话在当前格式默认不换行。
echo "$name" #分别输出$name $age $sex
echo "$age"
echo "$sex"
Shell基础3
shell的运算符:
1)数值运算的方法
如果我们需要进行数值运算,可以采用以下三种方法中的任意一种:
使用declare声明变量类型:既然所有变量的默认类型是字符串型,那么只要我们把变
量声明为整数型就可以进行运算了。使用declare命令就可以实现声明变量的类型。命令如
下:
格式:declare
【+/-】【子选项】 变量名
子选项:
-:给变量设定类型属性。
+:取消变量的类型属性。
-a:将变量声明为数组型。
-i:将变量声明为整数型(integer)。
-r:将变量声明为只读变量。注意,一旦设置为只读变量,既不能修改变量的值也不能删除变量,甚至不能通过+r取消只读属性。
-x:将变量声明为环境变量。
-p:显示指定变量的被声明类型。
例:数值运算
[root@localhost ~]# aa=11
[root@localhost ~]# bb=22
[root@localhost ~]# declare -i cc=$aa+$bb #将变量声明为整数型。
[root@localhost ~]# echo $cc
33
例:数组变量类型
所谓数组,就是相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的
变量用一个名字命名,然后用编号区分他们的变量集合。这个名字成为数组,编号称为下
标。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也会称为下标变量。
变量和数组都是用来保存数据的,只是变量只能赋予一个数据值,一旦重复赋值,后一
个值就会覆盖前一个值。而数组可以赋予一组相同类型的数据值。
例:
[root@localhost ~]# name[0]="aa" #数组中第一个变量
是“aa”
[root@localhost ~]# name[1]="bb" #数组中第二个变量
是“bb”
[root@localhost ~]# name[2]="cc" #数组中第三个变量
是“cc”
[root@localhost ~]# echo $name #输出数组的内容,如果只写数名,
aa 那么只会输出第一个下标变量。
[root@localhost ~]# echo ${name[1]} #下表1输出了bb
bb
[root@localhost ~]# echo ${name[*]} #用数组【*】输出数组所有内容
aa bb cc
(数组下表是从0开始的,在调用数组时,需要用${数组[下标]}的方式来读取)
例:环境变量
我们可以用declare命令把变量声明为环境变量,和export命令的作用是一样的。
[root@localhost ~]# declare -x test=123 #用declare命令-x选项将test=123声明为环境
变量。
[root@localhost ~]# env | grep test #在env中查找是否有test的环境变量。
test=123
(环境变量可用在创建变量的shell和从该shell派生的任意子shell或进程中,因此,环境
变量通常又被称为全局变量。环境变量被创建时所处的shell被称为父shell,如果在父
shell中再创建一个shell,那么该shell被称为子shell。当子shell产生时,它会继承父
shell的环境变量为自己所用,所以说环境变量可从父shell传给子shell。但注意,环境变
量只能向下传递而不能向上传递。“传子不传父”)
补充:在父shell中设置的变量,在子shell中可以看见。
在子shell中设置的变量,在父shell中看不见。
例:只读属性
[root@localhost ~]# declare -r test #给test 赋予只读属性
[root@localhost ~]# test=456 #test变量的值不能修改了
bash: test: readonly variable #bash,test,只读变量
[root@localhost ~]# declare +r test #试图取消只读属性
bash: declare: test: readonly variable #失败..
[root@localhost ~]# unset test #删除变量
bash: unset: test: cannot unset: readonly variable #再次失败.....
(一旦给变量设定了只读属性,那么这个变量既不能修改变量的值,也不能删除变量,不能
用+r选项取消只读属性。但是,因为这个变量只是命令行声明的,所以只要重新登录或重
启,这个变量就会消失。)
例:查询变量属性和取消变量属性
变量属性的查询使用-p选项,变量属性的取消使用+选项。命令如下:
[root@localhost ~]# abc=123 #变量赋值abc=123
[root@localhost ~]# declare -p abc #用declare -p查看
declare -- abc="123"
[root@localhost ~]# declare -i abc #declare -i声明变量abc为整数型
[root@localhost ~]# declare -p abc #查看
declare -i abc="123"
[root@localhost ~]# name[0]=aa #数组
[root@localhost ~]# name[1]=bb
[root@localhost ~]# name[2]=cc
[root@localhost ~]# declare -p name #查看数组型
declare -a name='([0]="aa" [1]="bb" [2]="cc")'
[root@localhost ~]# declare -p test #test变量是环境变量和只读变量
declare -rx test="123"
[root@localhost ~]# declare +x test #取消test变量的环境变量属性
[root@localhost ~]# declare -p test #查看test
declare -r test="123"
shell常用运算符:
算数符运算是指加,减,乘,除,余等常见运算,值得注意的是shell只支持整数计
算,也就是所有可能产生小数的运算都会舍去小数部分。
例1:加减乘除
[root@localhost ~]# aa=$(( (11+3)*3/2 ))
[root@localhost ~]# echo $aa
21
#虽然乘除的优先级高于加,但是通过小括号可以调整运算优先级。
变量的测试与内容置换:
变量置换方式 |
变量y没有设置 |
变量y为空值 |
变量y设置值 |
x=${y-新值} |
x=新值 |
x为空 |
x=$y |
x=${y+新值} |
x为空 |
x=新值 |
x=新值 |
x=${y=新值} |
x=新值 y=新值 |
x为空 y值不变 |
x=$y y值不变 |
补充:x=${y-新值}如a=${b-c},1、如果b没有值的时候,那么a=c 2、b设定了空值的时候,那么a=空 3、如果b设定了值,那么a=b设定的值。
作用:它可以在没有取到值的时候可以默认给它设定一个值。
例1:x=${y-新值}
[root@localhost ~]# unset y
[root@localhost ~]# x=${y-new}
[root@localhost ~]# echo $x
new
[root@localhost ~]# echo $y
[root@localhost ~]# #变量y没有设置值时,x=新值。
[root@localhost ~]# y=""
[root@localhost ~]# x=${y-new}
[root@localhost ~]# echo $x
[root@localhost ~]# #变量y为空时,x为空。
[root@localhost ~]# y=aa
[root@localhost ~]# x=${y-new}
[root@localhost ~]# echo $x
aa #变量y为aa时,x=$y。
五、环境变量配置
1.source 命令功能:在不退出登录的情况下,能够让环境变量的修改立即生效。
例如,当我们修改了/etc/profile文件,并想让它立刻生效,而不用重新登录,就可以使用source命令,如source /etc/profile。
[root@localhost ~]# source 环境变量配置文件
[root@localhost ~]# . 环境变量配置文件
补充:前提是环境变量配置文件。source用在修改过之后的环境变量文件上让其立即生效。
2.环境变量配置文件
1)登录时生效的环境变量配置文件
在Linux系统登录时主要生效的环境变量配置文件有以下五个:
/etc/profile (在当前shell生效)
/etc/profile.d/*.sh
~/.bash_profile
~/.bashrc
/etc/bashrc
注意:在7.3和7.6版本的centos中,额外写入到/etc/profile文件的变量定义并不会在
正常登录后生效。在su -切换用户后生效。建议写入到/etc/bashrc或/~/.bashrc中。
/etc/profile: 在用户登录过程先调用/etc/profile文件在这个环境变量配置文件中会定义这些默认环境变
量:
USER变量:根据登录的用户,给这个变量赋值(就是让USER变量的值是当前用户)
LOGNAME变量:根据USER变量的值,给这个变量赋值。
MAIL变量:根据登录的用户,定义用户的邮箱为/var/spool/mail/用户名。
PATH变量:根据登录用户的UID是否为0,判断PATH变量是否包含/sbin/,/usr/sbin/,/usr/local/sbin/这三个系统命令目录。
HOSTNAME变量:更改主机名,给这个变量赋值。
HISTSIZE变量:定义历史命令的保存条数。
umask:定义umask默认权限。注意/etc/profile文件中umask权限是在“有用户登录过程(也就是输入了用户名和密码)”时才会生效。
调用/etc/profile.d/*.sh文件,也就是调用/etc/profile.d/目录下所有以.sh结尾的文件。
由/etc/profile文件调用/etc/profile.d/*.sh文件这个目录中所有以.sh结尾的文件都会被/etc/profile文件调用,这里最常见的就是lang.sh文件,而这个文件又会调用/etc/sysconfig/i18n文件(默认语系配置文件Centos6
~/.bash_profile文件主要有两个功能:
调用了~/.bashrc文件。
在PATH变量后面加入了”:$HOME/bin“这个目录。那也就是说,如果我们在自己的家目录中建立bin目录,然后把自己的脚本放入~/bin目录,就可以直接执行脚本,而不是通过绝对路径执行(需要创建~/bin/目录)。
由~/.bash_profile文件调用~/.bashrc文件在~/.bashrc文件中主要实现了:定义默认别名,所以自己定义的别名也放进了这个文件。 补充:/etc/ bashrc和/etc/profile和~/.bashrc文件都可以通过重新登录让其生效生效。可以执行命令 . . /banshrc把它放在当前执行还可以通过source命令去执行文件。
调用/etc/bashrc由~/.bashrc调用了/etc/bashrc文件在/etc/bashrc文件中主要定义了这些内容:
PS1变量:也就是用户的提示符,如果我们想要永久修改提示符,就要在这个文件中修改。
umask:定义umask默认权限。这个文件中定义的umask是针对”没有登录过程(也就是不需要输入用户名和密码时,比如从一个终端切换到另一个终端,或者进入子shell)“时生效的。如果是”有用户登录过程“,则是/etc/profile文件中umask生效。
PATH变量:会给PATH变量追加值,当然也是在”没有登录过程“时才生效。
调用/etc/profile.d/*.sh文件,这也是在”没有登录过程“时才调用。在”有用户登录过程“时,/etc/profile.d/*.sh文件已经被/etc/profile文件调用过了。
这样这五个环境变量配置文件会被依次调用,如果你修改后打算对所有用户生效,那么可以放入/etc/profile环境变量配置文件。
1)可是如果我们误删除了这些环境变量,比如删除了/etc/bashrc文件,或删除了 ~/.bashrc文件,那么这些文件中配置就会失效(~/.bashrc文件会调用/etc/bashrc文件)
那么命令是提示符会变成:
-bash-4.1# (ps1没有被定义,这里显示的是bash的版本)
2) 注销时生效的环境变量配置文件在用户退出登录时,只会调用一个环境变量配置文件,~/.bash_logout文件。默认没有写入任何内容,可是如果我们希望在退出登录时执行一些操作,比如备份或sync命令,就可以把命令写入这个文件。
3)
3)其他配置文件
还有一些环境配置文件,最常见的就是~/bash_history文件,也就是历史命令保存文件。这个文件在之前的课程中已经讲过了,这里只是把他列入环境变量配置文件中。
补充:写变量的时候全部文件写上的读取顺序是先是etc下的生效,后是家目录的生效。先是全局的生效后是局部生效。
3、shell登录信息
1)/etc/issue
我们在登录tty1-tty6这六个本地终端时,会有几行欢迎信息。这些欢迎信息就是保存
在/etc/issue文件中的,我们可以对这个文件进行查看:
[root@localhost ~]# cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m
可以支持的转义符我们可以通过man agetty命令查询,在表中我们列出常见的转义符作用:
转义符 |
作用 |
\d |
显示当前系统日期 |
\s |
显示操作系统名称 |
\l |
显示登陆终端号 (常用) |
\m |
显示硬件体系结果,如:i386,i686等 |
\n |
显示主机名 |
\o |
显示域名 |
\r |
显示内核版本 |
\t |
显示当前系统时间 |
\u |
显示当前登陆用户的序列号 |
2)/etc/issue.net
/etc/issue是在本地终端登录是显示欢迎信息的,如果远程登录(如ssh远程登录,或telnet远程登录)需要显示欢迎信息(警告信息),则需要配置/etc/issue.net这个文件了。使用这个文件时有以下两点需要注意:
首先,在/etc/issue这个文件中支持的转义符,在/etc/issue.net文件中不能使用。其次,ssh远程登录是否显示/etc/issue.net文件中的欢迎信息,是由ssh的配置文件决定的。
如果我们需要ssh远程登录可以查看/etc/issue.net的欢迎信息,那么首先需要修改ssh的配
置文件/etc/ssh/sshd_config加入以下内容:
[root@localhost ~]# cat /etc/ssh/sshd_config | grep Banner
#Banner none
Banner /etc/issue.net
(在#Banner none后加入上述内容。这样在ssh远程登录的时候,也可以显示欢迎信息,只是不再可以识别\d和\l等信息了。(注意需要重启service shhd restart)
3)/etc/motd
/etc/motd文件中也是显示欢迎信息的,这个文件和/etc/issue及/etc/issue.net文件的区别是:/etc/issue及/etc/issue.net是在用户登录之前显示欢迎信息,而/etc/motd是在用户输入用户输入用户名和密码正确登录之后显示欢迎信息。在/etc/motd文件中的欢迎信息,无论是本地登录,还是远程登录都可以显示。
4)定义Bash快捷键
[root@localhost ~]# stty -a #查询所有快捷键
speed 38400 baud; rows 22; columns 73; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
..........
定义ctrl+p快捷键为强制终止,^字符只要手工输入即可。
[root@localhost ~]# stty intr ^p
[root@localhost ~]# ^P
[root@localhost ~]# ^P
[root@localhost ~]# stty -a
speed 38400 baud; rows 22; columns 73; line = 0;
intr = ^P; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
............
(强制终止变成了ctrl+p)
- 点赞
- 收藏
- 关注作者
评论(0)