1:区分大小写

   Linux是区分大小写的,所以,我们写的shell脚本也是区分大小写的

2:特殊字符

104847114.jpg

3:函数形式:


#1
function name
{
    code
}
#2
function()
{
    code
}

   函数部分必须出现在调用它的语句之前,否则必须声明;

4:声明

   脚本第一行必须对所调用的编译器进行声明,如:/bin/bash;否则,脚本会在默认的编译器中执行,即用户所在系统定义的shell,在一个非预期的shell中执行可能导致不可预料的错误!

5:注释即风格


#!/bin/bash
#
# SCRIPT: NAME_of_SCRIPT
# AUTHOR: AUTHORS_NAME
# DATE:   DATE_of_CREATION
# REV:    1.1.A (Valid are A, B, D, T, Q, and P)
#               (For Alpha, Beta, Dev, Test, QA, and Production)
#
# PLATFORM: (SPECIFY: AIX, HP-UX, Linux, OpenBSD, Solaris, other flavor,
#                      or Not platform dependent)
#
# REQUIREMENTS: If this script has requirements that need to be noted, this
#               is the place to spell those requirements in detail.
#
#         EXAMPLE:  OpenSSH is required for this shell script to work.
#
# PURPOSE: Give a clear, and if necessary, long, description of the
#          purpose of the shell script. This will also help you stay
#          focused on the task at hand.
#
# REV LIST:
#        DATE: DATE_of_REVISION
#        BY:   AUTHOR_of_MODIFICATION
#        MODIFICATION: Describe what was modified, new features, etc--
#
#
# set -n   # Uncomment to check script syntax, without execution.
#          # NOTE: Do not forget to put the # comment back in or
#          #       the shell script will never execute!
# set -x   # Uncomment to debug this shell script
#
##########################################################
#         DEFINE FILES AND VARIABLES HERE
##########################################################
THIS_SCRIPT=$(basename $0)
##########################################################
#              DEFINE FUNCTIONS HERE
##########################################################
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
##########################################################
#               BEGINNING OF MAIN
##########################################################
# End of script

6:控制语句

   if...then语句


if [test_commond]
    then
        commands
fi


if [test_command]
    then
        commands
else
        commands
fi


if [test_command]
    then
        commands
elif [test_command]
    then
        commands
elis [test_command]
    then
        commands
:
:
:
else (optional)
    commands
fi



   for...in语句


for loop_variable in arguement_list
do
    commands
done


   while语句

while test_condition_is_true
do
 commands
done


   until语句


until test_condition_is_true
do
    commands
done


   case语句


case $variable in
match-1)
    commands_to_execute_for_1 ;;
match-2)
    commands_to_execute_for_2 ;;
    :
    :
    :
*)(optional--any other value)
    commands_to_execute_for_no_match ;;
esac

7:break continue return exit用法区别

   break:跳出循环

   continue :下一轮循环

   return:用于在函数中将数据返回,或者是返回一个结果或者是代码给调用脚本

   exit:退出整个脚本,将返回码发送给系统

8:here文档

   用于将输入重定向到某个交互式脚本或者程序

9:符号命令

113029171.jpg

10:特殊参数$@与$*区别

   他们都允许一次访问所有的命令行参数,除非使用双引号“”将它们括起来,否则它们具有相同的功能!

   $*将整个参数列表作为一个参数来获取

   $@获取整个参数列表,并将其分隔成不同的参数

   

[root@pacteralinux shellscript]# ./arguementtest.sh 1 2 3 4 5
1 2 3 4 5
[root@pacteralinux shellscript]# ./arguementtest2.sh 1 2 3 4 5
1
2
3
4
5
[root@pacteralinux shellscript]# cat arguementtest.sh
for token in "$*"
do
        echo $token
done
[root@pacteralinux shellscript]# cat arguementtest2.sh
for token in "$@"
do
        echo $token
done
[root@pacteralinux shellscript]#

11:双引号"",单引号'',短引号``

   单引号:所见即所得

   双引号:部分——允许字符替换和命令替换

   短引号:命令

12:shell脚本中的数学

   ++  --   +  -  !~(逻辑非,二进制取反) * /  % <<   >>   > < >= <= == !=  &(按位与)  &&(逻辑与) |(按位或) ||(逻辑或)  ^(按位异或)

13:内置数学表达式

   130243698.jpg:

14:在远程主机上运行命令

   ssh user2hostname   command_to_execute

15:设置陷阱

   脚本结束后会反悔一个退出码,捕捉退出码执行一些操作,就可以在脚本退出之前执行一些操作!不能捕获kill -9信号

   131534907.jpg

   

[root@pacteralinux shellscript]# cat arguementtest.sh
for token in "$*"
do
        echo $token
