shell 脚本基础

 

 

   脚本类似批处理,简单来讲就是把许多的指令集合在一起,并提供循环、条件、判断等重要功能,语法简单实用,用以编写程序,大大简化管理员的操

,并可以完成图形工具所无法实现的功能:自动化运维。而为脚本的优点很明显:避免不必要的错误;节省时间

 

‘脚本的基本写法:

[root@mail-qq mnt]# vim test.sh

 

[root@mail-qq mnt]# cat test.sh

#!/bin/bash                           //写脚本的环境,

echo hello word                       //脚本具体将要执行的命令

 

环境一共有下面6种

/bin/sh

/bin/bash

/usr/bin/sh

/usr/bin/bash

/bin/tcsh

/bin/csh

 

 

 

二、脚本有两种方法可以执行:

1. sh 跟脚本的名称

[root@mail-qq mnt]# sh test.sh

hello word

2.给x权限,即执行权限:

[root@mail-qq mnt]# chmod +x test.sh

[root@mail-qq mnt]# /mnt/test.sh           //脚本的绝对路径

hello word

 

 

三、变量($)

[root@mail-qq mnt]# sh test.sh

LOCAL USER is root

[root@mail-qq mnt]# cat test.sh

#!/bin/bash

NAME="LOCAL USER is"

echo $NAME $USER

[root@mail-qq mnt]# vim test.sh

[root@mail-qq mnt]# sh test.sh

LOCAL USER is root

my name is student_DUCK

[root@mail-qq mnt]# cat test.sh

#!/bin/bash

NAME="LOCAL USER is"

echo $NAME $USER

FIRSTNAME=student

FAMNAME=DUCK

echo my name is ${FIRSTNAME}_$FAMNAME

 

 

[root@mail-qq mnt]# echo $a

1

[root@mail-qq mnt]# echo $a0

 

[root@mail-qq mnt]# echo ${a}0                     //变量和其他字符组合使用时需要用{}将变量括起来!!!!!

10

 

[root@mail-qq mnt]# vim test.sh

[root@mail-qq mnt]# sh test.sh

LOCAL USER is root

my name is student_DUCK

TIME is Tue Apr 25 07:28:19 EDT 2017

[root@mail-qq mnt]# cat test.sh

#!/bin/bash

NAME="LOCAL USER is"

echo $NAME $USER

FIRSTNAME=student

FAMNAME=DUCK

echo my name is ${FIRSTNAME}_$FAMNAME

TIME=$(date)

echo TIME is $TIME

 

四、四则运算以及计算的几种命令:

 

- 减法

+ 加法

** 幂运算

* 乘法

/ 除法

% 余数

 

方法1:[]表示计算

 

[root@mail-qq mnt]# echo $[1+2]      + 加法

3

[root@mail-qq mnt]# echo $[5-4]      -减法

1

[root@mail-qq mnt]# echo $[5*4]      *乘法

20

[root@mail-qq mnt]# echo $[2**10]     *幂运算

1024

ot@mail-qq mnt]# echo $[24/6]      /除法

4

[root@mail-qq mnt]# echo $[10%3]      %取余   结果显示余数:10除3等余3,余1,所以结果为1

1

方法2:expr

[root@mail-qq mnt]# echo `expr 2 \* 3`

6

[root@mail-qq mnt]# echo `expr 10 \% 3`

1

[root@mail-qq mnt]# echo `expr 10 \/ 3`

3

[root@mail-qq mnt]# echo `expr 10 \+ 3`

13

[root@mail-qq mnt]# echo `expr 10 \- 3`

7

凡方法3: let

[root@mail-qq mnt]# let A=1+2

[root@mail-qq mnt]# echo $A

3

[root@mail-qq mnt]# let C=2*10

[root@mail-qq mnt]# echo $C

20

[root@mail-qq mnt]# let D=2**10

[root@mail-qq mnt]# echo $D

1024

 

 

<VARIABLE>++ 增量后

<VARIABLE>-- 减量后

+= 加等

-= 减等

 

[root@mail-qq mnt]# vim 2test.sh

[root@mail-qq mnt]# sh 2test.sh

1

2

3

4

5

6

7

8

9

10

[root@mail-qq mnt]# cat 2test.sh

