2013-10-02 91 views
1

我有一個腳本下方,做了幾件事情...Unix shell腳本,需要調整腳本的性能?

#!/bin/bash 

# Script to sync dr-xxxx 
# 1. Check for locks and die if exists 
# 2. CPIO directories found in cpio.cfg 
# 3. RSYNC to remote server 
# 5. TRAP and remove lock so we can run again 

if ! mkdir /tmp/drsync.lock; then 
     printf "Failed to aquire lock.\n" >&2 
     exit 1 
fi 
trap 'rm -rf /tmp/drsync.lock' EXIT # remove the lockdir on exit 

# Config specific to CPIO 
BASE=/home/mirxx 
DUMP_DIR=/usrx/drsync 
CPIO_CFG="$BASE/cpio.cfg" 

while LINE=: read -r f1 f2 
do 
    echo "Working with $f1" 
    cd $f1 
    find . -print | cpio -o | gzip > $DUMP_DIR/$f2.cpio.gz 
    echo "Done for $f1" 
done <"$CPIO_CFG" 

RSYNC=/usr/bin/rsynC# use latest version 
RSYNC_BW="4500" # 4.5MB/sec 
DR_PATH=/usrx/drsync 
DR_USER=root 
DR_HOST=dr-xxxx 
I=0 
MAX_RESTARTS=5 # max rsync retries before quitting 
LAST_EXIT_CODE=1 

while [ $I -le $MAX_RESTARTS ] 
do 
    I=$(($I + 1)) 
    echo $I. start of rsync 
    $RSYNC \ 
      --partial \ 
      --progress \ 
      --bwlimit=$RSYNC_BW \ 
      -avh $DUMP_DIR/*gz \ 
       [email protected]$DR_HOST:$DR_PATH 
    LAST_EXIT_CODE=$? 
    if [ $LAST_EXIT_CODE -eq 0 ]; then 
     break 
    fi 
done 

# check if successful 
if [ $LAST_EXIT_CODE -ne 0 ]; then 
    echo rsync failed for $I times. giving up. 
else 
    echo rsync successful after $I times. 
fi 

我想什麼上面的就是變化,此行..

find . -print | cpio -o | gzip > $DUMP_DIR/$f2.cpio.gz 

我期待改變上述這樣它就可以爲CPIO_CFG中的每個入口啓動一個並行進程。我相信我必須在最後使用&?我是否應該實施任何安全預防措施?

是否也可以修改上述命令以包含一個排除列表,我可以通過cpio.cfg文件中的$ f3傳入。

對於下面的代碼..

while [ $I -le $MAX_RESTARTS ] 
do 
    I=$(($I + 1)) 
    echo $I. start of rsync 
    $RSYNC --partial --progress --bwlimit=$RSYNC_BW -avh $DUMP_DIR/*gz [email protected]$DR_HOST:$DR_PATH 
    LAST_EXIT_CODE=$? 
    if [ $LAST_EXIT_CODE -eq 0 ]; then 
     break 
    fi 
done 

這裏同樣的事情,是有可能運行多個線程RSYNC一個在$ dump_dir中發現的。廣州文件/ *。GZ

我覺得上面會大大提高我腳本的速度,這個框相當強壯(AIX 7.1,48內核和192GB RAM)。

謝謝你的幫助。

+2

在發送到後臺的子shell中執行查找,例如'(cd $ f1 && find。-print | cpio -o | gzip> $ DUMP_DIR/$ f2.cpio.gz&)' –

+0

這似乎是朝着正確的方向發展,我該如何做到這一點,所以我一直等到所有人在繼續使用腳本執行rsync之前,先完成CPIO。 – exxoid

+2

'help wait'' wait',好吧,等待所有子流程完成 –

回答

1

原始代碼是一個傳統的批處理隊列。讓我們添加一些精益思想......

實際的工作流程是轉換和傳輸壓縮cpio格式的一組目錄。假設目錄/檔案之間不存在依賴關係,我們應該能夠創建一個用於創建檔案和傳輸的動作。

如果我們把腳本分解成函數,這應該會使我們的意圖更加明顯。

首先,創建一個函數transfer_archive()archive_name和一個可選number_of_attempts作爲參數。這包含您的第二個while循環,但用$archive_name代替$DUMP_DIR/*gz。細節將留作練習。

function transfer_archive { 
    typeset archive_name=${1:?"pathname to archive expected"} 
    typeset number_of_attempts=${2:-1} 

    (
     n=0 
     while 
      ((n++)) 
      ((n<=number_of_attempts)) 
     do 
      ${RSYNC:?} 
       --partial \ 
       --progress \ 
       --bwlimit=${RSYNC_BW:?} \ 
       -avh ${archive_name:?} ${DR_USER:?}@${DR_HOST:?}:${DR_PATH:?} && exit 0 
     done 
     exit 1 
    ) 
} 

我們使用一個子shell,( ... )有兩個出口語句在函數內部。
該函數將返回subshel​​l的退出值,可以是true(rsync成功)或false(嘗試過多)。

然後我們結合起來,與創建存檔:

function create_and_transfer_archive { 
    (
     # only cd in a subshell - no confusion upstairs 
     cd ${DUMP_DIR:?Missing global setting} || exit 

     dir=${1:?directory} 
     archive=${2:?archive} 

     # cd, find and cpio must be in the same subshell together 
     (cd ${dir:?} && find . -print | cpio -o) | 
      gzip > ${archive:?}.cpio.gz || return # bail out 

     transfer_archive ${archive:?}.cpio.gz 
    ) 
} 

最後,主循環將處理所有的目錄並行:

while LINE=: read -r dir archive_base 
do 
    (
     create_and_transfer_archive $dir ${archive_base:?} && 
      echo $dir Done || echo $dir failed    
    ) & 
done <"$CPIO_CFG" | cat 

而是與cat管的,你可以只添加wait在腳本結尾處,但是 它具有捕獲後臺進程的所有輸出的良好效果。

現在,我已經掩蓋了一個重要方面,那就是您可以在 平行中運行的作業數量。這將相當好地擴展,但實際維護一個 作業隊列會更好。超過一定的數字,增加更多的工作將開始減慢速度,並且在那個時候你將不得不添加一個工作計數器和一個工作限制。一旦達到作業限制 ,停止啓動更多create_and_transfer_archive作業,直到過程完成。

如何跟蹤這些工作是一個單獨的問題。

+0

代碼已經過去練習了,我最好添加一些測試。刪除了邏輯中的一些嚴重錯誤。 –