shell脚本,看这一篇就够了!!!

shell总览

1、初始shell
计算器语言的类型、定义、分类,使用场景、常见元字符

计算器语言的类型

编译型语言
c语言、c++语言、java语言
运行编译型语言是相对于解释型语言存在的,编译型语言的首先将源代码编译生成机器语言,再由机器运行机
只翻译第一次,后面则只需要使用第一次翻译的内容
​
解释型语言
php语言、python语言、bash语言
相对于编译型语言存在的,源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码 进行解释运行。
每次都得翻译,不会保存

shell的定义

一种程序语言,有变量、关键字、各种控制语句,有自己的语法结构,利用shell程序设计的语言,可以编写功能很强、代码阶段的程序
#!      shebang 定义解释器。如#!/bin/bash,使用/bin/bash执行脚本(bash shell)会解释该文本下的内容,执行时,bash会解释好显示出来

shell的分类

/bin/sh        符号连接,/bin链接的是use/bin,
/bin/bash       bash shell的标准安装位置
/sbin/nologin     阻止用户登陆的系统
​
echo $SHELL       查看当前正在使用的shell
vim /etc/passwd     编辑登录时使用的shell

使用场景

什么时候不适合使用Shell编程:
    1. 资源紧张的项目,特别是那些速度是重要因素的地方(排序,散序,等等)
    2. 程序要进行很复杂的数学计算,特别是浮点计算,任意精度的计算,或者是复数计算
    3. 要求交叉编译平台的可移植性(使用C或者是Java代替)
    4. 需要结构化编程的复杂应用(需要变量类型检查和函数原型等等)
    5. 对于影响系统全局性的关键任务应用。
    6. 安全非常重要。你必须保证系统完整性和抵抗入侵,攻击和恶意破坏。
    7. 项目由连串的依赖的各个部分组成。
    8. 多种文件操作要求(Bash被限制成文件顺序存取,并且是以相当笨拙,效率低下的逐行的存取方式)
    9. 需要良好的多维数组支持。
    10. 需要类似链表或树这样的数据结构。
    11. 需要产生或操作图象或图形用户界面。
    12. 需要直接存取系统硬件。
    13. 需要端口号或是socket I/O。
    14. 需要使用可重用的函数库或接口。
    15. 所有的私有的不开源的应用程序(Shell脚本的源代码是直接可读,能被所有人看到的)
Shell 能做什么?
    1. 自动化批量系统初始化程序 (update,软件安装,时区设置,安全策略...)
    2. 自动化批量软件部署程序 (LAMP,LNMP,Tomcat,LVS,Nginx)
    3. 应用管理程序 (KVM,集群管理扩容,MySQL,DELLR720批量RAID)
    4. 日志分析处理程序(PV, UV, 200, !200, top 100, grep/awk)
    5. 自动化备份恢复程序(MySQL完全备份/增量 + Crond)
    6. 自动化管理程序(批量远程修改密码,软件升级,配置更新)
    7. 自动化信息采集及监控程序(收集系统/应用状态信息,CPU,Mem,Disk,Net,TCP                Status,Apache,MySQL) 8. 配合Zabbix信息采集(收集系统/应用状态信息,                   CPU,Mem,Disk,Net,TCP Status,Apache,MySQL)
    8. 自动化扩容(增加云主机——>业务上线)
    zabbix监控CPU 80%+|-50% Python API AWS/EC2(增加/删除云主机) + Shell Script(业务    上 线)
    9. 俄罗斯方块,打印三角形,打印圣诞树,打印五角星,运行小火车,坦克大战,排序实现 
    10. Shell可以做任何运维的事情(一切取决于业务需求)

shell的常见元素

文件描述符与输出重定向
0:Standard Input (STDIN)   标准输入
1:Standard Output (STDOUT)   标准正确输出
2:Standard Error Output (STDERR)   标准错误输出
>a    将正确输出的内容,输入到文本a
2>a   将错误输出的内容,输入到文本a
&>a   将正确错误输出的内容,混合输入到文本a
1>&2   将正确的输出当错误输出用
2>&1   将错误的输出当正确输出用
bash配置文件、bash shell特性、bash快捷键

bash配置文件

开局加载的一些乱七八糟的图案文件
/etc/motd
​
全局配置文件
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
个人配置文件
/root/.bash_profile
/root/.bashrc
​
profile     在用户登陆时执行
bashrc      在bash shell被打开时执行,每次开启新的终端或标签页时,都会读取这个文件
​
用户登录加载bash配置文件的顺序
​
登陆式shell加载配置文件过程
1、/root/.bash_profile
2、/root/.bashrc
3、/etc/bashrc
4、/etc/profile
5、/etc/profile.d/*.sh
​
非登录式shell加载文件过程
1、/root/.bashrc
2、/etc/bashrc
3、/etc/profile.d/*.sh

bash shell特性

历史              history
别名              alias
快捷键             tab
前后台作业         ctrl+z 将前台正在运行的作业放到后台,jobs 查看所有后台正在运行的作业,
fg %1 将后台正在运行的作业,转移到前台,bg %1 将后台暂停的作业,重新启动在后台运行
重定向             >
管道              |
命令排序执行:         
;               命令分割符
&&              前面成功,执行后面
||              前面不成功,执行后面
{}              
?*              正则表达式

bash快捷键

ctrl+a  切换到命令开始行
ctrl+e  切换到命令行末尾
ctrl+u  清除剪切光标之前的内容
ctrl+k  清除剪切光标之后的内容
ctrl+y  粘贴刚才所删除的字符(恢复u、k删除的内容)
ctrl+r  在历史命令中查找,输入关键字调出之前的命令
历史命令、通配符置换

历史命令

查看历史命令
history         查看历史命令  /etc/profile下的historysize可以修改
​
显示历史命令的执行时间,添加变量,再使用history则会有时间显示
HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S"
​
调用历史命令
1、上下键
2、! 关键字
3、! 历史命令行号
4、!! 执行上一条命令
5、!$ 上一条命令的最后一个参数
    esc .       上一条命令的最后一个参数
    ctrl+r      在历史命令中查找,输入关键字调出之前的命令
​
别名
查看别名
alias
设置别名
    临时设置
    a=88    重启后失效
    永久设置
    vim /root/.bashrc
    添加别名

通配符置换

*   匹配0或多个字符
例如:a*b,a开头b结尾,不管中间有多少字符,都会被算在内
​
?   匹配一个字符
例如:a?b,a开头b结尾,中间只能有一个字符,可以是任意字符
​
[]  匹配[]中的某一个字符
例如:a[xyz]b,a开头b结尾,a与b中间只能有xyz其中一个字符才会匹配
a[0-9]b,a与b之间只能有一个a数字
a[!0-9]b,a与b之间只能有一个字符,但不能是阿拉伯数字
​
{}  匹配{}中的一串字符
例如:a{abc,xyz,123}b,a与b之间只能是abc、xyz、123这三个字符串之一
2、shell脚本规范
文件以.sh结尾,代表这个是shell脚本
.sh结尾的文件有高亮显示,省略sh则不易判断该文件是否为shell脚本
​
脚本规范如下
======================================
#!/usr/bin/bash         ---shebang蛇棒, 解释器, 翻译
#
#Author: newrain            ---Author  作者
#Email: newrain@163.com     ---Email   邮箱
#Github: https://github.com/newrain001      ---该脚本的网址
#Date: 2019/**/**           ---创建时间
​
echo "woaixuexi"            ---打印我爱学习到终端屏幕
======================================
​
第一行#!/usr/bin/bash          语法规定shell脚本文件的第一行为为整个文件的解释器
第二行#开头的行为为注释器,用来说明文件及标定所属人使用,解释这个脚本的
​
执行脚本的方式
1、sh 脚本.sh
2、bash 脚本.sh
3、./脚本.sh         需要执行权限(chmod a+x)可执行所有脚本
4、. 脚本.sh
5、source 脚本.sh
3、变量
变量的类型、变量运算、变量引用、读取用户标准输入

变量的类型

变量
bash作为程序设计语言和其他高级语言一样,也提供使用和定义变量的功能
​
预定义变量、环境变量、自定义变量、位置变量
预定义变量:
    $?      echo $?     最后一次执行命令的返回状态,变量为0时,则证明上一条命令正确;变量不为0,则证明上一条命令执行错误
    $$      执行命令时,最后加上$$,顺便生成的进程号(pid)
    $!      echo $!     查看后台运行最后一个进程的进程号(pid)
​
自定义变量:
    定义:变量名称=值
        变量名称:只能由字母、数字、下划线组成;不能以数字开头
        注意:要让变量名称有意义
        =   赋值符号,前后不能有空格
        引用变量:$变量名 或 ${变量名}
    例如:
        a=100           添加变量a=100
        echo $a         查看变量a等于100
        echo $aa        如果输入两个aa,则查询不到aa变量,显示为空
        echo %{a}a      将a用${}包起来,则a单独成为变量,与后面的a没有关系
​
    查看单个变量:echo $变量名
    查看所有变量:set          自定义变量和环境变量
    取消变量:unset 变量名      
