• shell编程笔记


    查看目录

    tree -i -f | awk '{if(!system("test -d "$1))print $1}'

    批量快速创建user

    for i in user{0..10}; do
        useradd $i
        echo 123456 | passwd --stdin $i
    done

    使用if语句判断

    #!/bin/bash
    #文件判断
    if [ -e $1 ]; then
        echo "file exists"
    fi
    
    if [ -r $1 ]; then
      echo "readable"
    fi
    
    if [ -w $1 ]; then
      echo "writable"
    fi
    
    if [ -x $1 ]; then
      echo "executeable"
    fi
    
    if [ -s $1 ]; then
      echo "have contents"
    fi
    
    if [ -d $1 ]; then
      echo "directory"
    fi
    
    if [ -f $1 ]; then
      echo "file"
    fi
    
    if [ -c $1 ]; then
      echo "charactor device"
    fi
    
    if [ -b $1 ]; then
        echo "block device"
    fi
    
    #字符串判断
    if [ $1 = "admin" ]; then
        echo "you are admin"
    fi
    
    if [ $1 != "demon" ]; then
        echo "you are not demon"
    fi
    
    if [ -z $1 ]; then
        echo "zero string"
    fi
    
    if [ -n $1 ]; then
        echo "not empty"
    fi
    
    
    #数字判断
    if test $1 -eq 4; then
        echo "$1=4"
    fi
    if test $1 -ne 4; then
        echo "$1!=4"
    fi
    if test $1 -gt 4; then
        echo "$1>4"
    fi
    if test $1 -ge 4; then
        echo "$1>=4"
    fi
    if test $1 -lt 4; then
        echo "$1<4"
    fi
    if test $1 -le 4; then
        echo "$1<=4"
    fi
    
    
    #C语言语法
    if (( $1 != 'demon' )); then
        echo "[C]not demon"
    elif (( $1 > 5 )); then
        echo "[C]$1 > 5"
    fi
    
    #更兼容的用法
    if [[ $str == "hello" ]]; then
        echo $str
    fi
    
    if [[ -d $dir ]]; then
        echo $dir is directory
    fi

     循环 与 选择

    #POSIX用法
    for
    ((i=0;i<10;i++)); do if [ $i -eq 5 ]; then continue elif [ $i -eq 9 ]; then break; fi echo $i done read -p "Enter a char: " char case $char in [a-z]|[A-Z]) echo "A letter" ;; [0-9]) echo "A digut" ;; *) echo "function key" ;; esac echo '$#: ' $# echo '$@: ' $@ echo '$*: ' $*
    #shift用法 while [ $# -gt 0 ]; do if [[ $str == "" ]]; then str=$1 else str="$str-$1" fi shift done echo $str

    数组

    #!/bin/bash
    a="hello"
    arr=($a  1  2  "c"  d)
    
    length=${#arr}                # 5
    arr[5]=$arr
    
    echo length is $length        # 6
    
    for i in ${arr[@]}; do
        echo $i
    done
    
    for i in `seq 0 $length`; do     # 0 ~ 5
        arr[$i]=$i
    done
    
    i=0
    
    while [ $i -lt ${#arr[*]} ]; do
        echo ${arr[$i]}
        let "++i"
    done

    函数

    function add(){
        tot=1
        for (( i=1;i<=$1;i++ )); do
            tot=$(($tot*$i))
        done
        echo $tot
    }
    
    add 6   #720
    
    function sum(){
        return $(($1+$2))
    
    }
    
    sum 30 40
    
    echo "30 + 40 = $?"
    
    echo $$         #pid
    echo $-         #set
    echo $!         #the lastest pid

    cut 提取用户名

    cut -d: -f1 /etc/passwd
    cat /etcpasswd | awk -F: '{print "username: "$1"("$2")"}'

     awk 一些常见用法

    for i in `awk -F: '{print $1}' /etc/passwd |head` ; dosleep 1
        echo $i
    done
    
    for i in `df -Th | awk '{if(NR==2)print int($6)}'`; do
        echo usage: $i%
    done
    
    
    df -Th | awk 'END{print "row: "NR "
    col: "NF}'

    测试文件[access.log]

    192.168.10.1  root.php
    192.168.10.2  bin.php
    192.168.10.4  daemon.php
    192.168.10.2  adm.php
    192.168.10.1  lp.php
    192.168.10.1  sync.php
    192.168.10.2  shutdown.php
    192.168.10.6  halt.php
    192.168.10.2  mail.php
    192.168.10.2  uucp.php
    192.168.10.2  operator.php
    192.168.10.3  games.php
    192.168.10.4  gopher.php
    192.168.10.1  ftp.php
    192.168.10.7  nobody.php
    192.168.10.2  vcsa.php
    192.168.10.4  abrt.php
    192.168.10.4  ntp.php
    192.168.10.3  saslauth.php
    192.168.10.2  postfix.php
    192.168.10.3  sshd.php
    192.168.10.2  tcpdump.php
    192.168.10.3  dbus.php
    192.168.10.1  apache.php
    192.168.10.8  mysql.php

    awk 过滤 192.168.10.1 访问的记录

     cat access.log | awk  '$1 ~ /192.168.10.1/ {print $0}'

    awk 过滤非 192.168.10.1 访问的记录

     cat access.log | awk  '$1 !~ /192.168.10.1/ {print $0}'

    sed 只打印第5行数据

     cat passwd  |sed -n '5'p

    sed 打印第5到8行数据

     cat passwd  |sed -n '5,8'p

    sed 屏蔽第3到20行数据

    cat passwd  |sed  '3,20'd

    sed 打印登录用户

    cat passwd  | sed -n '/bash/'p

    sed 显示第一行到包含sync的行

    cat passwd  | sed -n 1,/sync/p

    sed 显示从sshd到最后一行

     cat /etc/passwd | sed -n '/sshd/,$'p

    uniq 相同合并并统计

     cat access.log  | awk '{print $1}' | sort | uniq  -c

    uniq 打印出现超过一次的行

     cat access.log  | awk '{print $1}' | sort | uniq  -d

    sort 按字母升序

     cat access.log  | awk '{print $1}' | sort

    sort -r 按字母降序

    cat access.log  | awk '{print $1}' | sort -r

    sort 也可以自己分割文件排序,不用awk, -t指定分隔符默认空格, -k指定按哪一列排序

     cat access.log | sort -t: -k1

    split 将文件进行分割成多个小文件

     split -5 passwd splitname
    #ls
    #passwd  splitnameaa  splitnameab  splitnameac  splitnamead  splitnameae

    颜色库

    #!/bin/bash
    #name color.sh
    #auth demonxian3
    da=` echo -e "33[31m"` #danger su=` echo -e "33[32m"` #success wa=` echo -e "33[33m"` #warning pr=` echo -e "33[34m"` #primary vi=` echo -e "33[35m"` #violet in=` echo -e "33[36m"` #info de=` echo -e "33[37m"` #default cl=` echo -e "33[0m"` #clear

    项目一   目录文件统计

    #!/bin/bash
    #author demonxian3
    line
    =`tree -i -f .|wc -l` files=`tree -i -f .| head -n $(($line-1))` fileCount=0 dirCount=0 for file in $files; do if [ -d $file ]; then dirCount=`expr $dirCount + 1` ; echo $file else fileCount=`expr $fileCount + 1` fi done echo "Dir:"$dirCount echo "Files:"$fileCount


    项目二  文件修改监视器

    #!/bin/bash
    #name filemonitor
    #auth demonxian3
    len
    =`tree -i -f | wc -l` len=`expr $len - 1 ` files=`tree -i -f | head -n $len` timestamp=() idx=0 for file in $files; do mtime=`date +%s -r $file` timestamp[$idx]="$mtime#$file" idx=$(($idx+1)) done idx=$(($idx-1)) function check(){ for i in `seq 0 $idx`; do file=${timestamp[$i]:11} oldtime=${timestamp[$i]:0:10} newtime=`date +%s -r $file` if [ $newtime -ne $oldtime ]; then echo "$file has been modified" timestamp[$i]="$newtime#$file" fi done } while true; do check sleep 1 done

    项目三  编写系统服务脚本以及实现开机自启

    /etc/rc.d/init.d 目录下存放着许多服务脚本, 可以使用service  和  chkconfig 来实现服务关闭开启或者开机自启动

    为了方便,系统会制作链接目录链接上面的路径, /etc/init.d/  ->  /etc/rc.d/init.d/

    如果不想通过chkconfig 来实现开机自启,也可以通过写入启动脚本 /etc/rc.d/rc.local  或者 /etc/rc.d/rc.local 实现自启动

    如果想把一个服务脚本改造成 chkconfig 可以识别的启动项,需要在脚本前端添加如下两行

    # chkconfig: 2345 90 21
    # description:  myservicename service daemon

    2345表示不指定runlevel等级时运行的默认等级

    90表示开启时的顺序 S90开头

    21表示关闭时的顺序 K21开头、

    只要将脚本放到 /etc/rc.d/init.d下就可以通过services 来启动脚本

    项目四  awk 分析apache日志访问记录

    #!/bin/bash
    #[09/May/2018:07:59:32]
    
    UsrAgent=$1
    
    
    cat /var/log/httpd/access_log | awk '
    BEGIN{
        dan="33[31m"
        suc="33[32m"
        pri="33[34m"
        war="33[33m"
        vio="33[35m"
        inf="33[36m"
        def="33[37m"
        cls="33[0m"
        usrAgent=$useragent
    }
    {
        if("'"$UsrAgent"'") print vio "user-agent: " $12$13$14$15$16$17$18$19$20$21$22$23$24$25$26$27$28$29$30$31$32 cls
    
    
        len=length($10);
        len=3-len;
        while((len--)>0)
            $10=$10" "
    
        len=length($6);
        len=6-len;
        while((len--)>0)
            $6=$6" "
    
        print war $1"	" cls,
        suc substr($4,5,3)"/"substr($4,2,2)" "substr($4,14,8) cls,
        substr($6,2,5),
        $9,
        $10,
        inf $7 cls
    }'

    使用方法:

    # bash analysis.sh

    IP         日期     方法   返回码 长度  访问的页面

    查看用户代理

    # bash analysis.sh 1

    项目五  根据日志404频繁访问进行iptables的封杀, 封杀半个小时

    #!/bin/bash
    # banshell.sh
    
    
    # [Notice] clear iptables
    `iptables -F` #calculate the
    time for ban time curHour=`date +%H` curMinu=`date +%M` starttime="$curHour:$curMinu" curMinu=$(($curMinu + 30)) if [[ $curMinu -gt 59 ]]; then curHour=$(($curHour + 1)) curMinu=$(($curMinu % 60)) fi stoptime="$curHour:$curMinu" dangerIP=`cat /var/log/httpd/access_log | grep 404 | awk '{print $1}' | sort | uniq -c | awk '{if($1>30)print $2}'` for i in $dangerIP; do res=`iptables -nvL | grep $i` if [[ $res == "" ]]; then `iptables -A INPUT -s $i -m time --timestart $starttime --timestop $stoptime -j DROP ` else echo "go" fi done

    项目六  制作操作菜单

     

     通过点可以实现shell文件包含

    .  shellname.sh

    编写菜单

    #!/bin/bash
    #name menu.sh
    #auth demonxian3
    . color.sh       #包含color库 function menu(){ cat << EOF $pr ********************************************* * Operation Menu * ********************************************* $cl $in * * * 1) add a user * * 2) set passwd * * 3) del a user * * 4) select user * * 5) print disk space * * 6) print mem space * * 7) quit * * * ********************************************* $cl EOF } if [[ $0 == "menu.sh" ]]; then menu fi

    编写 交互处理 和 逻辑处理

    #!/bin/bash
    #name func.sh
    #auth demonxian3
    . menu.sh function addUsr(){ read -p "Enter the username: " user read -p "Enter the password: " pass `useradd $user` `echo "$pass" | passwd --stdin "$user" 1>/dev/null` id $user } function setPasswd(){ read -p "Enter the username: " user read -p "Enter the password: " pass echo $pass | passwd --stdin $user 1> /dev/null if [ $? -eq 0 ]; then echo "Successfully" fi } function delUsr(){ read -p "Enter the username: " user `userdel -r $user 1> /dev/null ` if [ $? -eq 0 ]; then echo "successfully" fi } function selectUsr(){ cat /etc/passwd | awk -F: '{ if(NR%4==0) printf(" "); len=length($1); while(len++<20)$1=$1" " printf($1" ") }END{ printf(" ") }' } function selectDisk(){ df -Th | grep sda | awk 'BEGIN{print "deviceName fs total used free perc where"}{print $1" "$2" "$3" "$4" "$5" "$6" "$7}' } function selectMem(){ free -h | grep -vw "cache" } while true; do clear menu read -p "Input your select: " input case $input in 1) addUsr ;; 2) setPasswd ;; 3) delUsr ;; 4) selectUsr ;; 5) selectDisk ;; 6) selectMem ;; *) echo "Invalid selection" ;; esac read -p "Press any key to continue" done

    以下命令将文中所有的字符串idiots替换成managers:
    :1,$s/idiots/manages/g
    通常我们会在命令中使用%指代整个文件做为替换范围:
    :%s/search/replace/g
    以下命令指定只在第5至第15行间进行替换:
    :5,15s/dog/cat/g
    以下命令指定只在当前行至文件结尾间进行替换:
    :.,$s/dog/cat/g
    以下命令指定只在后续9行内进行替换:
    :.,.+8s/dog/cat/g
    你还可以将特定字符做为替换范围。比如,将SQL语句从FROM至分号部分中的所有等号(=)替换为不等号(<>):
    :/FROM/,/;/s/=/<>/g
    在可视化模式下,首先选择替换范围, 然后输入:进入命令模式,就可以利用s命令在选中的范围内进行文本替换。

  • 相关阅读:
    悲观锁、乐观锁、行级锁、表级锁
    MySQL中锁详解(行锁、表锁、页锁、悲观锁、乐观锁等)
    刷题-力扣-148. 排序链表
    刷题-力扣-206. 反转链表
    刷题-力扣-203. 移除链表元素
    刷题-力扣-474. 一和零
    刷题-力扣-494. 目标和
    刷题-力扣-160. 相交链表
    刷题-力扣-34. 在排序数组中查找元素的第一个和最后一个位置
    刷题-力扣-33. 搜索旋转排序数组
  • 原文地址:https://www.cnblogs.com/demonxian3/p/9000423.html
Copyright © 2020-2023  润新知