标签搜索
MemoryCloud Blog

Shell总结

kennedy
2024-02-01 / 0 评论 / 24 阅读 / 正在检测是否收录...

Shell

07eb477fbbe021eea60e70aac6f5d71

linux内核(kernel),操作计算机硬件资源,告诉CPU干什么、需要多少内存...

linux用户操作作用在外层应用程序,内核不能直接识别用户的操作指令,需要借助Shell命令行解释器(解释、调用程序,向内核发起申请),才能让内核完成命令操作

查看Linux下的shell的解释器

c7eaba29814c029df39b3dd5e0c64c5

默认bash shell

dbe9c253786265ccc3e3d8c2cc28c04

Hello Word案例

shell脚本一般一.sh为后缀,且第一行必须是 #!/bin/bash 或者 #!/bin/sh

执行脚本

1.sh、bash + 脚本相对或绝对路径

2.对文件添加可执行权限X,./脚本文件执行

3.对文件添加可执行权限X,用 “.” 或者“source” + 文件相对路径或绝对路径==不会启动子shell==

==.和./执行的逻辑不一样,.是命令,./是当前目录下执行某文件==

变量

全局变量:当前的shell和子shell都可以访问

局部变量:只对当前shell有作用,其余子shell和父shell都不管用

1.常用系统变量

$HOME 家目录

$PWD 当前目录

查看全部全局变量:env 或者printenv==(只是系统的全局变量)==

c687fa27445c8b03583bb82c88bc736

查看具体某一个环境变量:printenv + 变量名

a506406e65d69c3c95f7ea86c59b30f

set查看系统的全局变量和局部变量,==包括自己定义的==

04ace77460452cda2a75a4560329086

自定义变量(默认定义为字符串)

局部变量

变量名=变量值,===前后不能有空格==

变量值如果有空格,使用双引号

myname=“wang tao”

全局变量

export myname,寓意为导出,子shell即可生效

如果在子shell更改,退出子shell后不生效,只在子shell或者子shell的子shell生效

查看子shell进程 ps -f,bash启动新子shell

==局部变量输出==

1.使用“.”或者“source”,在当前shell执行,不启动子shell即可生效

2.使用export将局部变量变为全局变量

只读变量(不能更改的常量)
readonly a=wang

d9190e0c821d2af74e47c0f1e07b40f

变量常量的撤销

unset + 变量名,==常量不可uset==

变量名规则

1.不能以数字开头,==环境变量名建议大写==

2.bash中默认变量类型为字符串类型,无法直接数值运算

3.变量值有空格,需要用单/双引号

创建脚本命令

将脚本文件放在/bin/下,输入脚本文件名即可执行(带后缀)

15699e9dddc56c7144cc1cb30ba10d1

特殊变量

1.$n

$n(n为数字,0表示脚本名称,(1-9)表示第一到第九个参数),十以上的参数需要用{},{10}

示例

#!/bin/sh
echo "Hello Word! SH "
echo "Hello,$1"
echo "Hello $0"

执行

# ./hello.sh wangtao
Hello Word! SH 
Hello,wangtao
Hello ./hello.sh

单引号中不会编译特殊符号,会按照源字符输出

#!/bin/bash
echo '========$0========='
echo script name: $0
echo 1st paramater: $1
echo 2nd parameter: $2
# ./part wang liu
========$0=========
script name: ./part
1st paramater: wang
2nd parameter: liu
2.$

获取当前输入参数的个数,常用于循环(参数个数失败会报错)

#!/bin/bash
echo '========$0========='
echo script name: $0
echo 1st paramater: $1
echo 2nd parameter: $2
echo parameter number: $#
[root@sre_shell ~]# ./part wang liu
========$0=========
script name: ./part
1st paramater: wang
2nd parameter: liu
parameter number: 2
3.$*

$* :代表命令行中所有的参数,会把所有参数看成一个整体

$@:代表命令行所有参数,把每个参数区分对待(数组)

echo $*
echo $@
# ./part wang liu
wang liu
wang liu

不加"" 两者没有区别

[root@sre_shell ~]# cat parameter_for.sh 
#!/bin/bash
echo '$*'
for para in "$*"
do
    echo $para
