Linux运维常用shell脚本之文件和字符串管理实例

Shell脚本
372
0
0
2022-12-25

1、判断输入是否为数字

方法1:
if [[ $1 =~ ^[0-9]+$ ]]; then
    echo "Is Number."
else
    echo "No Number."
fi
方法2:
if [ $1 -gt 0 ] 2>/dev/null; then
    echo "Is Number."
else
    echo "No Number."
fi

方法3:

echo $1 |awk '{print $0~/^[0-9]+$/?"Is Number.":"No Number."}'  #三目运算符
DIR=$1
KEY=$2
for FILE in $(find $DIR -type f); do
    if grep $KEY $FILE &>/dev/null; then
        echo "--> $FILE"
    fi
done

2、 将目录下大于k的文件转移出去

编写shell脚本,将/usr/local/test目录下大于100k的文件转移到/tmp目录下:

#!/bin/bash
for FILE in `ls /usr/local/test`
do 
    if [ -f $FILE ] ; then 
        if [ `ls -l  $FILE | awk `{print $5}` -gt 100000 ] ; then 
            mv $FILE  /tmp/
        fi 
    fi
done

================

#!/bin/bash
for FileName in `ls -l  /usr/local/test | awk '$5>102400' {print $9}`
do 
        mv $FileName  /tmp/
done
ls -al  /tmp/
echo  "done!"

3、批量修改文件名

# touch article_{1..3}.html

# ls

article_1.html  article_2.html  article_3.html

现在想把article改为bbs:

方法1:

for file in $(ls *html); do

    mv $file bbs_${file#*_}

    # mv $file $(echo $file |sed -r 's/.*(_.*)/bbs\1/')

    # mv $file $(echo $file |echo bbs_$(cut -d_ -f2) 

done

方法2:

for file in $(find . -maxdepth 1 -name "*html"); do

     mv $file bbs_${file#*_}

done

方法3:

# rename article bbs *.html

4、ftp自动登录批量下载文件

##### 从ftp服务器上的/home/data 到 本地的/home/databackup####
#!/bin/bash
ftp -n<<!
open 192.168.1.171
user guest 123456
binary
cd /home/data
lcd /home/databackup
prompt
mget *
close
bye
!

5、ftp自动登录上传文件

####本地的/home/databackup to ftp服务器上的/home/data####
#!/bin/bash
ftp -n<<!
open 192.168.1.171
user guest 123456
binary
hash
cd /home/data
lcd /home/databackup
prompt
mput *
close
bye
!

6、ftp自动登录下载单个文件

####ftp服务器上下载/home/data/a.sh to local /home/databackup####
#!/bin/bash
ftp -n<<!
open 192.168.1.171
user guest 123456
binary
cd /home/data
lcd /home/databackup
prompt
get a.sh a.sh
close
bye
!

7、ftp自动登录上传单个文件

####把本地/home/databachup/a.sh up ftp /home/databackup 下####
#!/bin/bash
ftp -n<<!
open 192.168.1.171
user guest 123456
binary
cd /home/data
lcd /home/databackup
prompt
put a.sh a.sh
close
bye
!

8、监控目录,将新创建的文件名追加到日志中

需安装inotify-tools软件包。

#!/bin/bash
MON_DIR=/opt
inotifywait -mq --format %f -e create $MON_DIR |\
while read files; do
  echo $files >> test.log
done
12.16 多个网卡选择
function local_nic() {
    local NUM ARRAY_LENGTH
    NUM=0
    for NIC_NAME in $(ls /sys/class/net|grep -vE "lo|docker0"); do
        NIC_IP=$(ifconfig $NIC_NAME |awk -F'[: ]+' '/inet addr/{print $4}')
        if [ -n "$NIC_IP" ]; then
            NIC_IP_ARRAY[$NUM]="$NIC_NAME:$NIC_IP"    #将网卡名和对应IP放到数组
            let NUM++
        fi
    done
    ARRAY_LENGTH=${#NIC_IP_ARRAY[*]}
    if [ $ARRAY_LENGTH -eq 1 ]; then     #如果数组里面只有一条记录说明就一个网卡
        NIC=${NIC_IP_ARRAY[0]%:*}
        return 0
    elif [ $ARRAY_LENGTH -eq 0 ]; then   #如果没有记录说明没有网卡
        echo "No available network card!"
        exit 1
    else
        #如果有多条记录则提醒输入选择
        for NIC in ${NIC_IP_ARRAY[*]}do
            echo $NIC
        done
        while truedo
            read -p "Please enter local use to network card name: " INPUT_NIC_NAME
            COUNT=0
            for NIC in ${NIC_IP_ARRAY[*]}do
                NIC_NAME=${NIC%:*}
                if [ $NIC_NAME == "$INPUT_NIC_NAME" ]; then
                    NIC=${NIC_IP_ARRAY[$COUNT]%:*}
                    return 0
                else
                   COUNT+=1
                fi
            done
            echo "Not match! Please input again."
        done
    fi
}
local_nic

如果有只有一个网卡就不选择。

9、监控LINUX目录和文件变化

利用一个脚本能够实时监控web目录下文件的变化,也就是对该目录的增删改操作都会记录到相应日志下。

主要有两个脚本:

脚本1:将需要监控的目录的原始状态保存到LOG日志 脚本2:将脚本1的原始状态与本脚本比对,如果目录文件发生变化,则将变化的内容保存到日志。

1,监控 /home/www/ 目录改动,并将改动的文件rsync到/home/www3目录

2,监控方法为监控文件的md5值,如果md5值与上次不同,即发生改变

注:原理实际上利用的是du -sb输出值来判断文件的变化,再利用diff进行比对。

1.在执行脚本前要保存原始的状态:

# vi initial.sh

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin/:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 监控的目录
DIR=/root
# 临时文件
TMP_A=/tmp/a.txt
# 遍历指定目录下的文件大小及路径并重定向到日志文件
find $DIR -print0 | xargs -0 du -sb  > $TMP_A

2.执行监控脚本 # vi monitor.sh

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin/:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
# 监控的目录
DIR=/root
# 日期变量
DATE=`date +%F_%H:%M`
# 临时文件
TMP_A=/tmp/a.txt
TMP_B=/tmp/b.txt
TMP_C=/tmp/c.txt
# 日志文件
LOG=/var/log/filemodify.log
# 遍历指定目录下的文件大小及路径并重定向到日志文件
find $DIR -print0 | xargs -0 du -sb  > $TMP_B
# 比较目录变化,并将变化的文件写入日志
DIFF=$(diff $TMP_A $TMP_B)
if [[ -z $DIFF ]];
 then 
   echo "Nothing change" >> $LOG 
 else 
   echo "Here is the change" >> $LOG 
   echo "" >> $LOG 
   echo "$DIFF" |awk '{print $3}'|sort -k2n |uniq |sed '/^$/d' |tee $TMP_C >> $LOG 
   if [ -s $TMP_C ];
     then 
       echo "" >> $LOG 
       echo "It modified at $DATE" >> $LOG
# 将当前监控的目录结构覆盖为初始状态
       find $DIR -print0 | xargs -0 du -sb  > $TMP_A 
   fi
fi
echo "====================================" >> $LOG
#清理临时文件
rm -rf $TMP_B $TMP_C

Shell脚本监控目录内文件改动

#! /bin/bash
webroot="/home/www/"
cp /dev/null rsync_file
if [ ! -f file.md5 ];then
  find $webroot -type f -exec md5sum {} \; >>file.md5
else 
  for file in $(md5sum -c file.md5|awk -F':' '/FAILED/{print $1}')
    do 
      if [ -f $file ];then
      filename_z=$(echo $file|sed 's#/#\\/#g')
      sed -i "/ $filename_z/"d file.md5
      md5sum $file >> file.md5
      echo $file >> rsync_file
      else 
      echo $file >>rsync_rm
      fi 
    done 
  for newfile in $(find $webroot -type f)
    do
      grep $newfile file.md5 >/dev/null 2>&1
      if [ $? -gt 0 ];then 
      md5sum $newfile >> file.md5
      echo "$newfile" >> rsync_file
      fi 
    done
for rfile in $(cat rsync_file)
do
rsync -avzp $rfile /home/www3/
done

10、统计当前目录中以.html结尾的文件总大小

方法1:

# find . -name "*.html" -maxdepth 1 -exec du -b {} \; |awk '{sum+=$1}END{print sum}'

方法2:

for size in $(ls -l *.html |awk '{print $5}'); do

    sum=$(($sum+$size))

done

echo $sum

递归统计:

# find . -name "*.html" -exec du -k {} \; |awk '{sum+=$1}END{print sum}'

11、 获取随机字符串或数字

获取随机8位字符串:

方法1:

# echo $RANDOM |md5sum |cut -c 1-8

471b94f2

方法2:

# openssl rand -base64 4

vg3BEg==

方法3:

# cat /proc/sys/kernel/random/uuid |cut -c 1-8

ed9e032c

获取随机8位数字:

方法1:

# echo $RANDOM |cksum |cut -c 1-8

23648321

方法2:

# openssl rand -base64 4 |cksum |cut -c 1-8

38571131

方法3:

# date +%N |cut -c 1-8

69024815

cksum:打印CRC效验和统计字节

12、获取字符串长度

# VAR='hello world!'
# echo $VAR
hello world!
# echo ${#VAR}
12

13、截取字符

截取从offset个字符开始,向后length个字符。

截取hello字符串:
# VAR='hello world!'
# echo ${VAR:0:5}
hello
截取wo字符:
# echo ${VAR:6:2}
wo
截取world!字符串:
# echo ${VAR:5}
world!
截取最后一个字符:
# echo ${VAR:(-1)}
!
截取最后二个字符:
# echo ${VAR:(-2)}
d!
截取从倒数第3个字符后的2个字符:
# echo ${VAR:(-3):2}
ld

14、替换字符串

格式:${parameter/pattern/string}

# VAR='hello world world!'
将第一个world字符串替换为WORLD:
# echo ${VAR/world/WORLD}
hello WORLD world!
将全部world字符串替换为WORLD:
# echo ${VAR//world/WORLD}
hello WORLD WORLD!

15、定义一个颜色输出字符串函数

方法1:

function echo_color() {
    if [ $1 == "green" ]; then
        echo -e "\033[32;40m$2\033[0m"
    elif [ $1 == "red" ]; then
        echo -e "\033[31;40m$2\033[0m"
    fi
}

方法2:

function echo_color() {
    case $1 in
        green)
            echo -e "\033[32;40m$2\033[0m"
            ;;
        red)
            echo -e "\033[31;40m$2\033[0m" 
            ;;
        *) 
            echo "Example: echo_color red string"
    esac
}

使用方法:echo_color green "test"

function关键字定义一个函数,可加或不加。

16、打印乘法口诀

方法1:
# awk 'BEGIN{for(n=0;n++<9;){for(i=0;i++<n;)printf i"x"n"="i*n" ";print ""}}'
方法2:
for ((i=1;i<=9;i++)); do 
   for ((j=1;j<=i;j++)); do
     result=$(($i*$j))
     echo -n "$j*$i=$result " 
   done 
   echo
done

输入五个100数之内的字符,统计和、最小和最大

COUNT=1
SUM=0
MIN=0
MAX=100
while [ $COUNT -le 5 ]; do 
    read -p "请输入1-10个整数:" INT
    if [[ ! $INT =~ ^[0-9]+$ ]]; then 
        echo "输入必须是整数!" 
        exit 1
    elif [[ $INT -gt 100 ]]; then 
        echo "输入必须是100以内!" 
        exit 1
    fi
    SUM=$(($SUM+$INT))
    [ $MIN -lt $INT ] && MIN=$INT
    [ $MAX -gt $INT ] && MAX=$INT 
    let COUNT++
done
echo "SUM: $SUM"
echo "MIN: $MIN"
echo "MAX: $MAX"