Linux云自动化运维第十九课

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux云自动化运维第十九课相关的知识,希望对你有一定的参考价值。

第十一单元 Bash Scripts

 

一、Bash脚本基础

 

1.BASH = GNU Bourne-Again Shell,BASH是GNU组织开发和推广的一个项目。

2.Bash脚本类似批处理,简单来讲就是把许多的指令集合在一起,并提供循环、条件、判断等重要功能,语法简单实用,用以编写程序,大大简化管理员的操作,并可以完成图形工具所无法实现的功能。

3.如何创建新shell脚本?

1)创建包含bash命令的文本文件。文件的第一行应为:

#!/bin/bash

2)使文件可执行(使用chmod +x scripts)

3)将文件放置在用户的$PATH的目录中

~/bin – 用于用户的私有程序

/usr/local/bin – 本地开发、系统上的其他人使用的脚本

/usr/local/sbin - 本地开发、由root使用的脚本直接运行脚本和使用source命令运行脚本是不同的!

4)脚本调试模式:

#!/bin/bash -x

# bash -x scripts

5)示例:

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash -x

echo "Hello world!"

[[email protected] mnt]# sh test.sh

Hello world!

[[email protected] mnt]# bash test.sh

Hello world!

[[email protected] mnt]# chmod +x test.sh

[[email protected] mnt]# bash -x test.sh

+ echo ‘Hello world!‘

Hello world!

[[email protected] mnt]# ./test.sh

+ echo ‘Hello world!‘

Hello world!

[[email protected] mnt]# vim  test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

cat

[[email protected] mnt]# sh test.sh

^Z

[1]+  Stopped                 sh test.sh

[[email protected] mnt]# ps ef

  PID TTY      STAT   TIME COMMAND

 2068 pts/0    Ss     0:00 -bash [email protected]=ibus LANG=en_US.UTF-8 USER=root

 2108 pts/0    T      0:00  \_ sh test.sh XDG_SESSION_ID=2 HOSTNAME=localhost.lo

 2109 pts/0    T      0:00  |   \_ cat XDG_SESSION_ID=2 HOSTNAME=localhost.local

 2110 pts/0    R+     0:00  \_ ps ef XDG_SESSION_ID=2 HOSTNAME=localhost.localdo

 1844 tty1     Ss+    0:00 -bash HOME=/root USER=root SHELL=/bin/bash TERM=linux

[[email protected] mnt]# fg

sh test.sh

^C

[[email protected] mnt]# cat /etc/shells

/bin/sh

/bin/bash

/sbin/nologin

/usr/bin/sh

/usr/bin/bash

/usr/sbin/nologin

[[email protected] mnt]# bash -x test.sh

+ cat

^C

4.引用和转义

引用和转义在shell解析字符串时用于去除字符串中特殊字符或保留词语的特殊含义。这会导致按字面处理字符串,而不是展开变量或将其部分内容视作具有特殊含义。引用有三种类型:

1)弱引用

