1 shell脚本
1.1 shell作为应用程序
shell 命令解析器可以交互式地解释、执行用户输入的命令,将用户的操作翻译成机器可以识别的语言,完成相应功能。shell 是用户和 Linux 内核之间的接口程序。 Linux 系统中提供了好几种不同的 shell 命令解释器, 如 sh、 ash、 bash 等。一般默认使用 bash 作为默认的解释器。
1.2 作为程序设计语言
它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。完成类似于 windows 下批处理操作,简化我们对系统的管理与应用程序的部署称之为 shell 脚本。 shell 脚本是一种脚本语言,我们只需使用任意文本编辑器,按照语法编写相应程序,增加可执行权限,即可在安装 shell 命令解释器的环境下执行.
2 shell语法
2.1 shell 脚本的定义与执行
#!/bin/bash #!用来声明脚本由什么 shell 解释,否则使用默认 shell
#"#"号代表注释当前行
chmod + x test.sh ./test.sh # 增加可执行权限后执行
bash test.sh # 直接指定使用 bash 解释 test.sh
.test.sh(source test.sh) # 使用当前 shell 读取解释 test.sh
三种执行脚本的方式不同点:
./和 bash 执行过程基本一致,后者明确指定 bash 解释器去执行脚本,脚本中#!指定的解释器不起作用。前者首先检测#!,使用#!指定的 shell,如果没有使用默认的 shell
用./和 bash 去执行会在后台启动一个新的 shell 去执行脚本。用.去执行脚本不会启动新的 shell,直接由当前的 shell 去解释执行脚本。
2.2 变量
2.2.1 自定义变量
num=10 # 定义变量
i=$num # 把变量 num 的值付给变量 i
echo $num # 显示变量
unset varname # 清除变量
read string # 从键盘输入一个字符串付给变量 string
readonly var=100 # 定义一个只读变量,只能在定义时初始化,以后不能改变,不能被清除。
export var=300 # 使用 export 说明的变量,会被导出为环境变量,其它 shell 均可使用
等号两边不能直接接空格符,若变量中本身就包含了空格,则整个字符串都要用双引号、或单引号括起来;双引号内的特殊字符可以保有变量特性,但是单引号内的特殊字符则仅为一般字符。
name = aa //错误
name=aa bb //错误
name=“aa bb” //正确
echo “$name is me” //输出: aa bb is meecho ‘$name is me’ //输出: $name is me
#!/bin/bash
echo "this is the var test shell script "
name="edu"
echo "$name is me"
echo '$name is me'
echo "please input a string"
read string
echo "the string of your input is $string"
2.2.2 环境变量
shell 在开始执行时就已经定义了一些和系统的工作环境有关的变量,我们在 shell 中可以直接使用$name 引用。定义:一般在~/.bashrc 或/etc/profile 文件中(系统自动调用的脚本)使用 export 设置,允许用户后来更改。
env # 查看所有的环境变量
unset # 清除环境变量
常见环境变量:
HOME:用于保存注册目录的完全路径名。
PATH:用于保存用冒号分隔的目录路径名, shell 将按 PATH变量中给出的顺序搜索这些目录,找到的第一个与命 令名称一致的可执行文件将被执行。
HOSTNAME:主机名
SHELL:默认的 shell命令解析器
LOGNAME:此变量保存登录名
PWD:当前工作目录的绝对路径名
#!/bin/bash
echo "You are welcome to use bash"
echo "Current work dirctory is $PWD"
echo "the host name is $HOSTNAME"
echo "your home dir $HOME"
echo "Your shell is $SHELL"
2.2.3 预设变量
$#: 传给 shell 脚本参数的数量
$*:传给 shell 脚本参数的内容
$1、 $2、 $3、 …、$9:运行脚本时传递给其的参数,用空格隔开,第10个表示为${10}
$?:命令执行后返回的状态,通常用于检查上一个命令执行是否正确(在 Linux 中,命令退出状态为 0 表示该命令正确执行,任何非 0 值表示命令出错)。
$0:当前执行的进程名
#!/bin/bash
echo "your shell script name is $0"
echo "the params of your input is $*"
echo "the num of your input params is $#"
echo "the params is $1 $2 $3 $4"
2.2.4 引号的用法
“”(双引号):包含的变量会被解释
‘’(单引号):包含的变量会当做字符串解释
``(数字键 1 左面的反引号):反引号中的内容作为系统命令,并执行其内容,可以替换输出为一个变量。例如$ echo "today is date
"的输出是:today is 2012 年 07 月 29 日星期日 12:55:21 CST
2.3 条件测试语句
2.3.1 对文件的测试
1)按照文件类型
-e 文件名 文件是否存在
-s 文件名 是否为非空
-b 文件名 块设备文件
-c 文件名 字符设备文件
-d 文件名 目录文件
-f 文件名 普通文件
-L 文件名 软链接文件
-S 文件名 套接字文件
-p 文件名 管道文件
2)按照文件权限
-r 文件名 可读
-w 文件名 可写
-x 文件名 可执行
3)两个文件之间的比较
文件 1 -nt 文件 2 文件 1 的修改时间是否比文件 2 新
文件 1 -ot 文件 2 文件 1 的修改时间是否比文件 2 旧
文件 1 -ef 文件 2 两个文件的 inode 节点号是否一样,用于判断是否是硬链接
#!/bin/bash
test -e /dev/qaz
echo $?
test -e /home
echo $?
test -d /home
echo $?
test -f /home
echo $?
mkdir test_sh
chmod 500 test_sh
[ -r test_sh ]
echo $?
[ -w test_sh ]
echo $?
[ -x test_sh ]
echo $?
[ -s test_sh ]
echo $?
[ -c /dev/console ]
echo $?
[ -b /dev/sda ]
echo $?
[ -L /dev/stdin ]
echo $?
2.3.2 对字符串进行测试
s1 = s2 测试两个字符串的内容是否完全一样
s1 != s2 测试两个字符串的内容是否有差异
-z s1 测试 s1 字符串的长度是否为 0
-n s1 测试 s1 字符串的长度是否不为 0
#!/bin/bash
test -z $yn
echo $?
echo "please input a y/n"
read yn
[ -z "$yn" ]
echo 1:$?
[ $yn = "y" ]
echo 2:$?
2.3.3 对数字进行测试
a -eq b 测试 a 与 b 是否相等
a -ne b 测试 a 与 b 是否不相等
a -gt b 测试 a 是否大于 b
a -ge b 测试 a 是否大于等于 b
a -lt b 测试 a 是否小于 b
a -le b 测试 a 是否小于等于 b
#!/bin/bash
echo "please input a num(1-9)"
read num
[ $num -eq 5 ]
echo $?
[ $num -ne 5 ]
echo $?
[ $num -gt 5 ]
echo $?
[ $num -ge 5 ]
echo $?
[ $num -le 5 ]
echo $?
[ $num -lt 5 ]
echo $?
2.3.4 复合测试
test -e /home && test -d /home && echo "true"
test 2 -lt 3 && test 5 -gt 3 && echo "equal"
test "aaa" = "aaa" || echo "not equal" && echo "equal"
2.4 控制语句
#!/bin/bash
echo "Press y to continue"
read yn
if [ $yn = "y" ]; then # 这里注意中括号和表达式之间必须有空格
echo "script is running..."
else
echo "stopped!"
fi
#!/bin/bash
echo "This script will print your choice"
case "$1" in
"one")
echo "your choice is one"
;;
"two")
echo "your choice is two"
;;
"three")
echo "Your choice is three"
;;
*)
echo "Error Please try again!"
exit 1 # 也可以不加这一句
;;
esac
#!/bin/bash
echo "Please input your choice:"
read choice
case "$choice" in
Y | yes | Yes | YES)
echo "It's right"
;;
N* | n*)
echo "It's wrong"
;;
*)
exit 1
esac
#!/bin/bash
declare -i sum # 将sum声明为int类型
for (( i=1; i<=100; i=i+1 ))
do
sum=sum+i
done
echo "The result is $sum"
#!/bin/bash
for name in `ls`
do
if [ -f $name ];then
echo "$name is file"
elif [ -d $name ];then
echo "$name is directory"
else
echo "^_^"
fi
done
#!/bin/bash
declare -i i
declare -i s
while [ "$i" != "101" ]
do
s+=i;
i=i+1;
done
echo "The count is $s"
# 与 while 恰恰相反,当 condition 成立的时候退出循环,否则继续循环。
#!/bin/bash
declare -i i
declare -i s
until [ "$i" = "101" ]
do
s+=i;
i=i+1;
done
echo "The count is $s"
break # break 命令允许跳出循环。break 通常在进行一些处理后退出循环或 case 语句。
continue # continue 命令类似于 break 命令。只有一点重要差别,它不会跳出循环,只是跳过这个循环步骤。
2.5 函数
#!/bin/bash
is_it_directory()
{
if [ $# -lt 1 ]; then
echo "I need an argument"
return 1
fi
if [ ! -d $1 ]; then
return 2
else
return 3
fi
}
echo -n "enter destination directory:"
read direct
is_it_directory $direct
echo "the result is $?"