shell脚本
shell概述
- 
shell是一个程序,它连接了用户和内核,他可以解释用户输入的命令传递给内核,可以让用户更方便的使用liunx系统 
- 
Shell本身并不是内核的一部分,她它知识站在内核的基础上编写的一个应用程序 
- 
shell具备编程的能力,shell也是一种语言 
规范shell脚本组成
[root@localhost ~]# vim  user.sh
#!/bin/bash
#注释信息
可执行代码....
如何写好一个shell脚本
- 明确需求
- 整理步骤
- 运行脚本
- 优化脚本
编写脚本
- 
编写一个脚本 [root@localhost ~]# chmod u+x hello.sh (新文件默认没有执行,赋予它) [root@localhost ~]# /root/hello.sh hello world [root@localhost ~]# cat hello.sh #!/bin/bash #第一个脚本 echo hello world
- 
编写一个创建用户的脚本 [root@localhost ~]# vim user.sh [root@localhost ~]# chmod user.sh chmod: "user.sh" 后缺少操作数 Try 'chmod --help' for more information. [root@localhost ~]# chmod u+x user.sh [root@localhost ~]# /root/user.sh 更改用户 abc 的密码 。 新的 密码: 无效的密码: 密码少于 8 个字符 重新输入新的 密码: passwd:所有的身份验证令牌已经成功更新。 [root@localhost ~]# cat user.sh #!/bin/bash #创建用户 useradd abc echo 1 |passwd --stdin abc [root@localhost ~]#
- 
编写一个查看系统信息脚本 [root@localhost ~]# vim message.sh [root@localhost ~]# ./message.sh CentOS Linux release 7.5.1804 (Core) 3.10.0-862.el7.x86_64 total used free shared buff/cache available Mem: 1.8G 867M 70M 9.8M 883M 708M Swap: 2.0G 1.5M 2.0G ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.0.100 netmask 255.255.255.0 broadcast 192.168.0.255 inet6 fe80::2060:c7d7:fd75:674b prefixlen 64 scopeid 0x20<link> ether 00:0c:29:eb:58:95 txqueuelen 1000 (Ethernet) RX packets 69635 bytes 75165723 (71.6 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 28730 bytes 2019905 (1.9 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@localhost ~]# cat message.sh #!/bin/bash #查看系统信息 cat /etc/redhat-release #查看系统版本信息 uname -r #查看内核信息 free -h #查看系统内存 ifconfig ens33 #查看网卡信息 [root@localhost ~]#
- 
编写一个yum源脚本 [root@localhost ~]# vim yum.sh [root@localhost ~]# chmod u+x yum.sh [root@localhost ~]# ./yum.sh mkdir: 无法创建目录"/mnt/centos": 文件已存在 mount: /dev/sr0 写保护,将以只读方式挂载 mount: /dev/sr0 已经挂载或 /mnt/centos 忙 /dev/sr0 已经挂载到 /centos 上 /dev/sr0 已经挂载到 /mnt/centos 上 已加载插件:fastestmirror, langpacks Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com file:///media/repodata/repomd.xml: [Errno 14] curl#37 - "Couldn't open file /media/repodata/repomd.xml" 正在尝试其它镜像。 file:///media/repodata/repomd.xml: [Errno 14] curl#37 - "Couldn't open file /media/repodata/repomd.xml" 正在尝试其它镜像。 源标识 源名称 状态 base/7/x86_64 CentOS-7 - Base - mirrors.aliyun.com 10,072 centos centos 0 epel/x86_64 Extra Packages for Enterprise Linux 7 - x86_64 13,757 extras/7/x86_64 CentOS-7 - Extras - mirrors.aliyun.com 512 local local 3,971 updates/7/x86_64 CentOS-7 - Updates - mirrors.aliyun.com 4,135 repolist: 32,447 [root@localhost ~]# cat yum.sh #!/bin/bash #yum源 echo "正在创建文件夹"#可以添加一些此类的提示 mkdir /mnt/centos mount /dev/cdrom /mnt/centos echo "[centos] name=centos baseurl=file:///media enabled=1 gpgcheck=0" >>/etc/yum.repos.d/centos.repo yum clean all yum repolist [root@localhost ~]#
脚本的执行方式
- 
赋予脚本执行权限之后可以使用脚本的绝对路径或者当前路径执行 
- 
调用解释器执行脚本文件 [root@localhost ~]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin /usr/bin/sh /usr/bin/bash /usr/sbin/nologin /bin/tcsh /bin/csh [root@localhost ~]# sh hello.sh hello world [root@localhost ~]#
特殊符号补充
- 
$[] #四则运算(+,-,*,/,%) 
- 
$() #将命令的输出结果作为参数 
- 
`` #将命令的输出结果作为参数 [root@localhost ~]# echo $[1+1] 2 [root@localhost ~]# touch $(date +%F)-a.txt [root@localhost ~]# ls 2022-08-24-a.txt Centos-7.repo.1 hello.sh user.sh 公共 图片 音乐 anaconda-ks.cfg epel-7.repo initial-setup-ks.cfg visitor 模板 文档 桌面 Centos-7.repo flag message.sh yum.sh 视频 下载 [root@localhost ~]#
变量
- 
以固定的名称代替可能变化的值,提高脚本的灵活度来适应多变的环境 
- 
定义变量:变量名=变量值 
- 
取消变量:unset 变量名 
- 
定义变量注意事项: - 变量名由字母/数字/下划线组成,区分大小写,不能以数字开头,不能使用命令和特殊符号
- 若指定的变量名已经存在,相当于为此变量重新赋值
 [root@localhost ~]# c=a [root@localhost ~]# echo $c a [root@localhost ~]# [root@localhost ~]# unset c [root@localhost ~]#
read标准输入取值
- 
read读取用户在键盘输入的内容,并把内容存放在变量里,可以降低脚本的使用难度 
- 
命令格式:read -p “提示信息” 变量名 [root@localhost ~]# vim user.sh [root@localhost ~]# ./user.sh 用输入用户名:zhangsan 请输入新用户密码1234 更改用户 zhangsan 的密码 。 passwd:所有的身份验证令牌已经成功更新。 [root@localhost ~]# cat user.sh #!/bin/bash #创建用户 read -p '用输入用户名:' user useradd $user read -p '请输入新用户密码' password echo $password |passwd --stdin $user [root@localhost ~]#
变量种类
- 
环境变量:变量名一般都大写,用来设置用户/系统环境 
- 
位置变量:bash内置,储存执行脚本时提供的命令参数 
- 
预定义变量:bash内置,可直接调用的特殊值,不能直接修改 
- 
自定义变量:用户自定义 
- 
env命令查看系统所有的环境变量 
- 
set命令查看所有系统变量,包括用户自定义变量 
- 
环境变量 [root@localhost ~]# env XDG_SESSION_ID=2 HOSTNAME=localhost.localdomain SELINUX_ROLE_REQUESTED= TERM=xterm SHELL=/bin/bash HISTSIZE=1000 SSH_CLIENT=192.168.0.1 61254 22 SELINUX_USE_CURRENT_RANGE= SSH_TTY=/dev/pts/0 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:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=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:*.webm=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 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin PWD=/root LANG=zh_CN.UTF-8 SELINUX_LEVEL_REQUESTED= HISTCONTROL=ignoredups SHLVL=1 HOME=/root LOGNAME=root XDG_DATA_DIRS=/root/.local/share/flatpak/exports/share/:/var/lib/flatpak/exports/share/:/usr/local/share/:/usr/share/ SSH_CONNECTION=192.168.0.1 61254 192.168.0.100 22 LESSOPEN=||/usr/bin/lesspipe.sh %s XDG_RUNTIME_DIR=/run/user/0 DISPLAY=localhost:10.0 _=/usr/bin/env #获取环境变量的值 [root@localhost ~]# echo $PWD /root
- 
位置变量 - $0 #脚本名
- $1 #第一个参数
- $2 #第二个参数
- ........ #第....个参数
 [root@localhost ~]# vim test.sh [root@localhost ~]# ./test.sh ./test.sh 0 [root@localhost ~]# ./test.sh a c f ./test.sh a c 3 a c f 0 [root@localhost ~]# cat test.sh #!/bin/bash echo $0 echo $1 echo $2 echo $# echo $* echo $? [root@localhost ~]#
- 
预定义变量 - $0 代表脚本本身
- $* 显示所有参数内容
- $# 显示有多少个参数
- $? 显示上一条命令的执行结果 (0代表正确,非零代表错误)
- $$ 显示脚本进程号(Pid)
 