done
echo '$@'
for para in "$@"
do
    echo $para
done
[root@sre_shell ~]# ./parameter_for.sh a b c e
$*
a b c e
$@
a
b
c
e
4.$?

返回最后一次执行命令返回状态,如果为0,表示成功执行,如果非0(不同数值表示不同错误),表示不正确

58ad1fe4982bba2668cf869b69575e5

运算符

赋值默认为字符串,不可直接做运算

expr 1 + 1,expr 3 * 9 注意有空格

赋值格式
[root@sre_shell ~]# a=$((1+9))
[root@sre_shell ~]# echo $a
10
[root@sre_shell ~]# a=$[9*3]
[root@sre_shell ~]# echo $a
27
[root@sre_shell ~]# a=$[(2+3)*4] && echo $a
20
expr赋值格式
[root@sre_shell ~]# a=$(expr 9 \* 2)  
[root@sre_shell ~]# echo $a
18

[root@sre_shell ~]# a=`expr 9 / 3`
[root@sre_shell ~]# echo $a        
3
加法脚本
[root@sre_shell ~]# cat add.sh 
echo $[$1+$2]
[root@sre_shell ~]# ./add.sh 2 3
5
条件判断

基本语法 test + 条件表达式(==前后面有空格,否则都为0==)

[root@sre_shell ~]# test $a = hello
[root@sre_shell ~]# echo $?
0
[root@sre_shell ~]# test $a = hell
[root@sre_shell ~]# echo $?       
1

等价于==[ ]也有空格==

[root@sre_shell ~]# [ $a = hello ]
[root@sre_shell ~]# echo $?
0
[root@sre_shell ~]# [ $a = hell ] 
[root@sre_shell ~]# echo $?      
1

= ,!=是判断字符串是否相等  
[ 2 != 2 ]    1 这里比较的是字符串比较
-a -o

在同一个[ ]中可以用-a参数表示&&,-o表示||

[root@sre_shell ~]# echo $a
20
[root@sre_shell ~]# if [ $a -gt 18 ] && [ $a -lt 30 ]; then echo OK; fi
OK
[root@sre_shell ~]# if [ $a -gt 18 -a $a -lt 30 ]; then echo OK; fi
OK

[root@sre_shell ~]# if [ $a -gt 30 -o $a -lt 18 ]; then echo OK; fi      
[root@sre_shell ~]# 

[] 空值为 1 (假)

数值之间的比较参数

-eq 等于 -ne 不等于 -lt 小于

-le小于等于 -gt大于 -ge大于等于

[root@sre_shell ~]# echo $?
0
[root@sre_shell ~]# [ 8 -eq 8 ]
[root@sre_shell ~]# echo $?    
0
[root@sre_shell ~]# [ 8 -ne 8 ] 
[root@sre_shell ~]# echo $?    
1
[root@sre_shell ~]# [ 8 -lt 8 ]  
[root@sre_shell ~]# echo $?    
1
[root@sre_shell ~]# [ 8 -le 8 ] 
[root@sre_shell ~]# echo $?    
0
[root@sre_shell ~]# [ 8 -gt 8 ]  
[root@sre_shell ~]# echo $?    
1
[root@sre_shell ~]# [ 8 -ge 8 ] 
[root@sre_shell ~]# echo $?    
0
判断文件权限

-r 有读的权限 -w 有写的权限 -x有执行的权限

[root@sre_shell ~]# ls -l part 
-rwxr-xr-x. 1 root root 148 Mar  4 08:01 part
[root@sre_shell ~]# [ -r part ] && [ -w part ]
[root@sre_shell ~]# echo $?                   
0
判断文件类型

-e 表示文件存在 -f 表示存在且是一个常规文件 -d存在且是目录

[root@sre_shell ~]# ls
add.sh  anaconda-ks.cfg  hello.sh  part  test
[root@sre_shell ~]# [ -e part ]
[root@sre_shell ~]# echo $?
0
[root@sre_shell ~]# [ -f part ] 
[root@sre_shell ~]# echo $?    
0
[root@sre_shell ~]# [ -d part ]  
[root@sre_shell ~]# echo $?    
1
[root@sre_shell ~]# [ -d test ]
[root@sre_shell ~]# echo $?    
0
==案例(三元)==