#!/bin/bash

for ((i=1;i<=10;i++))

do

echo $i

done

例:+=

[root@mail-qq mnt]# vim 4test.sh

[root@mail-qq mnt]# sh 4test.sh

1

3

6

10

15

21

28

36

45

[root@mail-qq mnt]# cat 4test.sh

#!/bin/bash

for ((i=1;i<10;i++))

do

((j+=i))

echo $j

done

 

五、引用和转义

 

引用和转义在shell解析字符串时用于去除字符串中特殊字符或保留词语的特殊含义。这会导致按字

面处理字符串,而不是展开变量或将其部分内容视作具有特殊含义。

引用有三种类型:

弱引用

将字符串放置在双引号中,保留字符串中所有字符的文字值,$、`、\和!字符除外。换言之,变量

扩展和命令扩展在双引号内仍起作用。

echo “can I have a $FRUIT”

echo “The current time is $(date +%r).”

强引用

将字符串放置在单引号中,保留字符串中所有字符的文字值,同时禁用所有扩展:

echo “Make $$$ Fast”

rm 'untitled folder'

转义

非引用的\是转义字符。它保留了下一个字符的文字值。(例如,\$PATH是确切的字符串$PATH,而

不是PATH变量的内容。)

 

六、运算和逻辑运算常用符:

 

-lt 小于

-le 小于等于

 

-gt 大于

-ge 大于等于

 

-eq 等于

-ne 不等于

 

 

逻辑运算符:-o -a ! && ||

-a 并列关系

-o 选择关系

! 取反,例如:=等于  != 不等于

&& 如果条件成功

|| 如果条件失败

 

 

七、经典练习

 

经典练习1:写脚本执行后显示/etc/下文件是否村在:

 

[root@mail-qq mnt]# vim find_file.sh

[root@mail-qq mnt]# sh find_file.sh

/etc/hello is not exist

/etc/passwd/ is not exist

/etc/group is exist

[root@mail-qq mnt]# cat find_file.sh

#!/bin/bash

for NAME in /etc/hello /etc/passwd/ /etc/group

do

ls -l $NAME &>/dev/null && echo $NAME is exist ||echo $NAME is not exist

done

 

 

经典练习2:

[root@mail-qq mnt]# sh test.sh

LOCAL USER is root

[root@mail-qq mnt]# cat test.sh

#!/bin/bash -x

NAME="LOCAL USER is"

echo $NAME $USER

// 因为$USER是系统自定的变量,所以执行脚本之后就可以显示当前用户。

[root@mail-qq mnt]# echo $USER

root

 

经典练习3:

[root@mail-qq mnt]# vim test.sh

[root@mail-qq mnt]# sh test.sh

LOCAL USER is root

my name is lee_DUCK

TIME is Wed Apr 26 22:34:14 EDT 2017

[root@mail-qq mnt]# cat test.sh

#!/bin/bash

NAME="LOCAL USER is"

echo $NAME $USER

FIRSTNAME=lee

FAMNAME=DUCK

echo my name is ${FIRSTNAME}_$FAMNAME      //变量跟别的字符组合使用时,需要用大括号括起来

TIME=$(date)

echo TIME is $TIME          FIRSTNAME 和TIME都是变量,FIRSTNAME=后面是具体的字符,所以不用$(),

     TIME=后面之执行的是date命令,所以要$()

 

经典练习4:显示自己主机的IP (只显示自己的IP)

[root@mail-qq mnt]# sh show_ip.sh

mail-qq.qq.com's ip is : 172.25.254.195

[root@mail-qq mnt]# cat show_ip.sh

#!/bin/bash

IP=`ifconfig eth0 | grep inet | grep inet | grep inet6 -v | awk -F " " '{print $2}'`

HOSTNAME=`hostname`

echo "${HOSTNAME}'s ip is : $IP"

 

 

经典练习5:显示2到10之间的数字,以2为单位递增。

[root@mail-qq mnt]# sh number.sh

2

4

6

8

10

[root@mail-qq mnt]# cat number.sh

#!/bin/bash

for NUM in $(  seq 2 2 10 )           //显示从2开始以2为单位递增到10

do

echo $NUM

done

 

[root@mail-qq mnt]# sh number.sh

3

5

7

9

[root@mail-qq mnt]# cat number.sh

#!/bin/bash

for NUM in $(  seq 3 2 10 )           //显示从3开始以2为单位递增到10

do

echo $NUM

done

 

经典练习6:检查主机IP为172.25.254.1到172.25.254.40的主机是否开启,如果开启显示up,如果关闭显示down

 

[root@mail-qq mnt]# sh status_ip.sh

172.25.254.1 is down

172.25.254.2 is down

172.25.254.3 is down

172.25.254.4 is up

172.25.254.5 is down

        ……

[root@mail-qq mnt]# cat status_ip.sh

#!/bin/bash

for NUM in 172.25.254.{1..40}

do

if

ping -c1 -w1 $NUM &>/dev/null      //-w1 表示每秒执行一次ping命令

then

echo $NUM is up

else

echo $NUM is down

fi

done

 

经典练习7:将/mnt/userfile里面的内容每一行当作一个用户名建立用户。

[root@mail-qq mnt]# vim userfile   

[root@mail-qq mnt]#cat userfile

user1   user2  user3

[root@mail-qq mnt]# cat create_user.sh

#!/bin/bash

MAX=`wc -l /mnt/userfile | cut -d " " -f 1`      //找到/mnt/userfile的最大行,给到MAX

for NUM in `seq 1 $MAX`                          //从1到MAX 逐个递增

do

NAME=`sed -n ${NUM}p /mnt/userfile`  //从userfile的第一行逐行给到NAME

useradd $NAME                            //新建用户

done //for语句的结束

 

[root@mail-qq mnt]# sh create_user.sh

延伸1、:查看脚本运行之后产生的变化,查看用户是否已经建立

[root@mail-qq mnt]# cat /etc/passwd | grep bash | cut -d ":" -f 1   //显示所有存在的用户

root

student

natasha

user1

user2

user3

 

经典练习8:将/mnt/userfile里面的内容每一行当作一个用户名建立用户,并将/mnt/passfile里的每一行对应给到对应用户作为密码

 

[root@mail-qq mnt]# sh create_user.sh userfile passfile    //必须跟脚本涉及的两个文件(行数相同)

[root@mail-qq mnt]# cat create_user.sh

#!/bin/bash

MAX=`wc -l $1 | cut -d " " -f 1`

for NUM in `seq 1 $MAX`

do

NAME=`sed -n ${NUM}p $1`

PASS=`sed -n ${NUM}p $2`

useradd $NAME

echo $PASS|passwd --stdin $NAME

done

 

经典练习9:做一个1分30秒的倒计时:

 

[root@mail-qq mnt]# cat power_time.sh

#!/bin/bash

MIN=1

for ((i=3;i>=0;i--))

do

while

[ "$i" -eq "0" -a "$MIN" -gt "0" ]

do

echo -n "After ${MIN}:${i} is end "

echo -ne "\r" //光标移动到行首,并显示新的结果。

i=59

sleep 1

((MIN--))

done

echo -n "After ${MIN}:${i} is end "

echo -ne "\r"

sleep 1

done

 

经典练习10:建立用户。如果输入的用户存在,报错。如果用户不存在 执行建立用户。

[root@mail-qq mnt]# sh check_create.sh

please input username :user4

[root@mail-qq mnt]# cat /etc/passwd | grep bash | cut -d ":" -f 1

root

student

user1

user2

user3

user4

[root@mail-qq mnt]# sh check_create.sh

please input username :user4

Error: user is alredy exsit

[root@mail-qq mnt]# sh check_create.sh

please input username :user5

[root@mail-qq mnt]# cat /etc/passwd | grep bash | cut -d ":" -f 1

root

student

user1

user2

user3

user4

user5

 

[root@mail-qq mnt]# cat check_create.sh

#!/bin/bash

read -p "please input username :" USERNAME      //显示请输入用户名称,输入后执行后续操作。

CHECK=`getent passwd $USERNAME` //判断用户是否存在。

if //进入循环

[ -z "$CHECK" ] //“-z”表示为空,

then

useradd $USERNAME

else

echo "Error: user is alredy exsit"

fi //结束循环

 

 

 

经典练习11:用userfile里面的每一行作为用户名建立用户并将passfile里面的每一行,作为密码依次给到每个用户。

 

[root@mail-qq mnt]# sh user_create.sh userfile passfile

ERROR: user1 is already exsit

ERROR: user2 is already exsit

ERROR: user3 is already exsit

[root@mail-qq mnt]# vim userfile

[root@mail-qq mnt]# sh user_create.sh userfile passfile

Creating mailbox file: File exists

Changing password for user user4.

passwd: all authentication tokens updated successfully.

Creating mailbox file: File exists

Changing password for user user5.

passwd: all authentication tokens updated successfully.

Creating mailbox file: File exists

Changing password for user user6.

passwd: all authentication tokens updated successfully.

[root@mail-qq mnt]# cat /etc/passwd | grep bash | cut -d ":" -f 1

root

student

user1

user2

user3

user4

user5

user6

[root@mail-qq mnt]# cat user_create.sh

#!/bin/bash

if

[ -n "$1" -a -n "$2" ]

then

MAX_USER=`wc -l $1 | cut -d " " -f 1`

MAX_PASS=`wc -l $1 | cut -d " " -f 1`

if

[ "$MAX_USER" -eq "$MAX_PASS" ]

then

for NUM in `seq 1 $MAX_USER`

do

USERNAME=`sed -n ${NUM}p $1`

PASSWORD=`sed -n ${NUM}p $1`

CHECK=`getent passwd $USERNAME`

if

[ -z "$CHECK" ]

then

useradd $USERNAME

echo $PASSWORD | passwd --stdin $USERNAME

else

echo "ERROR: $USERNAME is already exsit"

fi

done

else

echo " ERROR:diffrent lines of two files"

fi

else

echo "ERROR:there is lack of files ,Please check"

fi

延伸2、:$? 和!的用法

$?  ,  != 的用法,

echo $? 输出的结果为:正确输出为0,不正确输出结果不为0

 

[root@mail-qq mnt]# [ 2 = 2 ]; echo $?

0

[root@mail-qq mnt]# [ 1 = 2 ]; echo $?

1

[root@mail-qq mnt]# [ 1 = 2 ] echo $?

-bash: [: missing `]'