done
trap 'echo "\nexit on a trap singal";exit' 1 2 3  15 0

解释:如果脚本以1 2 3 15 0信号退出,将会执行trap

   

[root@pacteralinux shellscript]# ./arguementtest.sh 22 33 ee gg
22 33 ee gg
\nexit on a trap singal

16:与用户通信

   133730523.jpg    :

17:大小写转换

   大写:UPCASE=$(echo $variable|tr '[a-z]' '[A-Z]')

           

[root@pacteralinux ~]# variable=fuwenchao
[root@pacteralinux ~]# UPCASE=$(echo $variable|tr '[a-z]' '[A-Z]')
[root@pacteralinux ~]# echo $UPCASE
FUWENCHAO
[root@pacteralinux ~]#

   小写:DOWNCASE=$(echo $variable|tr  '[A-Z]' '[a-z]')

   可以使用typeset命令控制变量在shell中的属性:

   大写:typeset -u  VARIABLE

           

[root@pacteralinux ~]# typeset -u wenchao123
[root@pacteralinux ~]# wenchao123=fuwenchaochaochao
[root@pacteralinux ~]# echo $wenchao123
FUWENCHAOCHAOCHAO
[root@pacteralinux ~]#

   小写:typeset -l

18:检测返回代码$?

   命令如果执行成功,返回0,否则,返回除0以外的整数

   