​
环境变量:
    echo $变量名           查看单个变量
    set                   查看所有自定义变量和环境变量
    enc                   仅查看所有环境变量
    unset 变量名           取消变量名
  作用范围:仅在当前shell中生效
    export 变量名称=值      设置环境变量,使该变量可以在子shell中使用
  可以在子shell中使用
    
  临时生效:
    a=1      重启后失效
  永久生效:
    写入到登录脚本中
    /root/.bashrc 
    /root/profile
    /etc/profile.d/* 
​
    echo $PATH      存储所有命令所在的路径
​
预定义变量:      (加在脚本中)
    $$  当前进程pid
    $?  命令执行后的返回状态,0或非0
    $#  位置参数的数量
    $*  所有位数参数的内容
    $@  所有参数
    $!  查看最后一个后台进程的pid
    
位置变量:
    vim s.sh
    ===================
    echo $1     添加预定义变量1
    echo $2     添加预定义变量2
    echo $@     展示变量都有什么
    echo $*     展示变量都有什么
    echo $#     展示有几个参数
    echo $$     展示当前进程的pid
    echo $?     命令执行后的返回值
    ===================
    sh s.sh x y
    添加$1和$2的变量为x和y
    
变量嵌套(扩展)
表示(变量)$var的长度
# eval 执行字符串内的可执行命令
[root@newrain ~]# a=b
[root@newrain ~]# b=c
[root@newrain ~]# eval echo '$'"${a}"
c
先获取a的值,通过再次构造echo命令,使用eval再一次执行语句,就达到我们的目的。

变量运算

变量运算:
    算式运算符:+、-、*、/、()、%(取余数)
    运算方式:$(())、$[]、expr
​
  例如:
    $(())方式
    echo $(( 5+2-(3*2)/5 ))
    =6
    
    $[]方式
    echo $[ 5 + 2 - (3*2)/5 ]       (3*2)/5是6/5,这里是整数除法,忽略余数,所以等于1
    =6
    
    expr方式(适合简单的计算,加减乘除不好混合用),因为*、/在shell中有特殊的含义,所以要加\用来转义
    expr 5 +3 =8
    expr 5 \* 8 =40
    expr 5'*' 8 =40
​
浮点运算:
  bash本身不能做小数点计算,需要用bc命令转换
  例如:
    echo "2*4" | bc             2乘4
    echo "2^4" | bc             2的4次方
    echo "scale=2;6/4" | bc     scale 精度  小数点两位,6除以4等于1.5,精度为小数点两位,所以等于1.50
    
  例子:
    计算信用卡一年的利息,日利率为0.05%
    m=$( echo 5/10000|bc -1 )     m等于5除以10000的值,这里的等于0.0005,-l表示使用标准的数学库
  或m=`echo 5/10000|bc -1`
    sum=10000                     设置变量sum等于10000
    for i in {1..365}             循环365次
    do                            开始循环
        sum=$(echo $sum+$sum*$m | bc )      sum赋予新的值,
        echo &sum                 每次循环迭代输出当前的sum值
    done                          循环结束
    echo $sum                     循环结束后,输出最终的sum值

bc命令详细解释

bc命令 是一种支持任意精度的交互执行的计算器语言。bash内置了对整数四则运算的支持,但是并不支持浮点运算,而bc命令可以很方便的进行浮点运算,当然整数运算也不再话下。
​
语法:
bc(选项)(参数)
​
选项:
-i:强制进入交互式模式;
-l:定义使用的标准数学库;
-w:对POSIX bc的扩展给出警告信息;
-q:不打印正常的GNU bc环境信息;
-v:显示指令版本信息;
-h:显示指令的帮助信息。
​
参数:
文件:指定包含计算任务的文件。
​
实例:
算术操作高级运算bc命令它可以执行浮点运算和一些高级函数:
echo "1.212*3" | bc 
3.636
​
设定小数精度(数值范围)
echo "scale=2;3/8" | bc
0.37
参数scale=2是将bc输出结果的小数位设置为2位。
​
进制转换
#!/bin/bash
abc=192
echo "obase=2;$abc" | bc
执行结果为:11000000,这是用bc将十进制转换成二进制
​
#!/bin/bash
abc=11000000
echo "obase=10;ibase=2;$abc" | bc
执行结果为:192,这是用bc将二进制转换为十进制。
​
计算平方和平方根:
echo "10^10" | bc
echo "sqrt(100)" | bc

变量引用

\   转义符号
当一个字符被引用时,其特殊含义将被无效
将有意义的变为无意义,将无意义的变为有意义
例如:\n
输入:echo -e '5\\n6\n7'
输出:5\n6
     7
\n是换行符,如果不加\,则换行,如果加\,则代表\n是一个无意义的符号
​
''      完全引用、强引
""      部分引用、弱引
例子:
设置变量;num=1
 强引:
   输入:echo '$num'
   输出:$num
 弱引:
   输入:echo "$num"
   输出:1

读取用户标准输入

read                        读取键盘输入的值,赋予给变量
read -t 5 变量               等待用户输入的时间为五秒
read -p '提示信息' 变量       提供给用户应该输入的信息
read -s -p '提示信息' 变量    使read命令中输入的内容不显示在屏幕
read -n 5 -p "提示信息" 变量  -n用于指定读取的字符数,到五个字符直接返回结果,不用回车
​
stty -echo      取消屏幕回显,执行完该命令后,输入的所有东西将不会显示,只会显示输出的内容
stty echo       关闭取消屏幕回显
4、脚本运行
脚本大纲、脚本执行的方式

脚本大纲

1、创建脚本文件
    指定命令解释器
    注释
    编写bash指令集合(脚本内容)
2、使用./执行,需要添加权限

脚本执行

在子shell中运行脚本:
sh 脚本
bash 脚本
在子shell中执行脚本,并将执行环境带如到父shell
. 脚本
source 脚本
所有程序都可以使用这种方式执行shell
chmod a+x     添加权限
./ 脚本
​
主要用sh
sh -x       执行该脚本并显示所有的变量
sh -n       不执行脚本,只是检查语法错误,返回所有错误语法(不适用)
sh -v       执行脚本前,把执行脚本内容显示在屏幕
5、变量替换
命令替换、变量替换、变量替换-匹配截取

命令替换

a=`date`        将a设置为date的变量
a=$(date)       和上面一样
echo $a         设置完命令变量之后,echo $a就和输入date是一样的效果

变量替换

1、${parameter:-word}
若parameter未设置,则用word代替parameter进行替换
===============
b=${b:-3}
===============
如果b有值,则b为1,如果b没有值,则b为3
​
2、${parameter:=word}
与前者类似
===============
b=${b:-3}
===============
如果b有值,则b为1,如果b没有值,则b为3
​
3、${parameter:+word}
若 parameter设置了,则用word代替parameter进行替换,parameter的值不变.
===============
b=1
b=${b:+3}
===============
不管b有没有值,b的值都将成为3
​
4、${parameter:?message}
若parameter为空或未设置,则message作为标准错误打印出来,这可用来检查变量是否正确设置
===============
b=${b:?3}
===============
若变量以赋值的话,正常替换.否则将消息message送到标准错误输出(若此替换出现在Shell程序中,那么该程序将终止运行)

变量替换-匹配截取

变量内容删除及替换
​
# 是去掉左边(在键盘上 # 在 $ 之左边)
% 是去掉右边(在键盘上 % 在 $ 之右边) 
单一符号是最小匹配;两个符号是最大匹配(贪婪匹配)。
​
设置变量:url=www.sina.com.cn
echo ${#url}                获取变量长度
echo ${url}                 正常显示变量内容
​
${变量#关键词}               从前往后,从符合第一个关键词的位置切除
输入:echo ${url#*.}        从前往后,最短匹配
输出:sina.com.cn
​
${变量##关键词}              从前往后,符合最后一个关键词的位置切除
输入:echo ${url##*.}       从前往后,最长匹配
输出:cn
​
${变量%关键词}               从后往前,从符合第一个关键词的位置切除
输入:echo ${url%.*}        从后往前,最短匹配
输出:www.sina.con
​
${变量%%关键词}              从后往前,符合最后一个关键词的位置切除
输入:echo ${url%%.*}       从后往前,最长匹配
输出:www
​
${变量/旧字符串/新字符串}       将旧字符串替换为新字符串,只替换第一个
输入:echo ${url/n/p}        匹配到第一个的旧字符替换为新字符
输出:www.sipa.com.cn
​
${变量//就字符串/新字符串}      替换所有旧字符串为新字符串
输入:echo ${url//n/u}
输出:www.sipa.com.cp        匹配到所有所有旧字符替换为新字符
​
===================================================================
索引及切片
设置变量:a=12345678
​
输入:echo ${a:5}          从第五位的下一位开始截取
输出:678
​
输入:echo ${a:3:4}        从第三位的下一位开始截取,只截取四位
输出:4567
​
输入:echo ${a:2:-1}       从第二位的下一位开始截取,截取到倒数第一位的上一位
输出:34567
basename & dirname获取文件或目录名
basename    除去目录后剩下的文件名
temp=/home/temp/1.test      设置变量
base=`basename $temp`       设置命令变量
echo $base                  查看变量
结果为:1.test                显示结果
​
dirname     除去文件后剩下的目录名
temp=/home/temp/1.test      设置变量
dir=`dirname $temp`         设置命令变量
echo $dir                   查看变量
结果为:/home/temp            显示结果
​
在脚本中添加
ehco $( cd $( dirname $0 ) ; pwd )
显示脚本所在的目录
6、shell编程-流程控制
shell编程-条件结构、分支if语句、分支case语句

shell编程-条件结构

test 是一个内置的命令,用于评估表达式并返回真(返回值为0)或假(非零返回值)。test 命令经常与条件语句(如 if、while、until)一起使用来控制程序的流程。
字符串比较、数字比较、文件测试
​
字符串
-n       test -n ""         ""中字符串长度不为空,则返回值为0,如果为空,则返回值为1
-z       test -z ""         ""字符串长度为零;不输入内容,则返回值为0,否则返回值为1
=        test a = b         判断两个字符串是否一样,如果a=a,则返回值为0,否则返回值为1
!=       test a != b        判断两个字符串是否不一样,如果a=a,则返回值为1,否则返回值为0
! -n = -z   ! -z = -n       反转
​
数字
eq  等于          ne  不等于
ge  大于等于       le  小于等于
gt  大于          lt  小于
​
文件
-f  存在且是普通文件
-d  存在且是目录
-h  存在且是软链接
-b  块设备
-c  字符设备
-e  文件存在

shell分支if语句

控制流:
在一个shell脚本中命令执行的顺序称作脚本的流
流控制命令:能让脚本的流根据条件而改变命令,称作为条件流控制命名
exit语句:退出程序的执行,并返回一个返回码,返回码为0正常退出,非0为非正常退出
例如:exit 0
​
if语句,if代码返回0为真,非0为假
条件判断:
=========================
if
[ $1 -eq 1 ];then
echo '等于1'
elif
[ $1 -eq 2 ];then
echo '等于2'
else
echo '既不等于1,也不等于2'
fi
=========================
​
多条件联合
逻辑与(和)
if [ $1 ] && [ $2 ]
if [ $1 -a $2 ]
if [[ $1 && $2 ]]
​
逻辑或
if [ $1 ] || [ $2 ]
if [ $1 -o $2 ]
if [[ $1 || $2 ]]

shell分支case语句

case语句,输入的变量来判断
======================
case $1 in 
a)
    echo 1
    ;;
b)
    echo 2
    ;;
c)
    echo 3
    ;;
*)
    echo "输入错误"
    exit
    ;;
esac
======================
​
if与case的区别:if是从上往下一条一条判断,case是直接去寻找目标,都可以用
7、shell编程-循环结构
shell循环-for语句、while语句、until语句

shell循环for语句

for i in {取值范围}     循环的内容可以是{1..100}{a..z}以及空格,换行,tab键隔开的内容
do                      循环开始
    循环体                 命令参数,执行一些操作后面跟上$i
done                    循环结束
​
循环脚本:
=============
for i in {1..100}
do
echo $i
done
=============
脚本作用:
挨个打印1到100
​
========================
for i in $(seq 1 100)
do
   echo $i
done
========================
和for i in {1..100}执行结果一样
seq 是一个用于生成序列的实用程序。它通常用于生成一系列的数字,但也可以生成其他序列
​
========================
for (( i=1;i <= 5;i++ ))
do
    echo $i
done
========================
类似c语言循环方式,可以使用,我还是觉着for i in {}更好用

shell循环while语句

while循环条件为真的情况下会循环,只要条件为真,可以一直循环
​
while 条件            while 关键字 条件    [ $1 -lt 10 ]
do                      开始循环
    循环体             命令参数,执行一些操作后面跟上$1
done                    循环结束
​
例子
=====================
#!/bin/bash
i=0
while [ $i -lt 100 ] 
do
echo $i
let i++
done
=====================
只要i小于100,就会一直循环下去,该例子中,i每打印一次,值就会+1,所以i等于99的时候,就会停止循环

区别

for和while的区别
vim a
----------
vim wget sl
----------
​
如果是for循环
--------------------
for i in $(cat ./a)
do
   echo $i
done
--------------------
输出结果:
vim
wget
sl
​
如果是while循环
--------------------
while read l
do
   echo $l
done <./a
--------------------
或
--------------------
cat ./a | while read l
do
   echo $l
done
--------------------
输出结果
vim wget sl
​
for循环会将空格键,tab键,换行符的结果都以换行符展示出来
while循环不会修改格式,空格就是空格,tab就是tab
​
: 占位符
for循环
--------------------
for i in {1..100}
do
   :    #占位符,不会报错,方便以后填写内容
done
--------------------
​
while循环
--------------------
while : #这个:是真的,和1=1一样,无限循环
do
   :    #这个:是假的,就是为了z
done
--------------------

shell循环until语句

until 条件        当条件表达式,为假进行循环,为真则停止循环
do
循环体
done
​
例子
=====================
i=0
until [ 2 -eq 1 ]
do
echo $i
let i++
done
=====================
因为2不等于1,所以会一直循环下去
=====================
x=1
until [ $x -ge 10 ]
do
        echo $x
        x=`expr $x + 1` 
done
=====================
expr的作用是求值表达式,用来计算$x+1后的值
​
while可以用>、=、<号,但是until只能用字母-eq等来表示,还是统一用字母好
shell循环控制continue、break、exit、shift

shell循环控制continue、break、exit

continue、break、exit
=======================
echo "我在西安很想你"
for i in {1..10}
do
    if [ $i -eq 5 ];then
        continue、break、exit
    fi
    echo "想你第$i次"
done
=======================
continue    跳过单次循环,跳过第五次接着从第六次开始循环
break       跳过所有循环,遇到第五次的时候,将不会循环下列的循环参数,执行下一个脚本
exit        循环到第五次的时候,直接退出脚本

shell循环控制shift

shift命令
每次往命令命令参数前移动某位(shift后面跟的数字,不跟默认是1)
=====================
while [ $# -ne 0 ]
do
echo $1
shift
done
=====================
运行该脚本,后面跟上参数,每个参数只会运行一次,如果是shift 2则每次会往前移一位,如果参数是两个,则会显示第一个,如果参数是四个,则会显示第一个和第三个,参数只能为shift后面跟的数字的倍数,否则会报错
​
=====================
function test (){
    a=$1;shift 1
    echo $a
    echo $2
}
test 1 2 3
=====================
输出结果:
1
3
a=1     在没有shift前,$1就是位置变量第一个
$2=3    在shift后,$2就是位置变量向前移一位,就是位置变量的第三个
8、shell 编程-函数
定义函数、取消函数、函数传参、调用函数、命名空间、返回值

定义函数、取消函数、函数传参

function 函数名 (){
内容
}
​
或
​
函数名 (){
内容
}
​
完成特定功能的代码片段
函数必须先定义才能使用
优点:避免重复的代码
​
定义函数
a(){
echo "woaixuexi"
}
定义函数a为,打印woaixuexi到终端
​
取消函数
unset 函数名
​
函数传参
设定一个函数,在该函数中添加候选变量,后面引用函数时,再加上变量

调用函数

调用函数
本地脚本中,直接输入函数名字就可以调用函数
其他脚本中
1、需要加source 脚本的的文件名
2、输入脚本的定义函数,只需要调用一次文件名,就可以在新的脚本中一直调用,如果需要使用第二个不在同一个脚本中的函数,还需要再添加一次不同函数的脚本名
​
1、创建脚本
a.sh
=====================
zzz(){
echo 这是一个函数
}
=====================
​
2、创建调用函数的脚本
b.sh
=====================
source 绝对路径/a.sh
zzz
=====================
​
3、使用调用的函数
输入:sh b.sh
输出:这是一个函数

命名空间、返回值

命名空间
用法:local 变量
在shell脚本中,函数外和函数内的变量时一致的,函数内外不能赋值同样名字的变量,但是local可以实现局部变量,在函数开始时,输入local,则函数内的变量就和函数外没有关系
​
返回值
return
用来修改函数返回值的,可以将错的改为0,正确的改为其他,返回值不能超过0-255
注!!!
不能将函数名写为特殊字符,如ping,就会使函数失败,亲身经历
​
return返回值脚本:
===================
function networkCheck(){
    ping -w3 -c3 www.5idu.com &>/dev/null
    if [ $? -eq 0 ];then
        echo "网络正常"
        return 0
    else
        ping -w3 -c3 8.8.8.8 &>/dev/null
        if [ $? -eq 0 ];then
            echo "DNS无误,可以修改/etc/sysconfig/network-scripts/ifcfg-ens33 解决"
            return 1
        else
            echo "网络异常,请联系管理员"
            return 2
        fi
    fi
}
networkCheck
result=$?
echo "网络返回值 $result,如果网络异常,可以访问http://jiaming,寻找解决方案或拨打电话"
===================
​
没有使用命名空间的脚本
===================
a=1
function test (){
    echo $a
    a=2
}
test
echo $a
===================
执行结果:
1
2
函数和脚本中的变量是相通的
​
===================
a=1
function test (){
    local a
    echo $a
    a=2
}
test
echo $a
===================
执行结果:
​
1
local a,将变量a分到函数的环境中,所以第一个echo $a的值为空,第二个echo $a的值是以函数外面所定义的变量a进行取值
local,命令空间,将变量的值放到一个新的环境中
​
面试题
===================
a=li
b=$a
function test (){
    local
    a=$1
    b=$2;shift
    export c=$(eval echo $3)
}
​
test 10 20 30 $b
echo $a ${b} $c
===================
$a  值为10    local没有定义将哪个变量作为局部变量,local在此处不起任何作用,$1等于test后面跟的第一个参数,为10
$b  值为20    同上
$c  值为li    在给b赋值后,shift,将位置变量向前移一位,此时$3就变成了位置变量的第4个参数,又因为$b=$a,$a=li,eval echo $3,将变量嵌套的值打印出来,所以$b=$a=li,$c=$b,所以$c=li
9、shell编程-数组
定义数组、访问数组、遍历数组

定义数组

普通数组:只能用整数作为数组的索引
普通数组下标只能是数字
​
关联数组:可以使用字符串作为数组的索引
关联数组下标可以自己设置
​
一个变量可以定义多个值
普通数组定义:
定义:a=(1 2 3 4)
输入:echo ${a[0]}
输出:1
输入:echo ${a[1]}
输出:2
输入:echo ${a[2]}
输出:3
输入:echo ${a[3]}
输出:4
​
关联数组需要提前声明
输入:declare -A 变量名
输入:wowo=([name]=ljm [sex]=nan [age]=18)
输入:echo ${wowo[name]}
输出:ljm
输入:echo ${wowo[sex]}
输出:nan
输入:echo ${wowo[age]}
输出:18
​
关联数字定义变量前必须输入declare -A,否则变量只会输入最后一个值
需要修改值的话,只需要输入变量加下标直接修改
​
​
普通数组,使用空格隔开的每个元素
declare -a filelist 默认输入的,不需要手动输入
定义普通数组:
filelist=("li" "jia" "ming")
下标或索引   0     1     2
​
关联数组,必须先声明再定义
declare -A user     关联数组前的声明,全部打印出来的关联数组是无序的
user={[name]=jiaming [age]=18 [job]=student [gender]=nan}
echo ${user[name]}
输出:jiaming
​
echo ${filelist[@]}         打印所有元素
echo ${filelist[*]}         打印所有元素
echo ${!filelist[@]}        打印所有元素的下标 
echo ${#filelist[$]}        打印元素的个数
​
数组案例1
------------------------------
#a 完整备份  b 增量备份  c 差异备份
rule=(a b b c b b c)
datetime=$[`date +%u` -1]
case ${rule[$datetime]} in
a) echo "开始进行完整备份" ;;
b) echo "开始进行增量备份" ;;
c) echo "开始进行差异备份" ;;
esac
------------------------------
​
数组案例2
------------------------------
# ++i 先加1后赋值,i++ 先赋值后加1
while read line
do
    host[++i]=$line
done </etc/passwd
​
for i in ${!host[@]}
do
    echo $i--${host[$i]}
done
------------------------------
​
数组案例3
------------------------------
user=(李 佳 明)        #0-2
n=$[$RANDOM % 3]        #不超过3
echo "随机抽取用户为${user[$n]}"
------------------------------
​
随机生成一个si密码
------------------------------
#!/bin/bash
n=$((RANDOM % 8999))
a=$((n+1000))
echo $a
------------------------------

访问数组

设置变量:a=(1 2 3)
echo ${a[0]}        访问数组中的第一个值
echo ${a[@]}        访问数组中所有的值
echo ${#a[@]}       打印值的个数
echo ${!a[@]}       打印索引(下标)

遍历数组

==========================
#!/bin/bash                     解释器
while read a                    读取/etc/passwd的文件
do                              开始循环读取
    passwd[i++]=$a              将读取的文件设置为数组,并且按照每一行的类型设置为数组
done </etc/passwd               结束循环,添加输入的文件。完成数组的设置
for i in ${!passwd[@]}          循环数组的下标,后面是指数组的下标
do                              开始循环
    echo "$i:${passwd[i]}"      打印自增键,打印自增键对应数组下标的内容
done                            结束循环
==========================
读取文件中的行,然后加到一个数组中并进行遍历
自己理解:就是将文本中的内容,以行的形式添加成数组
10、正则表达式RE
正则表达式基本元字符、拓展元字符

正则表达式基本元字符

^       ^love       love开头的语句
$       love$       love结束的语句
.       l..e        l开头e结尾,中间包含两个字母的单词,一个点代表一个字母
*       o*          匹配字母o零次到多次,
.*      o*t         o*t表示匹配前面o零次到多次,以t结尾
[]      r[abcde]    匹配r后面紧跟着是abcde的单词,[abcde]单拿出来用,匹配括号中任意一个单词
[-]     [a-z][0-9]  同上
[^]     [^love]     取反,匹配文本中除了love这四个单词以外的单词
\       \n、\t、\b   转义,\n代表换行,\t代表一个tab键,\b退格,往前删一位
\<      \<r         只要r开头的单词,^是只要开头的语句,这个是单词
\>      t\>         t结尾的单词
\(\)    \(\)        匹配后的标签,不好搞,复制一份/etc/passwd文件测试
:%s/^\(.*\)\(:x:.*:\)\(.*\)/\3\2\1/g
使passwd中的文件,第一个:前的数据;第一个:后,最后一个:前的数据;最后一个:后的数据。调整一下位置,第一个整体代表数字1,第二个整体代表数字2,第三个整体代表数字3。使最后一段的位置放到第一个,第一段的位置放到最后一段,效果呈现
开始:(root)(:x:0:0:root:/root:)(/bin/bash)
结束:(/bin/bash)(:x:0:0:root:/root:)(root)
​
echo -e             转义,使带有特殊含义的字符变得有意义
\d      \d代表数字,默认为一个        \d+代表匹配多个数字
\s      \s代表空格,默认为一个        \s+代表匹配多个空格,sed中不支持/s
\n      \n代表换行
\t      \t代表一个tab键
\b      \b往前删一位
\a      \a发出警告声

正则表达式拓展元字符

grep -E         转义,默认正则开了一些转义
= 等于    != 不等于    =~ 匹配
+               [a-z]+oot       匹配前面的字符一次到多次,oot结尾的单词
?               o?t             匹配前面的字符零到一次,只匹配ot和t
|               a|b             匹配文件中a或b的单词
()              r(o|a)          匹配r下一个字母是o或a的单词
x{m}            o{1}            匹配一次o,可以有无数个o,因为o是按一个一个算的
x{m,}           o{1,}           最少匹配1次o
x{,m}           o{,3}           最多匹配3次o
x{m,n}          o{1,3}          最少匹配一次最多匹配三次o
11、shell编程-grep
egrep
grep    支持基本正则
grep -E 支持正则表达式的拓展元字符(或egrep)
greo -P 支持扩展正则,所有正则都支持,egrep搞不定的,用grep -P都可以搞定
grep -F 不支持任何正则或特殊符号,写的什么,就过滤什么(或fgrep)
grep -v 反向过滤
grep -i 不区分大小写
grep -o 只取出匹配到的部分(过滤[0-9]+、[a-z]+、[A-Z]+,可以使过滤的内容是一个整体)
grep -c 过滤出包含内容的列数
​
''  使变量没有意义,强引
""  使双引号中的内容是一个整体,变量可以使用
​
变量a=1
1、运用正则,判断需要[[]]
变量a=1
[[ $a =~ ^[0-9]+$ ]] && echo "yes" || echo "no"
查看左侧变量字符中是否包含右侧字符,包含则输出yes,不包含则输出no
​
2、*    0到多个
grep 'ro*' /etc/passwd
匹配0到多个r和o连在一起的字符,如ro、rro、oor、rrr、ooo
​
3、\<词首定位符   \>词尾定位符
grep -E "\<r" /etc/passwd
过滤出来R或r开头的单词,一个标点符号代表一个间断
grep -E "t\>" /etc/passwd
过滤出来以t结尾的单词,一个标点符号代表一个间断
​
4、^ 以什么开头
grep -E "^root" /etc/passwd
以root开头的语句
​
5、$ 以什么结尾
grep -E "bash$" /etc/passwd
以bash结尾的语句
​
6、. 匹配单个字符
grep "r..t" /etc/passwd 
匹配r开头,中间是任意两字符,t结尾的单词
​
7、.* 任意多个字符
grep "r.*t" /etc/passwd
过滤出来以r开头,t结尾,中间是任意字符,任意个数的单词
​
8、[] 匹配方括号中任意一个字符
grep -E "[Rr]oot" /etc/passwd
过滤出包含root和Root的单词
​
9、[] 匹配指定范围的一个字符
grep [a-z]oot /etc/passwd
过滤出a-z中任何一个后缀是oot的单词
​
10、[^] 取反,匹配不在括号中的所有字符
​
11、\(\) 匹配后的标签
:%s/^\(.*\)\(:x:.*:\)\(.*\)/\3\2\1/g
使passwd中的文件,第一个:前的数据;第一个:后,最后一个:前的数据;最后一个:后的数据。调整一下位置,第一个整体代表数字1,第二个整体代表数字2,第三个整体代表数字3。使最后一段的位置放到第一个,第一段的位置放到最后一段,效果呈现
​
例子:
grep -E "\<^[Rr].*[Nn]$\>" /etc/passwd
过滤出来以Rr开头,中间是任何字符,Nn结尾的语句
​
grep -E或egrep
1、+ 匹配一个或多个前导字符
egrep 'ro+t' /etc/passwd
匹配r开头,o是1到多次,t结尾的单词,r可以是无数次,o也可以是无数次,但是顺序不能变
​
2、? 匹配零个或一个前导字符
egrep 'ro?t' /etc/passwd
匹配r开头,o是零到一次,t结尾的单词,r和o都只能是一次的单词
​
3、a|b 匹配a或b
egrep "root|alice" /etc/passwd
匹配passwd中包含root或alice的单词
​
4、x{m} 字符x重复m次
创建文件
===========
love
love.
loove
looooove
===========
输入:egrep 'o{2}' a.txt       输出重复2的倍数o的单词,2、4、6、8个的二月孙
输出:loove
输入:egrep 'o{2,}' a.txt      输出o重复出现两次以上的单词
输出:loove
输出:looooove
输入:egrep 'o{6,7}' a.txt     输出o出现大于6次,小于7次的单词
输出:             没有包含的语句,则什么都不输出
​
例子:
ps aux | grep nginx | grep -v grep
判断nginx是否启动,如果能过滤出来,返回值为0,代表启动。
如果过滤不出来,返回值步为0,代表nginx未启动.
echo $?     -v 反向过滤,如果没有-v nginx,会将grep nginx过滤nginx的进程过滤出来,返回值还是0,将grep过滤掉,只过滤nginx
12、shell编程-sed
非交互编辑器-sed
sed "参数" '模式'
参数  -f 指定一个规则文件   -n 阻止输入行输出    -r 扩展正则    -i 确认修改
模式  s 替换    g 整行    d 删除    p 打印    a 追加    i插入
​
参数:
-f  编辑一个sed的规则文件,一行代表一个规则
    vim a
    ===========
    s/d/b/g
    s/q/p/g
    s/w/m/g
    ===========
    sed -f a 需要修改的文件名
​
-n  阻止行输入输出
    sed -n 's/要替换什么/替换成什么/g' 文件名
    -n基本搭配模式中的p执行,如果没有-n,则会将文件中所有的内容全部输出一遍,在输出一遍筛选的内容,-n则是将全部输出的内容删除
​
-r  扩展正则
    sed -r 's/[0-9]+/@/g' 文件名
    +号是正则表达式,使中间没有其他字符的数字成为一个整体,将数字替换成@
​
-i  确认修改
    sed -i.txt 's/a/b/g' 文件名
    文件中所有的a替换成b并保存,再创一个新文件,保存原来的文件,并以.txt结尾
​
模式:
s   替换
g   整行
    sed 's/a/b/' 文件名        将文件中的第一个a替换成b
    sed 's/a/b/g' 文件名       将文件中所有的a替换成b(全局替换)
​
d   删除
    sed '1d' 文件名        删除文件的第一行
    sed '1,2d' 文件名      删除文件从第一到第二行
    sed '2,$d' 文件名      删除文件从第二行到最后一行
    sed '/a/d' 文件名      删除文件中带有a的行
    sed '/a/,2d' 文件名    删除文件中第一个a到第二个a的行数
    sed '1~2d' 文件名      删除文件中,从第一行开始,每隔两行删除一行(删除奇数行)
    sed '0~2d' 文件名      删除文件中,从第零行开始,每隔两行删除一行(删除偶数行)
    sed '/a/,/b/d' 文件名  删除文件从带有a的行数到b的行数
    sed '^#.*/d;/^$/d' 文件名  删除文件中#开头的,和空行(^$代表空行)
