0%

linux运维学习笔记:shell基础

写在前面

shell脚本是linux运维学习的中的重点和难点,因此把这部分放到最后来整理。主要包括:

  • shell基础知识

  • 如何编写shell脚本?

  • 采用shell编写linux告警系统

首先是第一部分,shell基础。

什么是shell?

shell 是一种命令解释器,也是一种脚本语言。shell编写的程序成为脚本(script),能够调用所有的UNIX系统命令、实用程序、工具软件,以及二进位制文件;支持循环、判断等特定语法。

目前,常见的shell,还有zsh、ksh等。CentOS 默认安装的shell,叫做bash(Bourne Again Shell),简称sh。

这里先把整理shell作为命令解释器的部分。

命令历史 history

查看命令历史

  • history 命令可以查看命令历史
1
[root@stevey ~]# history | less

  • history -c 清空内存中的命令历史;

注:

  1. 该操作并不会清空.bash_history 内容。

  2. 命令历史只有在shell退出的时候,才会保存到.bash_history 当中。

history配置文件及修改

history配置文件

bash 可以记录命令历史,保存在当前用户家目录下的.bash_history 当中,默认支持1000条,

1
2
3
4
5
6
7
8
9
10
11
12
[root@stevey ~]# head /root/.bash_history   //注:当前是root操作
head /root/.bash_history
vi .ssh
rm -rf .ssh
ls
mkdir -p .ssh
cd .ssh
touch authorized_keys
vi/root/.ssh/authorized_kesy
vi /root/.ssh/authorized_keys
cd ~
chmod 700 .ssh

如何修改history配置文件?

第一步:编辑配置文件

1
vim /etc/profile

第二步:修改配置文件

1
2
3
HISTSIZE=n    //n为最大条数,默认1000

HISTORYFORMAT='%Y/%m/%d %H/%M/%S' //记录命令时间

第三步:source

1
source  /etc/profile

history永久保存

1
chmod +a ~/.bash_profile

注:该配置只对正常退出shell的时候才有效。

与命令历史相关特殊用法

  • !! 执行上一条命令

  • !n n代表数字,执行命令历史中的第n条命令

  • !$ $ 代表上一条命令最后的那个值

  • ![字符串] 字符串最少要有一个字符,比如m表示命令历史中最近的一个以m开头的命令

命令补全tab及其别名

补全插件安装 tab

  • shell的命令补全功能需要先安装插件
1
2
3
root@stevey php-7.2.4]# yum install -y bash-completion

init 6 //重启电脑,使用 reboot 也可以。

安装完成后重启电脑,就可以生效了。

alias 别名

终端输入 alias 可以查看当前已经设置的别名

注意:

  1. centos中,别名的配置文件在~/.bashrc ,也可以通过vim ~/.bashrc进行编辑设置;也有部分在 /etc/profile.d/下定义。

  2. alias 在macos下同样有效,不同在于配置文件在~/.bash_profile,也可以通过 vim ~/.bash_profile 进行编辑设置。

设置别名: alias [别名]=[具体命令]

别名是一个很有用的命令,可以玩出很多花样。比如,可以将平常的工作目录都是设置一个别名,这样就不用每次都输入一长串命令了。

注:

  1. 具体命令用英文单引号括起来;

  2. 括号两边是没有空格的;

1
2
3
4
[root@stevey ~]# alias test='cd /root/test/'
[root@stevey ~]# test
[root@stevey test]# pwd
/root/test

取消别名: unalias [别名]

1
2
3
[root@stevey test]# unalias test
[root@stevey ~]# test
-bash: test: command not found

shell当中的特殊字符

*用来匹配一个或多个字符

用来匹配一个字符。

[m-n]表示范围

注:m、n可以是数字范围,也可以是字母;符合范围中的一个,就可以被匹配出来;

{m,n} 表示范围中的一个,逗号是或的意思

m和n中间用逗号连接,是或的意思,符合范围中的一个可以被匹配出来。

1
2
3
[root@stevey test]# touch {1,3}.txt   //创建a.txt和3.txt
[root@stevey test]# ls
1.txt 3.txt b.txt test1 test2 test3

