Linux系统——shell脚本编程基础介绍
1、什么是shell
它是一个命令解释器,在linux/unix操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种操作输出的结果,输出到屏幕返回给用户,可以是交互式与非交互式的方式进行会话
[root@backup~]# head -1 /etc/passwd
root:x:0:0:root:/root:/bin/bash
shell脚本介绍:
当命令或语句不在命令行执行,而是通过一个程序文件执行时,这类文件就被称为shell脚本或shell程序文件,类似于WIN系统下面的批处理程序
2、shell脚本语言的种类
Bourneshell(包括shksh bash)
Cshell (csh)
在redhat和centos系统中,最常用的是bash
[root@backup ~]# cat /etc/redhat-release
CentOS release6.5 (Final)
[root@backup~]# tail -5 /etc/passwd
sshd:x:74:74:Privilege-separatedSSH:/var/empty/sshd:/sbin/nologin
tcpdump:x:72:72::/:/sbin/nologin
text:x:500:500::/home/text:/bin/bash
rsync:x:501:501::/home/rsync:/sbin/nologin
mysql:x:502:502::/home/mysql:/sbin/nologin
如何查看系统的默认shell
[root@backup~]# echo $SHELL
/bin/bash
不同的系统版本,bash版本也不同
[root@backup~]# bash --version
GNU bash, version 4.1.2(1)-release(x86_64-redhat-linux-gnu)
Copyright(C) 2009 Free Software Foundation, Inc.
LicenseGPLv3+: GNU GPL version 3 or later
This isfree software; you are free to change and redistribute it.
There is NOWARRANTY, to the extent permitted by law.
3、shell脚本编辑规范
通常在编辑器(vi/vim)中编写,由linux命令、bashshell命令、程序结构控制语句和注释内容组成
脚本规范:
1、第一行一般都是指定由哪个程序来执行解释脚本中的命令内容
[root@backup~]# cat /etc/init.d/nfs
#!/bin/sh
[root@backup~]# ll /bin/sh
lrwxrwxrwx.1 rsync rsync 4 Sep 29 11:56 /bin/sh -> bash
不同的脚本语言第一行开头内容有所不同,如下所示
#!/bin/sh
#!/usr/bin/awk 做C语言开发
#!/bin/sed
#!/usr/bin/expect 非交互式语言
由于centos和redhat linux默认的shell是bash,你可以加,也可以不加,为了规范加上最好
2、加上作者信息与版本信息与功能
3、脚本注释
说明脚本的内容与作用,可以自成一行,也可以放在命令后面,做命令的解释所用,在实际生产环境中这种注释内容是非常重要,规范的注释内容可以方便后续管理与其它人员查看,但尽量不要用中文注释内容
4、脚本以.sh为扩展名
方便后续查看哪些是脚本
5、代码书写习惯
成对的内容一次性写出如:‘’“” {} [ 里面的内容前后需有空格 ] ()
流程控制语句一次性写完
if []
then
返回中间输入内容
fi
通过缩进让代码容易读
4、shell脚本执行
它执行时,会先查看系统全局变量里的内容,然后从环境变量开始执行,再执行shell脚本的内容
执行几种方法:
1、bashscripts-name或sh scripts-name
通常为脚本文件没有执行权限时常用的方法
[root@backup~]# cd /server/scripts/
[root@backupscripts]# sh baktable_auto.sh
[root@backupscripts]# ll
total 20
-rw-r--r--.1 root root 236 Oct 11 00:42bakfenku_auto.sh
-rw-r--r--.1 root root 356 Oct 11 03:10baktable_auto.sh
-rw-r--r--.1 root root 739 Oct 12 13:36bak_zhuku.sh
-rw-r--r--.1 root root 1063 Oct 12 13:22 congku.sh
-rw-r--r--.1 root root 522 Oct 11 07:54 dump.sh
2、path/scripts-name或./ scripts-name
这种执行方法,必须需要执行权限,通过chmod +x scripts-name
[root@backupscripts]# ./congku.sh
-bash:./congku.sh: Permission denied
[root@backupscripts]# /server/scripts/dump.sh
-bash:/server/scripts/dump.sh: Permission denied
3、source scripts-name或 . scripts-name
此种方法是将脚本里的变量值返回到当前的shell中使用
[root@backupscripts]# vi text.sh
user=`whoami`
[root@backupscripts]# echo $user
[root@backupscripts]# . text.sh
[root@backupscripts]# echo $user
root
注:.表示从当前的shell中执行操作,exec执行命令但不在当前shell,source 在当前的bash环境下读取并执行脚本中的内容,并且脚本可以是无执行权限
5、shell变量介绍
变量分为:环境变量(全局变量)与局部变量
环境变量:
用于定义shell的运行环境,保证它的命令正确执行,shell通过环境变量来确定登陆用户名、命令路径、终端类型、登陆目录等,所有的环境变量都是系统的全局变量,环境变量也可以在命令行中设置,但用户退出时这些变量也会丢失,因此可以将变量配置在用户家目录中.baxh_profile文件中或全局配置/etc/profile文件或者/etc/profile.d/中定义,每次用户登陆时这些变量都将初始化
环境变量均为大写,环境变量应用于用户进程前,必须用export导出
[root@backupscripts]# echo $HOME
/root
[root@backupscripts]# echo $UID
0
[root@backupscripts]# echo $USER
root
[root@backupscripts]# echo $HOSTNAME
backup
自定义环境变量
export 变量名=值
[root@backup~]# NAME=beijing
[root@backup~]# export NAME
[root@backup~]# echo $NAME
beijing
显示和取消环境变量
[root@backup~]# env
HOSTNAME=backup
SELINUX_ROLE_REQUESTED=
TERM=linux
SHELL=/bin/bash
HISTSIZE=1000
SSH_CLIENT=192.168.1.20055802 22
SELINUX_USE_CURRENT_RANGE=
QTDIR=/usr/lib64/qt-3.3
OLDPWD=/server/scripts
QTINC=/usr/lib64/qt-3.3/include
SSH_TTY=/dev/pts/0
NAME=beijing
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.tbz=01;31:*.tbz2=01;31:*.bz=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/root
取消变量
unset USER 就可以直接取消
局部变量
本地变量只在shell生存周期有效
普通变量
[root@backup~]# a=192.168.1.2-$a
[root@backup~]# b='192.168.1.2-$a'
[root@backup~]# c="192.168.1.2-$a"
[root@backup~]# echo "a=$a"
a=192.168.1.2-
[root@backup~]# echo "b=$b"
b=192.168.1.2-$a
[root@backup~]# echo "c=${c}"
c=192.168.1.2-192.168.1.2-
单引号里的内容是什么就输出什么,双引号定义变量时会将双引号里的内容进行解析再输出结果
[root@backup~]# test=`date`
[root@backup~]# echo $test
Wed Oct 1223:09:23 EDT 2016
[root@backup~]# echo '$test'
$test
[root@backup~]# echo "$test"
Wed Oct 1223:09:23 EDT 2016
总结:无论定义变量还是输出变量,单引号,双引号,没有引号,都是上面的输出结果
如果使用命令做为变量,建议使用$(命令)
[root@backup~]# CMD=$(date)
[root@backup~]# echo $CMD
Wed Oct 1223:30:59 EDT 2016
[root@backup~]# echo /server/scripts/$CMD.txt
/server/scripts/WedOct 12 23:30:59 EDT 2016.txt
特殊变量(重点)
位置变量
$0 获取当前执行的脚本文件名,包括路径
[root@backupshell]# vi 0.sh
echo $0
[root@backupshell]# sh 0.sh
0.sh
$n (n是1...9),获取当前执行的脚本的第N个参数,n大于9的话,要用{},比如${10}
[root@backupshell]# vi n.sh
echo $1 $2$3 (取命令的第n个参数)
[root@backupshell]# sh n.sh ka ha li
ka ha li
$# 获取当前脚本命令行中参数的总的个数
[root@backupshell]# vi n.sh
echo $1 $2$3
echo $#
[root@backupshell]# sh n.sh d d d d d
d d d
5
进程状态变量
$? 获取上一个命令的返回值,0表示成功,非0表示失败
[root@backupshell]# 123
-bash: 123:command not found
[root@backupshell]# echo $?
127
[root@backupshell]# ls
0.sh n.sh
[root@backupshell]# echo $?
0
0表示成功,2是权限不够,127是没有找到运行的命令
$$ 获取当前执行的脚本的进程号
$* 获取当前shell的所参数,将所有命令行参数视为单个字符串
$@ 获取当前shell的所参数,将命令行每个参数视为一个字符串“$1 $2 $3”
[root@backupshell]# set "I am" a man
[root@backupshell]# echo $#
3
[root@backupshell]# for i in $*;do echo $i;done
I
am
a
man
[root@backupshell]# for i in $@;do echo $i;done
I
am
a
man ===============================>没加双引号没区别
[root@backupshell]# for i in "$*";do echo $i;done
I am a man
[root@backupshell]# for i in "$@";do echo $i;done
I am
a
man