​
a 追加
i 插入
    sed '/在哪一行下方插入/a\需要插入的内容/' 文件名      匹配到的下方插入
    sed '/在哪一行上方插入/i\需要插入的内容/' 文件名      匹配到的上方插入

作业题

非交互式编辑器,一次处理一行内容
测试文件
cat >> a.txt << EOF
0001 李梅 女 23 销售部 2040.00
0002 陈霞 女 20 销售部 1879.70
0003 程亮 男 26 销售部 2045.30
0004 刘辉 男 24 销售部 1915.00
0005 周波 男 21 销售部 1820.00
0006 苏健 女 20 销售部 1725.00
0007 苏康 男 26 销售部 2210.00
0008 王红 女 23 销售部 2043.00
0009 张三 男 28 销售部 2111.00
0010 李小 男 26 销售部 1850.00
0011 汤宏 男 29 销售部 1964.30
0012 田歌 女 24 销售部 1927.00
0013 李乐 男 26 销售部 2020.10
0014 丁丁 女 23 销售部 2120.00
0015 郑艳 女 22 销售部 1985.00
0016 许丽 女 25 销售部 1887.80
0017 崔霞 女 26 销售部 1973.30
0018 白亮 男 24 销售部 2564.60
>EOF
​
sed 's/销售部/技术部/' a.txt      将所有的销售部字段,全部修改成技术部
sed 's/销售部/技术部/;s/男/女/' a.txt   以;隔开,一次修改多个字段
sed -i.bak 's/销售部/技术部/' a.txt   -i确认修改,.bak添加备份文件
sed '/刘辉/d' a.txt       删除字段
sed '/刘辉/,$d' a.txt     匹配到第一个刘辉删除到最后
sed '1,/刘辉/d' a.txt     从第一行删除到匹配到的第一个刘辉
sed '/刘辉/,/张三/d' a.txt  从匹配到第一个刘辉删除到匹配到第一个张三中间全部删除
sed -r 's/[0-9]+/aaa/g'     -r支持正则,[0-9]+匹配多个数字,g全局,将所有数字替换为aaa
​
vim b.sed
-----------
s/张/王/g
s/女/男/g
-----------
sed -f b.sed a.txt      将规则写进文件里执行,-f使用文件执行命令
sed -n '/男/p' a.txt     -n阻止输入行输出,p打印选中的字段,如果没有-n,会将文本先全部打印一遍,再打印一遍选择的字段
sed '/丁丁/a\佳明' a.txt    在a.txt文件中的丁丁下面添加佳明
sed '/丁丁/i\佳明' a.txt    在a.txt文件中的丁丁上面添加佳明
sed '1~2d' a.txt        只显示奇数行
sed '0~2d' a.txt        只显示偶数行
sed '/#.*/d' a.txt      删除#后面的内容,基本都是删除配置文件中注释的
sed '/^$/d' a.txt       删除所有的空行
​
测试题:
--------------------------
静夜思
#提示
【作者】思乡
​
床前明月光。疑似地上霜,
举头望明月。低头思故乡,
--------------------------
==作业=
请将分割线上面的内容复制到文本中
1、将作者名字替换为李白
2、在作者行后面追加一列,唐朝
3、将,和。更换位置
4、将所有的,更换为,
5、将#开头的内容删除
6、将空行删除
7、将【】替换为[]
--------------------------
第一题:sed -i 's/作者/李白/' b.txt
第二题:sed -i '/【李白/a\唐朝' b.txt
第三题:sed -r -i 's/(.*)(。)(.*)(,)/\1\4\3\2/g' b.txt 
第四题:sed -i 's/,/,/g' b.txt 
第五题:sed -i '/^#.*/d' b.txt 
第六题:sed -i '/^$/d' b.txt 
第七题:sed -r -i 's/(【)(.*)(】)/\[\2\]/g' b.txt
​
修改ssh服务配置文件
拒绝root用户远程登录
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config 
修改端口22为2222
sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config 
修改dns反解析为no
sed -i 's/#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config 
​
修改nginx的配置文件
修改端口为80
sed -i 's/listen 80/listen 88;/' /etc/nginx/nginx.conf
sed -i -r 's/listen\s+[0-9]{2}\;/Listen 88/gi' /etc/nginx/nginx.conf
\s+ 多个空格,[0-9]{2} 0-9的数字出现2次,g 全局修改,i 不区分大小写
修改网站根目录为/opt/web
sed -i -r 's/usr\/share\/nginx\/html/opt\/web/' /etc/nginx/nginx.conf
​
修改selinux的配置
将selinux设置为永久关闭
sed -i 's/SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
13、shell编程-AWK
awk介绍
awk是行处理器:处理庞大文件时不会出现内存溢出或霍曼的问题
awk处理过程:依次对每一行进行处理,然后输出。默认分隔符是空格或tab键
​
awk的使用方法:
awk 参数 '{处理内容}'
awk 参数 'BEGIN{处理前要做的}{处理内容}END{处理后的内容}'
​
举例:
1、
输入:awk -F":" '{print $1,$3}' /etc/passwd
输出:root 0
     bin 1
     等等…………