将字符串放置在双引号中,保留字符串中所有字符的文字值,$、`、\和!字符除外。换言之,变量扩展和命令扩展在双引号内仍起作用。

echo “can I have a $FRUIT”

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

2)强引用

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

echo “Make $$$ Fast”

rm ‘untitled folder‘

3)转义

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

echo Make \$\$\$ Fast\!

ls untitled\ folder

[[email protected] ~]# echo # not a comment #

[[email protected] ~]# echo \# not a comment #

# not a comment

[[email protected] ~]# echo \# not a comment \#

# not a comment #

[[email protected] ~]# echo ‘# not a comment #‘

# not a comment #

[[email protected] ~]# echo ‘$HOME‘

$HOME

[[email protected] ~]# echo ‘`pwd`‘

`pwd`

[[email protected] ~]# echo ‘"Hello,world"‘

"Hello,world"

www.westos.org

6[[email protected] ~]# echo "$HOME"

/root

[[email protected] ~]# echo "`pwd`"

/root

[[email protected] ~]# echo ""Hello, world""

Hello, world

[[email protected] ~]# echo "\$HOME"

$HOME

[[email protected] ~]# echo "\`pwd\`"

`pwd`

[[email protected] ~]# echo "\"Hello, world\""

"Hello, world"

4)示例

[[email protected] mnt]# a=1

[[email protected] mnt]# echo $a

1

[[email protected] mnt]# echo \$a

$a

[[email protected] mnt]# echo "$a"

1

[[email protected] mnt]# echo ‘$a‘

$a

[[email protected] mnt]# echo $a $a $a

1 1 1

[[email protected] mnt]# echo \$a $a $a

$a 1 1

[[email protected] mnt]# echo ‘$a $a $a‘

$a $a $a

[[email protected] mnt]# echo "$a $a $a"

1 1 1

[[email protected] mnt]# echo ‘$a0 $a $a‘

$a0 $a $a

[[email protected] mnt]# echo ${a}0 \$a $a

10 $a 1

[[email protected] mnt]# echo * * * * *

createuser.sh deluser.sh exit.sh iduser.sh num.sh passwdfile show_ip.sh test.sh userfile createuser.sh deluser.sh exit.sh iduser.sh num.sh passwdfile show_ip.sh test.sh userfile createuser.sh deluser.sh exit.sh iduser.sh num.sh passwdfile show_ip.sh test.sh userfile createuser.sh deluser.sh exit.sh iduser.sh num.sh passwdfile show_ip.sh test.sh userfile createuser.sh deluser.sh exit.sh iduser.sh num.sh passwdfile show_ip.sh test.sh userfile

[[email protected] mnt]# echo "* * * * *"

* * * * *

[[email protected] mnt]# echo ‘* * * * *‘

* * * * *

[[email protected] mnt]# echo "!"

-bash: !: event not found

[[email protected] mnt]# echo ‘!‘

!

[ro[email protected] mnt]# echo "$"

$

[[email protected] mnt]# echo "$a"

1

[[email protected] mnt]# echo ‘$a‘

$a

[[email protected] mnt]# echo "`"

> 1

> ^C

[[email protected] mnt]# echo ‘`‘

`

[[email protected] mnt]# echo "\"

> a

> ^C

[[email protected] mnt]# echo ‘\‘

\

[[email protected] mnt]# echo your hostname is `hostname`

your hostname is localhost.localdomain

[[email protected] mnt]# echo ***** your hostname is `hostname` *****

createuser.sh deluser.sh exit.sh iduser.sh num.sh passwdfile show_ip.sh test.sh userfile your hostname is localhost.localdomain createuser.sh deluser.sh exit.sh iduser.sh num.sh passwdfile show_ip.sh test.sh userfile

[[email protected] mnt]# echo ‘***** your hostname is `hostname` *****‘

***** your hostname is `hostname` *****

[[email protected] mnt]# echo "***** your hostname is `hostname` *****"

***** your hostname is localhost.localdomain *****

5.Shell变量

shell变量用于为稍后在脚本中使用的名称指定值,并且仅限于shell命令行或从中声明变量的脚本。

若要定义或指定值:

FRUIT=apple

若要参考或使用变量:

$FRUIT

${FRUIT}

[[email protected] ~]# FIRST=John

[[email protected] ~]# LAST=Doe

[[email protected] ~]# echo $FIRST $LAST

John Doe

[[email protected] ~]# echo $FIRST_$LAST

Doe

[[email protected] ~]# echo ${FIRST}_$LAST

John_Doe

示例:

[[email protected] mnt]# a=1

[[email protected] mnt]# echo $a

1

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# sh test.sh

root

[[email protected] mnt]# cat test.sh

#!/bin/bash

echo $USER

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# sh test.sh

LOCAL USER is root

[[email protected] mnt]# cat test.sh

#!/bin/bash

NAME="LOCAL USER is"

echo $NAME $USER

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

NAME="LOCAL USER is"

echo $NAME $USER

FIRSTNAME=student

FAMNAME=duck

echo my name is $FIRSTNAME_$FAMNAME

[[email protected] mnt]# sh test.sh

LOCAL USER is root

my name is duck

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

NAME="LOCAL USER is"

echo $NAME $USER

FIRSTNAME=student

FAMNAME=duck

echo my name is ${FIRSTNAME}_$FAMNAME

[[email protected] mnt]# sh test.sh

LOCAL USER is root

my name is student_duck

[[email protected] mnt]# ls

test.sh

[[email protected] mnt]# vim show_ip.sh

[[email protected] mnt]# cat show_ip.sh

#!/bin/bash

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

echo "your ipaddress is : $IP"

[[email protected] mnt]# sh show_ip.sh

your ipaddress is : 172.25.254.64

6.命令替换

命令替换在子shell中执行指定命令并用命令输出替换脚本中的命令替换。

语法:

$(shell command)

示例:

touch datafile.$(id -un)

TODAY=$(date +%Y-%m-%d)

[[email protected] ~]# TAROUTPUT=$(tar cvf /tmp/backup.tar $(find /etc -type f -mtime 1))

tar: Removing leading `/‘ from member names

