linux下建立回收站防止誤刪除及定期清空

功能描述:

我們都知道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 <time>] [-s <size>]
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 <time> -  delete the file `time' days ago
  s <size> - 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 > $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 <<-EOF
        ${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 > $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  <<< "${fileList}" ###here string
### 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 <<-EOF
                ${delFileListTmp}
        EOF
        ### here document
}
### $$$del files in recycle
print_help()
{
 cat <<-EOF
        ${0##*/} version $VERSION
        Usage: ${0##*/} [-l] [-n] [-r]
               ${0##*/} -d -empty
               ${0##*/} -d [-f] [-t<time>] [-s <size>]
        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 <time> -  delete the file\`time' days ago
          s <size> - 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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章