-F,用什么符号作为分隔符,print $1,$3打印分开段落的第一列内容和第三列内容,逗号默认是以空格隔开
​
2、
输入:awk 'BEGIN{print 1/2} {print "ok"} END{print "----"}' /etc/hosts
输出:0.5
     ok
     ok
     ----
awk使用理解
NR:表示记录编号,当awk将行为记录时,该变量相当于当前行号
FNR:按不同的文件分开
NF:表示字段数量,当awk将行为记录时,该变量相当于当前列号
FS:输入字段分隔符,以什么符号区分割
OFS:输出字段分隔符,以什么分隔符显示
RS:输入记录分隔符
ORS:输出记录分隔符
​
FS(输入字段分隔符)
awk 'BRGIN{FS=":"}{print $1}' /etc/passwd
root
bin
…………等
​
OFS(输出字段分隔符)
awk 'BEGIN{FS=":";OFS="%%"}{print $1,$2}' /etc/passwd
root%%x
bin%%x
…………等
​
NR(添加行号,可以两个不同的文件将合并显示行号)
awk -F: '{print NF,$0}' /etc/passwd /passwd
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
…………
10 root:x:0:0:root:/root:/bin/bash
11 bin:x:1:1:bin:/bin:/sbin/nologin
…………等
​
FNR(添加行号,两个不同的文件将分开行号显示)
awk -F: '{print FNF,$0}' /etc/passwd /passwd
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
…………
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
…………等
​
RS(输入记录分隔符)
awk -F: 'BEGIN{RS="bin"}{print $0}' /etc/passwd
root:x:0:0:root:/root:/
/bash
​
:x:1:1:
:/
:/s
…………等       遇见bin就分隔
​
ORS(输出记录分隔符)
awk -F: 'BEGIN{ORS="#"} {print $1,$2,$3}' /etc/passwd
root x 0#bin x 1#daemon x 2#adm x 3#lp x 4#sync x 5#shutdown x 6#halt x 7#mail x 8#operator x 11#games x 12#ftp x 14#nobody x 99#systemd-network x 192#dbus x 81#polkitd x 999#sshd x 74#postfix x 89#chrony x 998#ntp x 38#nginx x 997#mysql x 27#
​
1、打印一个文件中的第二列和第三列
awk '{ print $2, $3}' 文件名
​
2、打印指定行指定列的某个字符
awk -F":" 'NR==3{ print $7 }' /etc/passwd
查看第三行。以:分隔的第七列
​
3、统计一个文件的行数
awk '{ print NR }' /etc/passwd
​
4、在脚本中传递变量到awk中
a=1000
echo | awk -v b=$a '{print b}'      -v可以在awk中设置变量
​
5、指定字段分隔符-F或BEGIN{FS=":"}
awk -F: '{ print $2,$3 }' /etc/passwd
awk 'BRGIN{ FS=":"}{print $2,$3}' /etc/passwd
​
6、在awk中使用for循环
awk -F: '{for(i=1;i<=2;i++) {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
分别打印每行每列
awk -F: '{ for(i=1;i<=NF;i++) {print $i}}' /etc/passwd
root
x
0
0
root
/root
/bin/bash
bin
x
1
1
bin
/bin
/sbin/nologin
daemon
x
2
2
daemon
/sbin
/sbin/nologin
​
7、在awk中使用if条件判断
显示管理员用户名
awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd
以:分隔,第一列的第三个参数等于0,则打印
awk -F":" 'NR==3{if($3==2){print "对的"}}' /etc/passwd
以:分隔,第三列的第三个参数等于2,则打印
​
统计系统用户
awk -F":" '{if($3>0 && $3<1000){i++}} END{print i}' /etc/passwd
以:分隔,如果第三个参数大于0和小于100,则一直增加到1000以内,最后打印出i的值
14、shell编程expect
expect安装、语法
yum -y install expect       安装expect
​
expect是一个免费的编程工具,用来实现自动交互任务,无需人为干预,用来实现自动交互功能的软件
用法:
1、定义脚本执行的shell
        #!/usr/bin/expect 类似于#!/bin/bash 