A&&B||C:A真执行B,否则执行C

[root@sre_shell ~]# [ $a -lt 300 ] && echo "$a<300" || echo "$a>300"
200<300

[]有字符串为真,空为假
[root@sre_shell ~]# [ ] && echo "ok" || echo "nook"
nook

流程控制

1.if
单分支
if [ 条件判断 ];then   #常用于命令行
    程序
fi
或者
if [ 条件判断 ]        #常用于文本脚本
then
    程序
fi
例
[root@sre_shell ~]# if [ $a -gt 18 ]; then echo OK; fi
OK

==传参防空==

[root@sre_shell ~]# cat iftest 
#!/bin/bash
if [ "$1"x = "wang"x ] #字符串拼接原理,保证有一个字母
then
        echo "hello,$1"
fi
多分支
if [ 条件判断 ]
then
    程序
elif [ 条件判断 ]
then
    程序
else
    程序
fi

if [ $2 -lt 22 ]
then
        echo "<22"
elif [ $2 -lt 25 ]
then
        echo "<25"
else
        echo ">25"
fi

[ ]中的条件判断两边必须要有空格 ,if elif 后面有空格

2.case
case $变量名 in
"值1")
    如果变量=值1,执行程序1
;;
"值2")
    如果变量=值2,执行程序2
;;
*)
    都不满足就执行此程序
;;
esac
[root@sre_shell ~]# ./case.sh 40
年轻
[root@sre_shell ~]# ./case.sh 60
老了
[root@sre_shell ~]# ./case.sh 30
加油
[root@sre_shell ~]# cat case.sh 
#!/bin/bash
case $1 in
"60")  # 60)可以不用""
        echo "老了"
;;
"40")
        echo "年轻"
;;
*) 
        echo "加油"
;;
esac
循环
1.for
for ((初始值;循环控制条件;变量变化))
do
    程序
done
[root@sre_shell ~]# chmod +x for.sh 
[root@sre_shell ~]# ./for.sh 
5050
[root@sre_shell ~]# cat for.sh 
#!/bin/bash
sum=0
for((i=0;i<=100;i++))
do
        sum=$[$sum+$i]  #内层$只是字符串拼接,外层$[]是按数值运算
done
echo $sum

传参式

[root@sre_shell ~]# cat sum1.sh 
#!/bin/bash
sum=0
for (( i=1;i<=$1;i++))
do
        sum=$[ $sum + $i ]
done
echo $sum
[root@sre_shell ~]# ./sum1.sh 100
5050
2.定值for
#!/bin/bash
for os in linux windows macos
do
    echo $os
down

[root@sre_shell ~]# ./dfor  
linux
windows
macos

[root@sre_shell ~]# for os in window linux macos; do echo $os;done
window
linux
macos
3.增强型{1..100}
[root@sre_shell ~]# for i in {1..100}; do sum=$[$sum+$i]; done; echo $sum
5050
[root@sre_shell ~]# ./for.sh 
5050
[root@sre_shell ~]# cat for.sh 
#!/bin/bash
sum=0
for i in {1..100}
do
    sum=$[$sum+$i]  #内层$只是字符串拼接,外层$[]是按数值运算
done
echo $sum
4.while循环
while [ 条件判断 ]#循环外的初始值
do
    程序 #包含程序结束条件
done
[root@sre_shell ~]# cat while.sh 
#!/bin/bash
a=1
while [ $a -le $1 ]
do
    sum2=$[$sum2+$a]
    a=$[$a+1]
done
echo $sum2
[root@sre_shell ~]# ./while.sh 100
5050
5.let(转义别的语法==C==)

let+C语言语法

#!/bin/bash
a=1
while [ $a -le $1 ]
do
    let sum2+=a
    let a++
done
echo $sum2

读取控制台

read读取控制台

从控制台读取用户的输入

read (选项) (参数) #有空格
-p 输入前的提示符
-t 指定等待时间(不加表示一直等待)
参数 指定读取值的变量名
[root@sre_shell ~]# cat read.sh 
#!/bin/bash
read -t 10 -p "请输入:" name #注意空格
echo "Hello $name"
[root@sre_shell ~]# ./read.sh 
请输入:wang
Hello wang

