Linux脚本:Bash脚本看这一篇就够了

前言

Linux脚本有很多解析器(Shell),不同解析器要求的脚本语法是不一样的。系统在解析脚本时,如果没有在脚本声明指定解析器,则会采用系统默认解析器来对脚本进行解析。sh是非常重要解析器,历史很悠久,地位很牢固。特别地,Bash是用途最广的Shell,而且是兼容sh的解析器,因此本文着重Bash Shell的研究。

一、脚本编程基本知识

1、脚本的编程方式

脚本的编写方式一般是在Linux上进行的,如果Linux有图形界面,那可以跟windows一样操作,如使用一些第三方应用VS去编写。如果Linux没有图形界面,则需要了解并学习”vi“或"vim"命令(还有其他命令请自查)的使用,推荐使用vim

2、声明Bash Shell

声明使用的解析器,可避免系统采用默认解析器去运行脚本带来的可能的错误。

#!/bin/bash

# 第一行的“井号+感叹号+脚本解释器程序路径”,说明这是一个可执行的脚本
# 任意行的单独的”井号“都是注释作用,非第一行的“井号+感叹号“也是注释作用
# 避免问题:你的脚本是Bash Shell,系统默认的是Csh,若不声明,那么你的脚本运行错误

 3、脚本的执行权限

Linux脚本 不以 后缀来判断它是否可执行,而是以命令 ”ls -l“ 来查看它是否是可执行文件,可使用chmod来变更脚本权限(该命令使用方式请自查文档),这样才能运行。

4、脚本的组织方式

脚本是由命令组成的,而命令的执行都是单独的,即使报错也不影响下一条命令的执行;一行语句可以包含多个命令,用";"隔开。

#!/bin/bash
# 运行cat命令,假使文件不存在
cat nobody.txt
echo $(pwd)
echo "nobody.txt不存在,也执行了pwd命令"
cat nobody.txt;echo $(pwd);
echo "nobody.txt不存在,就算写成一整条语句,也执行了pwd命令"

二、通过脚本学语法

1、标准输入与标准输出

脚本功能:根据脚本提示,手动给脚本输入一些文字,让脚本打印这些信息。

这里需要使用标准输出echo去提示用户操作,使用标准输入read读取用户输入的信息,使用printf将信息打印出来。

#!/bin/bash
# 给用户提示信息
echo "请告诉我你想做什么?"
# 使用read指令和work变量去接收用户的信息
read work
echo "你告诉我的信息我知道了,我使用printf命令去打印了你的信息:"
printf ${work}

(1)echo命令介绍

① echo将给定的每个字符串写入标准输出,每个字符串之间有一个空格,最后一个字符串后面有一个换行符。因此,可以直接这样使用:

echo "I" "Love" "me"

 ②由于shell别名和内置的echo函数,交互式地或在脚本中使用无修饰的echo可能会获得与这里描述的不同的功能。为避免shell的干扰,可以这样使用echo:

env echo "123"

 ③由于历史和向后兼容的原因,某些裸露的选项类字符串不能作为非选项参数传递给echo。因此,可以通过printf来替代echo,进而避免这样的问题。比如,我想打印 -n 这个字符串,因为echo的选项里是有 -n 的,他会把字符串当作指令来用,因此执行如下指令是不输出的:

echo "-n"
echo -n

 ④一些格式化输出可以参照官方文档,或使用 ”man echo“ 查看,如设置末尾不输出回车:

echo invocation (GNU Coreutils 9.1)echo invocation (GNU Coreutils 9.1)icon-default.png?t=N7T8https://www.gnu.org/software/coreutils/manual/html_node/echo-invocation.html#echo-invocation

(2)read命令介绍

①从标准输入中读取一行,并将其拆分为多个字段。这些字段是以空格进行分配,分配方式可根据选项进行更改,默认分配方式如下:

$ read a b
asdasd asdas asdasd
$ echo $a
asdasd
$ echo $b
asdas asdasd