注释符号#

跟js当中的 //, python中的# 一样,这里也是表示注释的意思,# 后面的内容会被忽略。

1
2
3
[root@stevey ~]# a=2 #sdscsdc      //#后面是注释
[root@stevey ~]# echo $a
2

脱义字符 \

比如,* 在shell当中都是特殊字符,如果恰好就想输入*或者本身,就需要使用到脱义字符;使用脱义字符后,后面跟的特殊字符会还原成普通字符。

1
2
3
4
[root@stevey ~]# ls *.txt    //这里*是通配符,表示一个或多个字符,下面输出结果都匹配这个规则
1.txt a.txt b.txt
[root@stevey ~]# ls \*.txt //跟在脱义符后面,*就是普通字符,特指`*.txt`这一个文件。
ls: cannot access *.txt: No such file or directory

$变量提示符

$ 是普通用户的变量提示符,root 用户是#

  • 与!连用,表示上条命令的最后一个参数

用户家目录

对root用户来说是/root/,普通用户是/home/username/

1
2
3
4
5
6
7
8
9
[root@stevey test1]# su - yuanfeng
Last login: Tue Apr 10 11:07:07 HKT 2018 on pts/0
[yuanfeng@stevey ~]$ pwd
/home/yuanfeng //普通用户家目录
[yuanfeng@stevey ~]$ su -
Password:
Last login: Wed Apr 18 09:00:16 HKT 2018 from 172.16.155.1 on pts/1
[root@stevey ~]# pwd
/root //root用户家目录

;适用于多条命令写在同一行,使用 ;隔开

1
for i in `seq 1 100` ; do echo $i; done   //类似于js里面的for循环,把4条命令放在同一行书写

& 命令后台执行

1
2
[root@stevey ~]# vmstat 1 > a.txt &
[3] 76388

[]字符组合

可以是字符组合中的任意一个,也可以表示范围

&&|| 三个特殊的分隔符

这三个命令都是在同一个输入两条不同命令时作为连接符使用,但是意义各有不同。假定有同一行有A、B两条command

  • A ; B 相当于“and”,不管A是否执行成功,都会执行B;

  • A && B 只有A执行成功,B才执行;否则,B不执行

  • A || B 相当于“or”,A执行成功则B不执行;A执行不成功则B执行,A、B两条总有一条会执行。

管道符 |

管道符的作用,一般针对文档操作比较常用,就是将前面命令的输出结果作为后面命令的输入。

常见的,比如:

  • cat head tail less more:这些都是查看文档的;

  • grep:正则匹配工具;

  • sort:排序;

  • wc:统计,通常跟-l 选项;

  • cut:截取字符

  • uniq:检查及删除文本文件中重复出现的行列,常用参数 -c ,命令行格式:uniq-c testfile 检查文件并删除文件中重复出现的行,并在行首显示该行重复出现的次数。

  • tee:读取标准输入的数据,并将其内容输出给文件,类似于输出重定向,不过会同时显示出来,经常跟在管道符后面。

  • tr:替换或删除文件中的字符。比如,要将文本内容读取出来转换成大写字符,可以使用cat testfile |tr a-z A-Z 或者 cat testfile |tr [:lower:] [:upper:],两者作用是一样的。

  • split:将一个文件分割成若干个。常见用法,比如split -n README n 表示行数,把文件每n行为一组,拆分切割成多个以”x”开头的小文件。

  • sed:利用script来处理、编辑文本文件。这个比较复杂,教程在这里

  • awk:同样很复杂,教程在这里

示例:

  • wc命令用来统计指定文件中的字节数、字数、行数,并将统计结果显示输出。常见参数-c表示字节数;-l表示行数。与wc连用,可以实现统计的效果。
1
2
3
4
5
[root@stevey ~]# cat /etc/passwd | wc -l  //统计passwd一共有多少行
21

[root@stevey ~]# ll | wc -l //统计当前目录下一共有多少文件
12
  • grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

输入输出重定向

命令 说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。

用法示例:

  • 输出重定向 command1 > file

示例1:

1
2
3
4
5
6
[root@stevey ~]# touch 1.txt
[root@stevey ~]# who > 1.txt //who命令用于显示系统中有哪些使用者,这里是将who命令的查询结果输出到1.txt
[root@stevey ~]# cat !$
cat 1.txt
root tty1 2018-04-16 15:10
root pts/0 2018-04-16 15:11 (172.16.155.1)

示例2:

1
2
3
4
[root@stevey ~]# echo 'this is a test' > 1.txt  //echo 命令用于字符串的输出
[root@stevey ~]# cat !$
cat 1.txt
this is a test
  • 追加重定向 command >> file
1
2
3
4
5
6
7
8
[root@stevey ~]# pwd
/root
[root@stevey ~]# pwd >> 1.txt //pwd查询结果追加到1.txt
[root@stevey ~]# tac 1.txt //倒序查询1.txt内容,可以看到刚刚追加进去的内容

/root
root pts/0 2018-04-16 15:11 (172.16.155.1)
root tty1 2018-04-16 15:10
  • 2> 错误重定向
1
2
3
[root@stevey ~]# ls aaa 2> a.txt
[root@stevey ~]# cat a.txt
ls: cannot access aaa: No such file or directory
  • 2>> 错误追加重定向
1
2
3
4
[root@stevey ~]# ls aaa 2>> a.txt
[root@stevey ~]# cat a.txt
ls: cannot access aaa: No such file or directory
ls: cannot access aaa: No such file or directory
  • &> 重定向 相当于上述输出重定向和错误重定向的集大成者

  • 输入重定向 command < file
1
2
3
4
5
6
7
8
9
10
[root@stevey test]# cat 1.txt
czsdfvf
ewfefw
raferfw2
egregrere
gerer23fss
[root@stevey test]# wc -l < 1.txt //输入重定向
5
[root@stevey test]# wc -l 1.txt
5 1.txt

作业控制

指的是在shell运行当中的过程控制,主要包括:

  • 暂停:ctrl + Z

  • 前台恢复:fg (指的是foreground)

  • 后台运行:bg (指的是background)

  • 撤销:ctrl + c (这个最常用,尤其是输错命令的时候)

练习环节:

实验了一下教材练习,有几个需要注意的点:

  • 当有两个以上的任务都被暂停的时候,bash 会给暂停的任务编号。此时,输入 jobs 可查看;切换任务使用 fg n,其中 n 为任务编号。

使用&,命令在后台运行,就会显示该任务的pid,如果要结束任务,使用kill + pid

1
2
3
4
5
6
7
8
9
10
[root@stevey ~]# vmstat 1 > a.txt &
[3] 76388
[root@stevey ~]# kill 76388 //结束该任务
[root@stevey ~]# ps //ps命令查询当前进程
PID TTY TIME CMD
993 pts/0 00:00:00 bash
76367 pts/0 00:00:00 vi
76368 pts/0 00:00:00 vmstat
76389 pts/0 00:00:00 ps
[3] Terminated vmstat 1 > a.txt //这就是刚才被结束的进程

shell变量

变量,可以理解为通过一些比较简单的字符来替代某些具有特殊意义的设定或者数据。比如,因为有了PATH变量,查看目录的时候,只需要ls即可。

系统环境变量都存在哪里?

系统级配置文件:

注:对系统级配置的更改会影响到所有用户;

文件名 特性 包含内容
/etc/profile login shell 该文件预置了PATH、USER、LOGNAME、MAIL、INPUTRC、HOSTNAME、HISTSIZE、umask
/etc/bashrc no-login shell 该文件预设umask,以及PS1;PS1的格式为[user@hostname dir]# user是用户名;hostname是主机名;dir是当前目录;$是一个特殊字符,root用户此处是#

