一、shell脚本规范事项
1.脚本第一行加脚本解释器:#!/bin/bash 或 #!/bin/sh
2.若脚本中有中文,则需要在系统中加"export LANG="zh_CN.UTF-8"",并且在脚本中重新定义字符集,使其和系统中的字符集一致
3.shell脚本以.sh结尾,并且放到制定位置:例如"/server/scripts"
4.所以成对的符号,和循环语句的关键词,要一次性写完,防止遗漏
5.全局变量全部大写,局部变量可以全部小写或者使用驼峰语法进行书写,例如:"myBook"
6.函数命名可采用首字母大写,并且语义要清晰,例如:"createFile"
7.尽量在函数最后加上返回值,有些不会用到返回值的也一样
二、高级命名规范:
1.常规shell用.sh结尾:例如:shell.sh
2.模块的启动和停止脚本统一命名为start_模块名.sh和stop_模块名.sh
3.监控脚本一般以_mon.sh结尾
4.控制脚本一般以_ctl.sh为后缀
三、shell脚本的变量和文件检查规范
在脚本中要检查配置项是否为空、是否可执行等,尤其是对于一些重要的、会影响下面脚本正常运行的配置项,需要进行是否为空的检查。
字符子串的特殊用法:
${变量:-word}:若变量值为空或未赋值,则返回word字符串并代替变量的值
用于:如果变量未定义,则返回备用值,防止因为变量未定义或为空而导致异常
${变量:=word}:若变量值为空或未赋值,则设置这个变量的值为word,并且返回其值,位置变量和特殊变量不适用
用于:基本上同第一个,只是在第一个的基础上又额外给了“变量赋值”
${变量:?word}:若变量值为空或未赋值,则word字符串将被作为标准错误输出,否则输出变量的值
用于:捕捉由于变量未定义而导致的错误,并退出程序
${变量:+word}:若变量值为空或未赋值,则什么也不做,否则word字符串将代替变量的值
注:
若将":"去掉,则将定义中的"若变量值为空或未赋值"改为"未赋值",用于测试变量是否赋值
例一:
[centos@mycentos ~]$ echo $test #变量为空
[centos@mycentos ~]$ res=${test:-UNSET}
[centos@mycentos ~]$ echo $res #打印res变量,返回UNSET,因为test没有赋值
UNSET
[centos@mycentos ~]$ echo $test #test仍然没有值
对于${test:-UNSET},当test变量没有值时,就返回变量结尾设置的UNSET字符串,有值时就返回test的值。
例子二:
[centos@mycentos ~]$ unset test #test为空
[centos@mycentos ~]$ unset res #res为空
[centos@mycentos ~]$ echo $res
[centos@mycentos ~]$ res=${test:=UNSET} #对res变量进行赋值
[centos@mycentos ~]$ echo $res #因为test为空,所以打印UNSET
UNSET
[centos@mycentos ~]$ echo $test #此处test被赋值,原来是没有定义的,与例一有所不同
UNSET
结论:
${变量:=word}
当变量(res)和变量(test)值没有定义时,会给变量(res)赋值":="后面的内容,同时会把":="后面的内容赋值给变量test,此方法可以解决变量没有定义的问题,确保没有定义的变量始终有值
例子三:
[centos@mycentos ~]$ echo ${key:?not defined}
-bash: key: not defined
[centos@mycentos ~]$ key=1
[centos@mycentos ~]$ echo ${key:?not defined}
1
[centos@mycentos ~]$ unset key
[centos@mycentos ~]$ echo ${key:?not defined}
-bash: key: not defined
${变量:?word}此例可以用于设置变量未定义二报错的具体内容,如"not defined"
例子四:
[centos@mycentos ~]$ oldboy=${oldgirl:+word}
[centos@mycentos ~]$ echo $oldboy #oldgril没有赋值,所以打印变量oldboy为空
[centos@mycentos ~]$ oldgirl=19
[centos@mycentos ~]$ oldboy=${oldgirl:+word} #此处需要重新定义
[centos@mycentos ~]$ echo $oldboy #oldgirl有值后,打印出来":+"后面的内容
word
此例可用于测试变量(oldboy位置)是否存在,若oldboy的值为word,则证明oldgirl变量有值存在
在系统脚本中看防止变量为空的应用:
在apache1服务启动脚本/etc/init.d/httpd中
1 #!/bin/bash
2 #
3 # httpd Startup script for the Apache HTTP Server
4 #
5 # chkconfig: - 85 15
6 # description: The Apache HTTP Server is an efficient and extensible \
7 # server implementing the current HTTP standards.
8 # processname: httpd
9 # config: /etc/httpd/conf/httpd.conf
10 # config: /etc/sysconfig/httpd
11 # pidfile: /var/run/httpd/httpd.pid
12 #
13 ### BEGIN INIT INFO
14 # Provides: httpd
15 # Required-Start: $local_fs $remote_fs $network $named
16 # Required-Stop: $local_fs $remote_fs $network
17 # Should-Start: distcache
18 # Short-Description: start and stop Apache HTTP Server
19 # Description: The Apache HTTP Server is an extensible server
20 # implementing the current HTTP standards.
21 ### END INIT INFO
22
23 # Source function library.
24 . /etc/rc.d/init.d/functions
25
26 if [ -f /etc/sysconfig/httpd ]; then
27 . /etc/sysconfig/httpd
28 fi
29
30 # Start httpd in the C locale by default.
31 HTTPD_LANG=${HTTPD_LANG-"C"} #若HTTPD_LANG变量没有赋值(没有定义),则将HTTPD_LANG值变,此处为":"省略的情况
33 # This will prevent initlog from swallowing up a pass-phrase prompt if
34 # mod_ssl needs a pass-phrase from the user.
35 INITLOG_ARGS=""
36
37 # Set HTTPD=/usr/sbin/httpd.worker in /etc/sysconfig/httpd to use a server
38 # with the thread-based "worker" MPM; BE WARNED that some modules may not
39 # work correctly with a thread-based MPM; notably PHP will refuse to start.
40
41 # Path to the apachectl script, server binary, and short-form for messages.
42 apachectl=/usr/sbin/apachectl
43 httpd=${HTTPD-/usr/sbin/httpd} #若HTTPD没有赋值(没有定义):则将httpd赋值为"/usr/sbin/httpd"
44 prog=httpd
注:
1.在企业中,针对目录路径情况等的处理就可以采用上述变量不存在的方式,防止因目录不存在而导致的异常
实战一:删除7天前的过期数据备份
[centos@mycentos shell]$ cat 1.sh
#!/bin/bash
sudo find ${path-/tmp} -name "*.tar.gz" -type f -mtime +7 |xargs rm -f
1.如果忘记了定义path路径变量,又不希望其为空,就可以定义/tmp代替path空值返回值.
2.若忘记了定义path路径变量,还没有做特殊变量定义,此条命令会出现异常
补充:http脚本变量的定义方式:
httpd=${HTTPD-/usr/sbin/httpd}
prog=httpd
pidfile=${PIDFILE-/var/run/httpd/httpd.pid}
lockfile=${LOCKFILE-/var/lock/subsys/httpd}
此定义方式可以防止出现空值
四、shell调试技巧
1、使用dos2unix命令处理在Windows下开发的脚本
#!/bin/bash
i=1
sum=0
while((i<=100))
do
let i++
((sum+=i))
done
使用dos2unix进行格式化,会去除一些Windows的一些格式(例如空格)错误
---------------------------------------------------------------------------------------
2.bash命令调试
sh [-nvx] scripts.sh
-n :不会执行脚本,仅仅检查语法是否有问题,并且给出错误提示
-v :在执行脚本时,先将脚本的内容输出到屏幕上,然后执行脚本,如果有错误,也会给出错误提示
-x :将执行的脚本内容输出显示到屏幕上。
printf "totalsum is $sum"
export PS4='+${LINENO}' #此命令可以使追踪命令显示每行的行号
五、vim编辑器的配置
1.编辑vim相关文件
.viminfo 用户使用vim的操作历史记录
.vimrc 当前用户的配置文件
/etc/vimrc 系统全局vim的配置文件
/usr/share/vim/vim74/colors 配色魔板文件存放路径
注:
1.当配置/etc/vimrc文件时,所有用户的vim均会受影响
2.当编辑个人用户家目录下的隐藏文件.vimrc,则只有此用户的vim编辑受影响。
以下是个人的vim的配置,直接复制到家用户目录下的.vimrc即可
set nocompatible
set history=100
filetype on
filetype plugin on
filetype indent on
set autoread
set mouse=a
syntax enable
set nofen
set fdl=0
set expandtab
set tabstop=4
set shiftwidth=4
set softtabstop=4
set smarttab
set ai
set si
set wrap
set sw=4
set wildmenu
set nu
set cmdheight=1
set lz
set backspace=eol,start,indent
set whichwrap+=<,>,h,l
set magic
set noerrorbells
set novisualbell
set showmatch
set mat=2
set hlsearch
set ignorecase
set encoding=utf-8
set fileencodings=utf-8
set termencoding=utf-8
set smartindent
set cin
set showmatch
set guioptions-=T
set guioptions-=m
set vb t_vb=
set laststatus=2
set pastetoggle=<F9>
set background=dark
highlight Search ctermbg=black ctermfg=white guifg=white guibg=black
autocmd BufNewFile *.py,*.cc,*.sh,*.java exec ":call SetTitle()"
func SetTitle()
if expand("%:e") == 'sh'
call setline(1, "#!/bin/bash")
call setline(2, "#Auther:itboy")
call setline(3, "#Time:".strftime("%F %T"))
call setline(4, "#Name:".expand("%"))
call setline(5, "#Version:V1.0")
call setline(6, "#Description:this is a test script.")
endif
endfunc
2.vim的高级命令
ngg :调到n行
0 :到行开头
$ :到行结尾
L :移动到当前窗口最后一行 == G ,然后点"o",开始下一行编辑
H :移动到当前窗口最前面一行 ==gg
命令行模式下:"ctrl+:"后
/old :从上向下找"old"
%s/A/B/g :A全部替换为B "/"可以换成"#或@"
n1,n2 w filename : 将n1到n2行的内容保存到filename文件里
n1,n2 co n3 : 将n1到n2行的内容复制到n3的位置下
n1,n2 m n3 : 将n1到n2行的内容剪切到到n3的位置下
! “命令” :暂且退出vi,执行“命令”
vs filename : 竖直分屏显示filename ,q!退出分屏
1.多行注释:
1). 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块)模式;
2). 在行首使用上下键选择需要注释的多行;
3). 按下键盘(大写)“I”键,进入插入模式;
4). 然后输入注释符(“//”、“#”等);
5). 最后按下“Esc”键。 注:在按下esc键后,会稍等一会才会出现注释,不要着急~~时间很短的
2.删除多行注释:
1). 首先按esc进入命令行模式下,按下Ctrl + v, 进入列模式;
2). 选定要取消注释的多行;
3). 按下“x”或者“d”. 注意:如果是“//”注释,那需要执行两次该操作,如果是“#”注释,一次即可
3.多行删除
1).首先在命令模式下,输入“:set nu”显示行号;
2).通过行号确定你要删除的行;
3).命令输入“:32,65d”,回车键,32-65行就被删除了,很快捷吧
如果无意中删除错了,可以使用‘u’键恢复(命令模式下)
也可以用"del"在可视化中全删选择的内容
4.多行缩进
1). 首先按esc进入命令行模式下,按下Ctrl + v,进入列(也叫区块)模式;
2). 在行首使用上下键选择需要缩进的多行;
3). 最后按"="即可
六、Linux信号相关知识
一、现象描述:
1.当运行shell脚本时,如果按下Ctrl+c 或Ctrl+x(x为其他字符),程序会终止运行。
2.当不希望shell在运行时被终止,则可以使用屏蔽信号手段,让程序忽略用户输入的信号指令,从而继续运行shell程序。
二、信号含义:
信号是由一个整数构成的异步消息,它可以由某个进程发给其他进程,也可以在用户按下特定按键发生某种异常事件时,由系统发给某个进程。
1.Linux重要信号
HUP(1) 挂起,通常因终端掉线或用户退出而引发
INT(2) 中断,通常因为按ctrl + c组合键而引发
QUIT(3) 退出,通常因为按ctrl + \ 组合键而引发
ABRT(6) 中止 , 通常因为某些严重的执行错误而引发
ALRM(14) 报警 , 通常用来处理超时
TERM(15) 终止 ,通常在系统关机时发送
TSTP(20) 停止进程的运行,但该信号可以被处理和忽略,通常是Ctrl + z键而引发
注:
shell脚本中可以用数字来代表信号,也可以用信号的名字代表信号
2.trap命令
trap命令:
1.用于在接受到信号后将要采取的行动
2.常用于在脚本程序被中断时完成清理工作,或者屏蔽用户非法使用的某些信号
注:
使用信号名时需要省略前缀"SIG"
用法:
trap command signal
signal是接受到的信号 , command是接收到信号后应该采取的行动
trap "命令;命令" 信号名 或者 trap "命令;命令" 信号编号
例一:
处理单个信号:
[centos@mycentos ~]$ trap "" 2 #若执行动作为空,则可以用来屏蔽与数字对应的Ctrl+c信号
[centos@mycentos ~]$ trap ":" 2 #此处恢复Ctrl + c 的信号
[centos@mycentos ~]$ ^C #已恢复
例二:
同时处理多个信号:
[centos@mycentos ~]$ trap "" 1 2 3 20 #<==执行这些数字信号,什么都不做,即屏蔽这些信号
[centos@mycentos ~]$ trap ":" 1 2 3 20 #<==执行这些信号,恢复对应的功能
[centos@mycentos ~]$ ^C
[centos@mycentos ~]$ trap "" HUP INT QUIT TSTP #<==执行这些名称信号,什么都不做,即屏蔽这些信号
[centos@mycentos ~]$ trap ":" HUP INT QUIT TSTP #<==执行这些名称信号,恢复对应的功能
[centos@mycentos ~]$ ^C
[centos@mycentos ~]$ trap "" `echo {1..64}` #<==屏蔽1-64所有的数字信号
实战二:
开发脚本实现触发信号后清理文件功能(信号触发后就会执行将新建的文件删除命令)
#!/bin/bash
#Auther:itboy
#Time:2018-11-20 10:09:42
#Name:3.sh
#Version:V1.0
#Description:this is a test script.
#<==捕获ctrl+c 键后即执行find删除命令,后退出脚本
trap "find /tmp -type f -name "old_*" | xargs rm -f && exit" INT
while true
do
touch /tmp/old_$(date +%F-%T) #<==在/tmp创建文件
sleep 5 #<==休息3秒
ls -la /tmp/old* #<==查看文件创建情况
done
实战三:
开发脚本,练习QUIT、TSTP、INT
#!/bin/sh
#捕获ctrl+c信号时,执行echo命令
trap 'echo "you are typing ctrl-c ,sorry,script will not terminate"' INT
#捕获Ctrl+\信号,执行echo
trap 'echo "you are typing ctrl-\ ,sorry,script will not terminate"' QUIT
#捕获ctrl+z信号,就会执行echo命令 (实测此处没有执行echo命令)
trap 'echo "you are typing ctrl-z ,sorry,script will not terminate"' TSTP
while true
do
echo "now , test signal $(date)"
sleep 5
done
效果如图:
[root@mycentos ~]# sh 2.sh
now , test signal Tue Nov 20 11:02:06 CST 2018
^Cyou are typing ctrl-c ,sorry,script will not terminate #按下ctrl+c执行
now , test signal Tue Nov 20 11:02:11 CST 2018
now , test signal Tue Nov 20 11:02:16 CST 2018
now , test signal Tue Nov 20 11:02:21 CST 2018
^\Quit (core dumped)
you are typing ctrl-\ ,sorry,script will not terminate #按下ctrl+\执行
now , test signal Tue Nov 20 11:02:25 CST 2018
now , test signal Tue Nov 20 11:02:30 CST 2018
^Z^Z #按下ctrl +z 键没有打印提示,但是程序停止运行了