01shell简介

0 阅读15分钟

shell简介

核心命令介绍

筛选信息

shell快捷键

命令执行说明
!!执行上一条命令
!num执行历史命令中的第num行命令
Ctrl 关键字执行内容匹配的命令
命令行切换说明
Ctrl + a光标迅速回到行首
Ctrl + e光标迅速回到行尾
Ctrl + k删除光标到行尾内容
Ctrl + u删除光标到行首内容
Ctrl + y粘贴删除的内容
Ctrl + c临时终止命令行命令
Esc + b移动到当前单词的开头
Esc + f移动到当前单词的结尾

grep命令

grep [OPTION]... PATTERN [FILE]...负责从数据源中检索对应的字符串,行过滤

选项说明
-i不区分大小写和忽略模式(正则)
-v查找不包含指定内容的行,反向选择
-w按单词搜索
-o只打印匹配关键字
-c统计匹配到的行数
-n显示行号
-r递归遍历目录查找
-A显示匹配行及后面多少行
-B显示匹配行及前面多少行
-C显示匹配行前后多少行
-l只列出匹配的文件名
-L列出不匹配的文件名
-e使用正则匹配
-E使用扩展正则匹配
^key以关键字开头
key$以关键字结尾
^$匹配空行
--color=auto可以将找到的关键词部分加上颜色显示

grep 高亮显示,centos7中已经设置了,存放在/etc/profile.d/colorgrep.sh文件中,如若大家使用的系统中没有设置颜色输出,可以使用以下方法来自行设置

# 临时设置,只针对当前终端和当前用户生效
alias grep='grep --color=auto'

# 永久设置
# 全局(针对所有用户生效)
echo "alias grep='grep --color=auto'" >> /etc/bashrc
source /etc/bashrc
# 局部(针对具体的某个用户)
echo "alias grep='grep --color=auto'" >> ~/.bashrc
source ~/.bashrc

# 示例
# 忽略大小写匹配包含root的行
grep -i root /etc/passwd
# 精确匹配ftp单词
grep -w ftp /etc/passwd
# 打印匹配到的关键字ftp
grep -wo ftp /etc/passwd
# 打印匹配到root关键字的行号
grep -n root /etc/passwd
# 忽略大小写,打印匹配到root关键字的行号
grep -ni root /etc/passwd
# 忽略大小写统计包含关键字root的行数
grep -nic root /etc/passwd
# 忽略大小写匹配以root开头的行
grep -i ^root /etc/passwd
# 匹配以bash结尾的行
grep bash$ /etc/passwd
# 匹配空行并打印行号
grep -n ^$ /etc/passwd
# 匹配以#号开头的行
grep ^# /etc/sudoers
# 匹配不以#号开头的行
grep -v ^# /etc/sudoers
# 匹配包含mail关键字及其后5行
grep -A 5 mail /etc/passwd
# 匹配包含mail关键字及其前5行
grep -B 5 mail /etc/passwd
# 匹配包含mail关键字及其前后5行
grep -C 5 mail /etc/passwd

sort命令

sort [OPTION]... [FILE]...信息排序,将文件的每一行作为一个单位,从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出

选项说明
-u去除重复行
-f忽略大小写,将所有的小写字母转换成大写字母进行比较
-r降序排列,默认是升序
-o将排序结果输出到文件中,类似重定向符号>
-n以数字排序,默认是按字符排序
-t分隔符,将每一行数据按照该选项指定的分隔符分成多个域。默认情况下是使用tab键或者空格符来分割的
-k第N列,指定用哪个域的数据来进行排序,-t和-k一般情况下是同时出现的。如果只使用-t的话,系统会默认使用分割以后的第一个域内的数据进行排序
-b忽略前导空格
-R随机排序,每次运行的结果均不同
cat > num.txt << EOF
9
8
6
8
4
7
2
1
EOF
# 内容升序
sort -n num.txt
# 内容降序
sort -r num.txt
# 升序去重
sort -nu num.txt
# 降序去重
sort -ru num.txt
# 先升序后降序再去重
sort -nru num.txt
# 随机排序
sort -R num.txt
# 升序去重后输出到一个文件
sort -nu num.txt -o a.txt