②可通过数组的方式 获取,如增加选项 -a ,更多选项请查阅官方文档,现展示如下:

$ read -a a
i love you !
$ echo ${a[@]}
i love you !
$ echo ${a[1]}
love

(3)printf命令介绍

从”(1)echo命令介绍“中,我们已经了解到echo的痛点,而解决这个痛点的方式是使用printf替代。printf 命令是模仿 C 程序库(library)里的 printf() 程序,而使用 printf 的脚本比使用 echo 移植性好。实际上,printf在格式化方面优势更大,展示如下:

printf "%-10s %-10s %-10s\n" 年级 班级 姓名;

(4)变量的引用

${work}是变量引用的方式之一,可以写成 $work,建议使用${work}方式,方便阅读。

2、数学运算

脚本功能:根据脚本提示手动输入数字,进行运算

#!/bin/bash
echo "请输入第一个数字:"
read one
one_int=$((10#${one}))
echo "请输入第二个数字:"
read two
two_int=$((10#${two}))
res=$((one_int+two_int))
res1=$((one_int-two_int))
res2=$((one_int*two_int))
res3=$((one_int/two_int))
res4=$((one_int%two_int))
res5=$((one_int**two_int))

echo 'echo单引号输出相加结果:${res}'
echo "echo双引号输出相加结果:${res}"

printf "printf双引号输出相加结果为:${res}\n"
printf 'printf单引号输出相加结果为:${res}\n'

printf "%-10s %-10s %-6s %-6s %-6s %-10s %-10s %-6s \n" 输入值1 输入值2 加 减 乘 除以 取余 幂
printf "%-7d %-7d %-5d %-5s %-5s %-8s %-8s %-5s \n" ${one_int} ${two_int} ${res} ${res1} ${res2} ${res3} ${res4} ${res5}

(1)运算的实现

①使用 (())实现运算,语法为 $((one_int+two_int));

②使用反引号实现,如a=`expr 1 + 2`。

(2)变量的简单赋值

使用等号进行赋值,中间不能有空格,实际上,空格在Linux脚本中非常重要,不能随意加空格或去掉空格,赋值的语法为 var=value。

(3)双引号与单引号

双引号内部可以引用变量,单引号会拒绝引用而原样输出

(4)运算符号

详见脚本的使用,表示如下:加(+)、减(-)、乘(*)、除(/)、取余(%)、幂(**)

(5)字符串转数字

字符串转数字的方法有很多,如使用sed或awk命令,这里采用的是$((10#${one})),10#代表转成10进制。

3、参数变量的引用

脚本功能:将参数变量的获取封装成函数,并打印这些结果

#!/bin/bash

#定义函数
function func(){
    printf "当前脚本名称:                 %s\n" $0
    printf "输入给脚本的第一个参数:       %s\n" $1
    printf "输入给脚本的参数数量:         %s\n" $#
    printf "输入给脚本的所有参数的数组:   $*\n"
    echo "输入给脚本的所有参数的数组:   $@"
    printf "上一条命令的执行情况:         %s\n" $?
    printf "当前脚本PID:                  %s\n" $$
}

#调用函数
func 参数1 参数2

(1)使用参数变量的注意事项

①$*与 $@不同点:不被双引号包裹时,二者相同,均为数组类型;当被双引号包裹时,$@没有变化,而$*的所有参数被整合为一个字符串。

②$?在上个命令执行成功时,返回0;失败时,为其它数值。

③$!表示后台运行的最后一个进程的ID号,请自行学习。

④$-表示显示Shell使用的当前选项,与set命令功能相同,请自行学习。

(2)函数封装与调用

①定义函数与引用函数的基本方式如脚本所示,关键词为function,本节暂不深入研究。

4、自定义变量的操作

脚本功能:展示不同的变量赋值方式,并将他们的结果全部打印。

#!/bin/bash
#变量的简单赋值,等号2边不能有空格,否则解析成命令,单引号与双引号有些区别,见上节描述
var_1=1
var_2="$0"
var_3='$0'
#变量的引用与修改,被修改的var_1值,不会让引用它的var4被修改
var_4=${var_1}
printf "var_1修改前:${var_1} \n"
printf "var_4=${var_4} \n"
var_1="1——1"
printf "var_1修改后:${var_1} \n"
printf "var_4=${var_4} \n"
#不被初始化的变量,默认值为null
var_5=
printf "不被初始化的变量var_5=${var_5} \n"
#获取指令变量,可使用$()或反引号``
var_6=$(pwd)
var_7=`pwd`
printf "${var_6} is ${var_7} \n"
#只读变量设置后,不能被删除,删除变量的方法为unset
var_8="我是只读变量"
readonly var_8
unset var_8
printf "${var_8},我不能被删除"

 (1)$() 与 反引号``的异同

都可以用于获取指令结果,但建议使用$(),因为它可以嵌套,而反引号不支持。

5、条件判断语句

脚本功能:判断脚本的参数数量、判断脚本名称、判断脚本的文件分别满足对应的条件然后打印相关信息。

#!/bin/bash

function func(){
#判断传入变量的数字
if [[ $# -eq 4 || $# -gt 4 ]]; then
        printf "传入变量的个数大于或等于4 \n"
elif [ $# -ge 2 ] || [ $# -le 3 ]; then
        printf "传入变量的个数等于2或等于3 \n"
elif [ $# -eq 1 ]; then
        printf "传入变量的个数等于1 \n"
else
        printf "传入变量的个数不在预期范围内 \n"
fi
#判断本脚本名称的字符串
if [[ $0="study_006.sh" ]] || [[ -n $0 ]]
then printf "本脚本名称与期望名称一致, 或脚本名称的长度不为0 \n"
else
        printf "本脚本名称与期望名称不一致,或长度为0 \n"
fi
#使用case语句重写“判断传入变量的数值”
case $# in
        0) printf "传入变量的个数不在预期范围内 \n" ;;
        1) printf "传入变量的个数等于1 \n" ;;
        2) printf "传入变量的个数等于2或等于3 \n" ;;
        "3") printf "传入变量的个数等于2或等于3 \n" ;;
        *) printf "传入变量的个数大于或等于4 \n" ;;
esac
#判断文件属性
if test -e $0 ;then
        printf "本文件存在 \n"
        if [[ -x $0 ]];then
                printf "文件具有执行权限 \n"
        fi
fi
}

func asd asd asd

(1)if语句注意事项

①如上脚本,可以知道语句的基本格式为 "if ... ;then...;fi",可选"else"、"elif...;then..."进行扩展,其中”;“可以使用回车替代。

②条件需要使用[]或[[]]进行包裹,里面语句的两端需要有空格才能被识别为条件,二者用法是有区别的,建议使用[[]],因为可以在里面使用 || 等逻辑操作符,[]是不可以的。

③[]或[[]]可以使用命令test来替代,test的使用例子为 

if  test 1 -eq 1 ;then echo "good";  fi

④书写这些语句时,建议培养使用习惯,如使用分号或使用回车号来构造语句,建议统一使用分号来避免误操作。

⑤if语句可以嵌套

(2)case语句注意事项

①如上脚本,case语句一定条件上可以替换if语句,增强可读性,但功能不算强大。语法为:

case ... in

0) ... ;;

1) ...;;

...

*) ...;;

esac

②假使参数值为数字0,而对应的条件0写成"0"也是可以匹配上的。

③*)表示其它匹配条件,即列举条件之外的情况。

④加入0和1输出结果相同,可通过 | 合并,写成  0|1)

