自动化运维脚本之shell简介

举报
tea_year 发表于 2024/11/20 15:09:31 2024/11/20
【摘要】 conputer resources:计算机资源kernel:内核shell:命令解释器programs:程序utilities:实用工具tools:工具一个完整的计算机包括硬件与软件。软件又分系统软件与应用软件。负责对硬件进行 管理与操作的是系统软件的内核 (kernel) 部分,用户是无法和内核打交道的,用户只能通 过应用程序或部分系统软件发出指令,这些指令会被翻译并传给内核。在Linu...



conputer resources:计算机资源

kernel:内核

shell:命令解释器

programs:程序

utilities:实用工具

tools:工具

一个完整的计算机包括硬件与软件。软件又分系统软件与应用软件。负责对硬件进行 管理与操作的是系统软件的内核 (kernel) 部分,用户是无法和内核打交道的,用户只能通 过应用程序或部分系统软件发出指令,这些指令会被翻译并传给内核。在Linux内核的系统 下,可以通过shell和内核进行沟通,从而达到使用计算机资源的目的。

每当用ssh工具远程连接到系统时,或在服务器前输入密码后。那个跳动的光标就是一 个shell。shell是指命令解释器,为用户和操作系统之间通信提供的一种接口。

shell不光是命令解释器,还是一种编程工具,称为脚本语言。与编译型语言 (C/C++, java等) 不同,脚本语言又称为解释型语言,这种经过语言的特点在于经过编写后不需要做 任何编译就可以运行。


目前redhat和centos发行版中默认有多种shell,可以在/etc/shells文件中进行查看:

在Linux中/bin/bashLinux默认的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内部命令。比如:cdpwd等。

第四顺位执行按照$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相关环境变量。) (envset的区别是,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)


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。