2、set timeout 30
        设置超时时间30s 
3、spawn
        spawn是进入expect环境后才能执行的内部命令,不能直接在默认的shell环境中执行 
        功能:传递交互命令
4、expect 
        这里的expect同样是expect命令
        功能:判断输出结果是否包含某项字符串,没有则立即返回,否则等待一段时间后返回,等待通过             timeout设置 
5、send
        执行交互动作,将交互要执行的动作进行输入给交互指令 
        命令字符串结尾要加上“r”,如果出现异常等待状态可以进行核查
6、interact 
        执行完后保持交互状态,把控制权交给控制台 
        如果不加这一项,交互完成会自动退出
7、exp_continue 
        继续执行接下来的操作
        
expect环境中设置变量用set,识别不了bash方式定义的变量
==================
#!/usr/bin/expect
set a 1
spwan echo $a
==================
chmod增加权限,./执行
输出;spawn echo 1     spawn执行shell环境的命令
​
免交互连接别人
1、
===============================================
#!/usr/bin/expect
spawn ssh root@需要连接的ip
expect {
        "yes/no" { send "yes\r";exp_continue }
        "password:" { send "连接ip的密码\r" }
} 
interact                执行完后保持交互状态,把控制权交给控制台,不加这个交互完成后会自动退出
===============================================
2、连接
yum -y install sshpass
sshpass -p '1' ssh -o StricHostKeyCheking=no root@密码
拷贝别人的目录
sshpass -p '1' scp -o StricHostKeyCheking=no root@密码

