目录
1 shell编程
1.1 概述
user02$ man bash-builtins
1.2执行脚本
#!/bin/bash
#This is to show what a example looks like
date
echo "Our first example."
echo #this inserts an empty line in output .
echo "We are currently in the following diractory."
echo
/bin/pwd
echo
echo "This diractory contains following files"
/bin/ls
user02@vir:~ $ chmod a + x test.shuser02@vir:~ $ ./test.sh # 方法一user02@vir:~ $ . test.sh # 方法二user02@vir:~ $ source test.sh # 方法三#source 或者 . 命令是 Shell 的内建命令,这种方式也不会创建子 Shell, 而是直接在交互式 Shell 下逐行执行脚本中的命令
user02$ /bin/bash ./test.sh
user02 $ (cd ..; ls -l ) # 不会改变工作目录
则有不同的效果,cd ..命令是直接在交互式Shell下执行的,改变交互式Shell的PWD
user02 $ cd ..; ls -l # 会改变工作目录
2. shell语法
2.1shell环境变量
环境变量可以从父进程传给子进程,因此 Shell 进程的环境变量可以从当前 Shell 进程传给 fork 出来的子进程。用printenv 命令可以显示当前 Shell 进程的环境变量。
2.2临时变量
user02$ VARNAME=HELLO #定义一个临时变量
user02$ export VARNAME=HELLO #定义一个环境变量
user02$ env | grep VARNAME #env能查到就是环境变量,查不到就是临时变量
user02$ unset VARNAME #取消环境变量
- 等号两边都不能有空格,否则会被Shell解释成命令和命令行参数
- 在定义变量时不用“VAR” 取变量值时要用。和C语言不同的是,Shell 变量不需要明确定义类型,事实上Shell变量的值都是字符串,比如我们定义VAR=45,其实VAR的值是字符串45而非整数。Shell 变量不需要先定义后使用,如果对一个没有定义的变量取值,则值为空字符串
2.3 文件名代换
* :匹配 0 个或多个任意字符? :匹配一个任意字符[ 若干字符 ]: 匹配方括号中任意一个字符的次出现一次的文件名
- Globbing 所匹配的文件名是由Shell 展开的,也就是说在参数还没传给程序之前已经展开了,比如上述Is ch0[012].doc命令,如果当前目录下有cho00.doc和ch02.doc,则传给Is命令的参数实际上是这两个文件名,而不是一个匹配字符串
命令代换
user02 $ DATE = `date`user02 $ echo = $DATE #$ 变量名:变量的值
命令代换也可以用S()表示:
user02$ DATE=$(date)
算数代换
使用$(()),用于算术计算,(())中的 Shell变量取值将转换成整数,同样含义的$[ ]等价例如:
user02$ VAR=45user02$ echo $(($VAR+3)) # 等价 $((VAR+3)) 或 $[VAR+3]
user02$ echo $[2#10+3] #二进制10,然后+3
user02$ echo $[8#10+3] # 八进制 10 ,然后 +3
转移字符
user02$ echo \$PATH
user02$ \\
创建文件 --test
touch --test #报错
user02$ touch -- --test或user02$ touch ./--test
user02$ ls \ # 按回车续行继续输入> -l # 按回车代表结束
单引号
user02$ echo "abcde"user02$ echo 'abcd'
双引号
user02$ VAR=`date`
user02$ echo "$VAR"2022 年 09 月 17 日星期六 10:22:52 CSTuser02$ echo "${VAR}"2022 年 09 月 17 日星期六 10:22:52 CSTuser02$ echo 'VAR'user02$ echo '${VAR}'
3. 脚本语法
3.1 条件测试
user02$ VAR=2user02$ test $var -gt 1user02$ echo $?
[ -d DIR ] 如果 DIR 存在并且是一个目录则为真[ -f FILE ] 如果 FILE 存在且是一个普通文件则为真[ -z STRING ] 如果 STRING 的长度为零则为真[ -n STRING ] 如果 STRING 的长度非零则为真[ STRING1 = STRING2 ] 如果两个字符串相同则为真[ STRING1 ! = STRING2 ] 如果字符串不相同则为真[ ARG1 OP ARG2 ] ARG1 和 ARG2 应该是整数或者取值为整数的变量, op 是 -eq ( 等于 ) -ne ( 不等于 ) - lt ( 小于 ) -le ( 小于等于 ) -gt ( 大于 ) -ge ( 大于等于 ) 之中的一个。
和C语言类似,测试条件之间还可以做与、或、非逻辑运算:。
[ ! EXPR ] EXPR 可以是上表中的任意一种测试条件, ! 表示 “ 逻辑反 ( 非 )” 。[ EXPR1 -a EXPR2 ] EXPR1 和 EXPR2 可以是上表中的任意一种测试条件, -a 表示 “ 逻辑与 ”[ EXPR1 -o EXPR2 ] EXPR1 和 EXPR2 可以是上表中的任意一种测试条件, -o 表示 “ 逻辑或 ”
例程:
$ VAR=abc$ [ -d user02 -a $VAR = 'abc' ]$ echo $?
$ VAR=abc
$ [ -d user02 -a "$VAR" = 'abc' ]$ echo $?
3.2分支
if/then/elif/fi
if [ -f ~/.bashrc ] ; then. ~/.bashrcfi
“==:==”是一个特殊的命令,称为空命令,该命令不做任何事,但Exit Status总是真。
echo "Is it morning? Please answer yes or no. "
read YES_OR_NO
if [ "$YES_OR_NO" = "yes" ]; then
echo "Good morning!"
elif [ "$YES_OR_NO" = "no" ]; then
echo "Good afternoon!"
else
echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
return ;
fi
test "$(whoami)" != 'root' && (echo you are using a non-privileged account;)
test "$VAR" -gt 1 -a "$VAR" -lt 3
例程:
#! /bin/bashecho " 请输入你要判别的文件名 : "read file_ nameif [ -f " $file_ name" ]; thenecho 'it is a fileelif [ -d " $file_ nane" ]; thenecho 'It is a dir'elif [ -p $file_ _name ] ; thenecho 'It is pipeelseecho 'it is not a known file'exit 1fi
case/esac
#! /bin/bash
echo "Is it morning? Please answer yes or no."
read YES_OR_NO
case "$YES_OR_NO" in
yes|y|Yes|YES)
echo "Good Morning!";;
[nN][oO])
echo "Good Afternoon!";;
*)
echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
return 1;;
esac
$ sudo /etc/init.d/nfs-kernel-server start
$1是一个特殊变量,在执行脚本时自动取值为第一个命令行参数,也就是start,所以进入start)分支执行相关的命令。同理,命令行参数指定为stop、reload 或restart 可以进入其它分支执行停止服务、重新加载配置文件或重新启动服务的相关命令