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 
               $DR_USER@$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 文件中的 $f 3 传入的排除列表。

对于下面的代码..

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

同样的事情在这里,是否可以运行多个 RSYNC 线程.gz一个用于 $DUMP_DIR/* 中找到的文件.gz

我认为以上内容会大大提高我的脚本的速度,盒子相当强大(AIX 7.1、48 个内核和 192GB RAM(。

谢谢你的帮助。

原始代码是传统的批处理队列。让我们添加一点精益思维...

实际的工作流程是以压缩的 cpio 格式转换和传输一组目录。 假设目录/存档之间没有依赖关系,我们应该能够创建一个用于创建存档和传输的单个操作。

如果我们将脚本分解为函数会有所帮助,这应该使我们的意图更加明显。

首先,创建一个函数transfer_archive()archive_name和可选number_of_attempts作为参数。 这包含您的第二个while循环,但将$DUMP_DIR/*gz替换为 $archive_name 。 细节将留作练习。

 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
     )
 }

在函数内部,我们使用了一个子外壳,(... )有两个退出语句。
该函数将返回子外壳的退出值,即 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作业,直到进程完成。

如何跟踪这些工作是一个单独的问题。

最新更新