不需要完全掌握,大部分免交互基本都有参数解决,实在解决不了照着下面的修改一下

expect环境中设置变量用set,识别不了bash方式定义的变量 
错误方式:
[root@newrain expect]# cat expect02.sh 
#!/usr/bin/expect
user=22
spawn echo $user
[root@newrain expect]# ./expect02.sh 
invalid command name "user=22"
    while executing
"user=22"
        (file "./expect02.sh" line 3)
        
        
正确方式:
[root@newrain expect]# cat ./expect02.sh 
#!/usr/bin/expect
set user 22
spawn echo $user
[root@newrain expect]# ./expect02.sh
spawn echo 22 ============================================================================
​
[root@newrain expect]# cat expect01.sh 
#!/usr/bin/expect
spawn ssh root@192.168.62.146
expect {
        "yes/no" { send "yes\r";exp_continue }
        "password:" { send "123\r" }
} 
interact
​
interact的作用测试
执行测试是否免交互:
要是用/usr/bin/expect的shell执行
[root@newrain expect]#/usr/bin/expect expect01.sh 
成功
擦除最后一行interact进行测试
[root@newrain expect]#/usr/bin/expect expect01.sh
进入之后立即退出 ============================================================================
\r的作用测试
[root@newrain expect]# cat expect01.sh 
#!/usr/bin/expect
set user root
set pass 123
set ip 192.168.62.146
spawn ssh $user@$ip
expect {
        "yes/no" { send "yes";exp_continue }
        "password:" { send "$pass" }
} 
interact
[root@newrain expect]# ./expect01.sh 
spawn ssh root@192.168.62.146 
root@192.168.62.146's password:
​
加上\r之后
[root@newrain expect]# ./expect01.sh
spawn ssh root@192.168.62.146
root@192.168.62.146's password:
Permission denied, please try again.
root@192.168.62.146's password: ============================================================================
设置变量的方式
[root@newrain expect]# cat expect01.sh #!/usr/bin/expect
set user root
set pass 123
set ip 192.168.62.146 
spawn ssh $user@$ip 
expect {
        "yes/no" { send "yes\r";exp_continue }
        "password:" { send "$pass\r" }
}
interact
============================================================================
设置位置参数的方式(拓展)
[root@newrain expect]# cat expect01.sh 
#!/usr/bin/expect
set timeout 30
set user [ lindex $argv 0 ]
set pass [ lindex $argv 1 ]
set ip [ lindex $argv 2 ]S
spawn ssh $user@$ip
​
expect {
        "yes/no" { send "yes";exp_continue }
        "password:" { send "$pass\r" }
}
interact
运行结果为:
[root@newrain expect]# ./expect01.sh root 123 192.168.62.146 
spawn ssh root@192.168.62.146
root@192.168.62.146's password:
Last login: Thu Aug 15 23:26:59 2019 from 192.168.62.136
#!/usr/bin/expect
set username hello    # 定义变量   
set passwd 1
spawn ssh $username@172.17.138.107   # 执行交互式命令
expect {    # 捕捉系统返回,与系统进行交互
    "yes/no" { send "yes\r";exp_continue }
    "password:" {send "${passwd}\r"}
}
expect  "*]$"   # 捕捉系统返回,与系统进行交互
send "touch /tmp/abcaaa\r"
send "ls /\r"
expect eof 
interact

脚本例子

sh a.sh         和bash一样,不会影响终端的内容
bash a.sh       和sh一样,不会影响终端的内容
. a.sh          和source一样,会影响终端的内容
source a.sh     和.一样,会影响终端的内容
chmod a+x 授权    ./执行需要授权,这个方式什么脚本都可以执行
./a.sh          不会影响终端的内容,但是可以执行所有脚本
​
举例:
vim /root/a.sh
----------
cd /opt
ls
----------
环境均在/root下执行
sh a.sh         执行完终端的环境还是在当前目录root下
bash a.sh       同上
. a.sh          执行完终端的环境在opt下,脚本会影响终端的环境
source a.sh     同上
./a.sh          执行完终端的环境还是在当前目录root下,可以执行所有脚本,但是需要授权
​
---------------------------------------------------------------------------------
预定义变量:
$$的脚本例子,当前进程的进程号(pid)
-----------------
echo "此程序将会运行半个小时,如果提前终止,可以执行括号内的指令(kill -9 $$)"
sleep 1800
-----------------
​
$!的例子,后台运行的最后一个进程的进程号(pid)
sleep 100 &
echo $!
kill -9 $!
​
======================
环境变量,所有地方都可以使用,脚本,其他bash中,都可以使用该变量
export a=b
vim /etc/profile中添加变量,也可以是环境变量
source /etc/profile执行该文件,使环境变量生效
​
======================
自定义变量,就是普通变量
a=b
​
======================
位置变量,要给传值
vim s.sh
---------------
echo "我叫$1,我今年$2岁"
---------------
sh s.sh 佳明 18
执行结果:我叫佳明,我今年18岁
​
---------------
ping -c1 -w1 $1 &>/dev/null && \
echo "到达 $1 ok" || \
echo "到达 $1 error"
---------------
sh s.sh baidu.com
执行结果:到达 $1 ok       为baidu.com可以ping通
执行结果:到达 $1 error    则代表baidu.com不可以ping通
​
=====================
脚本例子,脚本文件名为a.sh
------------------------------
time=`date +%y年%m月%d日-%H:%M`
echo $time
------------------------------
sh s.sh 直接运行即可,会显示当前时间
​
------------------------------
ip=`ifconfig ens33 | grep  "inet" | awk 'NR==1{print $2}'`
echo "主机的ip是:" $ip
------------------------------
sh s.sh 直接运行会显示当前ip
​
------------------------------
nowtime=$(uptime | awk '{print $1}')
echo 当前时间为:$nowtime
------------------------------
sh s.sh 直接运行会显示当前时间,uptime,显示系统已经运行了多久、当前有多少用户登录以及系统负载的平均值。
​
------------------------------
username=$(w -h | awk '{print $1}' | sort | uniq -c | awk '{print $2}')
echo 当前登陆的用户是:$username
------------------------------
sh s.sh 直接运行会显示当前登录的用户,w命令用于显示已经登陆系统的用户列表,并显示用户正在执行的指令,详细解释在下面,-h只包含用户登录的相关信息,sort将重复的字符串排序在一起,uniq -c去重,将重复的记在一起,前面标上次数,
​
------------------------------
num=$RANDOM
read -p "请输入一个数字:" num2
[ $num -lt $num2 ] && echo 你的数字大于$num || echo "你的数字小于$num"
------------------------------
sh s.sh 1000        $RANDOM是随机产生一个数字,范围在0-32767,-lt小于
​
要求该脚本必须在/opt下执行
----------------------
pwd=$(cd $(dirname $0) ; pwd )      得到脚本的确切位置
[ "$pwd" = /opt ] && echo "在/opt下" || echo "不在/opt下"
----------------------
​
----------------------
read -p "请输入一个数字:" n
if [ $n -gt 100 ];then
   echo "你输入的数字大于100"