[[email protected] ~]# echo $TAROUTPUT

/etc/hosts.allow /etc/hosts.deny /etc/sysconfig/iptables /etc/xinetd.d/tftp /etc/rht

/etc/firewalld/zones/public.xml.old /etc/firewalld/firewalld.conf.old /etc/xinetd.conf

示例:

[[email protected] mnt]# hostname

localhost.localdomain

[[email protected] mnt]# vim show_ip.sh

[[email protected] mnt]# cat show_ip.sh

#!/bin/bash

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

echo "$(hostname)‘s ipaddress is : $IP"

[[email protected] mnt]# sh show_ip.sh

localhost.localdomain‘s ipaddress is : 172.25.254.64

7.算术运算符

算术运算符指的是可以在程序中实现加、减、乘、除等数学运算的运算符。

operator meaning

<VARIABLE>++ 增量后

<VARIABLE>-- 减量后

- 减法

+ 加法

** 幂运算

* 乘法

/ 除法

% 余数

+= 加等

-= 减等

1)Shell计算命令:

$[]表示数学运算。

# echo $[1+2]

# a=1; echo $[$[$a+1]*2]

expr表示数学运算。

# echo `expr 1 + 2`

let指示数学运算。

# let A=1+2

# echo $A

(())表示数学运算。bash内建功能,效率高。

#!/bin/bash

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

do

((j+=i))

done

echo $j

2)示例

[[email protected] mnt]# echo $[1+2]

3

[[email protected] mnt]# echo $[2+2]

4

[[email protected] mnt]# echo $[5*2]

10

[[email protected] mnt]# echo $[5**2]

25

[[email protected] mnt]# echo $[10/2]

5

[[email protected] mnt]# echo $[9%2]

1

[[email protected] mnt]# echo $[3%5]

3

[[email protected] mnt]# echo `expr 5 \+ 2`

7

[[email protected] mnt]# echo `expr 5 \- 2`

3

[[email protected] mnt]# echo `expr 5 \* 2`

10

[[email protected] mnt]# echo `expr 5 \/ 2`

2

[[email protected] mnt]# echo `expr 5 \% 2`

1

[[email protected] mnt]# let A=1+2

[[email protected] mnt]# echo $A

3

[[email protected] mnt]# let A=3-1

[[email protected] mnt]# echo $A

2

[[email protected] mnt]# let A=2*5

[[email protected] mnt]# echo $A

10

[[email protected] mnt]# let A=5%2

[[email protected] mnt]# echo $A

1

[[email protected] mnt]# let A=5/2

[[email protected] mnt]# echo $A

2

8.循环:for循环用于值列表中的相同命令的重复。

[[email protected] ~]# for HOST in host{1..3};do echo $HOST;done

host1

host2

host3

[[email protected] ~]# for NUM in $(seq 2 2 8);do echo $NUM;done

2

4

6

8

1)循环与计算结合:

#!/bin/bash

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

do

((j+=i))

#j=`expr $j + $i`

#let j+=i

#j=$[j+=i]

done

echo $j

也可以写成一行:

# for((i=0; i<=100; i++));do j=`expr $j + $i` ;done;echo $j

2)数据库备份示例:

#!/bin/bash

for DB in $(mysql -e "show databases;" -E -N | grep -v ‘^*‘ | grep -v ‘schema$‘)

do

echo "Backing up $DB"

mysqldump $DB > /dbbackup/$DB.dump

done

echo ""