[root@mail-qq mnt]# [ 1 = 2 ] ; echo $?

1

[root@mail-qq mnt]# [ 1 = 1 ] ; echo $?

0

 

!=表示不等于。

 

[root@mail-qq mnt]# [ 1 != 1 ] ; echo $?

1

[root@mail-qq mnt]# [ 2 != 1 ] ; echo $?

0

经典练习12:脚本后面跟一个数,如果是10以内的显示0~10 ,如果不是显示not0~10

 

[root@mail-qq mnt]# sh number_check.sh

Please input a number : 9

9 is 0~10

[root@mail-qq mnt]# sh number_check.sh

Please input a number : 50

50 is not 0~10

[root@mail-qq mnt]# sh number_check.sh 5

5 is 0~10

[root@mail-qq mnt]# sh number_check.sh -5

-5 is not 0~10

[root@mail-qq mnt]# cat number_check.sh

#!/bin/bsah

if

[ -n "$1" ]

then

if

[ "$1" -ge "0" -a "$1" -le "10" ]

then

echo "$1 is 0~10"

else

echo "$1 is not 0~10"

fi

else

read -p "Please input a number : " NUMBER

if

[ "$NUMBER" -ge "0" -a "$NUMBER" -le "10" ]

then

echo "$NUMBER is 0~10"

