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 ‘!‘

!

[[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]alhost 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] ~]#

时间: 2024-08-10 21:21:10

Linux云自动化运维第十九课的相关文章

Linux云自动化运维第十六课

第八单元 Mariadb数据库 一.Mariadb安装 1.安装mariadb和mariadb-client组件: # yum groupinstall -y mariadb mariadb-client 2.启动mariadb服务: # systemctl start mariadb ; systemctl enable mariadb 3.校验mariadb的监听端口: # ss -antlp |grep mysql LISTEN 0 50 *:3306 *:* users:(("mysql

Linux云自动化运维第十四课

第三单元 高速缓存 DNS 一.DNS 总揽 1.权威名称服务器:存储并提供某区域 ( 整个 DNS 域或 DNS 域的一部分 ) 的实际数据.权威名称服务器的类型包括 1)Master : 包含原始区域数据.有时称作 " 主要 " 名称服务器 2)Slave : 备份服务器 , 通过区域传送从 Master 服务器获得的区域数据的副本.有时称作 " 次要 " 名称服务器 2.非权威 / 递归名称服务器:客户端通过其查找来自权威名称服务器的数据.递归名称服务器的类型

Linux云自动化运维第二十课

第五单元 iSCSI远程块存储 一.iSCSI概念 iSCSI(Internet SCSI)支持从客户端(发起端)通过IP向远程服务器上的SCSI存储设备(目标)发送SCSI命令.iSCSI限定名称用于确定发起端和目 标,并采用iqn.yyyy-mm.{reverse domain}:label的格式.默认情况下,网络通信是至iSCSI目标上的端口3260/tcp的明文. 1.iSCSI发起端:需要访问原始SAN存储的客户端. 2.iSCSI目标:从iSCSI服务器提供的远程硬盘磁盘,或"目标门

Linux云自动化运维第四课

Linux云自动化运维第四课 一.vim 1.vim光标移动 1)在命令模式下 :数字  ###移动到指定的行 G  ###文件最后一行 gg  ###文件第一行 2)在插入模式下 i  ###光标所在位置插入 I  ###光标所在行行首 a  ###光标所在字符的下一个位置 A  ###光标所在行行尾 o  ###光标所在行下一行 O  ###光标所在行上一行 s  ###删除光标所在字符插入 S  ###删除光标所在行插入 2.vim的退出模式 :q  ###当用vim打开文件但没有对字符作

Linux云自动化运维第二十一课

第二单元 高级网络配置 一.网络桥接 网络桥接用网络桥实现共享上网主机和客户机除了利用软件外,还可以用系统自带的网络桥建立连接用双网卡的机器做主机 二.网络桥接的配置 1.vim /etc/sysconfig/network-scripts/ifcfg-eth0 - BRIDGE=br0 2.vim /etc/sysconfig/network-scripts/ifcfg-br0 – TYPE=Bridge 3.示例: [[email protected] Desktop]# vim /etc/

linux云自动化运维基础知识14(设备挂载)

####1.设备访问####1.设备识别/dev/xdxn        ##硬盘设备/dev/sda1/dev/cdrom        ##光驱/dev/mapper/*        ##虚拟设备 2.设备的使用##<设备的发现>##fdisk -l        ##查看真实存在的设备cat /proc/partitions    ##系统能够识别的设备blkid            ##系统能够挂载使用的设备iddf            ##查看设备被系统使用的情况 ##<

linux云自动化运维基础知识7(进程)

####1.进程定义####进程就是cpu未完成的工作 ####2.ps命令####ps    a    ##关于当前环境的所有进程    x| -A    ##所有进程    f    ##显示进程从属关系    e    ##显示进程调用环境工具的详细信息    l    ##长列表显示进程的详细信息    u    ##显示进程的用户信息    -a    ##显示shell前台运行命令的进程,但不保函shell本身    ps ax -o %cpu,%mem,user,group,com

Linux云自动化运维第二课

一.Linux系统结构 1.Linux是一个倒树结构.Linux中所有的东西都是文件.这些文件都在系统的顶级目录中"/","/"是根目录."/"目录以下为二级目录,这些目录都是系统装机时系统自动建立的. 2.二级目录的作用: /bin ###二进制可执行文件,也就是系统命令.eg:删除/bin中的date文件,命令行输入date,会显示bash:date:command not found... /sbin ###系统管理命令存放位置 /boot

linux云自动化运维基础知识4(系统结构,vim,管理输入输出,正则表达式)

linux系统结构    linux是一个倒树结构   linux中所有的东西都是文件   这些文件都在系统顶级目录"/" /就是根目录  /目录以下为二级目录这些目录都是系统装机时系统自动建立的如图 2.二级目录的作用/bin    ##二进制可执行文件也就是系统命令/sbin   ##系统管理命令存放位置/boot   ##启动分区,负责系统启动/dev    ##设备管理文件/etc    ##大多数系统管理文件/home   ##普通用户的家目录/lib    ##32位系统库