csh 逻辑_shell脚本编写

一、shell脚本编程学习概述

(一)、学习shell脚本原因

提升工作效率

减少重复工作

完成批量操作

节省人力成本

(二)、学习shell必备知识

1、熟练使用编辑软件

vim

2、熟练使用常用命令

150个常用命令

三剑客命令

3、熟练使用系统符号

系统常用符号

系统通配符号

系统正则符号

(三)、学习shell方法技巧

(一)、技巧方法

会看脚本

模仿编写

(二)、高手核心

量的积累,产生质的变化

(三)、学习误区

依赖高手,拿来主义

二、shell脚本概念

Shell是一个命令解释器,它的作用是解释执行用户输入的命令及程序等

(一)、解释器工作方式

采用交互式方式进行解释

采用非交互式方式进行解释

(二)、shell种类

/bin/sh ---> 是bash一个软链接

/bin/bash ---> linux系统默认使用shell解释器

/sbin/nologin ---> 无法登陆访问shell

/usr/bin/csh

/usr/bin/rsh

三、shell脚本需掌握内容

(一)、掌握脚本基本语法

1、变量设定

普通变量

定义方式

先写变量名称,紧接着是 "=" ,最后是值。中间无任何空格

调用变量

通过echo命令加上 $变量名,即可输出变量的值。

双引号,以防止出错变量的值一般要加上

变量永久生效

将变量设置编写到文件中

(/etc/profile /etc/bashrc ~/.bashrc ~/.bash_profile)

环境变量

定义方式

export info=“I am HQ”

调取变量

echo $info

永久生效:

将变量设置编写到文件中

(/etc/profile /etc/bashrc)

条件表达式

if判断语法

单分支语句

if [ ]

then #则

命令

fi

双分支语句

if [ ]

then #则

命令

else #否则

命令

fi

多分支语句

if [ ]

then

elif [ ]

then

elif [ ]

then

else

fi

for循环

while循环

case语句

函数语法规范

数组

(二)、定义变量规范:

变量不能使用数字开头

定义变量时“=”两边不能有空格

变量建议由字母与“_”组成

变量设置见名知其义

1、养成脚本编写规范

脚本保存目录规范

将脚本文件统一保存在指定目录中

2、脚本编写规范

1、一个规范的Shell脚本在第一行会指出由哪个程序(解释器)来执行脚本中的内容

2、在shell脚本中,跟在 # 后面的内容表示注释,用来对脚本进行注释说明,

注释部分不会被当做程序来执行,仅仅是给开发者和使用者看的,系统解释器是看不到的,更不会执行

3、Shell脚本的开头会加版本、版权等信息

# Date:16:29 2018-10-20 --> 脚本编写时间

# Author: Create by xiaoxie --> 脚本作者

# Description: This script function is …… -->脚本作用

4、在shell脚本中尽量不用中文注释,尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰

5、Shell脚本的命名应以.sh为扩展名 例如:This is a premium name

6、成对的符号应尽量一次性写出来,然后退格在符号内增加内容,以防止遗漏。这些成对的符号包括: {}、[]、‘’、“” 等

7、中括号[]两端至少要有1个空格,因此,键入中括号时即留出空格[ ],

然后在退格键入中间内容,并确保两端都至少由一个空格

8、对于流程控制语句,应一次性将格式写完,再添加内容

如:一次性完成for循环语句的格式

9、通过缩进让代码更易读

10、对于常规变量的字符串定义变量值应加双引号,并且等号前后不能有空格,

需要强引用的,则用单引号(‘’),如果是命令的引用,则用反引号(``)

11、脚本中的单引号、双引号及反引号必须为英文状态下的符号

3、脚本运行方法

方法一:利用bash解释器命令运行脚本

[root@web01 /server/scripts/sh]# bash test01.sh

方法二:利用脚本绝对路径运行脚本

[root@web01 /server/scripts/sh]# /server/scripts/sh/test01.sh

方法三:利用 . 或者 source执行脚本

[root@web01 /server/scripts]# . /server/scripts/test01.sh

[root@web01 /server/scripts]#source /server/scripts/test01.sh