else

echo "$NUMBER is not 0~10"

fi

fi

 

test 或 [ ] 的一些参数:

-e 存在 (exist)

-b 是区(block)

-f 是常规的文件(file)

-d 是目录(directory)

-h -L   是链接(link)

 

[root@mail-qq mnt]# [ -f /etc/passwd ]; echo $?

0

[root@mail-qq mnt]# [ -d /etc/passwd ]; echo $?

1

[root@mail-qq mnt]# [ -d /etc ]; echo $?

0

[root@mail-qq mnt]# [ -b /dev/vdb ]; echo $?

0

[root@mail-qq mnt]# [ -e /etc/passwd ]; echo $?

0

 

经典练习13:脚本后面如果跟apple显示banana,如果是banana显apple,如果是其他字符显示i don't know

 

此处要用case 语句  !!!!!

 

[root@mail-qq mnt]# sh friut_check.sh apple

banana

[root@mail-qq mnt]# sh friut_check.sh banana

apple

[root@mail-qq mnt]# sh friut_check.sh peanut

I don't know

[root@mail-qq mnt]# cat friut_check.sh

#!/bin/bash

case "$1" in

apple)

echo banana

;;

banana)

echo apple

;;

*)

echo "I don't know"

esac

 

 

经典练习14:用[ ] 检查所给对象的类型是否与参数匹配,如果匹配显示对象就是参数代表的类型,如果不匹配显示对象不是参数代表的类型,其他情况显示unknow type

 

