一個清理指令碼的改進思路(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*
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查詢即可。