# 第一列为姓名,后面三列分别是语文、数学、英文的成绩
cat > num.txt << EOF
zhangsan 67 98 82
lisi 88 76 93
wangwu 98 82 73
EOF
# 按照第一列姓名进行排序
sort -t ' ' -k 1 num.txt
# 按照第四列英文进行排序
sort -t ' ' -k 4 num.txt
rm -f a.txt num.txt

处理信息

cut命令

cut OPTION... [FILE]...数据截取

选项说明
-b, --bytes=LIST只选中指定的这些字节
-c, --characters=LIST只选中指定的这些字符
-d, --delimiter=DELIM使用指定分界符代替制表符作为区域分界,分隔符不能以双引号引起来
-f, --fields=LIST仅选择这些字段;也打印任何不包含分隔符的行,除非指定了-s选项
-n与-b一起使用,不拆分多字节字符
--complement补全选中的字节、字符或域
-s, --only-delimited不要打印不包含分隔符的行
--output-delimiter=STRING使用STRING作为输出分隔符默认情况下使用输入分隔符
# 以:冒号分割,截取第1列内容
cut -d : -f 1 /etc/passwd
# 以:冒号分割,截取第1,6,7列内容
cut -d : -f 1,6,7 /etc/passwd
# 截取文件中每行第4个字符
cut -c4 /etc/passwd
# 截取文件中每行的1-4个字符
cut -c1-4 /etc/passwd
# 从第5个字符开始截取后面所有字符
cut -c5- /etc/passwd

tr命令

tr [OPTION]... SET1 [SET2]字符转换、替换、删除,从标准输入中替换、缩减和/或删除字符,并将结果写到标准输出

选项说明
-c, -C, --complementSET1取反
-d, --delete删除匹配SET1 的内容,并不作替换
-s, --squeeze-repeats如果匹配于SET1 的字符在输入序列中存在连续的重复,在替换时会被统一缩为一个字符的长度
-t, --truncate-set1先将SET1 的长度截为和SET2 相等
# 通过tr把反复出现的内容进行压缩,压缩后再处理
ifconfig ens33 | grep -w inet
        inet 192.168.91.101  netmask 255.255.255.0  broadcast 192.168.91.255

ifconfig ens33 | grep -w inet | tr -s " "
 inet 192.168.91.101 netmask 255.255.255.0 broadcast 192.168.91.255

ifconfig ens33 | grep -w inet | tr -s " " | cut -d " " -f 3
192.168.91.101


head -n 5 /etc/passwd > test1.txt
# 将每个数字都替换成@
tr '[0-9]' '@' < test1.txt
# 将所有小写字母替换成大写的
tr '[a-z]' '[A-Z]' < test1.txt

rm -f test1.txt

uniq命令

uniq [OPTION]... [INPUT [OUTPUT]]连续信息去重

选项说明
-c, --count按出现次数为行添加前缀
-d, --repeated只显示重复行
-i, --ignore-case忽略大小写
-s, --skip-chars=N避免比较前N个字符
-u, --unique只打印唯一的行
cat > uniq.txt << EOF
AA
aa
aa
bb
cc
cc
dd
EOF
# 去重显示
uniq uniq.txt
# 大小写不敏感去重
uniq -i uniq.txt
# 大小写不敏感去重后计数
uniq -ic uniq.txt
# 仅显示重复的内容
uniq -d uniq.txt

rm -f uniq.txt

组合信息

paste命令

paste [OPTION]... [FILE]...合并文件行内容输出到屏幕,不会改动源文件

选项说明
-d, --delimiters=LIST使用LIST中的字符替代制表分隔符
-s, --serial不使用平行的行目输出模式,而是每个文件占用一行
echo "hello" > a.txt

