1. shell的分类:
1>. Bourne Shell:标识为sh,该Shell由Steve Bourne在贝尔实验室时编写。在许多Unix系统中,该Shell是root用户的默认的Shell。
2>. Bourne-Again Shell:标识为bash,该Shell由Brian Fox在1987年编写,是绝大多数localhost发行 版的默认的Shell。
3>. Korn Shell:标识为ksh,该Shell由贝尔实验室的David Korn在二十世纪八十年代早期编写。它完 全向上兼容 Bourne Shell 并包含了C Shell 的很多特性。
4>. C Shell:标识为csh,该Shell由Bill Joy在BSD系统上开发。由于其语法类似于C语言,因此称为C Shell。
查看当前系统支持的shell:[root@localhost ~]# cat /etc/shells/bin/sh/bin/bash/sbin/nologin/usr/bin/sh/usr/bin/bash/usr/sbin/nologin
查看当前系统默认shell:[root@localhost ~]# echo $SHELL/bin/bash
2. shell脚本的基本元素:
对于一个基本的Shell程序来说,应该拥有以下基本元素:
1>. 声明:声明用哪个命令解释器来解释并执行当前脚本文件中的语句,一般写的解释器为 " #!/bin/bash "。
2>. 命令:可执行语句,实现程序的功能。
3>. 注释:说明某些代码的功能,通过在代码中增加注释可以提高程序的可读性。
(1). 单行注释:#开头的一整行都是注释,例如:#comment1#comment2#comment3……
(2). 多行注释,使用冒号“:”配合here document可实现多行注释,例如::<<BLOCK……注释内容BLOCK
4>. 赋予rx的权限。
3. shell脚本编写规范:
(1)脚本文件名应见名知意,例如backup_mysql.sh。
(2)文件开头指定脚本解释器 #!/bin/sh 或 #!/bin/bash。
(3)开头加版本特权等信息。
# Date:创建日期# Author:作者# Mail:联系方式# Function:功能# Version:版本
(4)脚本中尽量不要用中文注释。
(5)多使用内部命令常用的内部命令有:echo、eval、exec、export、read、shift、exit。
· echo可在屏幕上输出信息
echo参数选项: |
说明
|
-n
|
不换行输出内容
|
-e
|
解析转义字符
|
转义字符
|
说明
|
\n
|
换行
|
\r
|
回车
|
\t
|
制表符
|
\b
|
退格
|
\v
|
纵向制表符
|
示例:[root@localhost ~]# echo -n i have a cati have a cat[root@localhost ~]#[root@localhost ~]# echo i\thave\ta\tcatithavetatcat[root@localhost ~]# echo -e i\thave\ta\tcatithavetatcat[root@localhost ~]# echo -e "i\thave\ta\tcat"i have a cat
· eval命令:
命令格式:eval args
功能:当shell程序执行到eval语句时,shell读入参数args,并将它们组合成一个新的命令,然后执行。
[root@localhost test]# a='shuju;head -1 /etc/passwd'[root@localhost test]# echo $ashuju;head -1 /etc/passwd[root@localhost test]# eval echo $ashujuroot:x:0:0:root:/root:/bin/bash
· exec命令能够在不创建新的子进程的前提下,转去执行指定的命令,当指定的命令执行完毕后,该进程就终止了。
· export设置或者显示环境变量。
· read命令可从标准输入读取字符串等信息,传给shell程序内部定义的变量。
echo参数选项: | 说明 |
-p prompt | 设置提示信息 |
-t timeout | 设置输入等待时间,单位默认为秒 |
[root@localhost test]# read -t 10 -p "please input your name:" nameplease input your name:xiaoming[root@localhost test]# echo $namexiaoming[root@localhost test]# echo -n "please input your name:";read name1 name2#读取两个输入(以空格隔开),分别赋值给name1和name2变量please input your name:xiaoming xiaohong[root@localhost test]# echo $name1xiaoming[root@localhost test]# echo $name2xiaohong
· shift,在程序中每使用一次shift语句,都会使所有的位置参数依次向左移动一个位置,并使位置参数$#减1,直到减到0为止。
· exit,退出shell程序。在exit之后可以有选择地指定一个数作为返回状态。
注意:快速如何快速生成脚本开头的版本版权注释信息:
[root@localhost ~]# vim ~/.vimrcautocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"func SetTitle()if expand("%:e") == 'sh'call setline(1,"#!/bin/bash")call setline(2,"#########################")call setline(3,"#File name:".expand("%"))call setline(4,"#Version:v1.0")call setline(5,"#Email:admin@test.com")call setline(6,"#Created time:".strftime("%F %T"))call setline(7,"#Description:")call setline(8,"#########################")call setline(9,"")endifendfunc
4. shell脚本的执行方式:
(1)交互式执行:
[root@localhost ~]# for filename in `ls /etc`> do> if echo "$filename" | grep "passwd"> then> echo "$filename"> fi> done
(2)作为程序文件执行:对于一组需要经常重复执行的Shell语句来说,将它们保存在一个文件中来执行。我们通常称这种包含多个Shell语句的文件为Shell脚本,或者Shell脚本文件。脚本文件是普通的文本文件,可使用任何的文本编辑器查看或修改Shell脚本。
[root@localhost ~]# mkdir /test[root@localhost ~]# cd /test[root@localhost test]# vim test1.sh#!/bin/bashfor filename in `ls /etc`doif echo "$filename" | grep "passwd"thenecho "$filename"fidone
5. 执行脚本的方法:
(1)bash ./filename.sh(产生子进程,再运行,使用当前指定的bash shell去运行)。
(2)./filename.sh(产生子进程,再运行,使用脚本里面指定的shell去运行。使用该种方式执行需要x 权限)。
(3)source ./filename.sh(source命令是一个shell内部命令,其功能是读取指定的shell程序文件,并且依次执行其中的所有的语句,并没有创建新的子shell进程,所以脚本里面所有创建的变量都会保存到当前的shell里面)。
(4). filename.sh(和source一样,也是使用当前进程执行)。
示例一:
[root@localhost test]# vim test2.sh#!/bin/bashcd /tmppwd[root@localhost test]# ls -l test2.sh-rw-r--r--. 1 root root 24 Apr 30 20:09 test2.sh(1)[root@localhost test]# bash test2.sh/tmp(2)[root@localhost test]# ./test2.sh-bash: ./test2.sh: Permission denied[root@localhost test]# chmod a+rx test2.sh[root@localhost test]# ./test2.sh/tmp(3)[root@localhost test]# source test2.sh/tmp[root@localhost tmp]#(4)[root@localhost test]# . test2.sh/tmp[root@localhost tmp]#注意:执行shell脚本时,如果使用1和2这种方式执行会在当前的进程下产生一个新的bash子进程,所以子进程切换到了/tmp目录,当脚本结束,子进程也就结束了,所以当前进程的目录不会发生变化;3和4方式执 行时,不会产生新的进程,所以脚本执行结束后当前的目录会变成/tmp。
示例二:
[root@localhost test]# echo 'userdir=`pwd`' > test3.sh[root@localhost test]# cat test3.shuserdir=`pwd`(1)[root@localhost test]# bash test3.sh[root@localhost test]# echo $userdir[root@localhost test]#(2)[root@localhost test]# chmod a+rx test3.sh[root@localhost test]# ./test3.sh[root@localhost test]# echo $userdir[root@localhost test]#(3)[root@localhost test]# source test3.sh[root@localhost test]# echo $userdir/test(4)[root@localhost test]# . test3.sh[root@localhost test]# echo $userdir/test
6. shell脚本的退出状态:
在UNIX或者Linux中,每个命令都会返回一个退出状态码。退出状态码是一个整数,其有效范围为0~255。通常情况下,成功的命令返回0,而不成功的命令返回非0值。非0值通常都被解释成一个错误 码。行为良好的UNIX命令,程序和工具都会返回0作为退出码来表示成功。 Shell脚本中的函数和脚本本身也会返回退出状态码。在脚本或者是脚本函数中执行的最后的命令会决定退出状态码。另外,用户也可以在脚本中使用exit语句将指定的退出状态码传递给Shell。