⑤case语句可以嵌套

(3)数字判断使用到的参数

参数说明
-eq等于则为真
-ne不等于则为真
-gt大于则为真
-ge大于等于则为真
-lt小于则为真
-le小于等于则为真

(4)字符串判断使用到的参数

参数说明
=等于则为真
!=不相等则为真
-z 字符串字符串的长度为零则为真
-n 字符串字符串的长度不为零则为真

(5)文件判断使用到的参数

参数说明
-e 文件名如果文件存在则为真
-f 文件名如果文件存在且为普通文件则为真
-d 文件名如果文件存在且为目录则为真
-r 文件名如果文件存在且可读则为真
-w 文件名如果文件存在且可写则为真
-x 文件名如果文件存在且可执行则为真
-s 文件名如果文件存在且至少有一个字符则为真
-c 文件名如果文件存在且为字符型特殊文件则为真
-b 文件名如果文件存在且为块特殊文件则为真

 (6)条件判断使用到的逻辑操作符

①与 的表示方法:&&、-a

要求所有条件为真,则条件为真

②或 的表示方法:||、-o

要求任意条件为真,则条件为真

③非 的表示方法:!

要求条件反转为真时,条件为真

 6、循环语句

 脚本功能:通过打印的方式观察循环的过程,并知道实现的过程。

