shell脚本删除远程过期文件

应用场景:

我们在工作中经常会有要定时输出一些文件到磁盘上用作离线词表或者数据的冷备,但是如果这些数据不定期清理的话,则会对我们的磁盘造成巨大的浪费,人工手动清理的话,总是会有遗忘的时候,所以此刻就需要有一个自动清理的脚本。

假设现场:我们有一个定时生成词表到指定目录的程序,输出的目录名和词表前缀相同,且在生成词表的同时,会将词表名和对应的md5输出到词表同目录的list文件中用在校验。

任务:1.清理7天的词表文件 2.同时清理对应list中的数据

脚本内容

话不多说,先直接上脚本:

#只保留7天的数据
REMAIN_DAYS=7
HOST="root@10.10.123.251"
PASS="123456"
DICT_NAME="my_dictionary"
DICT_DIR="/export/data/${DICT_NAME}"
function clean() {
  local del_days=${REMAIN_DAYS}
  del_days=$(( del_days-1 ))
  echo "begin clean..."
  #删除过期文件
  echo "ssh -t "${HOST}" "find ${DICT_DIR} -mtime +${del_days} | xargs rm -rf {}""
  sshpass -p "${PASS}" ssh -t "${HOST}" "find ${DICT_DIR} -mtime +${del_days} | xargs rm -rf {}"
  #更新list:获取文件数和list行数,若list行数大于文件数,则去除过去的差值行数
  local file_nums=`sshpass -p "${PASS}" ssh -t "${HOST}" "find ${DICT_DIR} -name "${DICT_NAME}-*" | wc -l"`
  local list_nums=`sshpass -p "${PASS}" ssh -t "${HOST}" "cat ${DICT_DIR}/list | wc -l"`
  local file_nums_length=$(( ${#file_nums} ))
  local list_nums_length=$(( ${#list_nums} ))
  let file_nums=0+${file_nums:0:${file_nums_length}}
  let list_nums=0+${list_nums:0:${list_nums_length}}
  local minus_num=$(( list_nums - file_nums ))
  echo "file_nums:$file_nums, list_nums:$list_nums, minus_num:$minus_num"
  if [ $minus_num -gt 0 ]; then
    echo "delete list: 1,${minus_num}d"
    sshpass -p "${PASS}" ssh -t "${HOST}" "sed -i '1,${minus_num}d' ${DICT_DIR}/list"
  fi
  echo "clean finished..."
}

其中不少人可能会奇怪为什么会有这一段代码:

  local file_nums_length=$(( ${#file_nums} ))
  local list_nums_length=$(( ${#list_nums} ))
  let file_nums=0+${file_nums:0:${file_nums_length}}
  let list_nums=0+${list_nums:0:${list_nums_length}}

主要是因为刚开始没加这一段儿的时候一直报错")syntax error: invalid arithmetic operator (error token is",查了一下文档,说是因为用字符串做了数值计算逻辑导致的,然后想用这种方式把字符串转成数值。但是其实至今不知道那个是为什么报错,有知道的大佬也请解惑呀,感谢了。

下面也会对我这个脚本的知识点作一个具体梳理。

find -mtime +N/-N/N 的时间算法:

在unix或linux环境中经常会用到find -mtime这样的写法来找某某时间点之前的文件,至于如何写find -mtime +N/-N/N,原来并不是很清楚,今天找了些资料看看,画下了这个图,以便理解和记忆:

从图上可以看出,以当前时间点开始算起,+表示往左,从该时间点开始再继续往更早推,可以称作xx以外;-表示往右,从该时间点算起往后的时间推,可以称作xx以内;没有加减号表示据此此前第N天。因此:
我们来看下面这个例子:
我当前的时间2011年3月1日22:31,我有如下的文件:

E:	estpath>ls -l
total 0
-rwxrwxrwa   1 Administrator   None                  0 Feb 25 22:37 111.txt
-rwxrwxrwa   1 Administrator   None                  0 Feb 26 22:38 222.txt
-rwxrwxrwa   1 Administrator   None                  0 Feb 27 22:38 333.txt
-rwxrwxrwa   1 Administrator   None                  0 Feb 28 22:01 444.txt
-rwxrwxrwa   1 Administrator   None                  0 Feb 28 22:30 555.txt
-rwxrwxrwa   1 Administrator   None                  0 Mar  1 22:31 666.txt<--当前时间的文件
-rwxrwxrwa   1 Administrator   None                  0 Mar  2  2011 777.txt
 
E:	estpath>

-mtime +2,表示2天以外的,即从距离当前时间(2011-03-01 22:31)的2天前开始算起,往更早的时间推移。因此,距离当前时间的2天为:2011-02-27 22:31,在此前的文件,会被选出来。

E:	estpath>find ./ -mtime +2
./111.txt
./222.txt

-mtime +1,表示1天以外的,即从距当前时间的1天前算起,往更早的时间推移。因此2011-02-28 22:31前的文件属于该结果,2011-02-28 22:31后的文件不属于该结果:

E:	estpath>find ./ -mtime +1
./111.txt
./222.txt
./333.txt
./444.txt
./555.txt

-mtime 2, 距离当前时间第2天的文件,当前时间为2011-03-01 22:31,往前推2天为2011-02-27 22:31,因此以此为时间点,24小时之内的时间为2011-02-27 22:31~2011-02-28 22:31,因此这段时间内的文件会被选中出来:

E:	estpath>find ./ -mtime 2
./333.txt
./444.txt
./555.txt

-mtime 1, 距离当前时间第1天的文件,当前时间为2011-03-01 22:31,往前推1天为2011-02-28 22:31,因此以此为时间点,24小时之内的时间为2011-02-28 22:31~2011-03-01 22:31,因此这段时间内的文件会被选中出来:

E:	estpath>find ./ -mtime 1
./666.txt

-mtime -1 表示1天以内的,从距当前时间的1天为2011-02-28 22:31,往右推移:

E:	estpath>find ./ -mtime -1
./
./666.txt
./777.txt

-mtime -2 表示2天以内的,从距当前时间的2天为2011-02-27 22:31开始,往右推移:

E:	estpath>find ./ -mtime -2
./
./333.txt
./444.txt
./555.txt
./666.txt
./777.txt

find -mtime命令参数理解:

find . -mtime N
实际上你应该这样理解..
N * 24
+1 内表示 1 * 24 +24小时以外..
+0 才表示 0 * 24 +24小时以外
1 表示 1*24 + 24 到 24 之间..
0 表示 0*24 + 24 到 0 之间..
-1 表示 0*24 +24 内,甚至为未来时间...

记住0也是自然数....

Linux xargs命令

xargs 是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。

xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。

xargs 也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。

xargs 默认的命令是 echo,这意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代。

xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。

参数:

  • -a file 从文件中读入作为sdtin
  • -e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
  • -p 当每次执行一个argument的时候询问一次用户。
  • -n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
  • -t 表示先打印命令,然后再执行。
  • -i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
  • -r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
  • -s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
  • -L num 从标准输入一次读取 num 行送给 command 命令。
  • -l 同 -L。
  • -d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
  • -x exit的意思,主要是配合-s使用。。
  • -P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。

实例

xargs 用作替换工具,读取输入数据重新格式化后输出。

定义一个测试文件,内有多行文本数据:

# cat test.txt

a b c d e f g
h i j k l m n
o p q
r s t
u v w x y z

多行输入单行输出:

# cat test.txt | xargs
a b c d e f g h i j k l m n o p q r s t u v w x y z

-n 选项多行输出:

# cat test.txt | xargs -n3

a b c
d e f
g h i
j k l
m n o
p q r
s t u
v w x
y z

-d 选项可以自定义一个定界符:

# echo "nameXnameXnameXname" | xargs -dX

name name name name

结合 -n 选项使用:

# echo "nameXnameXnameXname" | xargs -dX -n2

name name
name name

读取 stdin,将格式化后的参数传递给命令

假设一个命令为 sk.sh 和一个保存参数的文件 arg.txt:

#!/bin/bash
#sk.sh命令内容,打印出所有参数。

echo $*

arg.txt文件内容:

# cat arg.txt

aaa
bbb
ccc

xargs 的一个选项 -I,使用 -I 指定一个替换字符串 {},这个字符串在 xargs 扩展时会被替换掉,当 -I 与 xargs 结合使用,每一个参数命令都会被执行一次:

# cat arg.txt | xargs -I {} ./sk.sh -p {} -l

-p aaa -l
-p bbb -l
-p ccc -l

复制所有图片文件到 /data/images 目录下:

ls *.jpg | xargs -n1 -I {} cp {} /data/images

xargs 结合 find 使用

用 rm 删除太多的文件时候,可能得到一个错误信息:/bin/rm Argument list too long. 用 xargs 去避免这个问题:

find . -type f -name "*.log" -print0 | xargs -0 rm -f

xargs -0 将 作为定界符。

统计一个源代码目录中所有 php 文件的行数:

find . -type f -name "*.php" -print0 | xargs -0 wc -l

查找所有的 jpg 文件,并且压缩它们:

find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz

xargs 其他应用

假如你有一个文件包含了很多你希望下载的 URL,你能够使用 xargs下载所有链接:

# cat url-list.txt | xargs wget -c

转载请注明出处:https://www.cnblogs.com/fnlingnzb-learner/p/13031967.html

原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/13031967.html