#测试目录是否存在
[root@pacteralinux shellscript]# ./testdir.sh
./testdir.sh: line 3: [0: command not found
dir doesnot exist
[root@pacteralinux shellscript]# ./testdir.sh
./testdir.sh: line 3: [0: command not found
dir doesnot exist
[root@pacteralinux shellscript]# cat testdir.sh
#!/bin/bash
test -d /usr
if ["$?" -eq 0]
 then
        echo "dir does exist"
else
        echo "dir doesnot exist"
fi
#vi testdir.sh
[root@pacteralinux shellscript]# ./testdir.sh
dir does exist
[root@pacteralinux shellscript]# cat testdir.sh
#!/bin/bash
test -d /usr
if [ "$?" -eq 0 ]
 then
        echo "dir does exist"
else
        echo "dir doesnot exist"
fi
[root@pacteralinux shellscript]#

   

19:输出控制

   静默运行:

       ./scriptname 2>&1>/dev/null    #将标准错误重定向到标准输出,然后将所有的输出发送到位桶,这样脚本不会输出任何内容到屏幕


20:使用getopts解析命令行参数

   getopts内置与shell中。可以捕获由单个字符所指定的有效命令行参数,单个字符前有一个+或者-号。为指定某个命令行开关项需要一开关参数,可以在开关项后面加一个:号,如果不需要开关项不需要任何参数,:号可以省略。所有这些选项集中到一起称为optionstring,后面跟随一些变量名。没个开关项的参数保存在一个称为OPTARG的变量中。如果整个optionstring前面有一个冒号,则任何未匹配的开关项将导致在variable中加载一个?号,命令的形式如下:

         getopts  optionstring VARIABLE [arguement......]


   对于需要花时间和进程去监控的脚本,可以为他们提供一个参数,即 -s 5 -m 10 -h 1 -p my_backup。注意开关项和参数之间不必存在空格!

144748897.jpg

注意:对于指定的每个选项s m h d p,在每个开关项后面加入了一个冒号,这就告诉getopts这些开关项需要一个参数。在optionstring之前的冒号要求getopts在给定一个未详细指明的选项时,将TIMED设置为?。这允许使用一个返回码1来调用usage函数和exit函数。

       getopts不管接收参数,因此如果希望退出,必须手动执行

       最后,while循环最后讲标准错误重定向到位桶,。在遇到一个为详细指明的参数时,getopts将发送一条消息给标准错误!



21:使用后台函数创建一个协作进程

   协作进程是前台进程和后台进程之间的通信连接

   为什么需要协作进程???

       在某个脚本中需要调用一个函数,当我们对主脚本进行定时控制时该函数完成所有的进程监视工作。这时问题就出现了:因为需要在后台运行这个函数,而且这个函数有一无限循环。由于不能通知循环终止,该循环将在主脚本以及函数终止后一直运行,这就导致了一个或者多个死进程,,因此,在主脚本中,需要一种方式来与该循环进行通信,这样后台函数在递减基数结束或者脚本使用ctrl+c键终止后,能够通知终止并且很快退出函数。为了解决这个问题,将proc_watch作为后台协作进程!

   理解:协作进程(函数)其实就是一个线程,启动后(方式)完成一些特定的操作,但是如果这个线程中有无限循环的话,主脚本退出后这个线程将会一直运行而消耗系统资源,但是这个线程又是一个死线程,所以又要一种方式与他通信告诉他什么时候结束!!!!!好吧,不多说,理解的最好方式就是看代码

       

152115364.jpg

152234599.jpg

152116705.jpg

152116635.jpg

说明:

  •      2个函数:trap_exit(与后台协作进程通信)和proc_watch(后台协作进程)

  •      后台协作进程的启动方式:proc_watch |&

  •      给后台协作进程发送消息print -p $BREAK_OUT,后台进程接收消息read ¥BREAK_OUT

  •      trap陷阱捕获1 2 3 15后调用trap_exit函数并退出exit 2


22:捕获命令的延迟输出

   当你希望活的命令输出却灭有捕获到时。until是良药

   

OUTFILE="/root/file.out"
cat /dev/null > $OUTFILE
until [ -s $OUTFILE ]   #知道file.out不为空
    do
        delayed_output_command >> $OUTFILE
    done
more $FILEOUT

 

23:逐行处理文件的最快方式

   重定向输入方式复制文件

       

[root@pacteralinux shellscript]# more proctextfast.sh
#!/bin/bash
OUTFILE=/root/outfile
INFILE=/root/infile
function while_read_line_bottom_FD_OUT
{
        >$OUTFILE
        exec 4<&1                    #Associate standard output with file descriptor 4
        exec 1>$OUTFILE              #redirect standard output to $OUTFILE
        while read LINE
                do
                        echo $LINE
                        :
                done<$INFILE
        exec 1<&4
        exec 4>&-   #restore standard output and close file descriptor 4
}
while_read_line_bottom_FD_OUT
[root@pacteralinux shellscript]#

 


使用文件描述符输入输出文件的方法复制文件

[root@pacteralinux shellscript]# more proctextfast2.sh
#!/bin/bash
OUTFILE=/root/outfile
INFILE=/root/infile
function while_read_in_out
{
        >$OUTFILE
        exec 3<&0
        exec 0<$INFILE
        exec 4<&1
        exec 1>$OUTFILE
        while read LINE
                do
                        echo "$LINE"
                        :
                done
        exec 1<&4
        exec 4>&-
        exec 0<&3
        exec 3>&-
}
while_read_in_out
[root@pacteralinux shellscript]# ./proctextfast2.sh




次快

o
[root@pacteralinux shellscript]# more proctextfast3.sh
#!/bin/bash
OUTFILE=/root/outfile
INFILE=/root/infile
function while_read_line_bottom_FD_OUT
{
        >$OUTFILE
        exec 4<&1                    #Associate standard output with file descriptor 4
        exec 1>$OUTFILE              #redirect standard output to $OUTFILE
        for LINE in $(cat $INFILE)      #for LINE in `cat $INFILE`
                do
                        echo $LINE
                        :
                done
        exec 1<&4
        exec 4>&-   #restore standard output and close file descriptor 4
}
while_read_line_bottom_FD_OUT





不使用文件描述符的情况下文件处理的最快方法


[root@pacteralinux shellscript]# cat proctextfast4.sh
#!/bin/bash
OUTFILE=/root/outfile
INFILE=/root/infile
function while_read_line_bottom_FD_OUT
{
        >$OUTFILE
        while read LINE
                do
                        echo $LINE>>$OUTFILE
                        :
                done<$INFILE
}
while_read_line_bottom_FD_OUT



当infile是个命令时:

   

[root@pacteralinux shellscript]# vi proctextfast5.sh
#!/bin/bash
OUTFILE=/root/outfile
INFILE=/root/infile
function while_read_line_bottom_FD_OUT
{
        >$OUTFILE
        while read LINE
                do
                        echo $LINE>>$OUTFILE
                        :
                done< <(date)   # <  <之间有空格
}
while_read_line_bottom_FD_OUT
~
[root@pacteralinux ~]# more outfile
Fri Dec 13 16:43:08 CST 2013




24:邮件通知技术

   在发生错误,任务结束,或者需要时发送通知给用户时一个很好的做法!

mail mailx

  •    mail -r uset@hostname -s "subject"  $MAILOUT_LIST < $MAIL_FILE

  •    cat $MIAL_FILE |  mail -r uset@hostname -s "subject"  $MAILOUT_LIST

mail换成mailx用法相同

使用sendmail来发送外发邮件

       sendmail -f uset@hostname -s "subject"  $MAILOUT_LIST < $MAIL_FILE



25:创建进度指示器

   一条小圆点:

               

[root@pacteralinux shellscript]# vi processbar.sh
#!/bin/bash
while  :
        do
                echo -n "."
                sleep 1
        done

   一条旋线