#!/bin/bash
# 无限循环与强制退出
while true # 可使用 : 代替true
do
        printf "条件true开始打印 \n"
        if [[ $0="study_007.sh" ]];then
                printf "条件true,强制打印结束 \n"
                break
        fi
done

# 有限循环与自动退出
int=0
while (( $int<10 )) # 可使用test、[[]]替代,<等价于-lt,建议数值对比时使用-lt
do
        printf "条件int,第 %s 次打印 \n" $int
        let "int++" # 等价于 (( int++ ))
        if [[ ${int} -eq 10 ]];then
                printf "条件int,打印结束 \n"
        fi
done

# 循环与命令
while pwd # 命令执行失败将不进入循环,如使用cp gogo bb
do
        printf "pwd指令执行为真,开始打印 \n"
        if [[ $0="study_007.sh" ]];then
                printf "pwd指令执行为真,打印结束 \n"
                break
        fi
done

# for无限循环替代while无限循环
for (( ; ; ))
do
        printf "条件true开始打印 \n"
        if [[ $0="study_007.sh" ]];then
                printf "条件true,强制打印结束 \n"
                break
        fi
done

# for有限循环替代while优先循环
for (( int_1=0 ; int_1<10 ; $(( int_1++ )) )) # 不能用 [[]] 替代 (())
do
        printf "条件int_1,第 %s 次打印 \n" $int_1
        # (( int_1++ ))
        # printf "int_1的数值为 ${int_1} \n"
        if [[ ${int_1} -eq 9 ]];then # 因为while的加1在前,而for的加1在后,因此判断条件为9
                printf "条件int_1,打印结束 \n"
        fi
done

# for与数组
arr=(0 1 2 3 4 5 6 7 8 9)
for i in ${arr[@]} # 可使用 arr[*] 替换 arr[@]
do
        printf "arr 为 ${i} \n"
done

# for与可迭代数列(数组的一种)
for i in 0 1 2 3 4 5 6 7 8 9
do
        printf "arr 为 ${i} \n"
done

# for与可迭代文本(数组的一种)
for i in my first book is " i can do it "
do
        printf "arr 为 ${i} \n"
done

# 循环中的continue与break
while :
do
        printf "continue 开始打印 \n"
        if [[ $0="study_007.sh" ]];then
                printf "continue 前一个语句 \n"
                continue
                printf "continue 后一个语句 \n"
        fi
done

(1)while语句注意事项

①循环需要通过条件为真去循环,当然while false是没有意义的,而while true是无限循环的写法之一,可通过break语句强制退出整个循环,通过continue退出后续语句而继续循环。

②用法见本脚本实例,把握关键字do...done

until语句与 while 在处理逻辑上完全相反,但使用方式上完全相同,等价于while false执行,while true不执行。

(2)for语句注意事项

①可以实现while的无限循环和有限循环,但不能像while一样直接判断命令的结果去执行循环,详见本脚本中的”循环与命令“;但是,for可以遍历数组,这个特性是while没有的。

②用法见本脚本实例,把握关键字do...done