此处用到函数  !!!!!!!!!!

 

[root@mail-qq mnt]# vim file_check.sh

[root@mail-qq mnt]# sh file_check.sh -f /etc/passwd

/etc/passwd is a file

[root@mail-qq mnt]# sh file_check.sh -f /etc/

/etc/ is not a file

[root@mail-qq mnt]# sh file_check.sh -d /etc

/etc is a directory

[root@mail-qq mnt]# sh file_check.sh -d /etc/passwd

/etc/passwd is not a directory

[root@mail-qq mnt]# sh file_check.sh -b /dev/vdb

/dev/vdb is a block

[root@mail-qq mnt]# sh file_check.sh -b /dev/

/dev/ is not a block

[root@mail-qq mnt]# sh file_check.sh -b

block is not a

[root@mail-qq mnt]# sh file_check.sh

 unknown type

[root@mail-qq mnt]# sh file_check.sh -b c

c is not a block

 

[root@mail-qq mnt]# cat file_check.sh

#!/bin/bash

CHECK () { //声明函数的名字:CHECK,()和{}为函数的格式

if                              //用到if语句,

[ $1 $2 ] //用到test[] 这个命令作为工具,例如:[ -f /etc/passwd ]

then 其中$1为 -f -b -d 等参数,是函数的第一个变量,也是脚本后面

echo $2 is a $3 跟的第一个变量;$2为需要CHECK的对象,是函数的第二个变量,也是

else 脚本后面跟的第二变量,$3为 是函数的第三个变量。是下面case里面的

echo $2 is not a $3 file 或者block 或者 directory。

fi

}

case "$1" in

-f)

CHECK -f $2 file

;;

-b)

CHECK -b $2 block

;;

-d)

CHECK -d $2 directory

;;

*)

echo " unknown type "

esac

 

 

expect语句

 

shell中利用expect实现自动应答脚本

 

[root@mail-qq mnt]# yum install expect -y //安装expect软件包

 

经典练习15:

[root@mail-qq mnt]# /mnt/answer.exp

spawn /mnt/ask.sh

input your name : xiaoyao

input your age : 26

input your calss : linux

xiaoyao is 26's old and xiaoyao is linux student

[root@mail-qq mnt]# cat ask.sh

#!/bin/bash

read -p "input your name : " NAME

read -p "input your age : " AGE

read -p "input your calss : " CLASS

echo $NAME is $AGE\'s old and $NAME is $CLASS student

[root@mail-qq mnt]# cat answer.exp

#!/usr/bin/expect

spawn /mnt/ask.sh

expect "name :"

send "xiaoyao\r"

expect "age :"

send "26\r"

expect "class :"

send "linux\r"

expect eof //执行后退出执行后的界面。

 

经典练习16:写即脚本,实现自动连接远程主机。

 

[root@mail-qq mnt]# mv ssh_95.exp ssh_215.exp

[root@mail-qq mnt]# /mnt/ssh_215.exp

spawn ssh root@172.25.254.215

root@172.25.254.215's password:

Last login: Fri Apr 28 02:48:32 2017 from 172.25.254.195

[root@mail-westos ~]#

 

[root@mail-qq mnt]# cat ssh_215.exp

#!/usr/bin/expect

spawn ssh root@172.25.254.215 //直接调用命令

expect {

"(yes/no)?" { send "yes\r";exp_continue}

"password:" { send "redhat\r"};

}

interact //动作执行后留在执行后的界面,

  连接后可以在远程主机上操作,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值