cat > b.txt << EOF
world
888
999
EOF

# 内容合并
paste a.txt b.txt
hello   world
        888
        999

# 自定义分隔符后合并内容
paste -d'@' a.txt b.txt
hello@world
@888
@999

# 将一个文件所有内容一行输出
paste -s b.txt
world   888     999

paste -d'@' -s b.txt
world@888@999

rm -f a.txt b.txt

xargs命令

xargs [OPTION]... COMMAND INITIAL-ARGS...命令结果传递,

xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。xargs 一般是和管道一起使用

注意:linux命令格式一般为"命令 命令选项 参数"。上一个命令的输出就是下一个命令的参数 这句话结合命令语法 应该知道输出的内容在下一个命令的位置了吧

选项说明
-0, --null各项之间由null而不是空格分隔。禁用引号和反斜杠处理
-a, --arg-file=FILE从FILE读取参数,而不是标准输入
-d, --delimiter=CHARACTER输入项用CHARACTER分隔,而不是用空格(回车)分隔。禁用引号和反斜杠处理
-E END如果END作为一行输入出现,则忽略输入的其余部分。当xargs分析到含有END这个标志的时候就停止
-e [END], --eof[=END]如果指定了END,则相当于-E END。否则,没有文件结束字符串
-L,-l, --max-lines=MAX-LINES每个命令行最多使用MAX-LINES非空输入行
-l每个命令行最多使用一个非空输入行
-n, --max-args=MAX-ARGS每个命令行最多使用MAX-ARGS参数
-P, --max-procs=MAX-PROCS一次运行最多MAX-PROCS进程
-p, --interactive运行命令前提示
--process-slot-var=VAR设置子进程中的环境变量VAR
-I R与--replace=R相同(必须指定R)
-i,--replace=[R]将初始参数中的R替换为从标准输入读取的名称。如果R未指定,则假定{}
-r, --no-run-if-empty如果没有参数(xargs的输入为空),则不执行任何命令。如果没有给出这个选项,COMMAND将至少运行一次。
-s, --max-chars=MAX-CHARS将命令限制为最多MAX-CHARS
--show-limits显示命令行长度的限制
-t, --verbose在执行命令之前打印命令
-x, --exit如果超出大小(参见-s),则退出
cat > num.txt << EOF
9
8
6
8
4
7
2
1
EOF

# 从文件中读取内容
xargs -a num.txt
9 8 6 8 4 7 2 1

# 从文件中读取内容时,指定内容结束符号
xargs -a num.txt -E 4
9 8 6 8

# 从文件中读取内容时,询问用户是否显示,y显示,其他不显示
xargs -a num.txt -p
echo 9 8 6 8 4 7 2 1 ?...y
9 8 6 8 4 7 2 1

# 从文件中读取内容时,指定每行显示几个内容
xargs -a num.txt -n4

# 从文件中读取内容时,指定每行显示几个内容,每显示一行询问一下用户
xargs -a num.txt -n4 -p
echo 9 8 6 8 ?...y
echo 4 7 2 1 ?...9 8 6 8
y
4 7 2 1

# 默认xargs以空格为分隔符,可以通过-d来自定义分隔符
echo "ab cd ef g" | xargs
ab cd ef g

echo "nameXnameXnameXname" | xargs -dX
name name name name

echo "nameXnameXnameXname" | xargs
nameXnameXnameXname

# -I 临时存储内容给一个对象,然后进行后续处理
xargs -a num.txt -I {} echo {}--bak
9--bak
8--bak
6--bak
8--bak
4--bak
7--bak
2--bak
1--bak

# -I的综合运用,转移文件并改名
touch a.txt b.txt c.txt

ls *.txt
a.txt  b.txt  c.txt  num.txt
ls *.txt | xargs -I {} cp {} {}.bak

rm -f *.txt*

# 给函数传参有些不一样,需要特别注意
cat > test.sh << "EOF"
#!/bin/bash
my_function() {
    echo "参数1: $1, 参数2: $2"
}
# # 导出函数以便在子进程中调用
export -f my_function
# 使用xargs将参数传递给函数,-n 指定命令每次执行时取几个参数(即xargs每次传递几个参数给函数);默认是通过空格分割字符串产生参数,可以通过-d指定分隔符;bash -c用于执行函数调用,$0$1分别代表第一个和第二个参数
echo "aa bb cc dd" | xargs -n 2 bash -c 'my_function "$0" "$1"'
EOF

/bin/bash test.sh
参数1: aa, 参数2: bb
参数1: cc, 参数2: dd

编程简介

编程语言解读

基础知识

image.png

外在关系

  • 业务数据:用户访问业务时候,产生的信息内容
  • 数据结构:静态的描述了数据元素之间的关系
  • 算法:解决各种实际问题的方法和思路
  • 数据结构 + 算法 = 程序

内在关系

  • 算法其实就是数据的表示和处理,而数据的处理受到数据的各种存储形式的约束,所以算法的效率和样式受到数据结构的严重约束
  • 数据结构存储下来的数据是为算法服务的,而算法存在的意义就是为了数据结构中的内容而存在的

所以说:数据结构和算法,是你中有我,我中有你的合二为一的关系

理解

我们一般说的数据不是干巴巴的字母数字,而是在某种场景下来对这些数据的含义进行分析等操作,数据一旦有了场景意义: 在不同场景的声音和含义。纯粹的数据加上场景,他们就有了新的名称:ADT

image.png

举例一: 数据类型-人 多个人,陈浩南、山鸡、大天二、大飞... 数据运算-关系 彼此间的团队联系 抽象数据类型=类型+运算=人+关系 洪兴

举例二: 游戏按钮“空格”:人物A(数据类型) + 打子弹(动作)

编程语言

编程

所谓的编程,就是将我们的功能思路用代码的方式实现出来。一般情况下,这些实现的思路主要有两种方式:

面向过程编程:将任务功能拆分成多个子部分,然后按照顺序依次执行下去。问题规模小,可以步骤化,按部就班处理。比较符合我们自己做一件事情的思路

面向对象编程:将任务功能拆分成多个子部分,然后按照顺序依次找不同的人执行下去。问题规模大,复杂系统。比较符合我们的领导指挥一个部门的人做事情的思路

image.png

编程语言

所谓编程语言,指的是以哪种风格代码方式把程序编写出来。每一种编程风格就是一系列的编程语言。

参考资料: www.tiobe.com/tiobe-index… hellogithub.com/report/tiob…

image.png

编程语言逻辑

语言分类

低级编程语言:

机器:

  • 二进制的0和1的序列,称为机器指令。
  • 一般人看不懂

汇编:

  • 用一些助记符号替代机器指令,称为汇编语言。
  • 一般人看不懂,但是能够有感觉

高级编程语言:

编译:

  • 借助于专属编译器将一些高级语言编译成机器代码文件,然后再交给程序去执行。
  • 如:C,C++等

解释:

  • 将高级语言的代码逐行加载到解释器环境,逐行解释为机器代码,然后再交给程序去执行。
  • 如:shell,python,php,JavaScript等

image.png

编程逻辑

编程语言的目的是通过风格化的编程思路将代码写出来后,实现项目功能的。为了实现功能,我们在代码层面通过一些代码逻辑来实现:

  • 顺序执行 - 程序按从上到下顺序执行
  • 选择执行 - 程序执行过程中,根据条件选择不同的顺序执行
  • 循环执行 - 程序执行过程中,根据条件重复执行代码

image.png

shell基础

shell简介

运维

所谓的运维,其实就是公司的内部项目当中的一个技术岗位而已,它主要做的是项目的维护性工作。它所涉及的内容范围非常多

image.png