③使用for遍历时,如果有双引号的存在,将被认为是一个整体,详见本脚本实例 ”# for与可迭代文本(数组的一种)“

(3)数字判断可以使用符号替代选项

如实例中的 -lt 可以使用 < 替代,建议使用 -lt ,因为当 -eq 时,对应的是 ==,容易混用赋值语句或字符串判断的 = 。

(4)let命令与(())

let命令可以与(())互相替换,使用的时候哪个方便用哪个就好。

(5)(()) 与 [[]]

(())用于整数运算,[[]]用于条件判断,二者不是一回事。while (( $int<10 ))可以使用 [[]]替换(()),但for (( int_1=0 ; int_1<10 ; $(( int_1++ )) ))  不能用 [[]] 替代 (())。原因是(())既可以作为运算使用,也可以作为条件使用,而[[]]只能作为条件使用。当不涉及运算时,[[]]才有可能替换(())。

(6)数组

①如脚本所示,数组的赋值方式采用()来包裹,里面元素采用空格划分

②数组的取值方式采用索引方式,形式如 ${arr[0]}、${arr[@]}、${arr[*]}等

③关联数组(类字典)的实现是以关键字 declare 来实现,使其像字典那样取数据或写数据,例子如下:

$ declare -A arr=(["book1"]="好书1" ["book2"]="好书2" ["book3"]="好书3")
$ echo ${arr["book1"]}
好书1
$ echo ${arr[@]}
好书1 好书3 好书2
$ arr["book1"]="好书1修改"
$ echo ${arr[*]}
好书1修改 好书3 好书2
$ echo ${arr["book1"]}
好书1修改

7、函数

脚本功能:实现函数的封装与调用,知道使用细节

#!/bin/bash

#中间命令失败
function func_01()
{
a=1
copy asd asd
b=2
}

#强制函数返回非0数字
function func_02
{
a=1
return 100
}

#最后一条命令失败
func_03()
{
a=1
copy asd asd
}


func_01
echo "func_01执行后返回值:$?"

func_02
echo "func_02执行后返回值:$?"

func_03
echo "func_03执行后返回值:$?"

(1)函数定义

①定义函数的方式如 function func(){}  ,建议采用这种方式,其他方式见脚本

②没有形式参数,可直接传参数,如在调用时直接传入: func 参数1 参数2 ...

(2)函数的返回值

①只能是数字,默认返回最后一条指令的执行情况,成功则返回0,失败则返回其它数字

②可强制返回指定数字,不能是非数字,关键字使用 return

(3)函数调用

 ①不带参数的调用,直接使用函数名:func

②带参数的调用,直接传参数:func 参数1 参数2 ...

8、模块化编程

脚本功能:在本脚本中调用其它脚本的函数,实现模块化编程(假如我们的文件为”函数“章节的脚本,现在创建新脚本去引用它)

#!/bin/bash
# 也可以使用  . study_008.sh 去调用,建议使用关键字source
source study_008.sh

func_01
echo "在$0文件中运行study_008.sh的函数,返回值为:$?"

(1)创建工程

①使用一个目录包含所有工程文件

②对文件进行分类,接着使用不同文件夹去包含同类文件

(2)目录命名

①一些公共方法的文件夹可以命名为common

②一些日志文件的文件夹可以命名为Log

(3)脚本命名

①可以根据功能命名

(4)模块调用

①引入时建议使用source关键字

②引入时建议使用相对路径

9、重定向研究

脚本功能:通过函数重定向的方式,研究重定向的原理,掌握其用法

#!/bin/bash

function func_01()
{
pwd
cp 000 111
} >error.txt 2>&1

function func_02()
{
pwd
cp 000 111
} 2>&1 >>error.txt

function func_03()
{
pwd
cp 000 111
} 2>&1 >/dev/null

function func_04()
{
pwd
cp 000 111
} &> error.txt

function func_05()
{
pwd
cp 000 111
} >error.txt 1>&2

function func_06()
{
cp 000 111
pwd
} >error.txt 1>&2

function func_07()
{
pwd
cp 000 111
} 1>&2 >>error.txt

