一個清理指令碼的改進思路
前幾天同事問我一個問題,說在unix環境下有個目錄下的檔案/資料夾太多了,已經報了開始報系統錯誤了,客戶希望能夠定時進行這些目錄的清理。
我連到那個環境去檢視,ls都需要等待很長時間沒有反應,最後嘗試使用find命令,根據檔名來查詢的時候反應才相對要快一些。
同事計劃使用crontab來實現。
使用的命令大體如下:
59 23 1 1,4,7,10 * find /xxxx/tmp -mtime +90 -type d -print|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)T\n" "${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查詢即可。
我連到那個環境去檢視,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)T\n" "${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查詢即可。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-1677250/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如何改進你的指令碼程式指令碼
- shell的引數和指令碼流程改進指令碼
- [20210428]改進pr.sql指令碼.txtSQL指令碼
- [Python] 用python做一個遊戲輔助指令碼,完整思路Python遊戲指令碼
- 【Ubuntu】Ubuntu常用的更新、清理命令指令碼Ubuntu指令碼
- windows系統垃圾清理指令碼Windows指令碼
- 一個改進後的根據STATSPACK來查詢哪段時間內的事務量最大的指令碼指令碼
- 一個分詞指令碼分詞指令碼
- 清理臨時表規範以及指令碼指令碼
- 一個方便 LeetCode 複習的指令碼LeetCode指令碼
- 改進你的c#程式碼的5個技巧(三)C#
- 改進c#程式碼的5個常用的小技巧C#
- 改進你的c#程式碼的5個技巧(四)C#
- elasticsearch 索引清理指令碼及常用命令Elasticsearch索引指令碼
- shell 備份檔案指令碼+自動清理指令碼
- 【BASIS】HANA備份指令碼,Catalog自動清理指令碼
- 向大家分享一個shell指令碼的坑指令碼
- 一個快速檢視trace的小指令碼指令碼
- 共享一個iptables的shell指令碼檔案指令碼
- 一個centos初始化指令碼CentOS指令碼
- 將一個Python指令碼做成一個Windows服務Python指令碼Windows
- blender python api 使用指令碼對一個靜幀 進行全方位渲染PythonAPI指令碼
- 分享工作中常用的一個Git指令碼Git指令碼
- 分享一個提高運維效率的 Python 指令碼運維Python指令碼
- 一個能夠生成 Markdown 表格的 Bash 指令碼指令碼
- 一個網站故障排查的、程式碼更新的簡便指令碼網站指令碼
- 擼一個 iOS 重簽名指令碼iOS指令碼
- 一個“指令碼執行夯死”問題的分析指令碼
- Shell:如何寫一個多選選單的指令碼指令碼
- 6 個方便的 Git 指令碼Git指令碼
- 寫一個Python指令碼刪除一個.py檔案的所有註釋Python指令碼
- 開始你的第一個JMeter指令碼:利用Jmeter錄製指令碼的2種方法彙總JMeter指令碼
- PHP 避免同時執行一個指令碼PHP指令碼
- 如何開發一個油猴(TamperMonkey)指令碼指令碼
- 使用Java實現一個JS指令碼引擎JavaJS指令碼
- 一個簡單的Linux啟動jar包的shell指令碼LinuxJAR指令碼
- 記一個JavaScript圖片輪播思路與程式碼JavaScript
- 一個用於生成大量mac地址的python指令碼MacPython指令碼
- 從零開始 實現一個自己的指令碼引擎指令碼