说明:三种方式区别

方法一 和 方法二 都是在子shell中执行脚本

方法三在父shell中进行运行

四、shell变量的设置

(一)、变量的赋值方法

方法一:直接赋值

a=1

方法二:传参赋值

a=$1

方法三:交互式赋值

read 变量名

read -p "提示信息" 变量名

read -t “输入超时时间” 变量名

(二)、脚本中特殊变量

位置变量

$0 用于获得脚本名称信息

应用示例

echo "Usage: $0 {请写入学生年龄和姓名}"

echo "学生名字: $1"

echo "学生年龄: $2"

$n 脚本的第n个传参数,n表示从1-9,大于9参数数量 使用${10}

应用示例

echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}

$# 位置参数的数量

应用示例

[ $# -eq 2 ] || echo "Usage: $0 {请写入学生年龄和姓名}"

$* 所有位置参数的内容,加引号时表示将多个参数作为一个整体

$@ 所有位置参数的内容,加引号时会将多个参数作为个体

不加双引号没有任何区别,将所有参数信息全部显示

加上双引号, 在循环体中,$* 会将所有参数看成一个整体,$@ 会将所有参数看成多个个体

状态变量

$? 获取上一个命令执行结果 成功用0 失败用非0

示例应用

[ $# -ne 1 ] && echo "Usage: $0 {请输入一个域名信息!}" && exit 2

ping -c 2 $1 &>/dev/null

[ $? -eq 0 ] && echo "This web_name $1 is ok. " || echo "This web_name $1 is error

$$ 获取一个脚本执行PID信息

示例应用

# $$ 获取脚本执行进程信息

echo $$ >/tmp/test.pid

$! 获取上一个程序或脚本后台运行的pid信息

示例应用

[root@web01 scripts ]# sh test04.sh & --- 让脚本在后台运行

[1] 118411

[root@web01 scripts ]# echo $! --- 获取上一个在后台运行脚本pid信息

118411

[root@web01 scripts ]# jobs --- 查看在后台运行的程序信息

[1]+ 运行中 sh test_ip.sh &

[root@web01 scripts ]# fg 1 --- 恢复后台运行程序到前台

$_ 获取脚本的最后一个参数信息 == esc .

应用示例

[root@web01 scripts 12:37:06]# sh test03.sh oldgirl olddog oldboy

oldgirl olddog oldboy

[root@web01 scripts 12:37:33]# echo $_

oldboy

变量子串

${paramter} 返回变量信息内容

应用示例

[root@web01 scripts ]# oldboy=linux

[root@web01 scripts ]# echo $oldboy

linux

[root@web01 scripts ]# echo ${oldboy}

linux

[root@web01 scripts ]# echo $oldboyisok

[root@web01 scripts ]# echo ${oldboy}isok

linuxisok

${#paramter} 返回变量字符长度

应用示例

OLDBOY="I am oldboy teacher"

echo ${#OLDBOY}

19

已知一个变量 OLDBOY="I am oldboy teacher",

问变量信息字符数量是多少, 如何统计

方法一:echo $OLDBOY|wc -L

方法二:expr length "$OLDBOY"

方法三:echo $OLDBOY|awk '{print length}'

方法四:echo ${#oldboy}

已知一个变量 OLDBOY="I am oldboy teacher my name is HQ"

请找出字符串长度小于3的信息

方法一:

oldboy="i am oldboy teacher my name is hq"

for a in $oldboy

do

if [ ${#a} -lt 3 ]

then

echo $a

fi

done

方法二: echo $OLDBOY|xargs -n1|awk '{if(length<3)print}'

方法三:echo $OLDBOY|awk '{for(i=1;i<=NF;i++)if(length($i)<3)print $i}'

方法四:echo $OLDBOY|egrep -wo "[a-Z]{1,3}"

${paramter:offset} 在变量中,从指定字符位置开始提取子串到结尾信息

应用示例

[root@web01 ~]# echo $oldboy

I am oldboy tnux ro r python eacher my name is sa gfd

[root@web01 ~]# echo ${oldboy:2}

am oldboy tnux ro r python eacher my name is sa gfd

[root@web01 ~]# echo ${oldboy:0}

I am oldboy tnux ro r python eacher my name is sa gfd

${paramter:offset:length} 在变量中,从指定字符位置开始提取子串到指定位置结束

应用示例

[root@web01 scripts ]# echo $OLDBOY

I am oldboy teacher my name is HQ

在变量中,从指定字符位置开始提取子串到指定位置结束

[root@web01 scripts ] # echo ${OLDBOY:2:2}

am

补充: 子串中offset信息可以从0开始

[root@web01 scripts ]# echo ${OLDBOY:0:4}

I am

[root@web01 scripts ]# echo ${OLDBOY::4}

I am

${paramter#word} 从变量开头开始删除最短匹配的word子串信息

应用示例

[root@web01 ~]# echo $oldboy

I am oldboy tnux ro r python eacher my name is sa gfd

[root@web01 ~]# echo ${oldboy#I*d}

boy tnux ro r python eacher my name is sa gfd

[root@web01 ~]# echo ${oldboy#I*t}

nux ro r python eacher my name is sa gfd

[root@web01 ~]# echo ${oldboy#a*t}

I am oldboy tnux ro r python eacher my name is sa gfd

此方法必须从第一个字符写起

${paramter##word} 从变量开头开始删除最长匹配(贪婪匹配)的word子串信息

应用示例

${paramter%word} 从变量结尾开始删除最短匹配的word子串信息

应用示例

${paramter%%word} 从变量结尾开始删除最长匹配的word子串信息

应用示例

${paramter/string/replace} 使用replace信息替换string字符串, 并且只替换第一个匹配的信息

应用示例

${praamter//string/replace} 使用replace信息替换string字符串, 但是会将所有信息全部替换

应用示例

变量替换

${paramter:-word} 当调取变量信息值为空时或未赋值, 就返回word字符串信息

应用示例

作用

如果变量未定义,则返回备用字符串信息,防止变量为空值或未定义导致异常

${paramter:=world} 当调取变量信息值为空时或未赋值,则设置指定字符串为新的变量值

应用示例

作用

如果变量未定义,用指定字符串直接给变量赋值

${paramter:?word} 当调取变量信息值为空时或未赋值,指定为赋值的错误提示信息

应用示例

作用

如果变量未定义,利用指定字符串进行错误提示说明

${paramter:+word} 当调取变量信息值为空时或未赋值,不做任何处理,否则word字符串将替代变量值

应用示例

作用

如果变量未定义, 调取变量信息时, 不会有任何显示

如何变量已定义, 调取变量信息时, 会显示指定字符串信息

?word与+word总结

?word: 变量未定义提示错误信息; 变量已定义显示变量信息

+word: 变量未定义不做任何处理; 变量已定义显示提示信息

(三)、变量算法

算术运算符

算术运算命令

(()) 实现整数数值运算

应用1:简单数值运算

[root@oldboy ~ ]# echo $((4*4))

16

[root@oldboy ~ ]# echo $((4/4))

1

[root@oldboy ~ ]# echo $((2**3))

8

应用2:识别变量做运算

[root@oldboy ~ ]# a=10

[root@oldboy ~ ]# echo $((a+1))

11

[root@oldboy ~ ]# echo $((a*2))

20

应用3:用于数值比较判断

[root@oldboy ~ ]# echo $((3<8))

1

[root@oldboy ~ ]# echo $((3>8))

0

[root@oldboy ~ ]# echo $((8=8))

-bash: 8=8: attempted assignment to non-variable (error token is "=8")

[root@oldboy ~ ]# echo $((8==8))

1

[root@oldboy ~ ]# echo $((7==8))

0

[root@oldboy ~ ]# echo $((7!=8))

1

[root@oldboy ~ ]# echo $((3<8 && 5==5))

1

[root@oldboy ~ ]# echo $((3>8 && 5==5))

0

[root@oldboy ~ ]# echo $((3>8 || 5==5))

1

[root@oldboy ~ ]# echo $((3>8 || 5==6))

0

比较信息成立会使用返回值1表示

比较信息不成立会使用返回值0表示

应用4:实现自增/自减运算

自增运算

a=a+1

a++:是先执行表达式后再自增,执行表达式时使用的是a的原值

++a:是先自增再执行表达示,执行表达式时使用的是自增后的a

自减运算

a=a-1

a--:是先执行表达式后再自增,执行表达式时使用的是a的原值

--a:是先自增再执行表达示,执行表达式时使用的是自增后的a

let 实现整数数值运算

应用1:简单整数运算

[root@web01 ~]# let i=5*9

[root@web01 ~]# echo $i

45

应用2:识别变量信息做运算

[root@web01 ~]# i=2

[root@web01 ~]# let i=i+2

[root@web01 ~]# echo $i

4

expr 实现整数运算

应用1:做数值信息简单运算

[root@web01 ~]# expr 2 \* 3

6

[root@web01 ~]# expr 2 + 3

5

应用2:判断输入参数信息是否为整数

[root@web01 ~]# i=5

[root@web01 ~]# expr $i+5

5+5

[root@web01 ~]# expr $i + 5

10

[root@web01 ~]# echo $?

0

[root@web01 ~]# i=oldboy

[root@web01 ~]# expr $i + 9

expr: 非整数参数

[root@web01 ~]# i=1.5

[root@web01 ~]# expr $i + 9

expr: 非整数参数

运算符两侧须有空格

应用3:统计字符串长度

[root@web01 ~]# oldboy="I am oldboy teacher"

[root@web01 ~]# expr length "$oldboy"

19

应用4:验证文件的扩展名

#!/bin/bash

if expr "$1" : ".*\.jpg" &>/dev/null

then

echo "这个传参文件是一个图片文件"

else

echo "这个传参文件不是图片信息"

fi

bc Linux中的计算器程序

seq -s+ 10 | bc

awk 实现数值运算

awk 'BEGIN{print 5*10-3+6}'

declare 实现数值运算

a=5;declare -i a=a+10;echo $a

五、shell脚本编写逻辑信息

(一)、逻辑判断语句

1、shell脚本条件表达式

条件表达式

test

说明:利用test进行表达式书写进行判断条件信息

规范:test命令和""之间至少有一个空格

[ ]

说明:利用中括号 进行表达式书写进行判断条件信息

规范:[]的边界和内容之间至少有一个空格

[[ ]]

说明:利用双中括号 进行表达式书写进行判断条件信息

规范: [[]]的边界和内容之间至少有一个空格

(())

说明: 利用双小括号 进行表达式书写进行判断条件信息

规范:(())(双小括号)两端不需要有空格

条件表达式特殊书写方式

[ ] && {

命令1

命令2

}

(二)、编写脚本格式说明

①. 开头编写解释器信息

#!/bin/bash

②. 开头编写脚本的注释

author 作者

data 日期

desc 脚本作用

(三)、if条件语句

单分支条件语句

语法

if [ 条件 ]

then #则

命令

fi

案例:输入2个数字,比较大小

双分支条件语句

语法

if [ 条件 ]

then #则

命令

else #否则

命令

fi

案例:判断用户并下载软件

#!/bin/bash

if [ $USER == "root" ]

then

yum ‐y install vsftpd

else

echo "您不是管理员,没有权限安装软件"

fi

多分支条件语句

语法

if 条件判断;then

命令

elif 条件判断;then

命令

else

命令

fi

(四)、结构条件语句(case语句)

case结构条件语句说明:

相当于多分支的if/elif/else条件语句, 但是它比这些条件语句看起来更规范更工整

常被应用于实现系统服务启动脚本等企业应用场景中

case结构条件语句语法:

case "变量" in

值1)

指令1...

;;

值2)

指令2...

;;

*)

指令3...

esac

case结构语句执行流程

case结构语句测试练习

①. 测试case语句打印水果菜单信息

. /server/scripts/sh/fruit_fun.sh

men

while true

do

read -p "please input inquire fruit: " num

case $num in

1|apple|a)

echo -e "\033[31m apple price is 10 \033[0m"

;;

2|strawberry|s)

echo -e "\033[32m strawberry price is 20 \033[0m"

;;

3|pear|p)

echo -e "\033[33m pear price is 30 \033[0m"

;;

4|grape|g)

echo -e "\033[34m grape price is 40 \033[0m"

;;

5|help|h)

men

;;

6|quit|q)

exit 1

;;

*)