function func_08()
{
cp 000 111
pwd
} 1>&2 >>error.txt

function func_09()
{
pwd
cp 000 111
} >error.txt

echo "开始---------------------------"
func_01
printf "func_01 >error.txt 2>&1: \n"
cat error.txt
rm -rf error.txt
echo "结束---------------------------" ; echo ""

echo "开始---------------------------"
func_02
printf "func_02 2>&1 >error.txt: \n"
cat error.txt
rm -rf error.txt
echo "结束---------------------------" ; echo ""

echo "开始---------------------------"
func_03
printf "func_03 2>&1 >/dev/null: \n"
cat error.txt
rm -rf error.txt
echo "结束---------------------------" ; echo ""

echo "开始---------------------------"
func_04
printf "func_04 &> error.txt: \n"
cat error.txt
rm -rf error.txt
echo "结束---------------------------" ; echo ""

echo "开始---------------------------"
func_05
printf "func_05 >error.txt 1>&2: \n"
cat error.txt
rm -rf error.txt
echo "结束---------------------------" ; echo ""

echo "开始---------------------------"
func_06
printf "func_06 >error.txt 1>&2: \n"
cat error.txt
rm -rf error.txt
echo "结束---------------------------" ; echo ""

echo "开始---------------------------"
func_07
printf "func_07 1>&2 >error.txt: \n"
cat error.txt
rm -rf error.txt
echo "结束---------------------------" ; echo ""

echo "开始---------------------------"
func_08
printf "func_08 1>&2 >error.txt: \n"
cat error.txt
rm -rf error.txt
echo "结束---------------------------" ; echo ""

echo "开始---------------------------"
func_09
printf "func_09 >error.txt: \n"
cat error.txt
rm -rf error.txt
echo "结束---------------------------" ; echo ""

(1)重定向

①重定向的对象为:0代表标准输入、 1代表标准输出、2代表标准错误输出

②重定向输入用 < 符号、<< 符号表示

③重定向输出用 > 符号、>> 符号表示

(2)重定向输入

①可以采用 ”命令 0< 文件名“  或 ”命令 < 文件名“,因为输入只有0这一个,建议采用后者直接重定向输入。

②< 与 << ,<< 不像 >> 有追加的含义,它只有一个作用,就是以特定标记来重定向,用法如下代码所示,其中names成对出现,可用其它字符代替,<<后面紧跟字符,否则空格会被当作特定标记:

cat <<names
yezi
qindong
huazheng
names

(3)重定向输出

①可以采用”命令 1> 文件名“  、”命令 2> 文件名“、”命令 &> 文件名“的方式重定向,其中 > 右边参数缺省时,默认数字为1,代表只重定向标准输出;&代表1和2都重定向。建议带数字的写法,这样阅读带数字的写法更能理解。

② 1>&2 与 2>&1,前者表示将标准输出重定向到标准错误输出,后者则与前者相反。

③1>&2 、2>&1 与  &> 的比较,观察本脚本的输出,可以知道2>&1与1>&2是相反的,即2>&1有输出时,1>&2没有输出;2>&1放在文件后可以全部输出,放在文件前只输出标准输出;&>有时等价于放在文件后面的2>&1,而实际&>不分前后,都会输出,相当于1>&2与2>&1的结合。因此,建议2>&1统一放在后面,只有&>时放中间,以避免误解,对比信息如下:

开始---------------------------
func_01 >error.txt 2>&1:
/home/yeqinfang
cp: cannot stat '000': No such file or directory
结束---------------------------

开始---------------------------
cp: cannot stat '000': No such file or directory
func_02 2>&1 >error.txt:
/home/yeqinfang
结束---------------------------

开始---------------------------
func_04 &> error.txt:
/home/yeqinfang
cp: cannot stat '000': No such file or directory
结束---------------------------

开始---------------------------
/home/yeqinfang
cp: cannot stat '000': No such file or directory
func_05 >error.txt 1>&2:
结束---------------------------