read+条件判断

[root@sre_shell ~]# cat read.sh 
#!/bin/bash
read -t 3 -p "请输入:" name
if [ $name ]
then
    echo "Hello $name"
else
    echo "no name"
fi

[root@sre_shell ~]# ./read.sh 
请输入:wang
Hello wang

[root@sre_shell ~]# ./read.sh 
请输入:no name

函数

系统函数

轻量化脚本

==变量+系统时间戳==
[root@sre_shell ~]# cat namedate.sh 
#!/bin/bash
filename="$1"_logtime_$(date +%s)
echo $filename

[root@sre_shell ~]# ./namedate.sh testname
testname_logtime_1709686703

[root@sre_shell ~]# date +%s
1709686712
==basename==

截取文件路径的文件名称(去掉路径也可去掉后缀)

basename /home/test/wang.test
wang.test
basename /home/test/wang.text .text
wang

==实际用法:生产带时间戳、拼接等字符串时 不能带上文件路径和后缀==

[root@sre_shell ~]# cat srcipt.sh 
#!/bin/bash
echo script_name: $0

[root@sre_shell ~]# ./srcipt.sh 
script_name: ./srcipt.sh

[root@sre_shell ~]# /root/srcipt.sh 
script_name: /root/srcipt.sh  #$0会取到文件路径和后缀

改进
#!/bin/bash
echo script_name: $(basename $0 .sh) #用()添加系统命令

[root@sre_shell ~]# ./srcipt.sh 
script_name: srcipt
dirname

和basename相反,==截取最后一个/之前的路径==

不管相对还是绝对路径,当做字符串处理,截取最后/前字符

[root@sre_shell ~]# dirname /root/while.sh 
/root
[root@sre_shell ~]# dirname /root/wang/test
/root/wang    #不管路径或者文件存不存在

脚本输出文件绝对路径

即使使用相对路径调用脚本也会获取绝对路径

[root@sre_shell ~]# cat dirname.sh 
#!/bin/bash
cd $(dirname $0)
echo script path: $(pwd)
简化
[root@sre_shell ~]# cat dirname.sh 
#!/bin/bash
echo script path: $(cd $(dirname $0); pwd)  #dirname有可能读取是相对路径,使用pwd获取绝对路径
[root@sre_shell ~]# ./dirname.sh 
script path: /root

自定义函数

function functionname()
{
    Action;
    [return int;]
}
必须在调用函数前声明函数,shell是逐行运行
函数返回值只能通过$?获取,return返回 如果不加就以最后一条命令运行结果作为返回值,return后跟数值n(0-255)

函数定义和调用

[root@sre_shell ~]# cat funtionname.sh 
#!/bin/bash
function sum()
{
    s=$[$1+$2]
    echo "sum="$s
}
read -p "number1: " a
read -p "number2: " b
sum $a $b

[root@sre_shell ~]# ./funtionname.sh 
number1: 23
number2: 43
sum=66

有返回值

[root@sre_shell ~]# cat funtionname.sh 
#!/bin/bash
function sum()
{
    s=$[$1+$2]
    return $s
}
read -p "number1: " a
read -p "number2: " b
sum $a $b
echo $?  # $?的取值范围是0-255,超出即进入下一次循环

[root@sre_shell ~]# ./funtionname.sh 
number1: 255
number2: 5
sum=4

优化

用return后,¥?只能捕获0-255,所以不用$?捕获

#!/bin/bash
function sum()
{
    s=$[$1+$2]
    echo $s
}
read -p "number1: " a
read -p "number2: " b
sum=$(sum $a $b)   #将函数echo的值转换并赋值
echo "sum="$sum
echo "sum^2="$[$sum*$sum] #二次计算

正则

​ 正则表达式使用单个字符申来描述、匹配一系列符合某个语法规则的字符串。在很多文本编辑器里,正则表达式通常被用来==检索、替换那些符合某个模式的文本==。在Linux中,grep,sed,awk等文本处理工具都支持通过正则表达式进行模式匹配。

用来定义一个模糊检索规则

常用于模糊检索;以什么开头的IP、什么结尾的文件

1.常规匹配