else
   echo "你输入的数字小于100"
fi
----------------------
-gt 大于
​
------------------------------
read -p "请输入你的年龄:" age
if [ -z "$age" ];then
        echo "你输入的内容为空"
        exit 1
fi
if [[ ! "$age" =~ ^[0-9]+$ ]];then          判断如果输入的值不是数字,则执行,=~匹配,^[0-9]代表匹配一个或多个数字,$代表结束
        echo "你输入的不是数字"
        exit 2
fi
if [ $age -le 18 ];then
        echo "你是一个未成年人"
elif [ $age -le 40 ];then
        echo "你是一个青年"
elif [ $age -le 60 ];then
        echo "你是一个中年人"
elif [ $age -gt 60 ];then
        echo "你是一个老年人"
else
        echo "外星人"
fi
------------------------------
sh s.sh 执行完后输入数字进行匹配
​
------------------------------
if [[ -d /var/lib/mysql || -n `ls /var/lib/mysql` ]];then
        echo "mysql已安装,且未进行初始化操作"
else
        echo "mysql未准备就绪"
fi
------------------------------
如果/var/lib/mysql有这个,且是目录和/var/lib/mysql下内容不为空,则执行mysql已安装,否则执行mysql未准备就绪
-d 存在且是目录,-n 输入的值不会空则返回值为0
​
------------------------------
#!/usr/bin/bash
net="192.168.253."
for i in {2..254}
do
   {   
   ip=${net}${i}
   ping -w1 -c1 $ip &>/dev/null
   if [ $? -eq 0 ];then
      echo "$ip up"
    else
       echo "$ip down"
    fi 
   }&
done
wait    当有需要放到后台执行的任务时,脚本运行结束,自动退出。不加wait需要自己按回车结束
------------------------------
批量ping主机ip
​
------------------------------
read -p "请输入用户名:" user
id $user
if [ $? -eq 0 ];then
   echo "用户$user 存在"
else 
   echo "用户$user 不存在"
fi
------------------------------
一个一个判断用户是否存在
​
------------------------------
if [ $# -lt 1 ];then
   echo "使用脚本方法:sh $0 需要检查的用户,使用空格隔开"
   exit
else
   for i in $@
   do
      echo "正在查询$i 中"
      sleep 1                   #这两段可以不加,纯粹显得高级
      id $i &>/dev/null
      if [ $? -eq 0 ];then
         echo $i 已存在
      else
         echo $i 不存在
      fi
   done
fi
------------------------------
sh s.sh root jiaming        批量判断,空格隔开
​
------------------------------
neihe=$(uname -a | awk '{print $3}' | awk -F"." '{print $1,$2}' | awk '{print $1}')
banben=$(uname -a | awk '{print $3}' | awk -F"." '{print $1,$2}' | awk '{print $2}')
if [[ $neihe -eq 3 && $banben -ge 9 ]];then
   echo "内核等于3,版本大于9"
else
   echo "有误"
fi
------------------------------
判断和
​
------------------------------
read -p "请输入用户前缀:" name
read -p "请输入是删除还是创建:" modify
read -p "请输入用户的个数:" num
if [[ ! -n "$name" && ! -n "$modify" && ! -n "$num" ]];then
   echo "输入内容有误,程序结束"
   exit
fi
​
if [[ $modify = "删除" ]];then
   cmd="/usr/sbin/userdel -r"
else
   cmd="/usr/sbin/useradd"
fi
​
for i in $(seq 1 $num)
do
   $cmd $name$i &>/dev/null && \
   echo $name$i 已${modify}成功 || \
   echo $name$i ${modify}失败
done
------------------------------
! -n如果输入的内容为空,返回值为0,该地方的作用是,如果输入的内容为空,则执行。没有用到返回值,! -n和-z是一个意思。&&为成功则执行,||为失败则执行
脚本安装mysql
#!/usr/bin/bash
​
password="Qianfeng@123"
cat << EOF
功能:
1、yum安装mysql5.7、8.0版本
2、初始化功能
3、清理安装环境
EOF
​
rpm -qa | egrep "mysql|mariadb" &>/dev/null
if [ $? -eq 0 ];then
    read -p "当前环境已安装mysql,是否清理[Y|N]" result
    if [ "$result" = Y ] || [ "$result" = "y" ];then
        echo "开始清理mysql环境"
        systemctl stop mysqld mariadb &>/dev/null
        yum remove -y `rpm -qa | egrep "mysql|mariadb"` &>/dev/null
        rm -rvf /var/log/mysqld.log /etc/my.cnf /var/lib/mysql-files /var/lib/mysql/
    else
        echo "无法继续执行安装操作,程序终止"
        exit
    fi
fi
​
yum clean all && yum makecache
if [ $? -eq 0 ];then
    echo "开始安装mysql"
    yum install -y https://dev.mysql.com/get/mysql80-community-release-el7-11.noarch.rpm &>/dev/null && \
    read -p "请选择安装版本的版本号[80|57](default 57):" level
    level=${level:=57}
    if [ "$level" -eq "57" ];then
        yum install -y mysql-community-server --nogpgcheck --enablerepo mysql57-community --disablerepo mysql80-community
    elif [ "$level" -eq "80" ];then
        yum install -y mysql-community-server --nogpgcheck
    fi
else
    echo "yum源有问题,请检查"
fi
​
systemctl enable mysqld --now
if [ -f /var/log/mysqld.log ];then
    passwd=$(grep password /var/log/mysqld.log | awk 'END {print $NF}')
    mysqladmin -uroot -p"$passwd" password "$password"
cat <<EOF
mysql $level 安装完成
数据目录位置:/var/lib/mysql
命令位置:/usr/bin
配置文件位置:/etc/my.cnf
日志文件目录:/var/log/mysqld.log
历史数据位置:/tmp/mysql_data
初始密码:Qianfeng@123
EOF
else
    echo "日志文件未找到,修改密码失败"
fi
脚本高级编译安装nginx
mkdir nginx
cd nginx
vim color.sh
--------------------------------
#!/usr/bin/bash
​
function error(){
    echo -e "\e[31m[`date '+%H:%M:%S'`]$@\e[0m"
}
sleep 0.5
​
function warning(){
    echo -e "\e[33m[`date '+%H:%M:%S'`]$@\e[0m"
}
sleep 0.5
​
function success(){
    echo -e "\e[32m[`date '+%H:%M:%S'`]$@\e[0m"
}
sleep 0.5
--------------------------------
​
vim lib.sh
--------------------------------
#!/usr/bin/bash
​
function networkCheck(){
    local host
    host=$1
    host=${host:=www.baidu.com}
    ping -w1 -c1 $host &>/dev/null
    if [ $? -eq 0 ];then
        success "网络检查正常"
    else
        error "网络检查异常"
    fi
}
​
function yumCheck(){
    yum clean all &>/dev/null
    yum makecache &>/dev/null
    if [ $? -eq 0 ];then
        success "yum 检查正常"
    else
        error "yum 检查异常"
    fi
}
​
function checkUser(){
    local user
    user=$1
    user=${user:=root}
    if [ "$USER" = "$user" ];then
        success "当前执行用户为$user"
    else
        error "用户不匹配,当前用户为$user"
    fi
}
​
function firewalld(){
    systemctl disable firewalld --now
    getenforce &>/dev/null
    if [ $? -eq 0 ];then
        success "防火墙,selinux已关闭"
    else
        setenforce 0
        sed -i 's/SELINUX=.*/SELINUX-disabled/g' /etc/selinux/config
        success "未关闭,已设置关闭防火墙,selinux"
    fi
}
--------------------------------
​
vim nginx_install.sh
--------------------------------
#!/usr/bin/bash
​
source ./color.sh
source ./lib.sh
​
nginx_level=1.16.1
nginx_install_dir=/usr/local/nginx
​
warning "此脚本编译安装nginx,会清理yum安装程序"
​
function check(){
    networkCheck
    yumCheck
    checkUser
}
​
function install(){
    yum -y install gcc make zlib-devel pcre pcre-devel openssl-devel wget && \
    wget -c http://nginx.org/download/nginx-$1.tar.gz && \
    tar xzf nginx-$1.tar.gz && cd nginx-$1 && \
    ./configure --user=nginx --group=nginx --prefix=$2 && make && make install && \
    success "编译安装完成" || error "编译安装失败"
}
​
function init(){
    useradd nginx -s /sbin/nologin
    echo "export PATH=$PATH:$1/bin" > /etc/profile.d/nginx.sh
    $1/sbin/nginx && success "nginx 启动成功" || error "nginx 启动失败"
    firewalld
}
​
check
install $nginx_level $nginx_install_dir
init $nginx_install_dir
--------------------------------
sh nginx_insta
邮件脚本
vim mail.sh
--------------------------------
#!/bin/bash
​
filelist="/etc/group /etc/sudoers /etc/passwd /etc/sysctl.conf /etc/hosts /etc/resolv.conf"
hashfile_path=/tmp/.hashcheck
hashstatus='init'
status=$hashstatus
​
function init(){
    md5sum $filelist > $hashfile_path
}
​
function check(){
    result=$(md5sum -c $hashfile_path 2>/dev/null | grep FAILED)
    if [ -z "$result" ];then
        hashstatus="ok"
        echo "[$(date)] 重要文件防篡改程序:检查正常" >> /var/log/filecheck-`date "+%F"`.log
    else
        hashstatus="error"
        echo "[`date`] 重要文件防篡改程序:检查异常!!!" >> /var/log/filecheck-`date "+%F"`.log
    fi
    if [ $status != $hashstatus ];then
        echo $result | mail -s "[$(hostname)] 文件防篡改程序状态 $hashstatus" 18392971625@163.com
        status=$hashstatus
    fi
}
​
if [ "$1" = "init" ];then
    init
else
    if [ ! -f $hashfile_path ];then
        echo "请先执行初始化操作: sh $0 init"
    else
        while :
        do
            check
            sleep 5
        done
    fi
fi
--------------------------------
sh mail.sh init     初始化,将文件的哈希值输入到文件中
sh mail.sh          运行脚本,每五秒循环一次
tailf /var/log/filecheck-`date "+%F"`.log   运行脚本的时候,查看日志
需要开启三个终端,一个看日志,一个运行脚本,一个负责修改文件,当第一次修改或md5sum哈希值发生修改的时候
脚本安装php
VERSION_ID=$(cat /etc/redhat-release | sed -r 's/.* ([0-9]+)\..*/\1/')
yum remove -y remi-release
yum install -y https://mirrors.ustc.edu.cn/remi/enterprise/remi-release-${VERSION_ID}.rpm
sed -e 's|^mirrorlist=|#mirrorlist=|g' \
    -e 's|^#baseurl=http://rpms.remirepo.net|baseurl=https://mirrors.ustc.edu.cn/remi|g' \
    -i /etc/yum.repos.d/remi*.repo
yum clean all
yum makecache
id nginx &>/dev/null && {
    phpUser='nginx'
} || {
    id www 2>/dev/null || useradd -s /sbin/nologin www
    phpUser='www'
}
# -----------------------------------------------
# version="56"
version="74"
# version="82"
​
yum install -y php${version} php${version}-php-fpm php${version}-php-mysqlnd php${version}-php-bcmath php${version}-php-pdo php${version}-php-openssl php${version}-php-gd php${version}-php-mbstring php${version}-php-xml php${version}-php-mcrypt php${version}-php-zip && {
    if [ ! -f "/etc/opt/remi/php${version}/php-fpm.d/www.conf.bak" ]; then
        \cp /etc/opt/remi/php${version}/php-fpm.d/www.conf /etc/opt/remi/php${version}/php-fpm.d/www.conf.bak
    fi
​
    echo "[www]
user = ${phpUser}
group = ${phpUser}
listen = /dev/shm/php-fpm-${version}.sock
listen.allowed_clients = 127.0.0.1
listen.owner = ${phpUser}
listen.group = ${phpUser}
listen.mode = 0666
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 20
pm.max_spare_servers = 50
slowlog = /var/opt/remi/php${version}/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/opt/remi/php${version}/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path]    = /var/opt/remi/php${version}/lib/php/session
php_value[soap.wsdl_cache_dir]  = /var/opt/remi/php${version}/lib/php/wsdlcache" >/etc/opt/remi/php${version}/php-fpm.d/www.conf
    systemctl restart php${version}-php-fpm
    systemctl enable --now php${version}-php-fpm
​
    chown -R ${phpUser}:${phpUser} /var/opt/remi/php${version}/lib/php/session
    chown -R ${phpUser}:${phpUser} /var/opt/remi/php${version}/lib/php/wsdlcache
}
 
命令集合解释
w命令
用于显示已经登陆系统的用户列表,并显示用户正在执行的指令。执行这个命令可得知目前登入系统的用户有哪些人,以及他们正在执行的程序。单独执行w命令会显示所有的用户,也可指定用户名称,仅显示某位用户的相关信息。
USER 列显示了登录用户的用户名。
TTY 列显示了用户使用的终端类型,通常是物理终端(如tty1、tty2等)或伪终端(如pts/0、pts/1等,这些通常用于SSH或终端仿真器连接)。
FROM 列显示了远程主机的地址(如果适用),或者如果用户在本地登录则可能是空的。
LOGIN@ 列显示了用户登录到系统的时间。
IDLE 列显示了用户空闲的时间长度。
JCPU 列显示了与终端关联的进程所使用的CPU时间。
PCPU 列显示了当前进程所使用的CPU时间。
WHAT 列显示了用户当前正在执行的命令。
​
sort命令用于对文本文件的行进行排序,并将结果输出到标准输出(通常是终端)或重定向到文件中。sort命令可以对文本文件中的字符串或数字进行排序,支持多种排序选项和参数。
以下是一些常用的sort命令选项:
-n:按照数字大小进行排序,而不是按照字符顺序。
-r:反向排序,即从大到小或从Z到A。
-t:指定字段分隔符,用于指定非默认的字段分隔符(默认为制表符)。
-k:按照指定的字段进行排序。例如,-k 2表示按照第二列进行排序。
-u:去除重复的行。
-o:将排序结果输出到指定的文件中,而不是标准输出。
​
uniq
是一个在 Unix 和 Unix-like 系统(如 Linux)中常用的命令行工具,用于从排序后的文本文件中删除重复的行。如果不先对输入进行排序,uniq 命令可能无法正确识别所有重复的行,因为它只比较相邻的行。
uniq [OPTION]... [INPUT [OUTPUT]]
INPUT 是要处理的文件。如果省略,uniq 会从标准输入读取。
OUTPUT 是可选的,指定输出文件的名称。如果省略,uniq 会将结果发送到标准输出。
常用选项:
-c 或 --count:在每行前加上该行在输入文件中出现的次数。
-d 或 --repeated:仅显示重复的行。
-D 或 --all-repeated:对于每组重复的行,显示每一行。
-f 或 --skip-fields=N:忽略每行的前 N 个字段。字段是由空格分隔的。
-i 或 --ignore-case:比较时不区分大小写。
-s 或 --skip-chars=N:忽略每行的前 N 个字符。
-u 或 --unique:仅显示唯一的行(即不重复的行)。
-z 或 --zero-terminated:以空字符(\0)而不是换行符来分隔行。这通常在处理以空字符结尾的文件名列表时很有用。
​
tr
"tr" 通常在不同的上下文中有不同的含义,但最常见的是指 Unix/Linux 系统中的一个命令行工具,名为 tr(translate 或 delete characters)。这个工具用于对从标准输入读取的字符进行替换、删除或压缩。
​
以下是一些 tr 的基本用法示例:
替换字符:
---------------------------------
echo "hello world" | tr 'o' 'O'  
# 输出: hEllO wOrld
---------------------------------
​
删除字符:
---------------------------------
echo "hello world" | tr -d 'o'  
# 输出: hell wrld
---------------------------------
​
压缩字符:
---------------------------------
echo "hello    world" | tr -s ' '  
# 输出: hello world
---------------------------------
​
转换大小写:
---------------------------------
echo "HELLO WORLD" | tr '[:upper:]' '[:lower:]'  
# 输出: hello world
---------------------------------
其他提取数值
怎么取根分区磁盘使用率及剩余内存:
df -h | grep root | awk '{print $(NF-1)}' | cut -d% -f1
返回结果:5  (不加最后一段cut,则会显示5%)
​
free -m | awk '/^Mem/{print $4}'
返回结果:3608
======================================
怎么取ip地址:
ip -f inet a show dev ens33
-f指要显示的网络地址族,inet指显示ipv4的地址族,show代表要显示的信息,dev要显示哪个网络接口信息,ens33显示ens33的网络结构信息
返回结果:
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    inet 192.168.253.131/24 brd 192.168.253.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
提取ip地址:
ip -f inet a show dev ens33 | awk 'NR==2{print $2}' | cut -d/ -f1
返回结果:192.168.253.131
cut 从文本中截取指定列的命令 -d以什么字段分隔 -f要打印哪个字段
======================================
哪个用户登录过终端:
w -h | awk '{print $1}' | sort | uniq -c | awk '{print $2}'     显示哪个用户登录过终端
sort 将出现的字符全部排序
uniq -c 将出现的字符统计次数,并且归结为一类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值