以xx项目为例:

  • 规划:我们需要多少资源来支持项目的运行
  • 管理:项目运行过程中的所有内容都管理起来
  • 流程规范:所有操作都形成制度,提高工作效率
  • 平台:大幅度提高工作效率
  • 监控:实时查看项目运行状态指标
  • 告警:状态指标异常,告知工作人员处理
  • 安全:网站运营安全措施
  • 优化:保证用户访问网站体验很好
  • 考核:权责分配,保证利益

自动化运维:就是将图里面所有的工作都使用自动化的方式来实现。实现自动化的方式很多,常见的方式:工具和脚本。工作中常见的脚本有哪些呢?shell脚本和其他开发语言脚本

shell语言

在计算机科学中,Shell就是一个命令解释器。shell是位于操作系统和应用程序之间,是他们二者最主要的接口,shell负责把应用程序的输入命令信息解释给操作系统,将操作系统指令处理后的结果解释给应用程序

image.png

一句话,shell就是在操作系统和应用程序之间的一个命令翻译工具

shell实践

shell分类

在不同的操作系统上,shell的表现样式是不一样的,按照我的角度,它主要分为两类

  • 图形界面shell,图形界面shell就是我们常说的桌面
  • 命令行式shell,windows系统:cmd.exe 命令提示字符,linux系统:sh / csh / ksh / bash(默认) / ...

image.png

# 查看当前系统的shell类型
echo $SHELL
/bin/bash

# 查看当前系统环境支持的shell
cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash

# 更改默认的shell,chsh <用户名> -s <新shell>
chsh zhang -s /bin/sh
Changing shell for zhang.
Shell changed.

su zhang

echo $SHELL
/bin/sh

exit

chsh zhang -s /bin/bash
Changing shell for zhang.
Shell changed.

su zhang

echo $SHELL
/bin/bash

exit

# 安装shell
yum list | grep zsh
yum install -y zsh

cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/zsh

shell实践

命令行实践方式

手工敲击键盘,在shell的命令行输入命令,按Enter后,执行通过键盘输入的命令,然后shell返回并显示命令执行的结果。重点:逐行输入命令、逐行进行确认执行

whoami
pwd
date +"%F %T"

文件实现方式

就是说我们把手工执行的命令a,写到一个脚本文件b中,然后通过执行脚本b,达到执行命令a的效果。重点:按照文件内容的顺序执行

cat > test << "EOF"
whoami
pwd
date +"%F %T"
EOF

/bin/bash test

rm -f test

shell脚本实践

脚本基础

当可执行的Linux命令或语句不在命令行状态下执行,而是通过一个文件执行时,我们称文件为shell脚本

应用场景

重复化、复杂化的工作,通过把工作的命令写成脚本,以后仅仅需要执行脚本就能完成这些工作。自动化分析处理、自动化备份、自动化批量部署安装、等等...

脚本创建

创建脚本的常见编辑器是vi/vim,shell脚本的命名简单来说就是要有意义,方便我们通过脚本名,来知道这个文件是干什么用的

脚本注释

单行注释:除了首行的#不是注释外,其他所有行内容,只要首个字符是#,那么就表示该行是注释

多行注释:多行注释有两种方法,:<<! ... ! 和 :<<字符 ... 字符

脚本实践

cat > get_netinfo.sh << "EOF"
#!/bin/bash
:<<!
功能:获取当前主机的网卡设备信息
作者:test
版本:V0.1
联系:www.test.com
!

# 获取ip地址信息
ifconfig ens33 | grep -w inet | awk '{print $2}' | xargs echo "IP: "

# 获取掩码地址信息
ifconfig ens33 | grep -w inet | awk '{print $4}' | xargs echo "NetMask: "

# 获取广播地址信息
ifconfig ens33 | grep -w inet | awk '{print $6}' | xargs echo "Broadcast: "

# 获取MAC地址信息
ifconfig ens33 | grep ether | awk '{print $2}' |xargs echo "MAC Address: "
EOF

# 执行脚本
/bin/bash get_netinfo.sh
IP:  192.168.91.101
NetMask:  255.255.255.0
Broadcast:  192.168.91.255
MAC Address:  00:0c:29:2c:2e:d5