[root@kernel_shell archive]# cat /etc/passwd | grep wang
wang:x:1000:1000::/home/wang:/bin/bash

2.常用特殊字符

^ ;匹配一行的开头

可以接一个字符和一个字符串

[root@kernel_shell archive]# cat /etc/passwd | grep ^w  #以w字母开头的
wang:x:1000:1000::/home/wang:/bin/bash
wangtao:x:1001:1001::/home/wangtao:/bin/bash
$ ;匹配一行的结束

h$ 匹配以h结尾的行

[root@kernel_shell archive]# cat /etc/passwd | grep h$
root:x:0:0:root:/root:/bin/bash
wang:x:1000:1000::/home/wang:/bin/bash
wangtao:x:1001:1001::/home/wangtao:/bin/bash

如果同时出现^,$,中间匹配的字符必须是和那一行一模一样才会匹配成功

[root@kernel_shell archive]# cat /etc/passwd | grep ^wang:x:1000:1000::/home/wang:/bin/bash$
wang:x:1000:1000::/home/wang:/bin/bash
[root@kernel_shell archive]# 

^,$之间如果没有字符,则是匹配空行

[root@kernel_shell archive]# cat /root/archive/kong.sh | grep -n ^$
1:
2:k



3:
4:
[root@kernel_shell archive]#
-n 显示空行所在的行号
“ . ” 任意一个字符

“ . ”匹配任意==一个==字符

[root@kernel_shell archive]# cat /etc/passwd | grep r..t
#r和t之间只有两个字符的
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
dockerroot:x:997:994:Docker User:/var/lib/docker:/sbin/nologin
“ * ”上个字符0此和多次

匹配*前面字符0此和多次

[root@kernel_shell archive]# cat /etc/passwd | grep ro*t
#匹配到有 rt、rot、root、roooot......等的行

.*可以匹配任何行

==^$,.*联用==

.*可用于限定开头和结尾,不限定中间字符的正则

[root@kernel_shell archive]# cat /etc/passwd | grep ^w.*sh$
wang:x:1000:1000::/home/wang:/bin/bash
wangtao:x:1001:1001::/home/wangtao:/bin/bash
[root@kernel_shell archive]# cat /etc/passwd | grep ^a.*var.*in$
# a任意var任意in的行
adm:x:3:4:adm:/var/adm:/sbin/nologin
字符串区间“[]”

[ ] 表示匹配某个范围的一个字符

[6,8]:匹配6或8

[0-9]:匹配0-9的数字

[0-9]*:匹配任意长度的数字字符串

[a-z]:匹配一个a-z之间的字符

[a-z]*:匹配任意长度的字母字符串

[a-c,e-f]:匹配a-c或者e-f之间的任意字符

[root@kernel_shell ~]# cat /etc/passwd | grep r[a,b]t #可以不加“,”

[root@kernel_shell ~]# echo "raaaabbbbabat" | grep r[ab]*t
raaaabbbbabat

[root@kernel_shell ~]# echo "rabt" | grep r[ab]t 
无结果,[ab],[a,b]都只匹配一个字符a,b

[root@kernel_shell ~]# cat /etc/passwd | grep r[a-z]*t
转义

特殊字符无法加入正则,需要借助转义符号 \

[root@kernel_shell ~]# cat read.sh | grep '\$'
if [ $name ]
    echo "Hello $name"
    
匹配的字符串:'/root/\$name'

判断合法手机号码

[root@kernel_shell ~]# echo 17628274871 | grep ^1[3456789][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]       
17628274871
[root@kernel_shell ~]# echo 12628274871 | grep ^1[3456789][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] 
[root@kernel_shell ~]# 

脚本

