`
universsky
  • 浏览: 92790 次
文章分类
社区版块
存档分类
最新评论

SHELL 脚本编程教程

 
阅读更多
SHELL 脚本教程

【1】SHELL范式

规定一个范式,有利于统一程序风格,增加可读性。对于编写SHELL,拷贝修改即可。

范式:

ASSIGN SHELL/指定壳

DESCRIPTION/程序说明

BODY/程序体

扩展:

1 ASSIGN SHELL/指定壳,如果不指定壳,默认使用Bourne SHELL,建议使用KSH

#!SHELL路径

1.1 CSH

#!/bin/csh

1.2 BSH

#!/bin/sh

1.3 KSH

#!/bin/ksh

2 DESCRIPTION/程序说明

#PROCEDURE NAME/程序名称

#PROCEDURE FUNCTION/程序功能说明

#AUTHOR/作者

#DATE/开发时间

#INPUT/输入

#OUTPUT/输出

#CALL/调用函数说明

#HISTORY/变更历史

3 BODY/程序体

INCLUDE LIBRARY /包含库文件

VARIABLE DEFINE/变量定义

FUNCTION DEFINE/函数定义

MAIN/程序入口

3.1 INCLUDE LIBRARY /包含库文件

. LIBRARY FILE/库文件名称

3.2 FUNCTION DEFINE/函数定义

#FUNCRION: FUNCTION NAME

#DESC : FUNCTION DESC

#INPUT : INPUT DESC

#OUTPUT : OUTPUT DESC

FUNCTION()

{

}

3.3 MAIN/程序入口(建议为)

程序启动说明

程序执行步骤

程序结束

exit 0

范式样例:

#!/bin/ksh

#################################################################################

# 程序名 : update.sh #

# 功能简介: 本程序完成WINV200R002M1D039P2升级 #

# 作者 : zhongwei/20150 #

# 开发时间: 2002-05-05 #

# #

# 函数说明: 函数定义 #

# CheckBackupDir() 检查备分目录,不完毕则创建 #

# CheckDbinstallDir() 检查SMP的数据库安装脚本目录 #

# CheckIfUpgraded() 检查是否已经升级 #

# UpdateSMPDir() 升级SMP的目录结构 #

# BackupDb() 备分数据库的脚本、数据 #

# BackupFile() 备分SMP目录的文件 #

# UpdateDb() 升级数据库 #

# UpdateFile() 升级文件 #

# #

# 修改历史: First Programming #

# 日期 : #

# 作者 : #

# 修改说明: #

#################################################################################

#应用库函数,要求库函数文件与当前SHELL同一目录

. ./comm_func.sh.rc

#定义变量

#程序名称

ProgName="SMP Platform Upgrade"

#标题

Title="WINV200R002 D039P2"

#目录和文件定义

WorkDir=`pwd`

LogDir=$WorkDir/log

TempDir=$WorkDir/temp

#日志与标志文件

ErrFile=$LogDir/update.err

LogFile=$LogDir/update.log

FlagFile=$LogDir/flag.flg

########################函数定义####################################

####################################################################

# 函数:PrintUsage

# 目的:定义打印用法函数。

# 输入:

# 输出:屏幕

####################################################################

PrintUsage()

{

echo "***************************************************************"

echo " NAME : ${ProgName} "

echo " VERSION : ${Title} "

echo " SYSTEM : WIN SMP "

echo " DESC : SMP platform or service upgrade "

echo " NOTICE : "

echo " COPYRIGHT : 2002, HUAWEI Tech. Co. Ltd. "

echo "***************************************************************"

echo " 1. Execute backup operation"

echo " 2. Execute upgrade operation"

echo " 3. Execute rollback operation"

echo " 0. Exit"

echo "Please input operation choice [0-3]:"

}

########### Main ##############

exit 0

##################### END OF PROCEDURE ###############

【2】SHELL编程格式与语法

Script是以行为单位,我们所写的Script会被分解成一行一行来执行。而每一行可以是命令、注解、或是流程控制指令等。如果某一行尚未完成,在行末加上"\" ,这个时候下一行的内容就会接到这一行的後面,成为同一行。

当Script中出现"#"时,再它後面的同一行文字即为注解,Shell会对其翻译。 在Script中要执行一个命令的方法和在命令列中一样,你可以前台或后台执行,执行命令时也会需要设定一些环境变量。

Script的流程控制和一般高级语言的流程控制没有什麽两样,也和高级语言一样有副程式。这些使得Script的功能更加强大。

2.1 SHELL基本术语与关键字

. 当前shell程序相同目录

.. 当前shell程序的上一级目录

break 退出for、while、until或case语句

cd 改变到当前目录

continue 执行循环的下一步

echo 反馈信息到标准输出

eval 读取参数,执行结果命令

exec 执行命令,但不在当前shell

exit 退出当前shell

export 导出变量,使当前shell可利用它

pwd 显示当前目录

read 从标准输入读取一行文本

readonly 使变量只读

return 退出函数并带有返回值

set 控制各种参数到标准输出的显示

shift 命令行参数向左偏移一个

test 评估条件表达式

times 显示shell运行过程的用户和系统时间

trap 当捕获信号时运行指定命令

ulimit 显示或设置shell资源

umask 显示或设置缺省文件创建模式

unset 从shell内存中删除变量或函数

wait 等待直到子进程运行完毕,报告终止

2.2 变量

Shell的类型只有字串变量,所以要使用数值运算则必须靠外部命令达成目的。而其变量种类有下列几种:

1. 普通变量

这是最常使用的变量,我们可以任何不包含空白字元的字串来当做变量名称。 设定变量值时则用下列方式:

var=string #不能是var = string,即等号两边不能有空格。与判断语句正好相反,判断语句表的=或者其他符号两边必须有空格,否则为赋值运算

取用变量时则在变量名称前加上一"$" 号,或者${name}。

name=Tom

echo name

echo $name

结果如下:

name

Tom

2.环境变量

和使普通变量相似,只不过此种变量会将其值传给其所执行的命令。要将一使 用者变量设定为系统变量,只要加上:

export var或者export var=var_value 或者setenv var var_valued

name=Tom

export name

以下是使用者一进入系统之後就已设定好的系统变量:

$HOME 使用者自己的目录

$PATH 执行命令时所搜寻的目录

$TZ 时区

$MAILCHECK 每隔多少秒检查是否有新的信件

$PS1 在命令列时的提示号

$PS2 当命令尚未打完时,Shell要求再输入时的提示号

$MANPATH man 指令的搜寻路径

3. 只读的使用者变量

和使用者变量相似,只不过这些变量不能被改变。要将变量设成只读的 ,只要加上:

readonly var

而若只打readonly则会列出所有只读的变量(ksh支持readonly命令。csh不支持,但是在shell程序中可以使用readonly修饰某个变量)。还有一点,系统变量不可以设定成只读的。

name=Tom

readonly name

echo $name

name=John

echo $name

(假设文件保存为aa)

结果如下:

aaa

aa[4]: name: This variable is read only

4. 特殊变量

有些变量是一开始执行Script时就会设定,并且不以加以修改,但我们不叫它只读的系统变量,而叫它特殊变量,因为这些变量是一执行程式时就有了,况且使用者无法将一般的系统变量设定成只读的。以下是一些等殊变量:

$0 这个程式的执行名字

$n 这个程式的第n个参数值,n=1..9

$* 这个程式的所有参数

$# 这个程式的参数个数

$$ 这个程式的PID

$! 执行上一个背景指令的PID

$? 执行上一个指令的返回值

$n,n只能为0-9的原因,是Bourne Shell的位置参数变量为$1~$9, 因此通过位置变量$n只能访问前9个参数。当你执行这个程式时的参数数目超过9 时,我们可以使用shift 命令将参数往前移一格,如此即可使用第10个以後的参数。除此之外,可以用set 命令改变$n及$*,方法如下:

set string

如此$*的值即为string,而分解後则会放入$n。如果set命令後面没有参数, 则会列出所有已经设定的变量以及其值。

echo Filename: $0

echo Arguments: $*

echo No. of args.: $#

echo 2nd arg.: $2

shift

echo No. of args.: $#

echo 2nd arg.: $2

set hello, everyone

echo Arguments: $*

echo 2nd arg.: $2

结果如下:

Filename: ex1

Arguments: this is a test

No. of args.: 4

2nd arg.: is

No. of args.: 3

2nd arg.: a

Arguments: hello, everyone

2nd arg.: everyone

5. 数组变量 (ksh支持)

name[index]=value

其中name为数组名称,index为数组下标,在ksh中数组最大支持1024,即index为0~1023.

或者

set –A name value1 value2…valuen

引用数组变量

${name[index]}

应用所有项:

${name[*]} #或者

${name[@]}

如:

set –A ser pps ppip mvpn

echo ${ser[2]}

echo ${ser[*]}

打印为:

mvpn

pps ppip mvpn

如:

set –A ser pps ppip mvpn

echo $ser[2]

echo $ser[*]

打印为:

pps[2]

pps[*]

6. SHELL变量

SHELL程序中可以直接使用一些变量。常用有:

SECONDS #ftp程序中判断超时经常使用这个变量

IFS #域分割符,缺省为空格或者TAB键,可以由用户指定

2.3 引用

某些字符在SHELL中具备特殊的含义:

如:& * + ^ $ ` " | ? [ ] ; ^ < >