脚本执行

脚本执行方法

  • 方法1:bash /path/to/script-name 或 /bin/bash /path/to/script-name(强烈推荐使用)
  • 方法2:/path/to/script-name 或 ./script-name(当前路径下执行脚本)
  • 方法3:source script-name 或 . script-name
  • 方法1变种:cat /path/to/script-name | bash

脚本执行说明

  • 方法1,脚本文件本身没有可执行权限或者脚本首行没有命令解释器时使用的方法,我们推荐用bash执行。使用频率:☆☆☆☆☆
  • 方法2,脚本文件具有可执行权限时使用,使用频率:☆☆☆☆
  • 方法3,使用source或者.点号,加载shell脚本文件内容,使shell脚本内容环境和当前用户环境一致。使用频率:☆☆☆,使用场景:环境一致性
# 执行示例
# 方法1
/bin/bash get_netinfo.sh

# 方法2
# 权限不够
./get_netinfo.sh
-bash: ./get_netinfo.sh: Permission denied

chmod +x get_netinfo.sh
./get_netinfo.sh

# 方法3
chmod -x get_netinfo.sh
source get_netinfo.sh
. get_netinfo.sh

# 方法1变种
cat get_netinfo.sh | bash
bash < get_netinfo.sh

脚本调试

我们在编写脚本的时候,往往会受到各种因素的限制,导致脚本功能非常大或者内容有误,如果直接执行脚本的时候,因为脚本内容有误,导致脚本执行失败。所以我们需要在脚本执行的时候,保证脚本没问题,我们可以借助于多种脚本调试方式来验证脚本

调试方式

  1. -n 检查脚本中的语法错误
  2. -v 先显示脚本所有内容,然后执行脚本,结果输出,如果执行遇到错误,将错误输出
  3. -x 将执行的每一条命令和执行结果都打印出来

简单实践

# 准备备份文件
cp get_netinfo.sh get_netinfo-error.sh
# 删除文件的最后一个字符
sed -i '$ s/.$//' get_netinfo-error.sh

# 错误脚本执行效果
/bin/bash get_netinfo-error.sh
IP:  192.168.91.101
NetMask:  255.255.255.0
Broadcast:  192.168.91.255
# 寻找匹配的 `"' 时遇到了非预期的文件结束符
get_netinfo-error.sh: line 19: unexpected EOF while looking for matching `"'
# 语法错误: 非预期的文件结尾
get_netinfo-error.sh: line 20: syntax error: unexpected end of file

# 检查语法调试
/bin/bash -v get_netinfo-error.sh

# 脚本跟踪
/bin/bash -x get_netinfo-error.sh

# 成功演示
/bin/bash -x get_netinfo.sh

rm -f get_netinfo-error.sh get_netinfo.sh

脚本开发规范

开发规范

  1. 脚本命名要有意义,文件后缀是.sh
  2. 脚本文件首行是而且必须是脚本解释器 #!/bin/bash
  3. 脚本文件解释器后面要有脚本的基本信息等内容。脚本文件中尽量不用中文注释;尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰;常见的注释信息:脚本名称、脚本功能描述、脚本版本、脚本作者、联系方式等
  4. 脚本文件常见执行方式:bash 脚本名
  5. 脚本内容执行:从上到下,依次执行
  6. 代码书写优秀习惯
    • 成对的内容一次性写出来,防止遗漏。如:()、{}、[]、''、``、""
    • []中括号两端要有空格,书写时即可留出空格[ ],然后再退格书写内容
    • 流程控制语句一次性书写完,再添加内容
  7. 通过缩进让代码易读(即该有空格的地方就要有空格)

规范解析

shell脚本开发规范重点:2-4-5 shell脚本开发小技巧:3-6-7

其他技巧

  1. 尽可能记忆更多的命令
  2. 掌握脚本的标准的格式
  3. 多看、多模仿、多思考