echo "please input inquire fruit: "

;;

esac

done

(五)、逻辑循环语句

for循环语句

概念说明

for循环语句主要用于执行次数有限的循环,而不是用于守护进程及无限循环

语法说明

根据变量数值进行循环

for 变量名 in 变量取值列表; do 指令 ;done

根据判断条件进行循环

for ((exp1;exp2;exp3));do 指令 ;done

嵌入式循环

情况一: 爷爷--爸爸--儿子

#!/bin/bash

for a in {1..3}

do

echo $a

for b in {a..c}

do

echo $a$b

for c in {A..C}

do

echo $a$b$c

done

done

done

情况二: 父亲--二子1/二子2

#!/bin/bash

for a in {1..3}

do

echo $a

for b in {a..c}

do

echo $a$b

done

for c in {A..C}

do

echo $a$b$c

done

done

(六)、while循环语句

语法

方法一:只要条件为真, 就会一直循环下去

while true

do

echo oldboy

done

方法二:条件判断

while ((条件语句)) [条件语句]

do

动作

done

#!/bin/bash

i=0

while [ $i -le 10 ]

do

echo oldboy $i

let i++

done

方法三:读取文件循环

#!/bin/bash

while read 变量名

do

echo $变量名

done < user.txt

测试练习

1) 循环输出数值信息

#!/bin/bash

i=0

while [ $i -le 10 ]

do

echo oldboy $i

let i++

done

2) 循环读取文件内容

while read line

do

echo $line

done

调试测试脚本

sh -x 脚本

在windows写脚本注意

dos2unix 转码文件

六、脚本函数功能

(一)、脚本函数概念

函数是命令的集合,完成特定功能的代码块,代码块可以实现重复使用

(二)、脚本函数作用

①. 相同的程序段定义成函数, 可以减少整个程序的代码量, 提升开发效率

②. 增加程序的可读性 易读性 提升管理效率

③. 实现程序功能模块化 使得程序具备通用性(可移植性)

(三)、脚本函数语法

标准语法格式:

function 函数名(){ }

简化语法格式:

function 函数名 { }

函数名(){ }

系统自带函数

/etc/init.d/functions

(四)、脚本函数调用

①. 调用函数时,函数名前的function和函数名后的小括号都不要带

②. 函数的定义必须在要执行的程序前面定义或加载

③. shell执行系统中各程序顺序 系统别名--函数--系统命令--可执行文件

④. 函数执行时, 会和调用它的脚本共用变量, 也可以为函数设置局部变量及特殊位置参数

⑤. 在shell函数里面, return命令的功能与exit类似, return的作用是退出函数, 而exit是退出脚本文件

