Bash Scripts

#######Bash Scripts#######



1.Bash脚本基础
BASH = GNU Bourne-Again Shell,BASH 是 GNU 组织开发和推广的一个项目。
Bash脚本类似批处理,简单来讲就是把许多的指令集合在一起,并提供循环、条件、判断等重要功能,语法简单实用,用以编写程序,大大简化管理员的操作,并可以完成图形工具所无法实现的功能。

如何创建新shell脚本?
1. 创建包含bash命令的文本文件。文件的第一行应为:

#!/bin/bash

Bash Scripts

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

Bash Scripts

3. 将文件放置在用户的$PATH的目录中
~/bin – 用于用户的私有程序
/usr/local/bin – 本地开发、系统上的其他人使用的脚本
/usr/local/sbin - 本地开发、由root使用的脚本
直接运行脚本和使用source命令运行脚本是不同的!
脚本调试模式:
#!/bin/bash -x

# bash -x scripts

Bash Scripts


2.引用和转义
引用和转义在shell解析字符串时用于去除字符串中特殊字符或保留词语的特殊含义。这会导致按字面处理字符串,而不是展开变量或将其部分内容视作具有特殊含义。
引用有三种类型:
1)弱引用
将字符串放置在双引号中,保留字符串中所有字符的文字值,$、`、\和!字符除外。换言之,变量
扩展和命令扩展在双引号内仍起作用。
echo “can I have a $FRUIT”

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

Bash Scripts

2)强引用
将字符串放置在单引号中,保留字符串中所有字符的文字值,同时禁用所有扩展:
echo 'Make $$$ Fast'

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

Bash Scripts

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

ls untitled\ folder

Bash Scripts

举例:
[[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"
[[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"

3.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

Bash Scripts


4.命令替换
命令替换在子shell中执行指定命令并用命令输出替换脚本中的命令替换。
语法:
$(shell command)
示例:
touch datafile.$(id -un)

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

Bash Scripts

[[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

5.算术运算符

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

Bash Scripts

Bash Scripts

Shell计算命令:
用$[]表示数学运算。
# echo $[1+2]
# a=1; echo $[$[$a+1]*2]
用expr表示数学运算。
# echo `expr 1 + 2`
用let指示数学运算。
# let A=1+2

# echo $A

Bash Scripts

用(())表示数学运算。bash内建功能,效率高。
#!/bin/bash
for ((i=1;i<10;i++))
do
((j+=i))
done

echo $j

Bash Scripts

测试:

Bash Scripts


6.循环
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

Bash Scripts

7.循环与计算结合:
#!/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

Bash Scripts

测试:

Bash Scripts


8.数据库备份示例:
#!/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

Bash Scripts

测试:

Bash Scripts



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

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

Bash Scripts

测试:

Bash Scripts

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

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

Bash Scripts

测试:

Bash Scripts


10.退出状态
Linux命令完成时,将返回退出状态。成功完成程序时,将返回0的推出状态。这被bash当作逻辑True值。非零退出状态通常表示发生了错误,并且被bash当作逻辑False值。
例如:grep的退出状态的含义:
0 – 在指定的文件中找到了模式
1 – 在指定的文件中未找到模式
>1 – 一些其他错误(无法打开文件、错误的搜索表达式等)
推出状态的值被存储在"?"中,可以使用以下命令查看:

# echo $?

Bash Scripts


11.test条件判断
test命令可用于评估bash脚本中的表达式。它评估其参数所指定的表达式,如果表达式为true,返回零退出状态,如果表达式为false,则返回非零退出状态。test具有替代语法,使用方括号"[]"将表达式括起来,这样更易于阅读。
语法:test EXPRESSION 或 [EXPRESSION]
非零或零长度字符串运算符:test -{n|z} STRING
[[email protected] ~]# [ -n westos ]; echo $?
0
[[email protected] ~]# [ -z westos ]; echo $?
1
字符串比较运算符:=、!=
[[email protected] ~]# [ abc = abc ]; echo $?
0
[[email protected] ~]# [ abc = ABC ]; echo $?
1
[[email protected] ~]# [ abc != ABC ]; echo $?
0
数字比较运算符:-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
文件状态运算符:test -{b|c|e|f|d|r|w|x|s|L} FILE/DIRECTORY
-b   ##块设备文件
-c   ##字符设备文件
-e   ##文件是否存在
-f   ##常规文件
-d   ##目录
-r   ##可读文件
-w   ##可写文件
-x   ##可执行文件
-S   ##套接字文件

-L   ##链接文件

Bash Scripts

测试:

Bash Scripts


[[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
二进制文件运算符:-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
逻辑运算符:-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

12.if语句
if命令检查if后面的命令或列表的退出值。如果第一个命令评估为true/零,则运行then之后的命令列表,直至任一else。如果第一个命令评估为false/非零,则运行else与fi之间的命令列表(反向平写if,标记if块的结束)。
语法:if command; then command; command2; else command3; fi
示例:
#!/bin/bash
if
   [ -z "$1" ]
then
   echo please give me a userfile
elif
[ ! -e "$1" ]
then
   echo "$1 is not exist!!"
else
   for NAME in `cat $1`
   do
   useradd $NAME
   done

fi

Bash Scripts

测试:

Bash Scripts



13.case语句
case语句 :它能够把变量的内容与多个模板进行匹配,再根据成功匹配的模板去决定应该执行哪部分代码。
#!/bin/bash
case "$1" in
none)
echo "all"
;;
all)
echo "none"
;;
*)
echo "Usage: $0 (all|none)"
;;

esac

Bash Scripts

测试:

Bash Scripts



14.expect语句
在shell中利用expect实现自动应答脚本。
#!/usr/bin/expect
这一行告诉操作系统脚本里的代码使用那一个shell来执行。
set timeout 10
设置后面所有的expect命令的等待响应的超时时间,单位为秒。
spawn talk
spawn是expect的内部命令,作用是给后面的shell指令加个壳,用来传递交互指令。
expect "who"
判断上次输出结果里是否包含“who”的字符串,如果有则立即返回,否则等待超时时间后返回。
send "westos\n"
执行交互动作,相当于手工输入"westos"。
expect eof
作用是在输出中搜索文件结束符,如果没有这一行,脚本会立即退出,得不到正确结果。
interact
执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。否则退出登录。
$argv 参数数组
expect脚本可以接受从bash传递过来的参数.可以使用[lindex $argv n]获得,n从0开始,分别表示第一个,第二个,第三个....参数。
举例:

交互输入脚本

Bash Scripts

expect脚本

Bash Scripts

测试:

Bash Scripts


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

1)临时设置,关闭shell后,无法生效

Bash Scripts

2)用户级别设置,只对当前用户生效,切换用户后无效

修改~./bash_profile文件

Bash Scripts

测试:

Bash Scripts

3)系统级别设置,切换用户后仍然生效

修改/etc/profile文件

Bash Scripts

测试:

Bash Scripts

使用env命令显示所有环境变量
使用set命令现实所有本地定义的shell变量
Bash启动脚本
在用户登录的时候,会运行全局变量文件/etc/profile,和用户自定义变量文件~/.bash_profile去初始化它们的环境变量。


16.别名
alias命令可以用来自定义属于自己的系统命令,写入~/.bashrc 文件永久生效。
查看别名:
# alias
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
...Bash Scripts
设置别名:
1)临时生效
# alias mycom='echo hello;hostname'
# mycomm
hello

server0.example.com

Bash Scripts

2)永久生效

vim /etc/bashrc

Bash Scripts

测试:

Bash Scripts


删除别名: unalias mycomm

Bash Scripts