/etc/profile/etc/bashrc的区别

  • /etc/profilelogin shell,通过终端输入用户名和密码进入到terminal,此时进入的shell环境就是login shell,例如,通过ssh远程进入到主机。因此,通过login shell运行的shell命令放入到.bash_profile中。

  • /etc/bashrcno-login shell,不需要输入用户名密码而进入的shell环境,通过gnome,KDE等桌面环境进入终端,此时进入的shell环境就是no-login shell。因此,通过no-login shell运行的shell命令放入到.bashrc文件中。

  • 在centos当中,’profile’系列文件的主要目的在于为登录shell设置环境变量和启动程序;而’rc’系列文件的主要目的在于设置功能和别名。

  • 在Mac OS系统中,每次运行terminal,系统会默认运行一个login shell环境,因此mac系统配置都在/etc/profile.bash_profile这两个文件中,一般安全起见,修改当前目录下的.bash_profile就可以了。

延伸阅读:

用户级别配置文件:

注:

  1. 用户级别的配置文件都是隐藏文件,以 . 开头,如果没有,可以新建;

  2. 对这里的配置文件进行修改,只会影响当前用户。

文件名 包含内容
.bash_profile 定义当前用户个人华路径及环境变量的文件名称,当用户登陆时,该文件仅执行一次
.bashrc 专属用户的shell的bash信息,可将别名、自定义变量写在这里,当登陆或每次打开新的shell,该文件都会被读取
.bash_history 记录命令历史
.bash_logout 定义用户退出时,需要执行的动作;当退出shell时,该文件会被执行

如何查看变量?

env 显示及设置用户变量

变量名 含义
HOSTNAME 主机名称
SHELL 当前的shell
HISTSIZE 执行命令的历史记录数量,默认是1000条
PATH 表示shell将到那些目录查找命令或程序
PWD 当前目录
LANG 与语言相关的环境变量,中文为zh_CN.UTF-8 ;english为 en_US.UTF-8
HOME 当前用户家目录
LOGNAME 当前用户登录名
set命令 :显示及设置shell变量

包括的私有变量以及用户变量,不同类的shell有不同的私有变量 bash,ksh,csh每中shell私有变量都不一样。

关于PS1的知识

PS ,即命令提示符,也就是终端最左侧用方括号括起来的部分;

PS1 是当前用户的命令提示符,是在用户根目录下的.bash_profile中定义的。

1
2
[root@stevey ~]# echo $PS1  //查看PS1
[\u@\h \W]\$ //含义为 当前用户名@不含域名的主机名 工作目录的最后一层目录名

默认特殊符号代表的意义

特殊符号 含义
\d 代表日期,格式为weekday month date,例如:”Mon Aug 1”
\H 完整的主机名称。例如:我的机器名称为:fc4.linux,则这个名称就是fc4.linux
\h 仅取主机的第一个名字,如上例,则为fc4,.linux则被省略
\t 显示时间为24小时格式,如:HH:MM:SS
\T 显示时间为12小时格式
\A 显示时间为24小时格式:HH:MM
\u 当前用户的账号名称
\v BASH的版本信息
\w 小写w,完整的工作目录名称。家目录会以 ~代替
\W 大写W,利用basename取得工作目录名称,所以只会列出最后一个目录
\# 下达的第几个命令
\$ 提示字符,如果是root时,提示符为:# ,普通用户则为:$

