前序:
Shell相当于操作系统的最外层的壳,能够与用户直接对话把用户输入的给到操作系统去处理,然后输出到屏幕给用户看到效果
流程:
通过shell壳中的bash解释器解析用户的输入——>然后给到操作系统的内核,再与硬件做交互
什么是shell脚本
就是多个linux命令放在一个脚本文件中,然后执行我们的文件读取其中的代码——>linux命令+循环控制语句(将linux命令一次性执行完)——>非交互式方式
编写第一个shell脚本
Shebang指的是文本文件中第一行前两个字符 #!
#! 后面的作为解释器的指令,比如下面就是py的
echo+$+大写变量名=默认的Shell,所以如果你用py的话肯定会报错
执行脚本
我们可以在外面自己去指定py或者其他的解释器去执行里面的脚本
注释
目录
1.bash xxx.sh——>无视权限
2. ./xxx.sh——>需要权限
3.source xxx.sh
4.bash < xxx.sh
浅谈Shell脚本
弱类型语言:在定义数据类型的时候,不需要主动声明修改类型
——>Shell语言定义的变量默认是字符串类型
cat /etc/shells
Bash的特性
除了作为命令处理器之外,还一个很牛逼的点在于bash支持通配符,管道符以及命令的判断
1.历史命令特性
查看历史命令数
history命令
-c :清除历史
-r : 恢复历史
!!:执行上次的命令
变量
当更新会话,或者宕机变量就会丢失,因为它是存储到内存当中的
比如外面name="Fairy同学"之后,如果在echo $name之前刷新了会话,那么就会丢失数据,因为会话已经发生改变了
变量名规则
变量是区分大小写的
变量的作用域(基于盒子的嵌套)
我们可以通过pstree命令去查看进程树
我们能够远程连接服务也是因为sshd的原因
父子shell的理念
ptree:得到进程树
环境变量:全局变量,针对当前Shell以及任意子线程
局部变量:针对Shell函数或者Shell脚本中定义
1.当我们执行sh再执行ptree
2.当我们先执行bash,然后再执行sh最后再执行ptree
例子:
当会话发生改变,内存中的变量会丢失
验证上一次是否成功
echo $?
判断上一次的命令是否成功,成功返回0,失败返回0-255
Shell面试题01
1.单引号不识别语义语法,双引号识别特殊符号语义语法
2.每次调用bash/sh解释器执行脚本时候,都会开启一个子shell,因此不保留当前的shell变量,通过pstree命令检查进程树——>也就是说父环境定义一个变量,shell脚本修改并不会将父环境的变量修改掉
我们可以利用source或者.符号在当前shell环境加载脚本保留变量
通过set寻找父子Shell环境变量的加载
1.环境变量一般指的是export内置命令导出的变量,一般用于定义shell的运行环境
2.shell可以通过环境变量确定登录的用户名,PATH路径,文件系统等
3.环境变量再命令行临时创建的话,当用户登出变量就会丢失
查看用户个人配置文件
vim ~/.bash_profile
不难发现 PATH被export输出生效,我们再里面加一行export name=Fairy
- # .bash_profile
-
- # Get the aliases and functions
- if [ -f ~/.bashrc ]; then
- . ~/.bashrc
- fi
-
- # User specific environment and startup programs
-
- PATH=$PATH:$HOME/.local/bin:$HOME/bin
-
- export PATH
不难发现,用户在登录之后会去加载用户个人配置文件的(~/.bash_profile)
然后我们尝试修改全局配置文件/etc/profile
在sh子shell中执行sh导致子之间也出现不同作用域
set:输出所有变量,包括全局变量,局部变量
env:只显示全局变量
env |wc -l
export
export|grep PATH
只读变量:readonly
Linux export命令 | 菜鸟教程 (runoob.com)
export |awk -F '[ :=]' '{print $3}'
特殊变量学习
1.$*是一次性的 ;2.$@是每个参数算一个命令
- # !/bin/bash
- echo "print each parm from \*\$*\""
- for var in "$*"
- do
- echo "$var"
- done
- echo "print each param from \"\$@\""
- for var in "$@"
- do
- echo "$var"
- done
解析:进行判断$#:参数不为两个就会输出错误,否则输出提示正确信息
创建一个test.sh然后bash xx.sh执行,echo $?——>得到上一次是否成功
批量修改文件
1.如何将变量对应的值进行去除
${变量/pattern//string} #将pattern中的string去掉
2.将文件的名称进行修改
我们首先先用一个变量进行挂载比如$f=test1.sh——>mv $f `echo ${f//.sh}`:将test1.sh后面的.sh去除
3.批量修改文件名称
for f in `ls test*`;do mv $f `echo ${f//t/}`;done
变量的处理
根据${}中的变量是否为空,——>进行后面的d
result=${change:=apple}
当变量不存在我们主动抛出错误信息
echo ${name:?该变量为空}
数据备份,删除过期的数据脚本
1.删除7天以上的过期数据
find 需要搜索的目录 -name 搜索的文件名字 -type 文件类型 -mtime +7|xargs rm -f
bug:当你指定文件名字的时候去删除可能出现文件不存在的情况
解决:我们将需要删除的文件挂载,然后利用变量处理${parameter:-word}——>变量为空xxx替换
find ${dir_path:=/root/TestData/} -name 'test*' -type f|xargs rm -f
Shell内置外置变量
内置命令:在系统启动时就加载到内存中,执行效率更加高,但是占用资源较多,比如cd
外置命令:系统需要从硬盘中读取程序文件,再从内存中加载,所以执行速度较慢
内置命令和系统一体的,是shell的一部分,不需要单独去读取某个文件,系统启动后就执行在内存中了;
Shell脚本完成开发
简而言之就是将复杂命令的执行过程通过逻辑代码——>组成一个脚本文件,最后执行该文件即可
- #! /bin/bash
-
- #这是用于显示日期,和谁登录过的脚本
- echo "The time and date are:"
-
- date
-
- echo ""
- echo "Let's see who's logged into the system:"
-
- who
-
- #! /bin/bash
- #显示你的个人用户信息
-
- echo "User info for username: ${USER}"
-
- echo "User UID is : $UID"
-
- echo "User Home is :" $HOME
Shell如何进行数值计算
shell开发接收用户输入数字,并根据运算符进行判断得到最终结果的计算脚本
- #! /bin/bash
-
- # 脚本开发
- #函数体
- print_usage(){
- printf "Please enter an Integer\n"
- # 给脚本的执行结果赋予一个状态码,退出码,默认是0 #?
- exit 1
- }
-
- #接收用户输入的命令,-p参数后面写,给用户看到提示信息
- #read -p "提示信息" 接收用户的变量
- read -p "Please input your number: " firstnum
-
- #进行对用户输入进行if判断,-n参数是if的语句,对字符串进行判断,如果为空就不成立
- #sed:字符串进行替换,将数字进行替换,留下字母
- if [ -n "`echo $firstnum|sed 's/[0-9]//g]' `" ]
- then
- print_usage
- fi
-
- # 此时输入运算符
- read -p "Please input your operator:" operator
-
- # 对运算符进行判断
- if [ "${operator}" !="+" ]&&[ "${operator}" !="-" ]&&[ "${operator}" !="*" ]&&[ "${operator}" !="/" ]
- then
- echo "只允许输入 +-*/"
- exit 2
- fi
-
- #对第二个变量进行接收
- read -p "Please input second number:" secondnum
- if [ -n "`echo $secondnum|sed 's/[0-9]//g'`"]
- then
- print_usage
- fi
-
- #执行该函数
- #print_usage
-
- # 最后进行数值计算,利用双小括号
- echo "${firstnum}${operator}${secondnum}结果是: $((${firstnum}${operator}${secondnum}))"
Sed命令
能够通过匹配对文件进行操作(类似正则表达式那种)
编辑文件或标准输入导出的文本拷贝。vi中的正则表达式命令在sed中大多可以通用
shell脚本之sed详解 (sed命令 , sed -e , sed s/ new / old / ... ) - Red_Point - 博客园 (cnblogs.com)
sed 's/[0-9]//g'
删除 0-9 的字符,即删除所有数字
Let命令
特点就是不用加上$即可完成计算
Linux let 命令 | 菜鸟教程 (runoob.com)
检测nginx服务是否运行的脚本
- #! /bin/bash
-
- #1.版本变量
- CheckUrl(){
-
- timeout=5
- fails=0 #失败的计数器
- success=0 #成功的计数器
- # 循环的检测
- while true
- do
- wget --timeout=${timeout} --tries=1 http://pythonav.cn/ -q -o /dev/null
- #echo $?判断是否成功
- if [ $? -ne 0 ]
- then
- let fails=fails+1 #失败次数+1
- else
- let success+=1
- fi
- #判断成功次数是否>1,判断该网站是否可以正常访问
- # -ge 大于等于
- if [ $success -ge 1 ]
- then
- echo "恭喜你,该网站正常执行"
- exit 0
- fi
- # 当错误次数>2,发送邮件
- if [ ${fails} -ge 2 ];then
- echo "该网站需要检查"
- exit 2
- fi
- done
- }
-
- #函数定义后需要执行
- CheckUrl
expr命令
expr支持简单的+-算法,并且可以作为判断使用,true为1,否则为0
返回个数
expr psl.ovpn ":" ".*n"
expr length $str1:可以得到str1的长度
- for str1 in I am Fairy, I Love PSL.
- do
- #进行判断
- if [ `expr length $str1` -lt 5]
- then
- echo $str1
- fi
- done
bc命令+tr命令
直接进入算数环境
我们可以结合echo来使用bc命令(利用管道符)
echo "4*4" | bc
计算1..100的和
1.我们echo {1..100}输出的所有树中间是空格我们可以利用tr命令将空格置为+
echo {1..100} | tr " " "+"
2.然后我们再交给bc去
echo {1..100} | tr " " "+" | bc
seq命令
1.1-100的和
seq -s " + " 100 | xargs expr
Linux基础:常用命令之seq命令详解 - 知乎 (zhihu.com)
awk命令