for DBDUMP in /dbbackup/*

do

SIZE=$(stat --printf "%s\n" $DBDUMP)

echo "$DBDUMP

$SIZE"

done

3)示例:

[[email protected] mnt]# vim num.sh

[[email protected] mnt]# sh num.sh

1

2

3

4

5

[[email protected] mnt]# cat num.sh

#!/bin/bash

for NUM in {1..5}

do

echo $NUM

done

[[email protected] mnt]# vim num.sh

[[email protected] mnt]# cat num.sh

#!/bin/bash

for NUM in $(seq 1 2 10)

do

echo $NUM

done

[[email protected] mnt]# sh num.sh

1

3

5

7

9

[[email protected] mnt]# vim exit.sh

[[email protected] mnt]# cat exit.sh

#!/bin/bash

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

do

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

done

[[email protected] mnt]# sh exit.sh

/etc/hello is not exit

/etc/passwd is exit

/etc/group is exit

[[email protected] mnt]# vim exit.sh

[[email protected] mnt]# cat exit.sh

#!/bin/bash

for NAME in {1..5}

do

ping -c1 -w1 172.25.254.$NUM &> /dev/null && echo 172.25.254.$NUM is up || echo 172.25.254.$NUM down

done

[[email protected] mnt]# sh exit.sh

172.25.254. down

172.25.254. down

172.25.254. down

172.25.254. down

172.25.254. down

[[email protected] mnt]# ls

createuser.sh  exit.sh    num.sh      show_ip.sh  userfile

deluser.sh     iduser.sh  passwdfile  test.sh

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# sh test.sh

1

2

3

4

5

[[email protected] mnt]# cat test.sh

#!/bin/bash

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

do

echo $i

done

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

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

do

echo $i

((i++))

done

[[email protected] mnt]# sh test.sh

1

3

5

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

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

do

echo $i

((i--))

done

[[email protected] mnt]# sh test.sh

10

8

6

4

2

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

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

do

((j+=i))

echo $j

done

[[email protected] mnt]# sh test.sh

1

3

6

10

15

21

28

36

45

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

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

do

echo $i

sleep 1

done

[[email protected] mnt]# sh test.sh

10

9

8

7

6

5

4

3

2

1

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

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

do

echo "After ${i}s is end"

sleep 1

done

[[email protected] mnt]# sh test.sh

After 10s is end

After 9s is end

After 8s is end

After 7s is end

After 6s is end

After 5s is end

After 4s is end

After 3s is end

After 2s is end

After 1s is end

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

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

do

echo -ne "After ${i}s is end \r"

sleep 1

done

[[email protected] mnt]# sh test.sh

[[email protected] mnt]#

9.示例:

[[email protected] mnt]# vim userfile

[[email protected] mnt]# cat userfile

lee

westos

linux

loo

[[email protected] mnt]# vim passwdfile

[[email protected] mnt]# cat passwdfile

123

234

345

456

[[email protected] mnt]# vim createuser.sh

[[email protected] mnt]# cat createuser.sh

#!/bin/bash

COUNT=`wc -l /mnt/userfile | cut -d " " -f 1`

for NUM in $(seq 1 $COUNT)

do

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

PASSWD=‘sed -n ${NUM}p $2‘

useradd $USERNAME

echo $PASSWD | passwd --stdin $USERNAME

done

[[email protected] mnt]# cp -p createuser.sh deluser.sh

[[email protected] mnt]# vim deluser.sh

[[email protected] mnt]# cat deluser.sh

#!/bin/bash

COUNT=`wc -l /mnt/userfile | cut -d " " -f 1`

for NUM in $(seq 1 $COUNT)

do

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

userdel $USERNAME

done

[[email protected] mnt]# cp -p deluser.sh iduser.sh

[[email protected] mnt]# vim iduser.sh

[[email protected] mnt]# cat iduser.sh

#!/bin/bash

COUNT=`wc -l /mnt/userfile | cut -d " " -f 1`

for NUM in $(seq 1 $COUNT)

do

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

id $USERNAME

done

[[email protected] mnt]# sh createuser.sh userfile passwdfile

Changing password for user lee.

passwd: all authentication tokens updated successfully.

Changing password for user westos.

passwd: all authentication tokens updated successfully.

Changing password for user linux.

passwd: all authentication tokens updated successfully.

Changing password for user loo.

passwd: all authentication tokens updated successfully.

[[email protected] mnt]# sh iduser.sh userfile

uid=1001(lee) gid=1001(lee) groups=1001(lee)

uid=1002(westos) gid=1002(westos) groups=1002(westos)

uid=1003(linux) gid=1003(linux) groups=1003(linux)

uid=1004(loo) gid=1004(loo) groups=1004(loo)

[[email protected] mnt]# sh deluser.sh userfile

[[email protected] mnt]# sh iduser.sh userfile

id: lee: no such user

id: westos: no such user

id: linux: no such user

id: loo: no such user

 

二、Bash位置参数

 

1.有两种简单的方法可以将用户输入读入bash中的变量。第一个方法是使用read提示用户输入(使用-p选项)并将其直接存储到一个或多个变量:交互式输入

# read -p ‘Enter your first and last name: ‘ FIRST LAST

2.另一个方法是使用位置参数来读取传递给脚本的命令行参数或选项输入。各种特殊变量存储传递的选项编号Bash解析的个别参数或整个原始命令行。

指定的位置参数总数:$#

位置参数自身:$0、$1、$2、$3....

所有位置参数: [email protected]、$*

3.示例:

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

echo $1

echo $2

echo $3

echo $*

echo $#

echo [email protected]

[[email protected] mnt]# ./test.sh

 

 

 

 

0

 

[[email protected] mnt]# ./test.sh hello

hello

 

 

hello

1

hello

[[email protected] mnt]# ./test.sh hello world

hello

world

 

hello world

2

hello world

[[email protected] mnt]# ./test.sh hello world linux

hello

world

linux

hello world linux

3

hello world linux

[[email protected] mnt]#

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# ./test.sh

Give me a world: hello linux world

hello linux world

[[email protected] mnt]# cat test.sh

#!/bin/bash

read -p "Give me a world: " HELLO

echo $HELLO

[[email protected] mnt]#

[[email protected] mnt]# vim id_check.sh

[[email protected] mnt]# cat id_check.sh

#!/bin/bash

read -p "Please input your name : " username

check=`getent passwd $username`

[ -n "$check" ] && (

echo "the user is exit"

) || (

read -p "Please input your passwd : " passwd

useradd $username

echo $passwd | passwd --stdin $username

)

[[email protected] mnt]# sh id_check.sh

Please input your name : student

the user is exit

[[email protected] mnt]# sh id_check.sh

Please input your name : linux

Please input your passwd : linux

Changing password for user linux.

passwd: all authentication tokens updated successfully.

[[email protected] mnt]# id linux

uid=1005(linux) gid=1005(linux) groups=1005(linux)

[[email protected] mnt]#  

 

三、退出状态

 

1.Linux命令完成时,将返回退出状态。成功完成程序时,将返回0的推出状态。这被bash当作逻辑True值。非零退出状态通常表示发生了错误,并且被bash当作逻辑False值。

2.例如:grep的退出状态的含义:

0 – 在指定的文件中找到了模式

1 – 在指定的文件中未找到模式

>1 – 一些其他错误(无法打开文件、错误的搜索表达式等)

3.退出状态的值被存储在"?"中,可以使用以下命令查看:

# echo $?

 

四、test条件判断

 

1.test命令可用于评估bash脚本中的表达式。它评估其参数所指定的表达式,如果表达式为true,返回零退出状态,如果表达式为false,则返回非零退出状态。test具有替代语法,使用方括号"[]"将表达式括起来,这样更易于阅读。

2.语法:test EXPRESSION 或 [EXPRESSION]

1)非零或零长度字符串运算符:test -{n|z} STRING

[[email protected] ~]# [ -n westos ]; echo $?

0

[[email protected] ~]# [ -z westos ]; echo $?

1

2)字符串比较运算符:=、!=

[[email protected] ~]# [ abc = abc ]; echo $?

0

[[email protected] ~]# [ abc = ABC ]; echo $?

1

[[email protected] ~]# [ abc != ABC ]; echo $?

0

3)数字比较运算符:-eq、-ne、-lt、-le、-gt、-ge

[[email protected] ~]# [ 1 -eq 1 ]; echo $?

0

[[email protected] ~]# [ 1 -ne 1 ]; echo $?

1

[[email protected] ~]# [ 1 -gt 2 ]; echo $?

1

4)文件状态运算符:test -{b|c|e|f|d|r|w|x|s|L} FILE/DIRECTORY

[[email protected] ~]# [ -b /dev/sda ]; echo $?

1

[[email protected] ~]# [ -c /dev/zero ]; echo $?

0

[[email protected] ~]# [ -e /etc/passwd ]; echo $?

0

[[email protected] ~]# [ -f /etc/passwd ]; echo $?

0

[[email protected] ~]# [ -d /etc/passwd ]; echo $?

1

[[email protected] ~]# [ -L /etc/passwd ]; echo $?

1

5)二进制文件运算符:-ef、-nt、-ot

[[email protected] bin]# [ /bin/mount -ef /usr/bin/mount ]; echo $?

0

[[email protected] bin]# [ /bin/mount -nt /usr/bin/mount ]; echo $?

1

[[email protected] bin]# [ /bin/mount -ot /usr/bin/mount ]; echo $?

1

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

[[email protected] bin]# [ 2 -gt 1 -a 1 -gt 2 ]; echo $?

1

[[email protected] bin]# [ 2 -gt 1 -o 1 -gt 2 ]; echo $?

0

[[email protected] bin]# [ ! 2 -gt 1 ]; echo $?

1

7)示例:

[[email protected] mnt]# [ "1" = "2" ] && echo yes || echo no

no

[[email protected] mnt]# [ "1" -lt "2" ] && echo yes || echo no

yes

[[email protected] mnt]# [ "1" -gt "2" ] && echo yes || echo no

no

[[email protected] mnt]# [ "1" -le "2" ] && echo yes || echo no

yes

[[email protected] mnt]# [ "1" -le "1" ] && echo yes || echo no

yes

[[email protected] mnt]# [ "1" -ge "2" ] && echo yes || echo no

no

[[email protected] mnt]# [ "1" -ne "2" ] && echo yes || echo no

yes

[[email protected] mnt]# [ "1" -eq "2" ] && echo yes || echo no

no

[[email protected] mnt]# [ "$a" -gt "0" -a "$a" -lt "10" ] && echo yes || echo no

yes

[[email protected] mnt]# a=100

[[email protected] mnt]# [ "$a" -gt "0" -a "$a" -lt "10" ] && echo yes || echo no

no

[[email protected] mnt]# vim test.sh

[[email protected] mnt]# cat test.sh

#!/bin/bash

MIN=1

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

do

while

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

do

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

i=5

((MIN--))

done

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

sleep 1

done

[[email protected] mnt]# sh test.sh

After 1:3 is end

After 1:2 is end

After 1:1 is end

[[email protected] mnt]#

[[email protected] mnt]# getent passwd user1

user1:x:1003:1003::/home/user1:/bin/bash

[[email protected] mnt]# getent passwd student

student:x:1000:1000:Student User:/home/student:/bin/bash

[[email protected] mnt]# CHECK=`getent passwd student`

[[email protected] mnt]# [ -n "$CHECK" ] && echo yes || echo no

yes

[[email protected] mnt]#

[[email protected] mnt]# vim ip_check.sh

[[email protected] mnt]# cat ip_check.sh

#!/bin/bash

ping -c1 -w1 $1 &> /dev/null && echo $1 is exit || echo $1 is not exit

[[email protected] mnt]# sh ip_check.sh 172.25.254.100

172.25.254.100 is exit

[[email protected] mnt]# sh ip_check.sh 172.25.254.242

172.25.254.242 is not exit

[[email protected] mnt]#

 

五、if语句

 

if命令检查if后面的命令或列表的退出值。如果第一个命令评估为true/零,则运行then之后的命令列表,直至任一else。如果第一个命令评估为false/非零,则运行else与fi之间的命令列表(反向平写if,标记if块的结束)。

语法:if command; then command; command2; else command3; fi

示例:

if test “$USER” != ‘root‘ ; then

echo you are not logged in as root

fi

if [ $(id -u) -lt 9 ] ; then

echo “The number $(id -u) is less than 9!”

fi

www.westos.org

9if grep “^${USER}:” /etc/passwd &> /dev/null ; then

echo “${USER} is a local user on the system.”

else

echo “${USER} is not a local user.”

fi

systemctl is-active mariadb > /dev/null 2>&1 ; MARIADB_ACTIVE=$?

systemctl is-active postgresql > /dev/null 2>&1 ; POSTGRESQL_ACTIVE=$?

if [ $MARIADB_ACTIVE -eq 0 ];then

mysql

elif [ $POSTGRESQL_ACTIVE -eq 0 ];then

psql

else

sqlite3

fi

练习:

[[email protected] mnt]# vim createuser.sh

[[email protected] mnt]# cat createuser.sh

#!/bin/bash

if

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

then

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

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

if

[ "$NUM1" -eq "$NUM2" ]

then

for NUM in `seq 1 $NUM1`

do

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

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

CHECK=`getent passwd $USERNAME`

if

[ -z "$CHECK" ]

then

useradd $USERNAME

echo $PASSWD | passwd --stdin $USERNAME

else

echo "The $USERNAME is exist"

fi

done

else

echo "error:$1‘s line is different $2,Please check $1 or $2"

fi

else

echo "error:Please give me username file and passwd file!!!"

fi

[[email protected] mnt]# vim userfile

[[email protected] mnt]# cat userfile

username1

username2

username3

username4

username5

username6

username7

username8

[[email protected] mnt]# vim passfile

[[email protected] mnt]# cat passfile

password1

password2

password3

password4

password5

password6

password7

password8

[[email protected] mnt]# sh createuser.sh

error:Please give me username file and passwd file!!!

[[email protected] mnt]# sh createuser.sh userfile passfile

The username1 is exist

The username2 is exist

The username3 is exist

The username4 is exist

The username5 is exist

The username6 is exist

The username7 is exist

The username8 is exist

[[email protected] mnt]# userdel -r username1

[[email protected] mnt]# userdel -r username2

[[email protected] mnt]# userdel -r username3

[[email protected] mnt]# userdel -r username4

[[email protected] mnt]# sh createuser.sh userfile passfile

Changing password for user username1.

passwd: all authentication tokens updated successfully.

Changing password for user username2.

passwd: all authentication tokens updated successfully.

Changing password for user username3.

passwd: all authentication tokens updated successfully.

Changing password for user username4.

passwd: all authentication tokens updated successfully.

The username5 is exist

The username6 is exist

The username7 is exist

The username8 is exist

[[email protected] mnt]#

[[email protected] mnt]# vim check_num.sh

[[email protected] mnt]# cat check_num.sh

#!/bin/bash

A=10

B=0

if

[ -n "$1" ]

then

if

[ "$1" -le "$A" -a "$1" -ge "$B" ]

then

echo ${1}属于0-10

else

echo ${1}不属于0-10

fi

else

echo "ERROR:give me a num!!!"

fi

[[email protected] mnt]# sh check_num.sh

ERROR:give me a num!!!

[[email protected] mnt]# sh check_num.sh 1

1属于0-10

[[email protected] mnt]# sh check_num.sh -7

-7不属于0-10

[[email protected] mnt]# sh check_num.sh 17

17不属于0-10

[[email protected] mnt]#

 

六、case语句

 

case语句 :它能够把变量的内容与多个模板进行匹配,再根据成功匹配的模板去决定应该执行哪部分代码。

case "$1" in

start)

systemctl start $2

;;

stop)

systemctl stop $2

;;

reload|restart)

systemctl stop $2

systemctl start $2

;;

*)

echo "Usage: $0 (start|stop|restart|reload)"

;;

esac

示例:

[[email protected] mnt]# vim case_file.sh

[[email protected] mnt]# cat case_file.sh

#!/bin/bash

case "$1" in

-b)

if

[ -b "$2" ]

then

echo "$2 is a block"

else

echo "$2 is not a block"

fi

;;

-f)

if

[ -f "$2" ]

then

echo "$2 is a file"

else

echo "$2 is not a file"

fi

;;

-d)

if

[ -d "$2" ]

then

echo "$2 is a dir"

else

echo "$2 is not a dir"

fi

;;

*)

echo "I Don‘t Know"

;;

esac

[[email protected] mnt]# sh case_file.sh

I Don‘t Know

[[email protected] mnt]# sh case_file.sh -d

 is not a dir

[[email protected] mnt]# sh case_file.sh -d /etc/

/etc/ is a dir

[[email protected] mnt]# sh case_file.sh -d /etc/passwd

/etc/passwd is not a dir

[[email protected] mnt]# sh case_file.sh -f /etc/passwd

/etc/passwd is a file

[[email protected] mnt]# sh case_file.sh -b /dev/vda1

/dev/vda1 is a block

[[email protected] mnt]#

 

 

七、expect语句

 

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

# cat talk

echo "who are you?"

read who

echo "hello, $who"

echo "are you

happy?"

read answer

echo "why?"

read answer

 

# cat auto

#!/usr/bin/expect

#set timeout 10

spawn ./talk

expect "who"

send "firefly\n"

expect "happy?"

send "Yes,I am happy.\n"

expect "why?"

send "任性!\n"

expect eof

exit

 

1)#!/usr/bin/expect

这一行告诉操作系统脚本里的代码使用那一个shell来执行。

2)set timeout 10

设置后面所有的expect命令的等待响应的超时时间,单位为秒。

3)spawn talk

spawn是expect的内部命令,作用是给后面的shell指令加个壳,用来传递交互指令。

4)expect "who"

判断上次输出结果里是否包含“who”的字符串,如果有则立即返回,否则等待超时时间后返回。

5)send "westos\n"

执行交互动作,相当于手工输入"westos"。

6)expect eof

作用是在输出中搜索文件结束符,如果没有这一行,脚本会立即退出,得不到正确结果。

7)interact

执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。否则退出登录。

8)$argv 参数数组

expect脚本可以接受从bash传递过来的参数.可以使用[lindex $argv n]获得,n从0开始,分别表示第一个,第二个,第三个....参数。

9)示例:

[[email protected] mnt]# vim 233.exp

[[email protected] mnt]# cat 233.exp

#!/usr/bin/expect

spawn ssh [email protected]

expect {

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

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

}

interact

[[email protected] mnt]# chmod +x 233.exp

[[email protected] mnt]# ./233.exp

spawn ssh [email protected]

The authenticity of host ‘172.25.254.42 (172.25.254.42)‘ can‘t be established.

ECDSA key fingerprint is f2:5e:9f:f4:87:12:4b:10:7a:42:16:1f:a0:3a:9a:53.

Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added ‘172.25.254.42‘ (ECDSA) to the list of known hosts.

[email protected]‘s password:

Last login: Wed Apr 26 15:51:51 2017

[[email protected] ~]#

 

八、环境变量

 

1.shell和脚本使用变量来存储数据 ,有些变量可以连同它们的内容传递给子进程,这些变量我们称之为环境变量。

[[email protected] ~]# LINUX=redhat

[[email protected] ~]# echo $LINUX

redhat

[[email protected] ~]# bash

[[email protected] ~]# echo $LINUX

[[email protected] ~]# exit

exit

[[email protected] ~]# export LINUX

[[email protected] ~]# bash

[[email protected] ~]# echo $LINUX

redhat

[[email protected] ~]# exit

exit

使用env命令显示所有环境变量

使用set命令现实所有本地定义的shell变量

2.Bash启动脚本

在用户登录的时候,会运行全局变量文件/etc/profile,和用户自定义变量文件

~/.bash_profile去初始化它们的环境变量。

/etc/profile

\_ /etc/profile.d/*.sh

~/.bash_profile

\_ ~/.bashrc

\_ /etc/bashrc

3.使用别名

alias命令可以用来自定义属于自己的系统命令,写入~/.bashrc 文件永久生效。

1)查看别名:

# alias

alias ls=‘ls --color=auto‘

alias mv=‘mv -i‘

alias rm=‘rm -i‘

...

2)设置别名:

# alias mycom=‘echo hello;hostname‘

# mycomm

hello

server0.example.com

3)删除别名:

unalias mycomm

4.使用函数

pathmunge () {

if [ "$2" = "after" ] ; then

PATH=$PATH:$1

else

PATH=$1:$PATH

fi

}

...

if [ "$EUID" = "0" ]; then

pathmunge /usr/sbin

pathmunge /usr/local/sbin

else

pathmunge /usr/local/sbin after

pathmunge /usr/sbin after

fi

5.示例:

[[email protected] mnt]# LINUX=redhat

[[email protected] mnt]# echo $LINUX

redhat

[[email protected] mnt]# bash

[[email protected] mnt]# echo $LINUX

 

[[email protected] mnt]# exit

exit

[[email protected] mnt]# export LINUX

[[email protected] mnt]# bash

[[email protected] mnt]# echo $LINUX

redhat

[[email protected] mnt]# exit

exit

[[email protected] mnt]# echo $LINUX

redhat

[[email protected] mnt]# bash

[[email protected] mnt]# echo $LINUX

redhat

[[email protected] mnt]# exit

exit

[[email protected] mnt]# vim /etc/profile

[[email protected] mnt]# cd

[[email protected] ~]# vim .bash_profile

[[email protected] ~]# alias

alias cp=‘cp -i‘

alias egrep=‘egrep --color=auto‘

alias fgrep=‘fgrep --color=auto‘

alias grep=‘grep --color=auto‘

alias l.=‘ls -d .* --color=auto‘

alias ll=‘ls -l --color=auto‘

alias ls=‘ls --color=auto‘

alias mv=‘mv -i‘

alias rm=‘rm -i‘

alias which=‘alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde‘

[[email protected] ~]# alias mycom=‘echo hello;hostname‘

[[email protected] ~]# mycom

hello

localhost

[[email protected] ~]# unalias mycom

[[email protected] ~]# mycom

bash: mycom: command not found...

[[email protected] ~]# 

以上是关于Linux云自动化运维第十九课的主要内容,如果未能解决你的问题,请参考以下文章

Linux云自动化运维第十六课

Linux云自动化运维第十四课

Linux云自动化运维第十七课

Linux云自动化运维第四课

Linux云自动化运维第二课

Linux云自动化运维第二十课