[root@kernel_shell ~]# cat phonenumber.sh 
#!/bin/bash
read -p "请输入手机号码:" number
number=$[$(echo $number | grep ^1[3456789][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$)]
if [ $number -eq 0 ]
then
        echo "手机号格式错误"
else
        echo "手机号格式正确"
fi 
[root@kernel_shell ~]# ./phonenumber.sh 
请输入手机号码:17628274871
手机号格式正确
[root@kernel_shell ~]# ./phonenumber.sh 
请输入手机号码:12545698965
手机号格式错误
[root@kernel_shell ~]# ./phonenumber.sh   
请输入手机号码:175282448911
手机号格式错误

正则优化

==-E参数==表示支持扩展正则表达:{},?......

grep -E ^1[3456789][0-9]{9}$
#出现9次

文本处理工具

cut

负责剪切数据,cut从文件的每一行剪切字节、字符、字段并将这些字节字符字段输出;

cut [选项参数] filename ls | cut (捕获剪切)

选项参数功能
-f列号,提取第几列
-d按照指定分隔符分割列,默认制表符“t”
-c按字符切割,后加n表示取第几列:-c 1

-d从第一行开始,遇到“”中匹配的字符中断,不包含本字符,作为一列,进入下一行

[root@kernel_shell ~]# cat cut.txt 
name  age   address
wang  20    sichuan
liu   24    bazhong
zhang 32    guiyang

[root@kernel_shell ~]# cut -d " " -f 1 cut.txt 以空格为分割 
name
wang
liu
zhang
[root@kernel_shell ~]# 

[root@kernel_shell ~]# cut -d "a" -f 1 cut.txt  
n
w
liu   24    b
zh
[root@kernel_shell ~]# 

区间剪切

[root@kernel_shell ~]# cut -d " " -f 2,3 cut.txt 
表示将每行以“ ”空格隔开,提取第二列和第三列
 age
 20
 
32 
[root@kernel_shell ~]# cat /etc/passwd | grep bash$ | cut -d ":" -f 1,6,7
root:/root:/bin/bash
wang:/home/wang:/bin/bash
wangtao:/home/wangtao:/bin/bash

-f 7- :7行以后

-f -4 :4行之前

[root@kernel_shell ~]# echo $PATH | cut -d ":" -f 3-
/usr/sbin:/usr/bin:/root/bin

截取IP地址

==有多少空格就算多少列==

[root@kernel_shell ~]# ip a | grep ens33$ | cut -d " " -f 6
192.168.10.144/24
[root@kernel_shell ~]#

awk(gawk)

grep+cut

文本分析工具,把文件逐行读入,以空格为默认分隔符将每行就行切片,切片的部分再进行分析处理;

awk [选项参数] '/pattern/{action} /pattern2/{action}...' filebame
pattern: 表示awk在数据中查找的内容,就是匹配模式
action: 在找到匹配内容时所执行的一系列命令

-F:指定输入文件分隔符

-v:赋值一个用户定义变量

搜索passwd 文件以root关键字开头的所有行,并输出该行的第7列。

[root@kernel_shell ~]# awk -F : '/^root/{print $7}' passwd 
/bin/bash
: 表示指定分割字符为 :  ,
讲符合正则的代码块切片,每个参数代表列号

等价
[root@kernel_shell ~]# cat passwd | grep ^root | cut -d ":" -f 7 
/bin/bash

搜索passwd 文件以root关键字开头的所有行,并输出该行的第1列和第7列,中间以“,”号分割。

[root@kernel_shell ~]# awk -F : '/^root/{print $1","$7}' passwd  
root,/bin/bash

grep+cut不好实现
[root@kernel_shell ~]# cat passwd  | grep ^root | cut -d ":" -f 1","7
root:/bin/bash

只显示/etc/passwd的第一列和第七列,以逗号分割,且在所有行前面添加列名user,shell 在最后一行添加"dahaige,/bin/zuishuai"。

[root@kernel_shell ~]# awk -F : 'BEGIN{print "user, shell"} {print $1","$7} END{print "dahaige,/bin/nihao"}' passwd 
user, shell
wang,/bin/bash
wangtao,/bin/bash
dahaige,/bin/nihao

==BEGIN在所有数据读取前执行,END在所有数据执行之后执行==

将passwd文件中的用户id增加数值1并输出

[root@kernel_shell ~]# awk -F ":" '{print $3+1}' passwd 

用户定义参数优化

[root@kernel_shell ~]# awk -F ":" -v i=1 '{print $3+i}' passwd 
awk内置变量

FILENAME:文件名
NR:已读的记录数(行号)
NF:浏览记录的域的个数(切割后,列的个数)

统计passwd文件名,每行的行号,每行的列数

[root@kernel_shell ~]# awk -F ":" '{print "文件名:" FILENAME"行号:"NR "列数:"NF}' passwd 
文件名:passwd行号:22列数:7
文件名:passwd行号:23列数:7

awk输出空行行号

[root@kernel_shell ~]# cat awk_kong.txt | awk '/^$/ {print NR}'
2
4
5

如果使用grep,默认格式会带“:”且无法更改
[root@kernel_shell ~]# cat awk_kong.txt | grep -n ^$
2:
4:
5:

优化捕获IP

[root@kernel_shell ~]# ip a | awk -d  '/ens3.$/ {print $2}'
192.168.10.144/24

综合案例

归档文件

实际生产中需要对重要数据就行归档备份

需求:实现一个每天对指定目录备份的脚本;输入一个目录名称(末尾不带/),将目录下的所有文件按天归档保存,将日期附加在归档文件名上,放在/root/archive下。

tar -c表示归档、-z表示压缩,后缀为.tar.gz

#!/bin/bash
#判断输入参数是否唯一
if [ $# -ne 1 ]
then
        echo "参数个数错误(一个参数作为归档目录名)"
        exit
fi

#从参数中获取目录名称
if [ -d $1 ] #判断目录是否存在
then
        echo
else
        echo "目录不存在"       
        exit
fi

dirname=$(basename $1)
dirpath=$(cd $(dirname $1); pwd)

#获取当前日期
date=$(date +%y%m%d)

#定义生成的归档文件名称

filename=archive_${dirname}_$date.tar.gz
dest=/root/archive/$filename

#开始归档
echo "开始归档"

tar -czf $dest $dirpath/$dirname

if [ $? -eq 0 ]
then
        echo "归档成功!"
        echo "归档文件为:$dest"
else
        echo "出现错误;"
        echo
fi

exit

[root@kernel_shell archive]# ls
archive_archive_240306.tar.gz  dayarc.sh

定时任务的设定

crontab -e -u root

* 2 * * * /root/archive/dayarc.sh /root/archive  #每天凌晨两点
[root@kernel_shell archive]# crontab -l
* 2 * * * /root/archive/dayarc.sh /root/archive

发送消息

利用linux自带的mesg和write工具,向其他用户发送消息

需求:实现向某个用户快速发送消息的脚本,输入用户作为第一个参数,后面接着需要发送的消息。脚本需要检测用户是否登录在系统中,是否打开消息功能,以及发送内容是否为空...

#!/bin/bash

#检测/passwd/文件是否存在输入的用户
#此模块尚未完善 可去除不影响正常功能
check_user=$(cat/etc/passwd | awk -d ":" -f 1 )
if [ -z check_user ]
then
    echo "未检索到用户$check_user!"
    echo "脚本退出!"
    exit
else
    sleep 1
    echo "检索到$check_user 用户"

# 1查看用户是否登录
login_user=$(who | grep -i -m 1 $1 | awk '{print $1}')
#  -i表示过滤忽略大小写  -m表示匹配最大值,只取第一个

if [ -z $login_user ]  #-z参数查看字符串是否为空
then
    echo "$1 不在线!"
    echo "脚本退出!"
    exit
else
    sleep 1
    echo "$1 检索在线"
fi

# 2查看用户是否开启mesage
is_allowed=$(who -T | grep -i -m 1 $1 | awk '{print $2}')

if [ $is_allowed != "+" ]
then
    echo "$1 没有开启mesage功能!"
    echo "脚本退出!"
    exit
else
    sleep 1
    echo "$1 mesage状态正常;"
fi

# 3判断消息内容是否为空
if [ -z $2 ]
then
    echo "消息为空!"
    echo "脚本退出!"
    exit
else
    sleep 1
    echo "开始发送消息"
fi

#从参数中获取要发送的消息
whole_msg=$(echo $* | cut -d " " -f 2-)


#获取用户登录终端
user_terminal=$(who | grep -i -m 1 $1 | awk '{print $2}')

#写入发送的消息
echo $whole_msg | write $login_user $user_terminal

if [ $? != 0 ]
then
    echo "消息发送失败!"
else
    echo "消息发送成功!"
fi
sleep 2
echo "脚本执行结束!"
1

评论

博主关闭了所有页面的评论