1. 程式人生 > 其它 >一個清理指令碼的改進思路(r5筆記第51天)

一個清理指令碼的改進思路(r5筆記第51天)

前幾天同事問我一個問題,說在unix環境下有個目錄下的檔案/資料夾太多了,已經報了開始報系統錯誤了,客戶希望能夠定時進行這些目錄的清理。 我連到那個環境去檢視,ls都需要等待很長時間沒有反應,最後嘗試使用find命令,根據檔名來查詢的時候反應才相對要快一些。 同事計劃使用crontab來實現。 使用的命令大體如下: 59 23 1 1,4,7,10 * find /xxxx/tmp -mtime +90 -type d -print|xargs rm –rf

其中關鍵的地方是使用了xargs,根據我之前的測試,發現xargs在大批量的檔案過濾時,效果還是不能讓人滿意的,而且在命令最後接入rm -rf,如果出現什麼紕漏,那影響可就大了。 所以開始我是不建議直接這麼用的。

根據分析,發現其實在幾個目錄下藥刪除的檔案目錄命名規則都比較固定。 比如是20141201的日誌,命名就類似下面的形式。 container-default-instanceJob-201412001_xxxxxx 其中變化的部分主要是時間的部分,所以決定使用find -name的方式效果要好一些,但是find -name結合xargs的時候如果檔案比較多,刪除的時候還是有問題,而且rm -rf的潛在隱患還是有。 一種比較直接的方式就是我們生成對應的檔案目錄名,如果匹配,則刪除,如果不匹配,也不會報出錯誤。 比方說我們根據需要刪除字2014年12月1日起某些天的記錄,則可以手工指定對應的檔名和時間戳。 rm -rf /xxxx/tmp/container-default-instanceJob-20141202* rm -rf /xxxx/tmp/container-default-instanceJob-20141203* rm -rf /xxxx/tmp/container-default-instanceJob-20141204* rm -rf /xxxx/tmp/container-default-instanceJob-20141205* rm -rf /xxxx/tmp/container-default-instanceJob-20141206* rm -rf /xxxx/tmp/container-default-instanceJob-20141207*

這種方式會避免不少的問題,刪除速度是沒有問題的。而且可以避免很多意外的情況。 但是缺點就是太手動了,感覺沒什麼技術含量。 我們來把這個過程自動化一下。能夠動態生成對應的檔案目錄名,每次執行之後都會把基準的時間重新調整。 比如我們刪除60天的記錄,假設起始時間為20141201,則60天后就是20150130,第二次執行這個命令就會把起始時間自動調整為20150130,終止時間就是20150331了。 第一次執行命令後,生成的刪除命令為: rm -rf /xxxx/tmp/container-default-instanceJob-20141202* .... rm -rf /xxxx/tmp/container-default-instanceJob-20150130*
第二次運行同樣的命令,生成的刪除命令為: rm -rf /xxxx/tmp/container-default-instanceJob-20150130* .... rm -rf /xxxx/tmp/container-default-instanceJob-20150331* 這種方式就比較動態了,而且刪除起來也是一個很穩定的過程。 首先採用shell的形式寫了如下的指令碼。

GetIncDate()
{
 L_DAY=$1
 days=$2
 L_TODAY=$(printf "%(%Y%m%d)Tn" "${L_DAY}0000 + ${days} day")
 print ${L_TODAY}
}
 
function gen_clean_script
{
for i in {1..$duration}
do
echo 'rm -rf /xxxxx/tmp/container-default-instanceJob-'`GetIncDate $initdate $i` >> gen_clean_script.sh
done
}

這種方式基於Linux環境實現,可以靈活的使用date命令的選項進行時間的計算。 但是問題來了,在Linux下可行的方案在unix底下沒有那些個命令選項。也就是說這個shell指令碼在unix下執行不了。問題還是基於一些命令的相容性。 最後嘗試把時間的計算用sql來實現,這樣也不會存在平臺的限制。 寫出的基於sql計算時間的shell指令碼如下:

function gen_clean_script
{
conn_str=$3
print "
conn  $conn_str
set linesize 200
set serveroutput on
set feedback off
begin
for i in 1..$2 loop
dbms_output.put_line('rm -rf /xxxxx/tmp/container-default-instanceJob-'||to_char(to_date('$1','yyyymmdd')+i,'yyyymmdd')||'*');

end loop;
end;
/
" |sqlplus -s /nolog > gen_clean_script.sh

}

function get_next_date
{
conn_str=$3
print "
conn  $conn_str
set serveroutput on
set feedback off
begin
dbms_output.put_line(to_char(to_date('$1','yyyymmdd')+$2,'yyyymmdd'));

end;
/
" |sqlplus -s /nolog > init.date
}


conn_str=n1/n1@xxxx
duration=60
if [[ ! -s init.date ]] ;then
echo '***********************************************'
echo '20141201' > init.date
initdate=20141201
echo $initdate
echo '***********************************************'
else
initdate=`cat init.date`
fi

gen_clean_script $initdate $duration $conn_str
get_next_date $initdate $duration $conn_str


cat gen_clean_script.sh 

問題的解決就有了一種相對比較可行的思路,這種方案有一個缺點就是需要連線資料庫,不過對於資料庫使用者的配置沒有其它要求,只要能執行sql查詢即可。