⑥. return语句会返回一个退出值给调用函数的当前程序, 而exit会返回一个退出值给执行程序的当前shell

⑦. 如果将函数存放在独立的文件中, 被脚本加载使用时, 需要使用source 或 "." 来加载

⑧. 在函数内一般使用local定义局部变量, 这些变量离开函数后就会消失

(五)、脚本函数传参

①. shell的位置参数($1 $2 $# $* $? $@)都可以作为函数的参数来使用

②. 此时父脚本的参数临时地被函数参数所掩盖或隐藏

③. $0比较特殊, 仍然是父脚本的名称

④. 当函数执行完成时, 原来的命令行脚本的参数即可恢复

⑤. 函数的参数变量是在函数体里面定义的

(六)、脚本函数分离

将编写的函数信息放入到指定的函数库文件中, 进行加载函数库文件, 实现函数信息分离

函数定义变量

脚本和函数中同时定义变量, 各自调用使用自己的变量信息

脚本和函数中一方定义变量, 各自调用使用对方的变量信息

函数的返回值

根据return返回值信息, 判断函数命令是否执行正确

七、shell脚本编程扩展说明

(一)、shell脚本控制指令

循环控制指令

break n

跳出本次循环体,继续执行之后操作

n 表示跳出循环的层数, 如果省略n, 表示跳出整个循环

continue n

跳出本次循环,继续执行下次循环

n 表示退出到第n层继续循环, 如果省略n, 表示跳出本次循环, 忽略本地循环的剩余代码

退出脚本指令

exit n

退出当前shell程序, n为上一次程序执行的状态返回值, n可以省略, 在下一个shell里可通过$? 接收exit n的n值

退出函数指令

return n

用于在函数里作为函数的返回值, 以判断函数执行是否正确, 在下一个shell里可通过 $? 接收 return n的值

(二)、shell脚本数组概念

shell数组概念介绍

1) 数据就是元素的集合, 把有限个元素(变量或字符内容)用一个名字来命名, 然后用编号对它们进行区分