在PS1中设置字符颜色的格式为[\e[F;Bm],其中F 为字体颜色,编号为30-37;B为背景颜色,编号为40-47,具体如下:

F字体颜色 B背景颜色 颜色
30 40 黑色
31 41 红色
32 42 绿色
33 43 黄色
34 44 蓝色
35 45 紫红色
36 46 青蓝色
37 47 白色

自定义命令提示符

方法一:使用export命令

1
PS1='\[\e[37;40m\][\[\e[34;40m\]\u\[\e[37;40m\]@\h \[\e[36;40m\]\w\[\e[0m\]]\\$ '

方法二: 修改 /etc/bashrc

1
2
3
4
5
vim /etc/bashrc

修改PS设定,按 `:wq` 保存退出。

source /etc/bashrc

方法三:自定义custom.sh

1
2
3
4
5
cd /etc/profile.d   //进入环境配置文件目录

touch custom.sh //新建custom.sh,将PS1设定写进该文件并保存退出

source custom.sh
echo $[变量名] 查看某个变量的值
1
2
3
4
[root@stevey ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@stevey ~]# echo $HOSTNAME
stevey

变量设定

关于变量设置的规则

命令行格式:export A='Alibaba' 其中,A代表变量名,'Alibaba'代表变量内容。设置变量要符合以下规则:

  • 变量格式 a=b , 其中a为变量名,b为变量内容,等号两边不允许有空格;

  • 变量名只能由英、数字以及下划线组成,而且不能以数字开头;

  • 当变量内容带有特殊字符(如空格)时,需要加上单引号;

  • 如果变量内容中需要用到其他命令运行结果则可以使用反引号;

  • 当变量内容含有特殊字符,需要做特殊处理,具体见下表:

变量内容 符号 示例
特殊字符(以空格) 使用单引号 myname=’steve yuan’
变量内容本身有单引号 使用双引号 mac=”steve’mac”
变量内容需要用到其他命令 使用反引号(tab键上面的那个键) hotkey=’pwd’
变量累加其他变量的内容 使用双引号 myname=”$LOGNAME”Steve

如何自定义变量

方法一:修改全局变量 /etc/profile
1
2
3
vim /etc/profile     //编辑此配置文件,添加变量,修改完成后按`esc` 键,输入  `:wq` 保存退出。

source /etc/profile //此方法会影响全局所有用户
方法二:修改当前用户变量 ~/.bashrc
1
2
3
vim ~/.bashrc     //编辑此配置文件,添加变量,修改完成后按`esc` 键,输入  `:wq` 保存退出。

source ~/.bashrc //此方法子对当前用户有效
方法三:export [变量] 更改全局变量

命令行格式: export [参数][变量名称]=[变量设置值]

参数 描述
-f   代表[变量名称]中为函数名称。
-n   删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。
-p   列出所有的shell赋予程序的环境变量。
  • 列出当前所有的环境变量 export -p

  • 定义环境变量赋值 export [变量名称]=[变量设置值]

取消变量 unset [变量名]

shell常用命令

cut命令:截取字段

命令行格式:cut [参数] [filename]

常用参数 含义
-b 以字节(bytes)为单位进行分割。
-c 以字符(characters)为单位进行分割。
-d 自定义分隔符,默认为制表符。
-f 与-d一起使用,表示域(fields),指定显示哪个区域。

注:必须指定 -b、-c 或 -f 之一。

以字节为单位分割

  • -b选项,执行此命令时,cut会先把-b后面所有的定位进行从小到大排序,然后再提取。

who|cut -b 3-5,8who|cut -b 8,3-5 一致

  • -b -3表示从第一个字节到第三个字节;-b 3-表示从第三个字节到行尾;-b -3,3-输出整行,不会出现连续两个重叠字母。

-c 选项 以字符为单位分割

这里涉及到字符编码的扩展知识。在UTF-8编码中,英文字母、数字各占一个字节;汉字有的是3个字节(基本等同于GBK编码,约20000多个汉字),有的是4个字节(包括50000多个汉字);

通过下面这个实验,就能看出-b-c 选项的差别。下图中那个问号,是因为遇到多字节字符,以为一个汉字占了三个字符,所以没办法完整显示。

-nb告诉cut不要将多字节字符拆开;这样做 -c 的效果是一样的。

-f 以域为单位分割

f表示域,后面跟数字;以域为单位时,要同时使用 -d 后面跟分隔符,用单引号括起来。命令行格式为:cut -d [分隔符] -f n [filename]

  • 以空格为单位,分割显示a.txt

  • 与管道符连用。例如,查看passwd第一列的内容

sort 命令: 排序

命令行格式:sort [参数] [filename]

常用参数 用法
-t 后面跟分隔符,跟cut命令-d选项作用一样。
-n 按照纯数字排序,字母和特殊符号视为0
-r reverse ,反向排序
-u 去掉重复项
-k 按照某一列的顺序进行排序

排序的优先级规则:

除非指定-r参数,否则按照一下优先级顺序

  • 以数字开头的行优先级最高;

  • 以小写字母开头的行优先级次之;

  • 待排序内容按字典序进行排序;

注:sort命令只做排序,并不会改动文件本身;如果需要排序后生成新的文件,可以采取输出重定向。

示例:

  • 文件内容进行排序,默认按照字母顺序进行排序
1
2
3
4
5
6
7
8
9
10
11
12
13
[root@stevey ~]# head -n 5 /etc/passwd | cut -d ':' -f 1 > a.txt    //准备实验文件,passwd这个文件比较长,所以只取第一列、前5行的内容,重定向到a.txt
[root@stevey ~]# cat a.txt //查看文件内容
root
bin
daemon
adm
lp
[root@stevey ~]# sort a.txt //省略参数,默认按照英文字母顺序进行a-z进行排序
adm
bin
daemon
lp
root
  • sort还可以同时对多个文件进行排序 sort [file1] [file2]
1
2
3
4
5
6
7
8
9
10
11
12
[root@stevey ~]# tail -n 5 /etc/passwd | cut -d ':' -f 1 > b.txt
[root@stevey ~]# sort a.txt b.txt
adm
bin
daemon
lp
postfix
root
sshd
user1
user2
yuanfeng
  • -r参数,进行反向排序
1
2
3
4
5
6
[root@stevey ~]# sort -r a.txt
root
lp
daemon
bin
adm
  • -k 按照某一列进行排序,比如下面对第9列进行排序 注意此处,如果跟n参数连用的话,k放在后面跟着数字,否则会报错

  • -n 使用纯数字排序,下面安装第5列的数字升序排列 注:字母和特殊符号被视为0

wc统计

命令行格式: wc [参数] [filename]

常用参数 用法
-l 统计行数
-m 统计字符数,包括换行符$
-L 大写L,统计字符数,不包括换行符$
-w 统计词数

示例

1
2
3
4
5
6
7
8
9
10
11
12
[root@stevey ~]# wc -l a.txt   //统计行数
5 a.txt
[root@stevey ~]# wc -m a.txt //统计字符数
23 a.txt
[root@stevey ~]# wc -w a.txt //统计词数
5 a.txt
[root@stevey ~]# cat a.txt
root
bin
daemon
adm
lp
  • wc还可以跟管道符连用,可以实现很多奇妙的效果
1
2
3
4
5
[root@stevey ~]# cat /etc/passwd | wc -l   //统计一共有多少密码
21

[root@stevey ~]# ll /root | wc -l //统计/root目录一共有多少个文件/文件夹
14

uniq 删除重复行并显示

注意:

  • 使用uniq前,要先用sort 进行排序,否则不起作用;

  • uniq 常用参数 -c 表示统计重复的行数;

  • uniq并不会真的删除重复项,如果确实需要删除的话,应输出重定向;

示例:

tee 类似输出重定向

读取标准输入的数据,并将其内容输出给文件,跟输出重定向相似,不过该命令会把输出内容显示出来。

tr 替换或删除文件中的字符

常用参数 用法
-d 删除某个字符,后面跟需要删除的字符
-s 删除重复的字符

示例:

  • -d 删除特定字符 注:这个也不是真正的删除文件,只是看起来删除了。
1
2
3
4
5
6
7
8
9
10
11
12
13
head -n 5 /etc/passwd | cut -d ':' -f 1 > a.txt
[root@stevey ~]# cat a.txt
root
bin
daemon
adm
lp
[root@stevey ~]# cat a.txt | tr -d a
root
bin
demon
dm
lp
  • cat testfile |tr a-z A-Z 或者 cat testfile |tr [:lower:] [:upper:],两者作用是一样的。

  • -s--squeeze-repeats:把连续重复的字符以单独一个字符表示;
1
2
echo "thissss is      a text linnnnnnne." | tr -s ' sn'
this is a text line.

split 切割文档

命令行格式:split [参数] [待切割文件] [切割生产文件]

常用参数 用法
-b 按照文件大小切割,单位为字节bytes
-l 按照行数切割
  • -b 按照大小切割

如果不指定目标文件名,这会以xaa、xab、xac……这样的格式名来自动保存生成文件。

1
2
3
4
5
[root@stevey test1]# ls
b.txt
[root@stevey test1]# split -b 100 b.txt
[root@stevey test1]# ls
b.txt xaa xab xac xad xae xaf xag xah

指定文件名的命令

-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!