功能描述:
我们都知道linux不同于windows的一点是Windows有回收站机制,这样如果我们想将之前删掉的一个文件还原直接到回收站里就可以实现,这给了我们一次反悔的机会。所以我考虑在我的linux上也加入这个功能,来防止“rm -rf”造成的误删除导致数据丢失。
我现在通过脚本来实现这个回收站机制。rm脚本实现的是删除,替换了原系统中的rm,将删除的文件都回收到了用户家目录下的一个叫./recycle的目录里了,到时只要在这个目录里找回就可以啦,注意rm删除的东西都被真的删除,就有个问题啦:回收站的东西无法删除,解决这个问题就要有另一个脚本啦,清空回收站的脚本,用recycle来实现。1.rm删除文件和文件夹,用法与自带rm命令相似
2.recycle显示回收站里面的内容:可以按名字排序,也可以按删除时间排序。
recycle -d可以进入整理回收站的模式:
用法举例如下 recycle -d -empty清空回收站
recycle -d -t 3清空3天前的文件
recycle -d -s 5清空超过5M的文件
recycle -d -t 3 -s 5清空3天前且大小超过5M的文件
$ rm --help
Usage: rm [-r] [-f] [file]...
del file and move it the recycle
与系统自带的rm命令参数一致
复制代码
$ recycle --help
recycle version 1.0
Usage: recycle [-l] [-n] [-r]
recycle -d -empty
recycle -d [-f] [-t ] [-s ]
manipulate the recycle
Options:
l - list the deleted file with long format
n - sort the deleted file by name
r - list the deleted whth reverse order
d - delete file mode
empty - empty the recycle
h - Help
t - delete the file `time' days ago
s - delete file which size greater the `size' megabyte
复制代码
如果要定期清空回收站的话,就添加一个计划任务。
环境描述:
现在我有不止一台的linux系统,如果一台一台的scp脚本会很麻烦,我选择使用salt来进行推送脚本,及设置计划任务来清空回收站。每台linux机器上基本都有root和dev两个用户,salt设置的只能root用户来使用,这样就没办法通过salt推送recycle命令来清空dev用户的回收站了,我在这儿采取的一个方法是:mv /home/dev/.recycle/* /root/.recycle/下做一下中转就可以通过salt来清空dev的回收站了。还有个问题如果服务器的硬盘比较小,如果某次删除的东西特别大,就会硬盘报警,我们可以写个脚本并设置计划任务来判断它的使用空间大于多少时就会清空回收站,配合定期清空回收站来使用,这个脚本叫recycle.sh。
推送脚本并赋予执行权限:salt '*' cp.get_file salt://files/rm /usr/local/bin/rm
salt '*' cp.get_file salt://files/recycle /usr/local/bin/recycle
salt '*' cp.get_file salt://files/recycle.sh /usr/local/bin/recycle.sh
salt '*' cmd.run 'chmod +x /usr/local/bin/rm'
salt '*' cmd.run 'chmod +x /usr/local/bin/recycle'
salt '*' cmd.run 'chmod +x /usr/local/bin/recycle.sh'
在salt服务器上设置计划任务:crontab -l
* 5 */3 * * /usr/bin/salt '*' cmd.run '/usr/local/bin/recycle -d -empty' &> /dev/null
* 1 */3 * * /usr/bin/salt '*' cmd.run '/bin/mv /home/dev/.recycle/* /root/.recycle/' &> /dev/null
* */1 * * * /usr/bin/salt '*' cmd.run '/usr/local/bin/recycle.sh' &> /dev/null
rm脚本:#
#
# =============================================
# Version : 1.1
# Date : 20090506
# Author : devinwang
# Changes : what is new
[ -d ~/.recycle ] || mkdir ~/.recycle
RECYCLE_DIR=~/.recycle
VERSION=1.0
function echo.log {
local line_no=${BASH_LINENO[0]}
local file_name=$0
echo "${file_name}:${line_no}:$@"
}
echo.ok() {
if [[ $1 == "-n" ]]; then
shift
echo -n -e"\\033[1;32m$@\e[0m"
else
echo -e"\\033[1;32m$@\e[0m"
fi
}
echo.err() {
if [[ $1 == "-n" ]]; then
shift
echo -n -e"\\033[1;31m$@\e[0m"
else
echo -e"\\033[1;31m$@\e[0m"
fi
}
function yesOrNo {
local answer=""
local ret=0
local message="$@, (Y)es/(N)o? [n] "
: ${REDIRECT:=/dev/tty}
while true ; do
read -p"${message}" answer $REDIRECT 2>&1
case"$answer" in
[yY]) ret=0; break ;;
[nN]|"") ret=1; break ;;
*) echo; continue
esac
done
return $ret
}
mvToRecycle() {
### file OR dir not exist
if [[ ! -a "$1" ]]; then
echo.err rm: cannotremove \`$1\': No such file or directory
return 1
fi
if [[ -d "$1" ]]; then
t="directory"
st="d"
else
t="file"
st="f"
fi
### dir
if [[ -d "$1" &&"$option" != *r* ]]; then
echo.err rm: cannotremove \`$1\'\: Is a directory
return 1
fi
### prompt
if [[ $option != *f* ]]; then
### if type no, return
yesOrNo "remove $t\`$1'" \
|| return 0
fi
### remove dir
mv -- "$1""${RECYCLE_DIR}/${DATE}_${st}_${1}" \
&& echo.ok removed $t \`$1\`;
echo ------------------------------;
echo "
如需要恢复请到~/.recycle目录里找回。"
}
print_help()
{
cat <
${0##*/} version $VERSION
Usage: ${0##*/} [-r] [-f] [file]...
del file and move it the recycle
EOF
# Handle unclosed quote for syntax highlighting '
}
### read option
option=""
while (( $# >= 1 )); do
case "$1" in
-h|--help) print_help; exit 0;;
--) shift; break;; #遇到`--',则option结束
-*) option="${option}$1"; shift;;
*) break;;
esac
done
DATE=$(date +%Y%m%d_%H%M%S)
while (( $# >= 1 )); do
#echo.log "$1"
mvToRecycle "$1"
shift
done
recycle脚本:#! /bin/bash
# Copyright 2009 (c), devinwang
# All rights reserved.
#
# Filename : recycle
# Author : devinwang
# Date : 20090506
# Version : 1.0 (init)
# Usage :
# Description: configuration file template
#
#
# =============================================
# Version : 1.1
# Date : 20090506
# Author : devinwang
# Changes : what is new
[ -d ~/.recycle ] || mkdir ~/.recycle
RECYCLE_DIR=~/.recycle
VERSION=1.0
### ^^^
必须进入回收站所在的目录
[[ -d ${RECYCLE_DIR} ]] || { echo err: \`${RECYCLE_DIR}\' is not dir; exit 22;}
cd $RECYCLE_DIR
if (( $? != 0 )); then
echo -e "\\033[1;31mcannot change to dir$RECYCLE_DIR\\033[0m"
exit 1
fi
[[ "$PWD" == */.recycle ]] || { echo -e "\\033[1;31mcwderr\\033[0m"; exit 9; }
[[ "`echo ${RECYCLE_DIR}`" == "$PWD" ]] || { echo -e"\\033[1;31mcwd err\\033[0m"; exit 9; }
### ^^^必须进入回收站所在的目录
function echo.log {
local line_no=${BASH_LINENO[0]}
local file_name=$0
echo "${file_name}:${line_no}:$@"
}
echo.ok() {
if [[ $1 == "-n" ]]; then
shift
echo -n -e"\\033[1;32m$@\e[0m"
else
echo -e"\\033[1;32m$@\e[0m"
fi
}
echo.err() {
if [[ $1 == "-n" ]]; then
shift
echo -n -e "\\033[1;31m$@\e[0m"
else
echo -e"\\033[1;31m$@\e[0m"
fi
}
function yesOrNo {
local answer=""
local ret=0
local message="$@, (Y)es/(N)o? [n] "
: ${REDIRECT:=/dev/tty}
while true ; do
read -p "${message}"answer $REDIRECT 2>&1
case"$answer" in
[yY]) ret=0; break ;;
[nN]|"") ret=1; break ;;
*) echo; continue
esac
done
return $ret
}
### ^^^list the files in recycle
listFile() {
lsOption=""
isHasSize=false
if [[ $option == *l* ]]; then
ls_option="${lsOption} -sh"
isHasSize=true
fi
### file list
fileList="`ls -1 ${ls_option}${RECYCLE_DIR}`"
sortOption=""
### sort by name
if [[ $option == *n* ]]; then
sortOption="${sortOption} -k4"
fi
if [[ $option == *r* ]]; then
sortOption="${sortOption}-r"
fi
### sort the result
fileList=`echo "$fileList" |sort -t'_'${sortOption}`
offset_index=0
offset_year=$((0 + offset_index))
offset_month=$((4 + offset_index))
offset_day=$((6 + offset_index))
offset_hour=$((9 + offset_index))
offset_min=$((11 + offset_index))
offset_shortType=$((16 + offset_index))
offset_fileName=$((18 + offset_index))
while read i; do
#echo.ok "$i"
if [[ $i == total* ]];then
echo $i
continue
fi
if [[ $isHasSize ==true ]]; then
size="${i%% *}"
i="${i#* }"
fi
timeStr="${i:${offset_year}:4}-${i:${offset_month}:2}-${i:${offset_day}:2}${i:${offset_hour}:2}:${i:${offset_min}:2}"
shortType=${i:${offset_shortType}:1}
fileName=${i:${offset_fileName}}
if [[ $option == *l*]]; then
#echo "$timeStr $size $shortType $fileName"
printf "%s %-4s %s " "$timeStr" "$size""$shortType"
fi
### must set""
colorOption=""
if [[ $shortType == d]]; then
colorOption="\e[1;34m"
fi
echo -e"${colorOption}$fileName\e[0m"
done <<
### the while loop not exec in a subshell; if use pipeline, it will run in asubsehll;
}
### $$$list the files in recycle
emptyRecycle() {
### echo -e"\\033[1;32mpwd: ${PWD}\n\e[0m"
[[ "$PWD" ==*/.recycle ]] || { echo -e "\\033[1;31mcwd err\\033[0m"; exit9; }
[[ "`echo${RECYCLE_DIR}`" == "$PWD" ]] || { echo -e"\\033[1;31mcwd err\\033[0m"; exit 9; }
###yesOrNo "emptythe recycle " && $RM -rfv $RECYCLE_DIR/* && echo.okrecycle emptyed || return 0
$RM -rfv$RECYCLE_DIR/* > /dev/null && echo.ok recycle emptyed
}
### ^^^del files in recycle
delFile() {
echo -e "\\033[1;32mpwd: ${PWD}\n\e[0m"
RM='/bin/rm'
#echo.log hi
#echo.log "$@"
time=0
size=0
while (( $# >= 1 )); do
case "$1" in
-s) local -i size=$2; shift2;;
-t) local -i time=$2; shift2;;
-f) local forec=true; shift;;
-empty)
emptyRecycle
return $?
;;
*) break;;
esac
done
#echo.log $size
#echo.log $time
### 同时sie和time同时为0则退出。
if (( size == 0 && time == 0 )); then
echo.err size and timeis \`0\'
return 1
fi
### get the system date
date_now=`date -s now +%Y%m%d`
### *MUST* 检测cwd是否为回收站,如果不是则exit
### 防止误删其他目录
[[ "$PWD" == */.recycle ]] || { echo -e "\\033[1;31mcwd err\\033[0m"; exit 9; }
[[ "`echo ${RECYCLE_DIR}`" =="$PWD" ]] || { echo -e "\\033[1;31mcwd err\\033[0m";exit 9; }
### get the file in recycle
delFileListTmp="$(du -sb *)"
(( $? != 0 )) && return 1 ## recycle iempty
### read line, and analize it
while read line; do
line_size=${line%% *} ### get size
line_f2=${line#* } ### get file name: field 2
line_date=${line_f2:0:8} ### get del date
#echo.log $(( date_now- line_date ))
### 删除符合条件的文件
if (( line_size >=size*1024*1024 && date_now - line_date >= time)); then
### 没有-f时,提示是否删除
if [[ $forec != true ]]; then
[[ "`echo ${RECYCLE_DIR}`" =="$PWD" ]] || { echo -e "\\033[1;31mcwd err\\033[0m";exit 9; }
yesOrNo remove \`$line_f2\' \
|| continue
fi
### 检测cwd是否为回收站,如果不是则exit
### [[ "$PWD" == */.recycle ]] || { echo -e"\\033[1;31mcwd err\\033[0m"; exit 9; }
### [[ "`echo ${RECYCLE_DIR}`" == "$PWD" ]] || {echo -e "\\033[1;31mcwd err\\033[0m"; exit 9; }
$RM -fr $line_f2 && echo.ok remove \`$line_f2\'
#echo.log "$line_size" $line_date
fi
done <
${delFileListTmp}
EOF
### here document
}
### $$$del files in recycle
print_help()
{
cat <
${0##*/} version $VERSION
Usage: ${0##*/} [-l] [-n] [-r]
${0##*/} -d -empty
${0##*/} -d [-f] [-t] [-s ]
manipulate the recycle
Options:
l - list the deleted file with long format
n - sort the deleted file by name
r - list the deleted whth reverse order
d - delete file mode
empty - empty the recycle
h - Help
t - delete the file\`time' days ago
s - delete file which sizegreater the \`size' megabyte
EOF
}
### read option
option=""
while (( $# >= 1 )); do
case "$1" in
-h|--help) print_help; exit 0;;
-d) option="${option}$1"; shift; break;;
--) shift; break;; #遇到`--',则option结束
-*) option="${option}$1"; shift;;
*) break;;
esac
done
if [[ $option == *-d* ]]; then
#echo.log $option
delFile "$@"
else
listFile
fi
recycle.sh脚本:#!/bin/bash
size=`du -s /root/.recycle/ | awk '{print $1}'`
date=`date +%F`
if [ $size -gt 10485760 ]; then
recycle -d -empty &> /dev/null
echo "
删除日期:$date" >> /var/log/recycle.log
fi