④ > 与 >> ,前者直接覆盖文件,后者基于文件进行追加操作

⑤ /dev/dull 该文件是个空文件,用在重定向中可使得输出信息不输出,前提是2>&1这个重定向放该文件后面。

10、正则表达式与Linux三剑客

脚本功能:给定一个文本(如ifconfig获取的网卡信息),采用grep、awk、sed对该文本进行处理

eth0      Link encap:Ethernet  HWaddr 02:9C:32:08:1E:F2
          inet addr:10.80.159.135  Bcast:10.80.159.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:605878 errors:0 dropped:0 overruns:0 frame:0
          TX packets:117274 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:48636892 (46.3 MiB)  TX bytes:1658079942 (1.5 GiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:92719 errors:0 dropped:0 overruns:0 frame:0
          TX packets:92719 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:10277069 (9.8 MiB)  TX bytes:10277069 (9.8 MiB)
#!/bin/bash

# 获取eth0的IP地址
cat study_012.txt | grep 'inet addr.*Bcast' | awk '{printf $2}' | sed 's/addr://g'

 (1)管道符 | 

 ①通过管道符,可以将输出的内容,从左边传递到右边

(2)正则表达式

①grep中使用了正则表达式的元字符 .* ,即匹配了除了换行符的所有字符

(3)Linux三剑客:grep、 awk、sed

①从上面的脚本可以知道,grep取行,awk取列,sed编辑

三、项目实战

1、监控应用程序

脚本功能:实现对应用程序SmoreScanner进程的监控,即每5秒查询一次SmoreScanner进程是否存在,如果存在,打印此时的内存情况,如果不存在,则杀掉该进程的守护进程SmorescannerUdpProcess,最后退出监控。这样就可以知道应用程序SmoreScanner崩溃了。

#!/bin/sh

while true
do
sleep 5s;
smore=$(pidof SmoreScanner);
echo "SmoreScanner pid is:  "; echo ${smore};
if [[ ${smore} != "" ]] ;then
        echo "sucess!";
        echo $(free -m)
else
        echo "SmoreScanner Error!";
        smoreudp=$(pidof SmorescannerUdpProcess);echo ${smoreudp};kill ${smoreudp};
        break
fi
done

2、反复杀掉某进程不断拉起

脚本功能:循环查询一个进程是否存在,如果存在,杀掉该进程,等待10秒后运行该进程,接着100秒后继续杀掉该进程,这样就可以看该应用程序不断异常拉起的稳定性了。

#!/bin/bash
while true
do
# 是否存在
if pgrep -x "/usr/bin/smoresensor" > /dev/null
then
    echo "smoresensor 存在,正在杀死..."
    killall  "smoresensor"
    echo "smoresensor 已成功终止"
else
    echo "smoresensor 不存在"
fi

# 等待10秒
sleep 10

#
echo "smoresensor"
/usr/bin/smoresensor &

sleep 100

done

核心要点pgrep -x "/usr/bin/smoresensor" > /dev/null ,用于在系统中搜索指定名称的进程。让我来解释一下:

  • pgrep: 这是一个用于查找进程的命令。它会根据进程的名称(或其他属性)来查找正在运行的进程,并返回进程的 ID(PID)。
  • -x: 这是 pgrep 命令的一个选项,表示仅匹配整个进程名称而不是其中的一部分。换句话说,它要求进程名称与指定的名称完全匹配。
  • "/usr/bin/smoresensor": 这是要查找的进程名称,即 "/usr/bin/smoresensor"。
  • > /dev/null: 这是将命令的输出重定向到 /dev/null,这样命令的输出就会被丢弃,不会显示在终端上。在这种情况下,如果进程存在,则命令会返回进程的 PID,如果进程不存在,则不会有任何输出。

因此,这条命令的作用是检查系统中是否存在名为 "/usr/bin/smoresensor" 的进程,但不会在终端上显示任何输出。

(持续更新中。。。)

  • 41
    点赞
  • 327
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion King

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值