改动时间
2020-03-12 21:51:24
Shell
Shell概述
- 把命令翻译为内核可以识别的语言
- 强大的编程语言,脚本语言,可以直接调用Linux系统命令
- Bash就是一种Shell,是Linux默认的一种Shell。
echo命令
echo 'hello world!' 有空格需要用引号,带有感叹号需要用单引号
-e支持\反斜杠控制的字符转换\\输出\本身
\b向左删除一个字符
\t制表符,也就是按了一下Tab键
\f换页
\n换行
\r回车
echo -e '\e[1;31m hello world\e[0m'颜色输出- 这里的前面
\e[1;后面\e[0m中间31m=红色 后面hello world输出内容 - 30=黑 31=红 32=绿 33=黄 34=蓝 35=洋红 36=青 37=白

编写第一个脚本
最好写
.sh扩展名#!/bin/bash所有Shell都要写这句话,不写的话有些语句会出错
vi hello.sh写入内容
1
2
3#!/bin/bash
#taopanfeng(www.taopanfeng.top)
echo 'TaoPanfeng is good man!'执行脚本

使用
bash 脚本执行,没有执行权限也可以
如果遇到不能执行的Shell脚本,例如Windows编写的放入Linux就会执行不了
需要安装yum -y install dos2unix来转换,执行转换dos2unix 文件
因为Windows换行符是M$结尾,而Linux是$结尾
可以使用cat -A 脚本文件来查看Shell隐藏内容
Bash的基本功能
历史命令与补全
历史命令
history
-c清空历史命令(不建议使用)-w把历史命令保存到文件~/.bash_history
修改默认保存条数
在~/.bash_history中默认保存1000条命令,先进先出vi /etc/profile进入配置文件,修改生效需重新登录
历史命令调用
上下箭头!n执行第几条
!!重复上一条!字符串重复最后一条以该字符串开头的命令
命令补全
Tab单击对1个补全Tab双击对多个可补全的进行列出
命令别名与常用快捷键
命令别名
alias 别名='原命令'定义别名alias查询所有别名
unalias 别名删除别名
命令执行顺序
- 绝对路径,相对路径执行的命令

- 别名
- 执行Shell内置命令

- 按照$PATH环境变量定义目录从左向右查找命令

别名永久有效
vi /root/.bashrc在里面添加就行了alias 别名='原命令'定义别名
Bash常用快捷键
Ctrl + A光标移到命令开头Ctrl + E光标移到命令结尾Ctrl + C终止当前命令Ctrl + L清空当前命令,相当于直接输入clear命令Ctrl + U清空当前正在输入的命令Ctrl + K删除光标后的所有内容,包括光标所在位置Ctrl + Y粘贴Ctrl + U或Ctrl + K的内容Ctrl + R进入搜索命令模式,回车执行,上下箭头退出搜索命令模式Ctrl + D退出当前终端
Ctrl + Z暂停,放入后台Ctrl + S暂停屏幕输出Ctrl + Q恢复屏幕输出
输入输出重定向
标注输入,输出
| 设备 | 设备文件名 | 文件描述符 | 类型 |
|---|---|---|---|
| 键盘 | /dev/stdin | 0 | 标准输入 |
| 显示器 | /dev/sdtout | 1 | 标准输出 |
| 显示器 | /dev/sdterr | 2 | 标准错误输出 |
输出重定向
把命令结果不直接显示,而是输出到文件中,比如
日志
文件不存在会创建,没有目录会报错
| 类型 | 符号 | 作用 | 示例 |
|---|---|---|---|
| 标准输出重定向 | 命令 > 文件 |
覆盖,命令正确则会覆盖,命令错误则清空内容 | ![]() |
| 标准输出重定向 | 命令 >> 文件 |
追加,正确会追加,错误则输出执行结果,原文件不动 | ![]() |
| 标准错误输出重定向 | 错误命令 2> 文件 |
覆盖,命令正确则会覆盖,命令错误则直接输出执行结果并清空文件内容 | ![]() |
| 标准错误输出重定向 | 错误命令 2>> 文件 |
追加,错误会追加,正确则输出执行结果,原文件不动 | ![]() |
| 正确输出和错误输出同时保存 | 命令 > 文件 2>&1或命令 &> 文件 |
覆盖,不论正确还是错误 | ![]() |
| 正确输出和错误输出同时保存 | 命令 >> 文件 2>&1或命令 &>> 文件 |
追加,不论正确还是错误 | |
| 正确输出和错误输出同时保存 | 命令 >> 文件1 2>>文件2 |
正确追加到文件1,错误追加到文件2 |
输入重定向
wc
-l只统计行数-w只统计单词数-c只统计字符数输入
wc回车就可以输入内容了,Ctrl + D结束Ctrl + D执行的行不计入行的统计空格和换行分割单词
空格和换行都记作1个单词


对文件操作
wc < 文件
多命令执行逻辑与管道符
多命令顺序执行
| 多命令执行符 | 格式 | 作用 | 示例 |
|---|---|---|---|
; |
命令1 ; 命令2 |
无逻辑,从左往右依次执行 | ![]() |
&& |
命令1 && 命令2 |
逻辑与and,1执行正确,2才执行;1执行执行,2也不执行 | ![]() |
|| |
命令1 || 命令2 |
逻辑或or,1执行错误,2才执行;1执行正确,2不执行 | ![]() |
管道符
命令1 | 命令2命令1正确输出作为命令2的操作对象
例如
netstat -taplun | grep -in 'establ'
表示在所有监听TCP,UDP协议,显示IP地址,端口号,进程号,进程名称
并筛选只查找有字符串establ的行,忽略大小写,并显示行号
通配符与其他特殊符号
通配符
| 通配符 | 作用 | 示例 |
|---|---|---|
? |
匹配一个字符 | ![]() |
* |
匹配0个或多个,也就是可以匹配任何内容 | ![]() |
[] |
匹配括号中任意一个字符,例如[abc]匹配a或b或c |
![]() |
[-] |
匹配括号中任意一个字符,例如[a-z]代表匹配一个小写字母 |
![]() |
[^] |
逻辑非,匹配不是括号中的任意一个字符,例如[^0-9]代表匹配一个不是数字的字符 |
![]() |
特殊符号
| 符号 | 作用 | 示例 |
|---|---|---|
'' |
单引号,在单引号中,如$ `(反引号)都没有特殊含义 |
![]() |
"" |
双引号,在双引号中所有特殊符号都没特殊含义,但除了$(调用变量的值) `(引用命令) \(转义符) |
![]() |
`` |
反引号,作用与$()相同,引用系统命令,推荐使用$(),因为`反引号经常被看错为'单引号 |
![]() |
$() |
和``作用一样,引用系列命令 |
![]() |
# |
在Shell脚本中,#开头的行代表注释 |
![]() |
$ |
用于调用变量的值 | ![]() |
\ |
转义符,在\后面跟的特殊符号将做为普通符号处理,如\$将作为字符串$输出,而不是引用变量 |
![]() |
Bash的变量
用户自定义变量
什么是变量
计算机内存的单元,可以改变存放的值.
变量定义规则
- 名称,可以是字母,数字,下划线组成;不能以数字开头,例如
2age是错误的 - 类型,默认字符串类型,如果要进行数值运算,需要指定为数值类型
- 赋值,使用
=,而且=两侧不能有空格 - 变量值若有空格,使用
''单引号或""双引号包括
- 变量的值可以使用
\进行转义 - 【追加变量】可以进行变量追加.不过需
"$变量名"或${变量名}【注意:第一种需要双引号】
- 命令结果赋值给变量,使用
``反引号或$()包含命令 - 环境变量名建议大写,便于区分
变量分类
自定义变量环境变量保存和系统操作相关的数据位置参数变量想脚本传参,传数据的,变量名固定,作用固定,值可以改预定义变量bash中定义好的变量,变量名固定,作用也固定,值可以改
设置用户自定义变量
- 变量定义
name="tao pan feng"
- 变量叠加
aa=123aa="$aa"456aa=${aa}7890
- 变量调用
echo $变量名
- 变量查看
set可以查看系统所有变量
- 变量删除
unset 变量名

环境变量
环境变量是什么
自定义变量只会对当前Shell生效,环境变量可以对当前Shell包括子Shell生效.- 如果把
环境变量写入相应配置文件,所有Shell都生效
设置环境变量
- 声明变量
export 变量名=变量值
- 查询变量
env只能查看环境变量
- 调用变量
echo $变量名 - 删除变量
unset 变量名



系统提示符变量PS1

- 定义系统提示符的变量,严格说不算是系统变量
env不能查看需要set查看
\d显示日期,格式星期 月 日\h主机名,默认localhost\t24小时制时间,格式HH:MM:SS\T12小时制时间,格式HH:MM:SS\A24小时制时间,格式HH:MM\u显示当前用户名\w显示目录完整名称\W当前所在目录的最后一个目录\#显示当前执行的第几个命令\$提示符,如果是root为#,如果为普通用户为$

- 修改要使用
''单引号括起来
系统环境变量PATH
可
env或set查看
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin使用
:分割多个路径例如我们输入命令
ls就会去第1个路径去找,找不到就去第2个路径去找,都找不到的话就会报错

查找路径
echo $PATH
变量叠加
PATH=${PATH}:/root/sh或PATH="$PATH":/root/sh

位置参数变量
也是
预定义变量
$n $* $@ $#
| 位置参数变量 | 作用 |
|---|---|
$n |
其中n为数字,$0代表命令本身,$1~9代表第1到9个参数,大于9的需要使用{}大括号,如${10} |
$* |
代表命令行中所有参数,$*把所有参数看为一个整体 |
$@ |
也表示命令行所有参数,不过$@把所有参数区分对待 |
$# |
代表命令行中所有参数的个数 |
$n示例



$* $@ $#示例

$*与$@区别
- 作为循环时,无论输入多少参数
$*都只会循环一次,因为它把参数看为整体 $@根据你输入参数个数来确定循环次数
预定义变量
$? $$ $!
| 预定义变量 | 作用 |
|---|---|
$? |
判断上一条命令是否正确执行,正确执行返回0 否则都不正确 |
$$ |
当前进程的PID进程号 |
$! |
后台运行的最后一个进程的PID进程号 |
$?示例


$$ $!示例

接收键盘输入read
-p提示信息,等待输入时输出提示信息-t秒数,等待用户输入的时间,单位秒,默认一直等待-n字符数,如果指定一个字符,输入一个字符就会直接执行,不用回车,默认回车执行-s隐藏输入数据
Bash的运算符
数值运算与运算符
declare声明变量类型
declare [+/-] [选项] 变量名
-给变量设置类型属性+给变量取消类型属性-p显示指定变量的被声明的类型-i将变量声明为integer整数类型

-x将变量声明为环境变量
数值运算 方法1
用
declare -i声明数值类型

数值运算 方法2
调用expr数值运算工具
cc=$(expr $aa + $bb)加号+两边需要有空格
这里是把expr $aa + $bb命令结果赋值给变量cc所以要使用$()括起来

数值运算 方法3
$((运算式))或$[运算式]
常用$((运算式))

运算符
优先级值越大越优先
| 优先级 | 运算符 | 说明 |
|---|---|---|
| 13 | -,+ | 单目负,单目正 |
| 12 | !,~ | 逻辑非,按位取反或补码 |
| 11 | *,/,% | 乘,除,取模 |
| 10 | +,- | 加,减 |
| 9 | <<,>> | 按位左移,按位右移 |
| 8 | <=,>=,<,> | 小于或等于,大于或等于,小于,大于 |
| 7 | ==,!= | 等于,不等于 |
| 6 | & | 按位与 |
| 5 | ^ | 按位异或 |
| 4 | | | 按位或 |
| 3 | && | 逻辑与 |
| 2 | | | 逻辑或 |
| 1 | =,+=,-=,*=,/=,%=,&=,^=,|=,<<=,>>= | 赋值,运算且赋值 |
运算符示例
全部写在$((运算式))或$[运算式]


变量测试与内容替换
| 变量置换方式 | 变量y没有设置 | 变量y为空值 | 变量y设置值 |
|---|---|---|---|
| x=${y-新值} | x=新值 | x为空 | x=$y |
| x=${y:-新值} | x=新值 | x=新值 | x=$y |
| x=${y+新值} | x为空 | x新值 | x=新值 |
| x=${y:+新值} | x为空 | x为空 | x=新值 |
| x=${y=新值} | x=新值,y=新值 | x为空,y值不变 | x=$y,y值不变 |
| x=${y:=新值} | x=新值,y=新值 | x=新值,y=新值 | x=$y,y值不变 |
| x=${y?新值} | 新值输出到标准错误输出(就是屏幕) | x为空 | x=$y |
| x=${y:?新值} | 新值输出到标准错误输出 | 新值输出到标准错误输出 | x=$y |
- 示例
x=${y-新值}


x=${y-新值}与x=${y:-新值}区别
环境变量配置文件
- 环境变量可在父Shell,子Shell任何地方执行
- 环境变量设置重启之后就不会再起作用
- 永久有效需写入配置文件
source命令
环境变量配置文件更改后需重启生效
可以使用source命令使其直接生效
source 配置文件或. 配置文件
简介
环境变量配置文件中主要定义对
系统的操作环境生效的系统默认环境变量
比如PATH路径PS1提示符HISTSIZE历史记录保持数HOSTNAME主机名等默认环境变量
- 对所有用户都生效
/etc/profile/etc/profile.d/*.sh/etc/bashrc
- 对用户自己生效 如果是root用户~就为
/root否则/home/用户名~/.bash_profile~/.bashrc
作用
流程图

已登录,未登录
- 已登录
- 需输入
用户名密码 - 流程1 2 3 4 5 6 7 8
- 需输入
- 未登录
- 无需输入
用户名密码
- 7 2 3 4 8
- 无需输入
流程分析
USER LOGNAME MAIL

PATH

HOSTNAME HISTSIZE

umask

调用文件
/etc/profile.d/*.sh和/etc/profile.d/sh.local

执行完毕
会执行
~/.bash_profile文件


其他配置文件和登录信息
注销是生效的环境变量配置文件
~/.bash_logout

其他配置文件
~/.bash_history
历史命令配置文件,注销之后才会写入
系统出问题进行排查错误会用到

Shell登录信息
/etc/issue
本地终端欢迎信息(例如VMware登录)
| 转义符 | 作用 |
|---|---|
\d |
当前系统日期 |
\s |
操作系统名称 |
\l |
登录的终端号,这个比较常用 |
\m |
显示硬件体系结构,如i386 i686 |
\n |
主机名 |
\o |
域名 |
\r |
内核版本 |
\t |
当前系统时间 |
\u |
当前登录用户的序列号 |

/etc/issue.net
远程终端欢迎信息(例如Xshell6登录)
- 在
/etc/issue.net中不能使用转义符 - 显示欢迎信息生效
- 默认显示

- 修改配置文件

- 重启服务

- 修改之后

- 默认显示
/etc/motd
登录后的欢迎信息
不管是本地还是远程登录,都可以显示此欢迎信息

Shell编程
正则表达式
正则表达式与通配符
正则表达式- 在文件中匹配符合条件的字符串
grepawksed等支持正则- 包含匹配

通配符- 匹配符合条件的文件名
*(0个或多个)?(一个字符)[](其中写的任何一个字符)lsfindcp不支持正则,所以需要使用Shell自己的通配符来匹配- 完全匹配

测试正则
原内容

a*
匹配所有内容,包括空白行

boo*

b.*t

^$

^[^a-zA-Z]
表示不以字母开头的行
字符截取命令
cut
提取列
-f列号,提取第几列-d分隔符,安装指定分隔符分割列

结合
grep
printf
输出不换行,可配合awk使用
输出类型
%ns输出字符串,n表示输出几个字符%ni输出整数,n表示输出几个数字%m.nf输出浮点数,m和n是数字,表示输出的整数位数和小数位数- 例如
%8.2f代表输出8位数,其中6位整数,2位小数
- 例如
输出格式
\a输出警告声音\b输出退格键,也就是Backspace键\f清除屏幕\n换行\r回车,也就是Enter键\t水平输出退格键,也就是Tab键\v数值输出退格键,也就是Tab键
示例






awk
列截取
注意点
- awk支持print与printf
- print输出会自动加换行符,Linux默认无print命令
- printf输出不会加入换行符,要换行需手动加
- cut命令不能按空格分隔,awk可以,awk包含cut功能
语法
awk '条件1{动作1} 条件2{动作2} ...' 文件名
默认分隔符 空格或制表符
表示符合条件1执行动作1,符号条件2执行动作2…
条件 > 例如x>10 x>=10 x<=10
动作 > 格式化输出,流程控制语句
基本用法
$0代表一行,$1 $2 …代表第1 2列

BEGIN
执行之前执行
指定分隔符的时候使用,因为第一行不会使用指定的分隔符


END
所有执行之后执行
条件运算符

sed
是一种轻量级流编辑器,可用来数据选取,替换,删除,新增的目录
一般要把cat查询的内容写入文件要使用>或>>写入重定向的方式,再对文件进行vi修改其内容
sed可以直接对cat结果进行修改
sed 选项 '动作' 文件名
- 注意:动作要使用
'单引号,只有使用-i选项才会改变原文件内容 - \反斜杠表示追加,命令未结束

- 选项
-n不加会把数据和sed处理的数据一起输出,加了会只输出sed命令处理的数据

-e允许对输入数据应用多行sed命令
-i用sed的修改结果自己修改读取数据的文件,而不是由屏幕输出
示例:把文件中的no改为yessed -i 's/PermitRootLogin no/PermitRootLogin yes/g' /etc/ssh/sshd_config
- 动作
a追加,在当前行后添加一行或多行,添加多行时,除最后一行,每行尾都要用\反斜杠代表数据未完结
c行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行,每行尾都要用\反斜杠代表数据未完结
i插入,在当前行前插入一行或多行,插入多行时,除最后一行,每行尾都要用\反斜杠代表数据未完结

d删除,删除指定行
p打印,输出指定行s字符串替换,用一个字符串替换另一个字符串,格式为s/旧串/新串/g


字符处理命令
排序命令sort
sort 选项 文件名
-f忽略大小写-r反向排序
-t指定分隔符,默认制表符-k n[,m]按照指定字段范围排序,从第n字段开始,m字段接收(默认到行尾)
-n以数值进行排序,默认按照字符串排序
统计命令wc
wc 选项 文件名
-l只统计行数-w只统计单词数-m只统计字符数

条件判断
按照文件类型判断
| 测试选项 | 作用 |
|---|---|
| -b | 判断文件是否存在,并判断是否为块设备文件,是块设备文件为真 |
| -c | 判断文件是否存在,并且是否为字符设备文件,是字符设备文件为真 |
-d |
判断文件是否存在,并且是否为目录文件,是目录为真 |
-e |
判断文件是否存在,存在为真 |
-f |
判断文件是否存在,并且是否为普通文件,是普通文件为真 |
| -L | 判断文件是否存在,并且是否为符号链接文件,是符号链接文件为真 |
| -p | 判断文件是否存在,并且是否为管道文件,是管道文件为真 |
| -s | 判断文件是否存在,并且是否为非空,非空为真 |
| -S | 判断文件是否存在,并且是否为套接字文件,是套接字文件为真 |
判断格式
test -e /root/anaconda-ks.cfg- 常用
[ -e /root/anaconda-ks.cfg ]


按照文件权限判断
| 测试选项 | 作用 |
|---|---|
-r |
判断该文件是否存在,并且该文件是否拥有读权限(ugo任何一个有读权限为真) |
-w |
判断该文件是否存在,并且该文件是否拥有写权限(ugo任何一个有写权限为真) |
-x |
判断该文件是否存在,并且该文件是否拥有执行权限(ugo任何一个有执行权限为真) |
| -u | 判断该文件是否存在,并且该文件是否拥有SUID权限(ugo任何一个有SUID权限为真) |
| -g | 判断该文件是否存在,并且该文件是否拥有SGID权限(ugo任何一个有SGID权限为真) |
| -k | 判断该文件是否存在,并且该文件是否拥有SBit权限(ugo任何一个有SBit权限为真) |

两个文件进行比较
| 测试选项 | 作用 |
|---|---|
文件1 -nt 文件2 |
判断文件1的修改时间是否比文件2的新(如果新为真) |
文件1 -ot 文件2 |
判断文件1的修改时间是否比文件2的旧(如果旧为真) |
文件1 -ef 文件2 |
判断文件1和文件2的i节点(ls -i)是否一致,可以判断是否为同一个文件,用来判断硬链接 |

两个整数进比较
| 测试选项 | 作用 |
|---|---|
整数1 -eq 整数2 |
整数1 == 整数2 |
整数1 -ne 整数2 |
整数1 != 整数2 |
整数1 -gt 整数2 |
整数1 > 整数2 |
整数1 -ge 整数2 |
整数1 >= 整数2 |
整数1 -lt 整数2 |
整数1 < 整数2 |
整数1 -le 整数2 |
整数1 <= 整数2 |

字符串的判断
| 测试选项 | 作用 | 示例 |
|---|---|---|
-z 字符串 |
判断是否为空(为空返回真) | ![]() |
-n 字符串 |
判断是否不为空(不为空返回真) | ![]() |
字符串1 == 字符串2 |
判断字符串1是否和字符串2相等(相等返回真) | ![]() |
字符串1 != 字符串2 |
判断字符串1是否和字符串2不相等(不相等返回真) | ![]() |
多重条件判断
| 测试选项 | 作用 | 示例 |
|---|---|---|
| 判断1 -a 判断2 | 逻辑与,1 2 都成立才为真 | ![]() |
| 判断1 -o 判断2 | 逻辑或,1 2 一个成立就为真 | ![]() |
| ! 判断 | 逻辑非,使原始的判断取反 | ![]() |
流程控制
if语句
单分支if条件语句
- 写法1,常用
1
2
3if [ 条件判断式 ];then
程序
fi - 写法2
1
2
3
4if [ 条件判断式 ]
then
程序
fi - 注意事项
- 开头是if 结尾是fi
- 条件判断式和中括号两边有空格
- 两种写法

双分支if条件语句
1 | if [ 条件判断式 ] |
- 示例1

- 示例2


多分支if条件语句
1 | if [ 条件判断式1 ] |

case语句
1 | case $变量名 in |

for循环
语法1
1 | for 变量 in 值1 值2 值3 ... |
- 示例1

- 示例2

语法2
1 | for((初始值;循环控制条件;变量变化)) |
- 示例1

- 示例2

while循环
1 | while [ 条件判断式 ] |

until循环
与while相反,表示不满足才循环





























