Shell Script 批次搬移檔案+crontab

摘要:Shell Script 批次搬移檔案+crontab

這次遇到一個大困難,

一個資料夾下,有72萬筆檔案資料

光用list,就等半天,等到crash,

 

檔案處理能力也受到資料夾底下有多少檔案影響,

光讀取資料下所有檔案,再做一個一個取出檔案,就會造成執行過長,而程式當掉。(PHP程式)

 

所以我就將72萬筆資料,移至temp檔,

並且寫了shell script ,每次執行,移出1000個檔案至處理資料夾,並再重算一次檔案列表

 

首先先,列出檔案列表到file_list.txt

然後再執行shell script

shell script中移完一千檔案後,再執行一次列出檔案列表到file_list

 

再設crontab,每十分鐘跑一次(也就是我十分鐘要消化1000個檔案的意思)

一小時可以執行6000的話,一天,可以消化,144000個檔案,大概6天後就會消化完。

 

在為了寫這個shell script,還遇到了。

在ubuntu 10以上,默認是dash而不是 bash

在條件判斷上有差,

dash是等於是用=

bash等於是用==

 

另外在字串比較上,會出問題(所以我就沒用字串比對,但還是能做)

 

#!/bin/bash
# batch move file to process
file=/var/https/file_list.txt

process_count=0
lns=`wc -l $file`
lines=`expr "$lns" : '\([0-9]*\)'`
process_limit=1000
count=0

while [ "$process_count" -lt "$process_limit" ] && [ "$count" -lt "$lines" ]
do
   data=$(head -n $count $file | tail -n 1)
   source_file=/var/https/source/$data
   dest_dir=/var/https/process/

   count=$(($count+1))

   file_exists=0
   test -f "$source_file" && file_exists=1

   if [ "$file_exists" = 1 ]
   then
      process_count=$(($process_count+1))
      echo "$count.$data"
      mv $source_file $dest_dir
   else
      echo "$count.$data not found";
   fi

done

ls /var/https/source/ > $file

 

其中大概語法解說如下:

變數設定直接使用

file=/var/https/file_list.txt

or

process_count=0

 

使用時用$

$file

 

條件使用[ ]

在[]中間,變數與符號之間都要固定的空格

[ x = y ]

 

while語法

while [ .... ] 

do

done

 

if語法

if [ ...]

fi

or

if [...]; then

fi

or 

if [...]

then

fi

 

運算

count=$((運算式))

 

執行指令,將結果輸出到變數

data=$(指令)

 

確認檔案是否存在

test -f "$source_file" && file_exists=1

-f 為檔案是否存在  && 為,若存在,則執行什麼。

 

讀取檔案第幾列

data=$(head -n $count $file | tail -n 1)

 

echo 列印資訊

mv 搬移檔案

wc -l 為,計算檔案內容列數

 

最後再下一次

 

ls /var/https/source/ > $file
 
重列出檔案內容至file_list.txt
以加快速度(每跑一個檔案判斷是否存在都會花時間)
 
這寫成move_file.sh檔案後
 
到crontab下十分鐘跑一次shell script即可
0 *    * * *   root    sh /var/https/move_file.sh
 
最後crontab好像實驗失敗了。
決定,在while迴圈最後加入
  mod=$(($process_count%100))
 
   if [ $mod = 0 ] && [ $process_count != 0 ]
   then
      sleep 75
   fi
 
然後將process_limit調到最大或一個段落所需要的數字
 
最後發現,我大概75秒可以處理100個檔案,
所以決定每搬移100個檔案,休息75秒。
 
又發現加快速度的方法,
由於某些檔案特大,導致,很難平衡預估處理時間。
將某些檔案特大的移出去到另一個資料夾下,待之後再處理
 
首先就是要找到哪些檔案特大的
使用
find source -type f -size +10 -printf "%f\n" > big_file.txt
這意思是找出10KB以上的檔案,匯整成一個file list
 
再用上面的shell script改寫就可以將大檔全部移出去。
 
這樣處理小檔就會比較快很多,而且固定。