可以使用双引号或者单引号或者\去掉特殊字符的含义,使成为一个普通字符.

1) ””可以去掉除$, \, ``之外的所有特殊字符的含义。

比如:

>echo * #输出当前某个的所有目录与文件

>echo “*” #输出*字符

>echo “`date`” #输出为date命令打印的时间“Tue Sep 17 11:31:58 MDT 2002”

>echo “$PATH” #输出当前用户的搜索路径

>echo “a\na” #输出为2行,一行一个a,此时\为特殊字符

2) ‘’单引号可以去掉\去掉引号以内包含的任何特殊字符的含义,使成为一个普通字符.

比如:

>echo ‘*’ #输出*字符

>echo ‘`date`’ #输出`date`

>echo ‘$PATH’ #输出$PATH

>echo ‘a\na’ #输出为2行,一行一个a,此时\为特殊字符

3) \可以去掉& * + ^ $ ` " | ?的特殊含义,\本身的特殊含义可以用\去掉,比如\\后面一个\就是普通字符

如:

>echo \* #输出*

2.4 标准输入与输出

当我们在shell中执行命令的时候,每个进程都和三个打开的文件相联系,并使用文件描述符来引用这些文件。由于文件描述符不容易记忆, shell同时也给出了相应的文件名。下面就是这些文件描述符及它们通常所对应的文件名:

文件文件描述符

输入文件—标准输入0

输出文件—标准输出1

错误输出文件—标准错误2

系统中实际上有1 2个文件描述符,但是正如我们在上表中所看到的, 0、1、2是标准输入、输出和错误

command > filename 把把标准输出重定向到一个新文件中

command >> filename 把把标准输出重定向到一个文件中(追加)

command 1 > fielname 把把标准输出重定向到一个文件中

command > filename 2>&1 把把标准输出和标准错误一起重定向到一个文件中

command 2 > filename 把把标准错误重定向到一个文件中

command 2 >> filename 把把标准输出重定向到一个文件中(追加)

command >> filename 2>&1 把把标准输出和标准错误一起重定向到一个文件中(追加)

command < filename >filename2 把command命令以filename文件作为标准输入,以filename2文件作为标准输出

command < filename 把c o m m a n d命令以f i l e n a m e文件作为标准输入

command << delimiter 把从标准输入中读入,直至遇到d e l i m i t e r分界符

command <&m 把把文件描述符m作为标准输入

command >&m 把把标准输出重定向到文件描述符m中

command <&- 把关闭标准输入

2.5 重新定向

输入定向:可以从文件或者标准输入设备得到输入

<

输出定向:

> #将命令的屏幕输出定向到文件

>> #将命令的屏幕输出定向到文件,采用Append方式

管道定向:

| #将一个命令的输出定向到另外一个命令的输出(某些命令不支持直接|定向)

如:将一条SQL输出到dbaccess执行

>echo “update basetab_pps set multiserviceflag=’00000000000” where msisdn=’13501300000”|dbaccess $TELLIN_DBNAME

>ps –ef |grep “manager” |grep –v “grep” | wc –l #多次管道定向

得到命令返回值,输出到变量:

var=`command`

如:

>echo Time=`date "+%y-%m-%d %H:%M:%S"` #输出Time=02-09-17 18:30:06

2.6 基本流程语句

1 顺序

2 条件语句if-then-fi

if condition

then

...

fi

我们经常使用的书写方式:使用;符号,在一行中包含多条命令与语句

if condition ;then

...

fi

3 条件语句if-then-else-fi

If condition

then

...

else

...

fi

if condition1

then

...

elif condition2

then

...

else

...

fi

4 while条件循环

while express

do

...

done

#从循环中退出使用 break和continue命令

5 for循环

for var in arg1 arg2 ... argn

do

...

done

#从循环中退出使用 break和continue命令

6 until循环

until express

do

...

done

#从循环中退出使用 break和continue命令

7 case选择语句

case var in

var1)

...

;;

var2|var3)

...

;;

*)

;;

esac

如升级程序选择菜单就是利用case建立的:

while true

do

#执行

echo ""

if [ "-${OprChc}" = "-1" ]; then

Backup #备份

elif [ "-${OprChc}" = "-2" ]; then

Upgrade #升级

elif [ "-${OprChc}" = "-3" ]; then

Rollback #回滚

elif [ "-${OprChc}" = "-0" ]; then

Log "Goodbye!"

Log ""

break

else

echo "Invalid input , please input again!"

fi

echo ""

PrintUsage

read OprChc

done

8 select选择语句(ksh支持)

select选择语句一般与case语句联合使用,用户生成用户交互菜单。语法为:

select var in value1 value2 value3 … valuen

do

done

select执行时会在value项生成一个列表,并且没有项之前给一个从1开始递增的数字。用户选择某个数字,相当于现在value对应项,赋值给var变量。如:

1) value1

2) value2

3) value3

n) valuen

#?

一般do done之间使用case语句。语法扩展为:

select var in value1 value2 value3 … valuen

do

case $var in

value1)

;;

value2)

;;

value3)

;;

valuen)

;;

*)

esac

done

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics