ThankNeko's Blog ThankNeko's Blog
首页
  • 操作系统

    • Linux基础
    • Linux服务
    • WindowsServer笔记
    • Ansible笔记
    • Shell笔记
  • 容器服务

    • Docker笔记
    • Kubernetes笔记
    • Git笔记
  • 数据库服务

    • MySQL笔记
    • ELK笔记
    • Redis笔记
  • 监控服务

    • Zabbix笔记
  • Web服务

    • Nginx笔记
    • Tomcat笔记
  • 数据处理

    • Kettle笔记
  • Python笔记
  • Bootstrap笔记
  • C笔记
  • C++笔记
  • Arduino笔记
  • 分类
  • 标签
  • 归档
  • 随笔
  • 关于
GitHub (opens new window)

Hoshinozora

尽人事,听天命。
首页
  • 操作系统

    • Linux基础
    • Linux服务
    • WindowsServer笔记
    • Ansible笔记
    • Shell笔记
  • 容器服务

    • Docker笔记
    • Kubernetes笔记
    • Git笔记
  • 数据库服务

    • MySQL笔记
    • ELK笔记
    • Redis笔记
  • 监控服务

    • Zabbix笔记
  • Web服务

    • Nginx笔记
    • Tomcat笔记
  • 数据处理

    • Kettle笔记
  • Python笔记
  • Bootstrap笔记
  • C笔记
  • C++笔记
  • Arduino笔记
  • 分类
  • 标签
  • 归档
  • 随笔
  • 关于
GitHub (opens new window)
  • 操作系统

    • Linux基础

    • Linux服务

    • Windows Server笔记

    • Shell笔记

      • Shell脚本介绍与变量
      • Shell流程控制与函数
      • Shell脚本常见应用
      • Ansible笔记

    • 虚拟化服务

    • 数据库服务

    • 监控服务

    • Web服务

    • 数据处理

    • Ops
    • 操作系统
    • Shell笔记
    Hoshinozora
    2023-04-05
    目录

    Shell脚本常见应用

    # Shell命令延时执行

    • 通过sleep命令阻塞Shell进程即可。
    • sleep [秒] - 延迟n秒后再继续执行,默认单位为秒。
    • 例如:sleep 5

    # 长命令续行

    • 在命令行过长影响阅读时,我们可以使用续行符/表示这一行还没有结束,声明下一行还是属于同一条命令行。

      echo -e \
      "ddddddddddddddddd"
      
      1
      2

    # 取随机数

    • 使用$((RANDOM % [指定范围数] + 1))
    • 余数不会超过或等于[指定范围数],可以加1防止取到0。

    # 脚本判断是否正确输入参数

    • if [ ! $# -eq 2 ];then
          echo “请输入2个参数”
      fi
      
      1
      2
      3

    # 判断当前用户

    • [ $USER == "root" ] && echo "当前用户为root"
      
      1

    # 判断变量是否为数字或英文

    • # 变量必须开头到结尾全是整数
      [[ $Num =~ ^[0-9]+$ ]];echo $?
      
      # 变量必须开头到结尾全是英文字母
      [[ $Num =~ ^[a-Z]+$ ]];echo $?
      
      1
      2
      3
      4
      5

    # 标准输入长文本到脚本

    • 可以使用<<标准输入重定向符号。另外需要注意shell中使用<<重定向符需要加上"-"符号。

      cat <<-EOF
      ...
      ...
      EOF
      
      1
      2
      3
      4

    # 判断服务是否启动

    • read -p "Please input name of service:" service
      
      systemctl status $service &> /dev/null
      if [ $? -eq 0 ];then
          echo "$service正在运行" && exit 0
      else
          echo "$service没有运行" && exit 1
      fi
      
      1
      2
      3
      4
      5
      6
      7
      8
    • 我们也可以先判断服务是否启动,再判断服务端口是否存在,最后判断服务进程是否存在。

      • systemctl is-active sshd - 通过命令执行字符串,判断是否启动
      • netstat -an | grep ":22" - 通过是否监听端口,判断是否启动
      • ps -aux | grep sshd | egrep -v "grep|@" - 通过是否有进程,判断是否启动

    # 美观的显示操作结果

    • action "[文本内容]" /bin/[ true | false ] - 输出有色彩且美观的操作结果。

    • 要先调用/etc/init.d/functions函数库才能使用action命令。

      #!/bin/bash
      . /etc/init.d/functions
      action "Web is OK."   /bin/true
      action "Web is Fail." /bin/false
      
      # 会输出
      Web is OK.                [  OK  ]
      Web is Fail.              [FAILED]
      
      1
      2
      3
      4
      5
      6
      7
      8

    # 在PS命令时排除自身

    • ps aux | grep [n]ginx
    • ps aux|grep nginx|grep -v grep|grep -v $$

    # 防止脚本重复运行

    • 通过加锁,判断锁文件来防止脚本重复运行,同时还可以配合trap和exit在正常退出脚本时清理锁文件。

    • 例如:

      # 脚本开始时判断是否有锁文件,如果有则表示已经有运行的脚本了
      if [ -e /tmp/test.pid ];then
          echo "process is already runing."
          exit 1
      fi
      
      # 如果没有则创建锁文件,再运行脚本
      echo $$ > /tmp/test.pid
      
      # 设置收到exit信号时要做的操作
      trap "rm -f /tmp/test.pid; echo Bye~" EXIT
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11

    # 跳板机设计思路

    • 执行脚本后,会显示一个能管理的主机菜单,供使用者选择来进行连接。而如果要使用多级菜单,则可以使用多个函数,每个函数都执行清屏,需要时直接调用菜单即可。
    • 需要死循环,不让用户退出。
    • 控制Ctrl+C信号,禁止使用Ctrl+C退出,防止用户退出跳板机进程。
      • trap "" HUP INT TSTP
    • 设为一连接Shell就执行。执行命令添加到/etc/bashrc或/etc/profile文件里即可。
    • 可以加个后门密码用于退出,以防特殊情况无法退出 (不写在菜单上)。
    • 如果要写的主机过多,可以将主机和菜单的IP设为变量,然后借助sed或者awk工具将变量名与命令这条字符串使用序列生成,然后在开头一个一个写IP就行了。

    # 文本创建用户思路

    • 判断是否是root用户执行。
    • 文本中写入 [用户名]:[密码]。
    • 使用for循环将其一行一行读入。
    • 在循环体中使用awk取出用户名和密码并赋值给变量。
    • 然后判断用户名是否存在。
    • 然后使用useradd和passwd命令进行创建,同时输出结果。

    # 自动创建用户思路

    • 判断是否是root用户执行。
    • 提示输入用户名前缀、创建个数、用户名后缀。
    • 判断输入的内容是否符合要求。
    • 符合要求则以随机密码开始创建。
      • 第一种方式(数字与小写字母组合):echo $((RANDOM)) | md5sum | cut -c 2-10
      • 第二种方式(数字与大写字母或_组合):cat /dev/urandom | tr -dc '_A-Za-z0-9'|head -c10
      • 第三种方式:expect软件包的mkpasswd。
    • 将用户名和随机密码保存到某文件中。

    # 统计Nginx访问日志

    • awk方式统计

      • awk '{ips[$1]+=$10 iptimes[$1]++} END{for (i in ips) print i"的总流量是"ips[i]/1024"KB 请求总 次数是"iptimes[i] }' access.log
    • shell数组方式统计

      declare -A ip_bytes
      declare -A ip_times
      while read line;do
          ip=$(echo $line|awk '{print $1}')
          ip_byt=$(echo $line|awk '{print $10}')
          let ip_times[$ip]++
          ip_bytes[$ip]=$((${ip_bytes[$ip]} + ${ip_byt}))
      done <access.log
      for i in ${!ip_times[@]};do
          echo "${i}的访问次数是${ip_times[$i]} 访问大小是$((${ip_bytes[$i]}))Bytes"
      done
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11

    # 按频率排序

    • 按单词频率排序
      • sort排序方法:cat test.txt | sed 's#[,.]##g'| xargs -n1 | sort | uniq -c | sort -nr
      • awk排序方法:cat test.txt | sed 's#[,.]##g'| xargs -n1 |awk '{word[$1]++} END{for(i in word)print word[i],i}' | sort -nr
    • 按字母频率排序
      • sort排序方法:cat test.txt | sed 's#[,.]##g'| grep -o [a-zA-Z] | sort | uniq -c | sort -nr
      • awk排序方法:cat test.txt | sed 's#[,.]##g' | grep -o "[a-zA-Z]" | awk '{word[$1]++} END{for(i in word)print word[i],i}' | sort -nr

    # 发送邮件方法

    • 通过postfix邮箱服务即可。

    • 发送方法

      • 在邮箱网站中

        • 关闭 POP3/SMTP 服务
        • 勾选 IMAP/SMTP 服务
        • 记录企业邮箱的SMTP服务器地址
        • 开启生成客户端授权密码并进行记录
      • 编写 /etc/mail.rc 文件

        set from=邮箱账号 smtp=smtp地址
        set smtp-auth-user=邮箱账号 smtp-auth-password=邮箱授权密码 smtp-auth=login
        
        1
        2
      • 重启邮件服务

        • systemctl restart postfix
      • 发送邮件

        • echo "内容" | mail -s "标题" [目标邮箱]
        • mail -s "[标题]" [目标邮箱] < 重定向或者管道符输入内容

    # MD5处理命令

    • md5sum命令可以生成或校验md5指纹文件,验证数据完整性等。
    • md5sum [参数] [目标文件]
      • md5sum [文件] - 生成文件的校验信息
      • md5sum -c [文件] - 验证文本内容中的校验信息

    # 数据备份

    • 例如有一个备份web服务器文件到备份服务器的需求,首先要确认好备份周期、需要备份的文件、web服务器和备份服务器的备份文件保留时长,例如:每天备份一次,web服务器保留7天内数据,备份服务器保留每周一的所有数据副本,其它要保留6个月的数据副本。

    • 然后根据需求先在命令行测试确认要执行的操作:

      # 0) 环境检查
      # 各服务器IP、主机名等配置好
      # 备份服务器的Rsync守护进程搭建配置好,可以正常收发数据
      # 备份服务器邮件服务配置好(postfix服务),可以正常收发邮件
      # 其他服务器的Rsync密码文件配置好
      
      # 1) 所有服务器的备份目录为/backup/[主机地址],创建传输后用户存放的目录
      mkdir -p /backup/[主机地址]
      
      # 2) 要备份的配置文件进行打包压缩备份
      # 如果因为绝对路径会报错可以cd到根目录,再以相对路径进行压缩
      # tar压缩时加上h参数可压缩软链接的源文件
      cd /
      tar -czhf /backup/[主机地址]/config_$FILE_TAIL ./var/spool/cron/root ./etc/rc.local ./server/scripts ./etc/sysconfig/iptables
      # 压缩之后进行解压文件进行检查
      ll /backup/[主机地址]/
      
      # 3) web服务器将网站文件进行打包压缩备份
      # 两个较大的目录可以分开进行压缩,防止解压时过于耗时
      cd /
      tar -czhf /backup/[主机地址]/www_$FILE_TAIL ./var/html/www
      tar -czhf /backup/[主机地址]/www_log_$FILE_TAIL ./app/logs
      
      # 4) Web服务器仅保留打包后的7天的备份数据
      # 防止备份数据太多磁盘占满,通过搜索备份目录修改时间(创建时间)大于七天的文件并进行删除
      find /backup/ -type f -mtime +7 -delete
      
      # 5)备份服务器上,保留每周一的所有数据副本,其它要保留6个月的数据副本
      # 在数据名称信息上加上周的信息,然后find搜索时通过!排除周一 date "+%F_week%w" --- %A 或 %w
      find /backup/ -type f -mtime +180 ! -name "*week1.tar.gz" -delete
      
      # 6)web服务器生成校验信息,然后发送备份文件到备份服务器
      find /backup/ -type f -mtime -0.5 ! -name "finger*" | xargs md5sum > $BACKUP_DIR/$IP_ADDR/finger.txt
      rsync -a /backup/ rsync_backup@10.0.0.41::backup/ --password-file=/etc/rsync.passwd
      
      # 7)备份服务器校验传输前后数据,把备份的成功或失败结果信息发给系统管理员邮箱中
      find /backup/ -type f -mtime -0.5 -name "finger*" | xargs md5sum -c | mail -s "`date '+%F'` - 数据备份情况" cecilies@qq.com
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
    • 再将操作编写为脚本:

      • 客户端

        #!/bin/bash
        
        #define variables
        Backup_dir='/backup'
        IP_addr=$(hostname -i | awk '{print $NF}')
        Tar_tail=$(date '+%F-week%w' -d "-1day").tar.gz
        
        #make directory
        mkdir -p $Backup_dir/$IP_addr   \
        
        #tar data
        cd /
        tar -czhf $Backup_dir/$IP_addr/config_$Tar_tail ./var/spool/cron/root ./etc/rc.local ./server/scripts ./
        etc/sysconfig/iptables  \
        
        #delete 7 day ago
        find /backup/ -type f -mtime +7 -delete
        
        #generate the finger file
        find /backup/ -type f -mtime -0.5 ! -name "finger*" | xargs md5sum > $Backup_dir/$IP_addr/finger.txt \
        
        #backup push data
        rsync -a /backup/ rsync_backup@10.0.0.41::backup/ --password-file=/etc/rsync.passwd
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
      • 服务端

        #!/bin/bash
        
        #delete 6 month ago data and leave monday data
        find /backup/ -type f -mtime +180 ! -name "*week1.tar.gz" -delete
        
        #check the md5 of data and send to e-mail
        find /backup/ -type f -mtime -0.5 -name "finger*" | xargs md5sum -c | mail -s "`date '+%F'` - 数据备份情况" cecilies@qq.com
        
        1
        2
        3
        4
        5
        6
        7
      • 为了提高通用性,使用变量代替一些可能会变动的东西,能够从系统中取出的信息就从系统中提取。

    • 添加定时任务:

      • 客户端

        # backup data
        0 0 * * * /usr/bin/sh /scripts/backup.sh &> /dev/null
        
        1
        2
      • 服务端

        • 时间要比客户端晚些,保证运维人员上班时能收到邮件即可。
        # backup check
        0 5 * * * /usr/bin/sh /scripts/check_backup.sh &> /dev/null
        
        1
        2
    • 全部做完后全部检查一遍,思考还有没有完善的余地即可。

    #Linux#Shell
    Shell流程控制与函数
    Ansible介绍与部署

    ← Shell流程控制与函数 Ansible介绍与部署→

    最近更新
    01
    二〇二五年四月十七日随笔
    04-17
    02
    二〇二五年四月十六日随笔
    04-16
    03
    二〇二五年四月九日随笔
    04-09
    更多文章>
    Theme by Vdoing | Copyright © 2022-2025 Hoshinozora | MIT License
    湘ICP备2022022820号-1
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式