认识Shell环境
- Shell是工作在Linux内核与用户之间的==解释程序==,相当于操作系统的“外壳”,是向Linux内核传达用户指令的“翻译官”,通常指BASH(/bin/bash),常见的还有zsh、tcsh,用于和操作系统内核交互,操作系统内核控制底层硬件
- windows下的Shell为cmd.exe
- 查看当前的Shell的命令为:echo $SHELL
- 可以手动选择Shell环境,直接在Shell中输入shell如:tcsh,相当于新建了一个子环境(父–子进程)
- shell操作有交互式和非交互式两种
交互式 | 非交互式 |
---|---|
人工干预、智能化程度低 | 需提前设计、智能化难度大 |
逐条解释执行、效率低 | 批量执行、效率高 |
方便在后台静悄悄地运行 |
shell脚本
- shell脚本指提前写好的可执行代码,用来完成特定任务的文件,特点为:顺序、批处理,解释型程序
- shell脚本编写步骤:
1. 理清任务 | 自然语言:步骤拆分、顺序化整理 |
---|---|
2. 编写可执行语句 | 脚本语言:各步骤如何实现 |
3. 完善脚本 | 界面友好/结构规范/代码优化 |
-
shell脚本一般以.sh结尾,==第一行 #!/bin/bash== 用来申明Shell环境
-
shell脚本的免交互及输出处理
- 免交互:通过选项 ==–stdin== 可以从标准输入读取字串;也可以从键盘或由另一个命令给出
1
2
3// 修改root密码
passwd --stdin root //从键盘读入
echo 1234567 | passwd --stdin root //由echo命令给出-
输出处理:
- 忽略无关输出:黑洞设备/dev/null
1
2相当于只能写入、不能读出的单向文件;存放到其中的数据都会丢失,用法:可执行语句 &> /dev/null,如:
echo 1234567 | passwd --stdin root &> /dev/null- 记录错误输出:根据需要,将出错信息保存到指定文件
1
2是针对后台脚本的有效排错手段,适用于不便交互但又需要查看报错的情况,用法:可执行语句 2>/路径/文件,如:
useradd root 2>/tmp/err.log
-
命令的组合运用
- 顺序分割–==使用分号==,格式:命令1;命令2;命令3…,依次执行,只有先后,没有逻辑关系
- 逻辑“与”分割–==使用&&==,格式:命令1 && 命令2 && 命令3…,逻辑关系为“而且”(and),期望所有命令都能执行成功,一旦出现失败,后续命令不再执行
- 逻辑“或”分割–==使用||==,格式:命令1 || 命令2 || 命令3…,逻辑关系为“或者”(or),任何一条成功都符合期望,只在前面的命令失败时,后续命令才执行
- 管道–==使用|==,格式:命令1|命令2,后续命令要能正确处理传来的文本,否则无意义,如:
1
find /etc -type f | wc -l //计算/etc下文件数量,将结果交给wc统计行数
-
shell脚本的运行方式
- 作为指定shell解释程序的参数
1
2-sh 代码文件路径 === bash 代码文件路径
-. 代码文件路径 === source 代码文件路径- 作为可独立运行的脚本程序
1
2为shell代码文件添加x权限,指定脚本路径即可运行.如:
chmod +x /root/first.sh;/root/first.sh
标准输入输出和重定向
Unix/Linux基本思想:普通文件、目录、鼠标、键盘…都是以文件形式存在;要访问硬件设备,必须找对应的设备文件
I/O交互设备
类型 | 设备文件 | 文件描述号 | 默认设备 | 备注 |
---|---|---|---|---|
标准输入 | /dev/stdin | 0 | 键盘 | 从此设备接收用户输入的数据 |
标准输出 | /dev/stdout | 1 | 显示器 | 通过此设备向用户报告正常的命令输出结果 |
标准错误输出 | /dev/stderr | 2 | 显示器 | 通过此设备报告执行中的错误信息 |
重定向:重新指定命令执行是I/O设备的方向
根据I/O方向和类型区分
类型 | 操作符 | 用途 | 举例 |
---|---|---|---|
重定向输入 | < | 将文本输入来源由键盘改为指定的文件 | mial -s ‘A Test Mail’ root@localhost < /root/mail.txt |
重定向输出 | > | 将命令行的正常输出保存到文件,而非显示器 | echo ‘nameserver 8.8.8.8’ > /etc/resolv.conf |
重定向输出 | >> | 与“>”类似,但操作是追加而不是覆盖 | |
重定向错误 | 2> | 将命令行的错误输出保存到文件,而非显示器 | |
重定向错误 | 2>> | 与“2>”类似,但操作是追加而不是覆盖 | |
混合重定向 | &> | 相当于“>”和“2>” |
脚本逻辑
变量值及范围控制
- 引号在赋值中的应用
- 双引号
1 | - 在双引号内允许$扩展,可调用其他变量的值 |
- 单引号
1 | - 所有字符均视为该字符本身(无特殊含义) |
- read读入变量值
1 | * 基本格式 |
- 变量的作用范围
- 局部变量:只在定义此变量的shell环境有效;自定义变量默认都是局部变量
- 全局变量:在当前shell及所有子shell环境下有效;子shell中若赋值同名变量,与父shell中变量无关
发布全局变量
1 | export 局部变量名[=变量值] .. .. |
数值运算及处理
bash内置机制仅支持整数运算
基本运算类别
加减乘除求模 ±*/%
1 | 1. expr工具:==expr 数值1 运算符 数值2== |
自增表达式
1 | 1. 加减乘除求模自增,如:i+=2 或 i=i+2 或 $[i+=2] |
let命令操作变量
1 | 操作变量值运算,并保存新结果,适用于不需要输出的情况,如:let x++ |
使用随机整数
- 环境变量RANDOM:随机生成0~32767之间的一个整数
- 扩大随机数范围:多个随机数相乘
- 缩小随机数范围:取余数,如:$[RANDOM%1000]取0~999的整数
整数序列
使用seq命令
1 | 使用格式:默认分隔符为\n |
bc计算器
bc运算器支持高精度的数值运算,输入bc进入交互式预算界面,quit退出,设置scale=n可约束小数位,也支持小数值的比较,大多数Linux系统已内置
使用举例:
- echo “scale=4;123.4*2.5” | bc
- echo “B” | bc
Shell变量
- 变量:以固定名称存放的可能会变化的值
- 定义/赋值变量
1 | 变量名=变量值 |
- 查看/引用变量:$变量名 或 ${变量名}
- 取消变量:退出shell变量自动失效 或 ==unset 变量名== 方式手动取消
变量的分类
- 存储类型:shell不作为高级编程语言,对存储类型的要求比较松散
- 使用类型
类型 | 说明 | 备注 |
---|---|---|
环境变量 | 变量名通常大写,由系统维护,用来设置工作环境,其中只有个别变量用户可以直接修改 | 配置文件:/etc/profile,~/.bash_profile |
位置变量 | 由bash内置,用来存储在执行脚本时提供的命令行参数 | {n}== |
预定义变量 | 由bash内置,一类有特殊用途的变量,可以直接调用,但不能直接赋值或修改 | 参见下表与定义变量定义 |
自定义变量 | 用户自主设置、修改及使用 |
env-列出所有环境变量;
set-列出所有变量
常见环境变量:PWD,PATH,USER,LOGNAME,UID,SHELL,HOME,PS1,PS2…
变量名 | 含义 | 备注 |
---|---|---|
$0 | 当前所在进程或脚本名 | |
$$ | 当前运行进程PID | |
$? | 命令执行后的状态值,0-正常 1或其他-异常 | |
$# | 已加载位置变量个数 | 如传入参数个数判断: if[ $# -ne 2 ] |
$* | 所有位置变量的值 |
条件测试
返回状态值:$?
专用测试工具test
1 | 格式: |
文件状态检测:test的参数则为文件或目录
测试选项 | 含义 | 举例 |
---|---|---|
-e | 检测对象是否存在Exist | [ -e /etc/test ];echo $? |
-d | 检测对象是否为目录Directory | |
-f | 检测对象是否为文件File | |
-r | 检测对象是否有可读权限Read | |
-w | 检测对象是否有可写权限Write | |
-x | 检测对象是否有可执行权限eXcute |
整数值比较
测试选项 | 含义 | 举例 |
---|---|---|
-eq | 等于Equal | [ $(who|wc -l) -eq 10 ]//判断登陆用户数等于10 |
-ne | 不等于Not Equal | |
-ge | 大于或等于 Greater or Equal | |
-le | 小于或等于 Lesser or Equal | |
-gt | 大于 Greater Than | |
-lt | 小于 Lesser Than |
组合多个条件
1 | 格式: |
字符串比较
1 | 格式: |
测试选项 | 含义 | 举例/说明 |
---|---|---|
= | 两字符串相同 | [ $USER = ‘root’ ] && echo $USER |
!= | 两字符串不同 | |
-z | 字符串值为空 | Zero |
-n | 字符串值不为空 | Not zero |
将条件取反
1 | 格式: |
字符串处理
截取字符串
- 使用expr命令,==expr substr $var1 起始位置 截取长度==
- 使用cut命令
1 | * 命令输出|cut -c 起始位置-结束位置,echo $var1|cut -c 5-6 |
- 使用${}
1 | 格式: |
字符串替换
使用${}
1 | 格式: |
tr单字替换工具
1 | 格式: |
路径分割
- dirname “路径字符串”:取目录位置
- basename “路径字符串”:取基本名称
使用随机字符串
- 随机数变量:RANDOM
- 特殊设备文件:/dev/urandom
- UUID生成命令:uuidgen
随机信息的转换:md5sum
依据输入文本计算出256位(32字符)的MD5编码值
- echo $RANDOM |md5sum
- head -1 /dev/urandom|md5sum
命令替换
- 反撇号`
- 适用场景:在命令行潜入另一个命令的输出结果;将命令的输出保存到指定变量
- 优先执行反撇号内的命令,并将执行结果作为输入
- 举例:rpm -qf
which tr
- $(可执行命令),优点为==可嵌套使用==,举例:rpm -qf $(which tr)
流程控制
if语句
1 | //单分支 |
说明:如果then要跟着条件测试写在一行,则需在then前加封号,如:
1 | if 条件测试 ;then |
for循环
1 | for 变量名 in 值列表 |
while循环
1 | while 条件测试 |
case分支
1 | case 变量值 in |
中断及退出控制
类型 | 含义 |
---|---|
break | 跳出当前所在循环体,执行循环体后的语句块 |
continue | 跳过循环体内余下的语句,重新判断条件以便执行下一次循环 |
exit | 退出脚本,可以指定返回的状态值,默认返回0 |
编写服务脚本
shell函数
type 名称 //查看名称对应类型
1 | 基本格式: |
系统服务管理
- 查看服务列表、自启状态
-
- chkconfig --list [服务名]
-
- chkconfig 服务名 on/off
- 启动/停止/重启服务
-
- service 服务名 start/stop/restart
-
- /etc/init.d/服务名 start/stop/restart
- ntsysv:可视化设置自启动状态
- shell脚本直接交给service控制,则将脚本或者脚本的快捷方式放到/etc/init.d/下即可
- shell脚本交给chkconfig工具管理,需设置适用级别、启动/停止顺序、服务说明
- 添加设置
1 | #!/bin/bash |
- 添加服务:chkconfig --add 服务名
文件的排序集统计
ls列表排序
- -S:按文档大小降序排列
- -t:按文档的修改时间降序排列
- -r:反序排列
uniq去重工具
1 | 用法1:uniq 文件 |
缺点:==未排序的文本会出现重复现象==,需配合其他方式先排序,再去重
方法:sort 文件名|uniq -c
sort工具
1 | 用法1:sort 文件 |
文本处理的的特殊应用
tac、rev反序输出
- tac:以行为单位反序,与cat命令效果相反
- rev: 以字符为单位反序,与echo命令效果相反
tee整合重定向
举例:uname -r|tee un.txt
unix2dos与dos2unix转换
windows和linux系统文本格式转换
1 | 安装:yum -y install unix2dos dos2unix |
xargs多参数处理
背景:ls、mv、rm、cp等命令给出的参数长度不能超过2.5M,基于*匹配、find等方式处理大量文件时容易出错
多参数的分散处理
- 利用find… … -exec… … 查找处理 //仅适用于处理文件或目录参数,如:find / -exec ls -lh {} ;
- xargs工具:根据给定的参数组(以行为单位)分次执行目标命令行
1 | 用法1:提供参数的命令 | xargs 目标命令,如:find /|args ls -lh |
expect预期交互控制
基于TCL编写的自动化交互式程序,可以用在Shell脚本中,为FTP、SSH等交互过程自动输送预先准备的文本或指令,而无需人工干预,出发的依据是预期会出现的特征提示文本
- 安装:yum -y install expect
- 手动交互
- 自动交互
1 | cat mike-ftp.sh |
- 调整执行环境:添加Sha-Bang环境声明
1 | cat mike-ftp.sh |
- SSH登陆免交互举例
1 | #!/usr/bin/expect |
应用技巧
正则表达式
使用“一串符号”来描述有共同属性的数据
egrep测试工具
- 用法1:egrep [选项] ‘正则表达式’ 文件
- 用法2:前置命令|egrep [选项] ‘正则表达式’
选项
1 | -i:忽略大小写 |
基本元字符
类型 | 含义 | 示例 | 说明 |
---|---|---|---|
^ | 匹配行首 | ^abc 或 ^# | 以abc开头的行 或 以#开头的行(比如注释行) |
$ | 匹配行尾 | abc$ 或 ^$ | 以abc结尾的行 或 空行 |
. | 单个字符 | . | 除换行符\n以外的任意单个字符 |
+ | 最少匹配一次 | a+ 或 (abc)+ | 一个或多个连续的a 或 一个或多个连续的abc |
? | 最多匹配一次 | a? 或 (abc)? | 0个或1个a 或 0或1个abc |
* | 匹配任意次数 | a* 或 (abc)* 或 .* | 0个或多个连续的a 或 0个或多个连续的abc 或 任意长度的任意字符串 |
{n} | 匹配n次 | (ab){3} | 匹配ababab |
{n,m} | 匹配n~m次 | (ab){1,3} | 匹配ab、abab、ababab |
{n,} | 匹配至少n次 | (ab){2,} | 匹配2个及以上连续的ab |
[] | 匹配范围内的单个字符 | [a-z] | 匹配任意小写字母 |
[]内加^ | 可取反 | [^a-z] | 匹配任意非小写字母 |
() | 组合为整体 | (ab) | 连续的ab |
或者 | root|bin | 匹配root、bin | |
\b | 单词边界 | \broot\b | 匹配root,不匹配keroot、rooty、brooty等字符串 |
< | 单词的开头 | <th | 匹配以th开头的单词 |
> | 单词的结尾 | th> | 匹配以th结尾的单词 |
awk文本过滤
awk:模式扫描及处理语言,创始人Aho、Weinberger、Kernighan,基于模式匹配检查输入的文本,逐行处理并print结果,目前最常用的实际是GNU版本的gawk
- 用法1:前置命令|awk [选项] ‘[条件]{编辑指令}’
- 用法2:awk [选项] ‘[条件]{编辑指令}’ 文件,如:awk -F “:” ‘{print $1,$2} /etc/passwd’
条件的表现形式
- 正则表达式,/正则表达式/ 🔥 ~匹配、!~不匹配,如:awk -F: ‘/^ro/{print}’ /etc/passwd
- 数值/字符串比较
- 逻辑比较
- 运算符
选项
1 | -F:指定分隔符,可省略,默认空格或Tab位,如:awk -F: '$1==ENVIRON["USER"]{print $3}' /etc/passwd //输出当前用户的UID信息 |
awk内置变量
变量 | 用途 |
---|---|
FS | 保存或设置字段分隔符,如 FS=“:” |
$n | 指定分隔符的第n个字段,如$1、$3分别表示第1、第3列 |
$0 | 当前读入的整行文本内容 |
NF | 记录当前处理的字段个数(列数) |
NR | 记录当前已读入行的数量(行数) |
FNR | 保存当前处理行在元文本内的序号(行号) |
FILENAME | 当前处理的文件名 |
ENVIRON | 调用Shell环境变量,格式:ENVIRON[“变量名”] |
awk处理的时机:可单独使用,也可以同时一起使用,具体如下:
- 行前处理,BEGIN{}:读入第一行文本之前执行,一般用来初始化操作
- 逐行处理,{}:逐行读入文本执行相应的处理,是最常见的编辑指令块
- 行后处理,END{}:处理完最后一行文本之后执行,一般用来输出处理结果
1 | awk 'BEGIN{print NR}END{print NR}' m.txt |
awk的流程控制
- if分支,如:if(条件){编辑指令1}else if(条件){编辑指令12}…else{编辑指令n}
1 | awk -F: 'BEGIN{i=0;j=0}{if($3<500){i++}else{j++}}END{print i,j}' /etc/passwd |
- while循环,如:while(条件){编辑指令}
- do while循环,如:do {编辑指令}while(条件)
- for循环,如:for(初值;条件;步长){编辑指令}
关键字 | 含义 |
---|---|
break | 结束当前的循环体 |
continue | 中止本次循环,转入下一次循环 |
next | 跳过当前行,读入下一行文本开始处理 |
exit | 结束文本读入,转入END{}执行,没有则直接退出 |
sed文本流处理
sed:Stream EDitor,流式编辑器,基于模式匹配过滤及修改文本,逐行处理并将结果输出到屏幕,可实现文本过滤/删除/替换/复制/剪切,以及导入/导出等各种操作
- 用法1:前置命令|sed [选项] ‘编辑指令’,如:se -n /etc/inittab |sed -n ‘4,7p’
- 用法2:sed [选项] ‘编辑指令’ 文件
1 | 编辑指令由“[定址符]处理动作”组成,[定址符]的格式为“[地址1,[地址2]]” |
选项:
1 | -n:屏蔽默认输出 |
处理动作:替换操作的分隔符“/”可用其他字符,如#、&等以便于修改文件路径
操作符 | 用途 | 指令示例 |
---|---|---|
p | 打印行 | 2,4p 输出2,3,4行 🔥 2p;4p输出第2行、4行 |
d | 删除行 | 2,4d 删除第2,3,4行 |
s | 字符串替换 | s/old/new/ 将每行第1个old替换为new |
s/old/new/3 将每行第3个old替换为new | ||
s/old/new/g 将所有的old替换为new | ||
4,+10p | 加10行 | 输出第4行及其后10行内容 |
n | 表示下一行 | p:n输出奇数行 |
n:p输出偶数行 | ||
$= | 输出文件的行数 | sed -n ‘$=’ a.txxt |
i | 行前插入文本 | 2iYY 在第2行前添加文本行YY |
4,7iYY 在第4-7行每一行钱添加文本行YY | ||
a | 行后插入文本 | 2aYY 在第2行后插入YY |
c | 替换当前行 | 2cYY 将第2行内容修改为YY |
r | 读取文件,结合-i选项才会存入,否则只输出 | 3r b.txt 在第3行下发插入文本b.txt |
w | 保存到文件,以覆盖方式 | 3w b.txt 将第3行保存到b.txt |
sed复制剪切
- 模式空间:存放当前处理的行,将处理结果输出;若当前行不符合处理条件则原样输出;处理完当前行再读入下一行来处理
- 保存空间:作用类似剪贴板,默认存放一个空行\n
选项:
1 | -H:模式空间 追加 到 保持空间 ,即复制 |
实战脚本
基本知识
- 查看用户信息:id gsuis