- 
自定义变量 
判断文件状态
- 
-e #判断文件是否存在,存在为真 
- 
-d #判断目录是否存在,存在为真 
- 
-f #判断文件是否存在 ,存在为真 
- 
-r #可读为真 
- 
-w #可写为真 
- 
-x 可执行为真 [root@localhost ~]# [ -e /wd ] [root@localhost ~]# echo $? 1 [root@localhost ~]# #查询当前用户对于文件是否可读 [root@localhost ~]# [ -r /etc/passwd ] [root@localhost ~]# echo $? 0 [root@localhost ~]#
整数比较
- 
-gt 大于 
- 
-ge 大于等于 
- 
-eq 等于 
- 
-lt 小于 
- 
-le 小于等于 
- 
-ne 不等于 [root@localhost ~]# [ 1 -gt 2 ] [root@localhost ~]# echo $? 1 [root@localhost ~]#
字符串对比
- 
== 相等 
- 
!= 不相等 [root@localhost ~]# [ root == visitor ] [root@localhost ~]# echo $? 1 [root@localhost ~]# [root@localhost ~]# [ root == $USER ] [root@localhost ~]# echo $? 0 [root@localhost ~]#
常用数值运算方式
- 
$[] #四则运算(+ - * / %) 
- 
$(()) #数值运算工具 (等同于中括号) 
- 
expr #数值运算工具 
- 
let #数值运算工具 [root@localhost ~]# echo `expr 10 \* 3` (有特殊符号时需要用\转义) 30 [root@localhost ~]# #需要先将结果赋予一个变量 [root@localhost ~]# let x=1+2 [root@localhost ~]# echo $x 3 [root@localhost ~]# #简写 [root@localhost ~]# x=3 [root@localhost ~]# echo $x 3 [root@localhost ~]# let x+=2 [root@localhost ~]# echo $x 5 [root@localhost ~]#
字符串判断
- 
-z #字符串的值为空为真 
- 
-n #字符串的值非空为真(等同于! -z) [root@localhost ~]# [ -z /etc/passwd ] [root@localhost ~]# echo $? 1 [root@localhost ~]# [ -n /etc/passwd ] [root@localhost ~]# echo $? 0 [root@localhost ~]#
条件判断结构
- 
当条件满足时执行什么,不满足执行什么 
- 
&& #逻辑与(并且) 
- 
|| #逻辑或(或者) 
- 
; #条件之间没有逻辑关系 a&&b #当a命令执行成功之后再执行b,如果a执行失败则b不执行 a||b #当a命令执行失败之后才会执行b,如果a成功之后则b不执行 a;b #执行a命令后执行b,两者无关系 [root@localhost ~]# [ -f /etc/passwd ] && tail /etc/passwd radvd:x:75:75:radvd user:/:/sbin/nologin pulse:x:171:171:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin gdm:x:42:42::/var/lib/gdm:/sbin/nologin gnome-initial-setup:x:990:984::/run/gnome-initial-setup/:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin ntp:x:38:38::/etc/ntp:/sbin/nologin tcpdump:x:72:72::/:/sbin/nologin visitor:x:1000:1000:visitor:/home/visitor:/bin/bash [root@localhost ~]# [ -f /etc/abc ] && tail /etc/passwd [root@localhost ~]# [root@localhost ~]# [ -r /etc/passwd ] || ll /etc/passwd [root@localhost ~]# echo $? 0 [root@localhost ~]# [root@localhost ~]# tail -2 /etc/passwd ; head -1 /etc/profile tcpdump:x:72:72::/:/sbin/nologin visitor:x:1000:1000:visitor:/home/visitor:/bin/bash # /etc/profile [root@localhost ~]#
if条件判断
- 
单分支语句 #第一种语法结构 if [条件判断]; then 条件成立时,执行命令 fi #第二种语法结构 if [条件判断] then 条件成立时,执行命令 fi [root@localhost ~]# vim test.sh [root@localhost ~]# ./test.sh [root@localhost ~]# cat flag shell [root@localhost ~]# [root@localhost ~]# vim test.sh [root@localhost ~]# ./test.sh [root@localhost ~]# cat flag shell [root@localhost ~]# cat test.sh #!/bin/bash if [ -f /root/flag ];then echo 'shell' >>flag fi [root@localhost ~]#
- 
双分支结构 if [条件判断]; then 条件成立时,执行命令a else 条件不成立时,执行命令b fi [root@localhost ~]# vim test.sh [root@localhost ~]# ./test.sh 此文档不是目录 [root@localhost ~]# cat test.sh #!/bin/bash if [ -d /root/flag ];then echo 'shell' >>flag else echo 此文档不是目录 fi [root@localhost ~]#

 
                
             浙公网安备 33010602011771号
浙公网安备 33010602011771号