2) 元素集合的名称, 就成为数组名

3) 用于区分不同内容的编号就称为数组下标

4) 组成数组的各个元素(变量)称为数组的元素, 有时称为下标变量

shell数组作用说明

可以将多个变量信息进行汇总定义, 避免单独定义的麻烦

可以进行数据信息统计

shell数组实践说明

普通数组定义

方法一:利用小括号定义数组

数组名称=(元素1 元素2 元素3)

方法二:利用小括号设置键值对

数组名称=([key1]=value1 [key2]=value2 [key3]=value3)

方法三:分别定义数组及元素信息

数组名称[下标]=元素

方法四:利用执行命令结果设置数组信息

array=(`命令信息`)

aaray=($(命令信息))

关联数组定义

declare -A 数组名 #指定某一个数组为关联数组

shell数组调用

查看数组所有元素信息

echo ${array[*]}

查看数组所有元素信息

echo ${array[*]}

echo ${array[@]}

查看数组指定元素信息

echo ${array[n]}

PS:元素未指定下标时,默认从"0"开始排序

查看数组元素长度信息

echo ${#array[*]}

echo ${#array[@]}

查看数组所有元素的索引信息

echo ${!array[*]}

普通数组与关联数组区别:

普通数组: 表示只能以数字作为索引(下标), 调取元素值信息

关联数组: 表示只能以数字或字符串作为索引(下标)

数组信息的扩展操作

输出数组长度信息(获取数组元素数量)

echo ${#array[*]}

添加数组数值信息

array[3]=oldbaby

删除数组数值信息

unset array[1]

数组数值信息的截取

echo ${array[*]:1开始截取位置:截取位数}

数组数值信息替换

echo ${array[*]/被替换数值/替换后数值}

数组的应用实践

遍历数组数值信息

方法一:获取所有信息遍历

#!/bin/bash

array=(

oldboy

olddog

oldgirl

oldbaby

)

for i in ${array[*]}

do

echo $i

done

方法二:利用索引信息遍历

#!/bin/bash

array=(

oldboy

olddog

oldgirl

oldbaby

)

for i in ${!array[*]}

do

echo ${array[$i]}

done

(三)、加快脚本运行效率

实现方法:{循环体}&

#!/bin/bash

for ip in 10.0.{0..63}.{1..254}

do

{ ping -c 3 -W 3 $ip &>/dev/null

if [ $? -eq 0 ]

then

echo $ip is online

else

echo $ip is offline

fi } &

done

八、shell脚本信号控制

(一)、脚本信号控制作用

在脚本执行过程中,可能会被一些键盘操作快捷方式所打断

影响脚本运行,脚本控制信号可以屏蔽这些信号

(二)、脚本信号

trap -l (查看所有信号)

HUP(1):挂起信号(终端或用户退出断开时自动触发信号)

INT(2):中断(键盘快捷键"ctrl+c"而产生的信号)

QUIT(3):退出(键盘快捷键"ctrl+\"而产生的信号)

ABRT(6):中止(因严重错误所产生的信号)

TERM(15):终止(系统关机时所产生的信号)

TSTP(20):停止进程运行(键盘快捷键"ctrl+z"所产生的信号)

(三)、识别信号命令 trap

命令语法:trap 命令 信号信息

命令作用

根据指定信号,完成指定操作

根据指定信号,进行信号屏蔽

九、shell脚本自动应答

(一)、自动应答作用

实现自动化管理,自动应答,自动响应

(二)、自动应答原理

第一步:运行一个程序或命令(spawn 命令信息)

第二步: 识别产生信息关键字 expect 捕获关键字 {send 应答信息}

第三步: 根据识别关键做处理 send 应答信息

(三)、自动应答脚本编写方式

第一步:下载安装expect软件程序

yum -y install expect

第二步:编写自动应答脚本

(脚本名称定义:脚本名称.exp)

#!/usr/bin/expect

# #!/usr/bin/expect 为自动化应答脚本声明信息

if { $argc != 2 } {

#自动应答脚本if判断格式 if { 条件表达式 } { 运行命令 }

# $argc 相当于 $#

puts "please input two paramter"

# puts 相当于 echo

exit 1

}

set ip [lindex $argv 0]

#自动化应答脚本位置变量设置方式 set 变量名 [lindex $argv n]

set cmd [lindex $argv 1]

set pass "123456"

#自动应答脚本变量设置方式 set 变量名 "变量值"

spawn ssh root@$ip $cmd

#运行的命令,$ip 调用变量

expect {

#捕获关键字

"yes/no" {send "yes\r";exp_continue}

#关键字信息 {send 应答信息;应答此条,自动跳到下一条交互处}

"password" {send "$pass\r"}

}

expect eof

#结束应答标志

第三步:运行自动应答脚本

(脚本运行命令:expect 脚本名称)

expect expect_test.exp 10.0.0.31 "df -h"

十、编写服务运行脚本使服务归systemctl管理

例:sersync服务

第一步:编写服务运行脚本

vim /server/scription/rsnc.sh

#!/bin/bash

. /etc/init.d/functions

case $1 in

start)

ps -ef | grep -v grep | grep sersync &>/dev/null

if [ $? -eq 0 ]

then

action "sersync is running... " /bin/true

else

/usr/local/sersync/sersync -dro /usr/local/sersync/confxml.xml &>/dev/null

[ $? -eq 0 ] && action "sersync start is " /bin/true || action "sersync start is " /bin/false

fi

;;

stop)

ps -ef | grep -v grep | grep sersync &>/dev/null

if [ $? -eq 0 ]

then

pid=$(ps -ef | grep -v grep | grep sersync | awk '{print $2}')

kill -9 $pid &>/dev/null

ps -ef | grep -v grep | grep sersync &>/dev/null

[ $? -ne 0 ] && action "sersync stop is " /bin/true || action "sersync stop is " /bin/false

else

action "sersync is not running ..." /bin/false

fi

;;

*)

echo "请输入正确命令"

esac

第二步:给脚本添加执行权限

chmod +x rsnc.sh

第三步:编写systemctl单元文件

/usr/lib/systemd/system/

[Unit] ---- 确认服务启动时依赖关系

# 单元文件描述说明

Description=OpenSSH server daemon

# 定义服务相关手册文档信息

Documentation=man:sshd(8) man:sshd_config(5)

# 定义服务运行依赖关系, 在指定服务启动后, 在启动相应服务

After=network.target sshd-keygen.service

# 定义服务运行依赖关系, 在指定服务启动前, 先启动相应后

Before=xxx

# 定义服务运行依赖关系, 需要和其他一些服务同时启动

Requires=

# 定义服务运行依赖关系, 希望有些服务和当前服务一起运行

Wants=sshd-keygen.service

[Service] ---- 确认服务启动命令和脚本信息 nginx

# 向后面参数发出通知, 启动服务程序

Type=notify

# 在服务启动时加载一个服务启动相关文件

EnvironmentFile=/etc/sysconfig/sshd

# 定义启动服务命令和脚本信息

ExecStart=serync start

ExecReload=sersync reload

KillMode=process

Restart=on-failure

RestartSec=42s

[Install] ---- 定义服务开机自动运行级别

WantedBy=multi-user.target

第四步:让systemctl加载新的单元文件

systemctl daemon-reload


版权声明:本文为weixin_42303568原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。