作者 主題: 備份 ext2/3 filesystem  (閱讀 6229 次)

0 會員 與 1 訪客 正在閱讀本文。

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5389
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
備份 ext2/3 filesystem
« 於: 2003-11-17 12:33 »
之前我們公司的 mail server 是採用 XFS 這個 filesystem, 所以很正常的就是用 xfsdump/xfsrestore 來做備份的處理.
但是幾個星期前, 系統開始出現一些異常的情形, 一個星期內會有兩三次造成 /home 的 partition 突然就不在 mount 的狀態下, 查了 XFS 的相關資料, 好像與某一個 bug 有關, 但這個 bug 目前仍未被解決... 所以, 在經過兩個星期之後, 我們決定換到 ext3 來使用.

這時, 就無法使用 xfsdump 來備份了.
原本一開始考慮用 dump 來備份, 但發現在 linux 2.4 之後, dump 的備份並不保證在活動狀態下的備份是正常可用的. 所以就只好轉由其他的備份方法.

我們試過使用 afio 來備份, 但是發現有時 afio 會突然就不動了, 就換回 cpio 來使用.

我們的備份是接另一台 NAS 機器上去, 然後 mount 到某個路徑, 接著就把備份的資料放到 NAS 上頭. NAS 另外有一個 spool 的路徑是存放上次備份之後到目前的每一封收進來的 email. 因為空間有限, 所以只存放一次的備份資料.

另外, 用 cpio 有點麻煩就是 quota, attr 都無法備份... 這個我們只能用 repquota -a 有 quota 記錄記下來, 至於 attr... 就不管了.

整個備份目前約要 6 小時, 這也是我們不考慮用磁帶的原因... 用磁帶可能會超過一天... :-(

這個檔案說明要備份那些路徑.
/etc/backup/vols.include.cpio
代碼: [選擇]
#
# /etc/backups/vols.include.cpio
# device to backup for cpio
#
# <device>              <session>       <fstype>        <remount>       <mount>
/dev/sda1               root            ext3            1               /
/dev/sda5               usr             ext3            0               /usr
/dev/sda6               var             ext3            0               /var
/dev/vg00/lv00          home            ext3            0               /home


這是備份的指令.
backup_cpio
代碼: [選擇]
#!/bin/sh

# today's string YYYYMMDD
TODAY=`date +%Y%m%d`

# backup file path
BAK_ROOT="/backup/"
DUMP_PATH="${BAK_ROOT}dump/"
BAK_PATH="${DUMP_PATH}dump.${TODAY}"
SPOOL_PATH="${BAK_ROOT}spool/"
MOUNT_PATH="/mnt"

# backup filename ext
BAK_EXT=".cpio.gz"

# cpio command
CPIO_CMD="/bin/cpio"

# zip command
ZIP_CMD="/bin/gzip"

# mount command
MOUNT_CMD="/bin/mount"

# umount command
UMOUNT_CMD="/bin/umount"

# split command
SPLIT_CMD="/usr/bin/split"

# split size
SPLIT_SIZE="1024m"

# cat command
CAT_CMD="/bin/cat"

# find command
FIND_CMD="/usr/bin/find"

# xargs command
XARGS_CMD="/usr/bin/xargs"

# rm command
RM_CMD="/bin/rm"

# ls command
LS_CMD="/bin/ls"
SORT_CMD="/usr/bin/sort"
UNIQ_CMD="/usr/bin/uniq"

# head command
HEAD_CMD="/usr/bin/head"

# wc command
WC_CMD="/usr/bin/wc"

# repquota command
REPQUOTA_CMD="/usr/sbin/repquota"

# config file for backup
VOLS_INCL_FILE="/etc/backup/vols.include.cpio"

if [ -f ${VOLS_INCL_FILE} ]; then
  date
  echo "---------------------------------------------------------------"
  echo "---------------------------------------------------------------"
  echo "---------------------------------------------------------------"
  echo "---------------------------------------------------------------"
  echo "List myself - ${0}"
  echo "---------------------------------------------------------------"
  cat ${0}
  echo "---------------------------------------------------------------"
  echo "End of File!"
  echo "---------------------------------------------------------------"
  echo "---------------------------------------------------------------"
  echo "---------------------------------------------------------------"
  echo "---------------------------------------------------------------"
  echo
  echo
  echo

  echo "---------------------------------------------------------------"
  echo "-------- ! ! ! B U C K U P   S T A R T   N O W ! ! !   --------"
  echo "-------- ! ! ! B U C K U P   S T A R T   N O W ! ! !   --------"
  echo "-------- ! ! ! B U C K U P   S T A R T   N O W ! ! !   --------"
  echo "-------- ! ! ! B U C K U P   S T A R T   N O W ! ! !   --------"
  echo "---------------------------------------------------------------"
  echo
  echo
  echo

  echo "---------------------------------------------------------------"
  echo "Create backup directory: ${BAK_PATH}"
  echo "---------------------------------------------------------------"
  mkdir ${BAK_PATH} 2> /dev/null
  cd ${BAK_PATH}
  echo
  echo

  echo "---------------------------------------------------------------"
  echo "Dump quota report to ${BAK_PATH}/quota.list"
  echo "---------------------------------------------------------------"
  ${REPQUOTA_CMD} -a | ${SORT_CMD} | ${UNIQ_CMD} > ${BAK_PATH}/quota.list
  echo
  echo

  echo "---------------------------------------------------------------"
  echo "Load volume file: ${VOLS_INCL_FILE}"
  echo "---------------------------------------------------------------"
  index=0
  declare -a device_names
  declare -a session_names
  declare -a fstype_names
  declare -a remount_names
  declare -a mount_names
  exec 9<&0
  exec <${VOLS_INCL_FILE}
  while read DEVICE_NAME SESSION_NAME FSTYPE_NAME REMOUNT_NAME MOUNT_NAME
  do
    case "${DEVICE_NAME}" in
      ""|\#*)
         continue;
         ;;
    esac
    device_names[$index]=${DEVICE_NAME}
    session_names[$index]=${SESSION_NAME}
    fstype_names[$index]=${FSTYPE_NAME}
    remount_names[$index]=${REMOUNT_NAME}
    mount_names[$index]=${MOUNT_NAME}
    let "index += 1"
  done
  exec 0<&9 9<&-
  echo "Total ${index} filesystem need to backup!"
  echo
  echo

  num=0
  while [ "$num" -lt "$index" ]; do
    DEVICE_NAME=${device_names[$num]}
    SESSION_NAME=${session_names[$num]}
    FSTYPE_NAME=${fstype_names[$num]}
    REMOUNT_NAME=${remount_names[$num]}
    MOUNT_NAME=${mount_names[$num]}
    let "num += 1"

    date
    OUTPUT_FILE="${BAK_PATH}/${SESSION_NAME}${BAK_EXT}"
    echo "---------------------------------------------------------------"
    echo "Backup ${DEVICE_NAME} [${SESSION_NAME}] to ${OUTPUT_FILE}..."
    echo "If you need to restore data [${SESSION_NAME}], here is the command:"
    echo
    echo " cd ${MOUNT_NAME}"
    echo " ${CAT_CMD} ${OUTPUT_FILE}.* | \ "
    echo " ${ZIP_CMD} -cd | \ "
    echo " ${CPIO_CMD} -idvm"
    echo
    echo "---------------------------------------------------------------"
    echo " *** Start backup..."
    echo " *** change directory to ${MOUNT_NAME}..."
    cd ${MOUNT_NAME}
    if [ "${REMOUNT_NAME}" == "1" ]; then
        echo " *** mount ${DEVICE_NAME} to ${MOUNT_PATH}..."
        ${MOUNT_CMD} -t ${FSTYPE_NAME} ${DEVICE_NAME} ${MOUNT_PATH}
        echo " *** change directory to ${MOUNT_PATH}..."
        cd ${MOUNT_PATH}
    fi
    echo " *** backup command:"
    echo
    echo " ${FIND_CMD} . | \ "
    echo " ${CPIO_CMD} -o -H crc | \ "
    echo " ${ZIP_CMD} -v | \ "
    echo " ${SPLIT_CMD} -b ${SPLIT_SIZE} --verbose - ${OUTPUT_FILE}."
    echo
#    ${FIND_CMD} . | \
#${CPIO_CMD} -o -H crc | \
#${ZIP_CMD} -v | \
#${SPLIT_CMD} -b ${SPLIT_SIZE} --verbose - ${OUTPUT_FILE}.
    if [ "${REMOUNT_NAME}" == "1" ]; then
        echo " *** change directory to ${MOUNT_NAME}..."
        cd ${MOUNT_NAME}
        echo " *** umount ${DEVICE_NAME} from ${MOUNT_PATH}..."
        ${UMOUNT_CMD} ${MOUNT_PATH}
    fi
    echo " *** End backup!"
    echo
  done

  date
  echo "---------------------------------------------------------------"
  echo "Done!"
  echo "---------------------------------------------------------------"
  echo
  echo

fi

date
echo "---------------------------------------------------------------"
echo "Remove old mail fils..."
echo "---------------------------------------------------------------"
cd ${BAK_PATH}
${FIND_CMD} ${SPOOL_PATH} -name 'bccmail.*' -mmin +1440 | \
${XARGS_CMD} ${RM_CMD} -f
echo
echo

date
echo "---------------------------------------------------------------"
echo "Remove old dump backup fils..."
echo "---------------------------------------------------------------"
CNT=`${LS_CMD} -d ${DUMP_PATH}dump.* | ${WC_CMD} -l`
if [ "$CNT" -gt "1" ]; then
  LDIR=`${LS_CMD} -d ${DUMP_PATH}dump.* | ${SORT_CMD} -r | ${HEAD_CMD} -n1`
  FILES=`${LS_CMD} -d ${DUMP_PATH}dump.*`
  for dirname in $FILES; do
    if [ "$dirname" != "$LDIR" ]; then
      echo "$dirname"
      ${RM_CMD} -rf $dirname
    fi
  done
fi
echo
echo

date
exit 0

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5389
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
備份 ext2/3 filesystem
« 回覆 #1 於: 2003-11-17 13:19 »
另外, 順便提一下, 我們老闆要求是 mail server 掛了就算了, 但是收進來的 email 可就不能不見.
也就是我們的 mail server 要確保上次的備份之後, 到了真的發生問題時, 由備份還原後, 這之前所有收過的 email 要能夠重送給所有的使用者.

所以... 我們就寫了一些小程式, 利用 procmail 來備份所有收到的 email.

/etc/procmailrc
代碼: [選擇]
:0 c
*
| /var/spool/bccmail/bccmail_recv.php


把收下來的 email 都利用 bccmail_recv.php 處理.

config.inc.php
代碼: [選擇]
<?php

// root path
$root_path "/var/spool/bccmail/";
$backup_path "/backup/spool/";

// domain
$mydomain "xxx.com";

// smtp server
$smtp_server "localhost";

// smtp port
$smtp_port 10025;

?>



functions.php
代碼: [選擇]
<?php

require_once dirname&#40;$argv[0&#93;&#41; . "/config.inc.php";

function writelog&#40;$buf&#41;
&#123;
  
global $root_path;

  
$file $root_path "log/" "gm_" strftime&#40;"%Y%m%d"&#41; . ".log";
  
$fp fopen&#40;$file, "at"&#41;;
  
if &#40;$fp != 0&#41; &#123;
    
$msg sprintf&#40;"%s [%d&#93; %s\n", strftime&#40;"%T"&#41;, getmypid&#40;&#41;, $buf&#41;;
    
fputs&#40;$fp, $msg&#41;;
    
fclose&#40;$fp&#41;;
  
&#125;
  
return;
&
#125;

function chop_newline&#40;$str&#41;
&#123;
  
return chop&#40;preg_replace&#40;"&#40;\r\n|\n|\r&#41;", "", $str&#41;&#41;;
&#125;

function move_error_msg&#40;$file&#41;
&#123;
  
global $root_path;

  
$old_file $root_path "incoming/" $file;
  
$new_file $root_path "errors/" $file sprintf&#40;".%d", getmypid&#40;&#41;&#41;; 
  
rename&#40;$old_file, $new_file&#41;;
  
unlink&#40;$old_file&#41;;
&#125;

function newtempnam&#40;$dir, $prefix, $postfix&#41;
&#123;
  /* Creates a new non-existant file with the specified post and pre fixes */
    
  
if &#40;$dir[strlen&#40;$dir&#41; - 1&#93; == '/'&#41; &#123;
    
$trailing_slash "";
  &
#125; else &#123;
    
$trailing_slash "/";
  &
#125;
  /*The PHP function is_dir returns true on files that have no extension.
  The filetype function will tell you correctly what the file is */
  
if &#40;!is_dir&#40;realpath&#40;$dir&#41;&#41; || filetype&#40;realpath&#40;$dir&#41;&#41; != "dir"&#41; &#123;
    // The specified dir is not actualy a dir
    
return false;
  &
#125;
  
do &#123;
    
$seed substr&#40;md5&#40;microtime&#40;&#41;.posix_getpid&#40;&#41;&#41;, 0, 8&#41;;
    
$filename $dir $trailing_slash $prefix $seed $postfix;
  &
#125; while &#40;file_exists&#40;$filename&#41;&#41;;
  
$fp fopen&#40;$filename, "w"&#41;;
  
fclose&#40;$fp&#41;;
  
return $filename;
&
#125; 

?>



備份信件的程式.
bccmail_recv.php
代碼: [選擇]
#!/usr/bin/php4 -Cq
<?php

require_once dirname&#40;$argv[0&#93;&#41; . "/config.inc.php";
require_once dirname&#40;$argv[0&#93;&#41; . "/functions.php";

$program basename&#40;array_shift&#40;$argv&#41;&#41;;

$tempFile $root_path 'incoming/' .
            
sprintf&#40;"bccmail.%s.%d.msg", strftime&#40;'%Y%m%d.%H%M%S'&#41;, getmypid&#40;&#41;&#41;;
$fout fopen&#40;$tempFile, "wt"&#41;;
if &#40;$fout == 0&#41; &#123;
  
writelog&#40;"Can't open file&#58; " . $tempFile&#41;;
  
exit&#40;0&#41;;
&#125;

$fp fopen&#40;"php&#58;//stdin", "rt"&#41;;
if &#40;$fp == 0&#41; &#123;
  
writelog&#40;"Can't open stdin"&#41;;
  
fclose&#40;$fout&#41;;
  
unlink&#40;$tempFile&#41;;
  
exit&#40;0&#41;;
&#125;

while &#40;feof&#40;$fp&#41; == 0&#41; &#123;
  
$buf fgets&#40;$fp, 4096&#41;;
  
fputs&#40;$fout, $buf&#41;;
&#125;
fclose&#40;$fp&#41;;
fclose&#40;$fout&#41;;

chmod&#40;$tempFile, 0660&#41;;
writelog&#40;sprintf&#40;"incoming %s", basename&#40;$tempFile&#41;&#41;&#41;;

exit&#40;0&#41;;

?>



把收下來的信搬到 NAS 中.
bccmail_move.php
代碼: [選擇]
#!/usr/bin/php4 -Cq
<?php

require_once dirname&#40;$argv[0&#93;&#41; . "/config.inc.php";
require_once dirname&#40;$argv[0&#93;&#41; . "/functions.php";

error_reporting&#40;0&#41;;

$file $root_path "locks/bccmail.lck";
$fp fopen&#40;$file, "w+"&#41;;
if &#40;$fp == 0&#41; exit;
if &#40;flock&#40;$fp, LOCK_EX + LOCK_NB&#41; == false&#41; &#123;
  
fclose&#40;$fp&#41;;
  
writelog&#40;"lock failed!"&#41;;
  
exit;
&
#125;

$dir $root_path "incoming/";
if &
#40;$dh = opendir&#40;$dir&#41;&#41; &#123;
  
while &#40;&#40;$file = readdir&#40;$dh&#41;&#41; != false&#41; &#123;
    
if &#40;is_file&#40;$dir . $file&#41;&#41; &#123;
      
if &#40;&#40;fileperms&#40;$dir . $file&#41; & 0660&#41; == 0660&#41; &#123;
        
if &#40;substr&#40;$file, 0, 8&#41; == "bccmail."&#41; &#123;
          
process_file&#40;$file&#41;;
        
&#125;
      
&#125;
    
&#125;
  
&#125;
  
closedir&#40;$dh&#41;;
&#125;

flock&#40;$fp, LOCK_UN&#41;;
fclose&#40;$fp&#41;;

exit;

function 
process_file&#40;$file&#41;
&#123;
  
global $root_path;
  global 
$backup_path;

  
$oldname $root_path 'incoming/' $file;
  
$fp fopen&#40;$oldname, 'rt'&#41;;
  
if &#40;$fp == 0&#41; &#123;
    
writelog&#40;"Can't open file&#58; " . $oldname&#41;;
    
return 0;
  &
#125;

  
$hh substr&#40;$file, 17, 2&#41;;
  
$mm substr&#40;$file, 19, 2&#41;;
  
$file_dir $backup_path $mm '/' $hh '/';
  
$newname newtempnam&#40;$file_dir, $file . '.', '.gz'&#41;;
  
$fout gzopen&#40;$newname, 'wb9'&#41;;
  
if &#40;$fout == 0&#41; &#123;
    
fclose&#40;$fp&#41;;
    
writelog&#40;"Can't open file&#58; " . $newname&#41;;
    
return 0;
  &
#125;

  
while &#40;feof&#40;$fp&#41; == 0&#41; &#123;
    
$buf fgets&#40;$fp, 4096&#41;;
    
gzputs&#40;$fout, $buf&#41;;
  
&#125;
  
fclose&#40;$fp&#41;;
  
gzclose&#40;$fout&#41;;

  
unlink&#40;$oldname&#41;;
  
writelog&#40;"zip to $mm/$hh/" . basename&#40;$newname&#41;&#41;;
  
return 1;
&
#125;

?>



將信件重送的指令.
bccmail_resend.sh
代碼: [選擇]
#!/bin/sh

#
# execute the following command to re-send mail
#
#find /backup/spool/ -name 'bccmail.*.gz' | /var/spool/bccmail/bccmail_send.php

exit 0


bccmail_send.php
代碼: [選擇]
#!/usr/bin/php4 -Cq
<?php

require_once dirname&#40;$argv[0&#93;&#41; . "/config.inc.php";
require_once dirname&#40;$argv[0&#93;&#41; . "/functions.php";

error_reporting&#40;0&#41;;

$fp fopen&#40;"php&#58;//stdin", "rt"&#41;;
if &#40;$fp == 0&#41; &#123;
  
writelog&#40;"Can't open stdin"&#41;;
  
exit&#40;0&#41;;
&#125;

while &#40;feof&#40;$fp&#41; == 0&#41; &#123;
  
$buf chop_newline&#40;fgets&#40;$fp, 4096&#41;&#41;;
  
if &#40;is_file&#40;$buf&#41;&#41; &#123;
    
process_file&#40;$buf&#41;;
  
&#125;
&#125;
fclose&#40;$fp&#41;;

exit;

function 
process_file&#40;$file&#41;
&#123;
  
global $root_path;
  global 
$smtp_server;
  global 
$smtp_port;
  global 
$mydomain;

  
$total filesize&#40;$file&#41;;

  
$fp gzopen&#40;$file, "r"&#41;;
  
if &#40;$fp == 0&#41; &#123;
    
writelog&#40;"can't open file&#58; " . $file&#41;;
    
return 0;
  &
#125;
  
writelog&#40;sprintf&#40;"processing %s", $file&#41;&#41;;

  // from
  
$buf chop_newline&#40;gzgets&#40;$fp, 4096&#41;&#41;;
  
list&#40;$token, $from, $skip&#41; = split&#40;" ", $buf, 3&#41;;
  
if &#40;$token != 'From'&#41; &#123;
    
writelog&#40;"'From' not found!"&#41;;
    
gzclose&#40;fp&#41;;
    
return 0;
  &
#125;
  
writelog&#40;sprintf&#40;"From&#58; %s", $from&#41;&#41;;

  // Return-Path&#58;
  
$buf chop_newline&#40;gzgets&#40;$fp, 4096&#41;&#41;;
  
list&#40;$token, $return_path, $skip&#41; = split&#40;" ", $buf, 3&#41;;
  
if &#40;$token != 'Return-Path&#58;'&#41; &#123;
    
writelog&#40;"'Return-Path&#58;' not found!"&#41;;
    
gzclose&#40;fp&#41;;
    
return 0;
  &
#125;

  // delivered-to
  
$buf chop_newline&#40;gzgets&#40;$fp, 4096&#41;&#41;;
  
list&#40;$token, $to, $skip&#41; = split&#40;" ", $buf, 3&#41;;
  
if &#40;$token != 'Delivered-To&#58;'&#41; &#123;
    
writelog&#40;"'Delivered-To&#58;' not found!"&#41;;
    
gzclose&#40;fp&#41;;
    
return 0;
  &
#125;
  
writelog&#40;sprintf&#40;"To&#58; %s", $to&#41;&#41;;

  
$smtp fsockopen&#40;$smtp_server, $smtp_port, $errno, $errstr, 30&#41;;
  
if &#40;$smtp == 0&#41; &#123;
    
writelog&#40;sprintf&#40;"connect to %s&#58;%d failed&#58; &#40;%d&#41; %s",
$smtp_server$smtp_port,
$errno$errstr&#41;&#41;;
    
gzclose&#40;$fp&#41;;
    
return 0;
  &
#125;

  // server response
  
while &#40;1&#41; &#123;
    
$msg fgets&#40;$smtp, 256&#41;;
    
if &#40;substr&#40;$msg, 0, 3&#41; != "220"&#41; &#123;
      
writelog&#40;sprintf&#40;"error &#40;220&#41;&#58; %s", chop_newline&#40;$msg&#41;&#41;&#41;;
      
fclose&#40;$smtp&#41;;
      
gzclose&#40;fp&#41;;
      
return 0;
    &
#125;
    
if &#40;substr&#40;$msg, 3, 1&#41; != "-"&#41; break;
    // multi-line response
  
&#125;

  
fputs&#40;$smtp, "HELO " . $mydomain . "\n"&#41;;
  // server response
  
while &#40;1&#41; &#123;
    
$msg fgets&#40;$smtp, 256&#41;;
    
if &#40;substr&#40;$msg, 0, 3&#41; != "250"&#41; &#123;
      
writelog&#40;sprintf&#40;"error &#40;250&#41;&#58; %s", chop_newline&#40;$msg&#41;&#41;&#41;;
      
fclose&#40;$smtp&#41;;
      
gzclose&#40;$fp&#41;;
      
return 0;
    &
#125;
    
if &#40;substr&#40;$msg, 3, 1&#41; != "-"&#41; break;
    // multi-line response
  
&#125;

  
fputs&#40;$smtp, "MAIL FROM&#58;<" . $from . ">\n"&#41;;
  // server response
  
while &#40;1&#41; &#123;
    
$msg fgets&#40;$smtp, 256&#41;;
    
if &#40;substr&#40;$msg, 0, 3&#41; != "250"&#41; &#123;
      
writelog&#40;sprintf&#40;"error &#40;250&#41;&#58; %s", chop_newline&#40;$msg&#41;&#41;&#41;;
      
fclose&#40;$smtp&#41;;
      
gzclose&#40;$fp&#41;;
      
return 0;
    &
#125;
    
if &#40;substr&#40;$msg, 3, 1&#41; != "-"&#41; break;
    // multi-line response
  
&#125;

  
fputs&#40;$smtp, "RCPT TO&#58;<" . $to . ">\n"&#41;;
  // server response
  
$ok 1;
  while &
#40;1&#41; &#123;
    
$msg fgets&#40;$smtp, 256&#41;;
    
if &#40;substr&#40;$msg, 0, 3&#41; != "250"&#41; &#123;
      
$ok 0;
      
writelog&#40;sprintf&#40;"error &#40;250&#41;&#58; %s", chop_newline&#40;$msg&#41;&#41;&#41;;
    
&#125;
    
if &#40;substr&#40;$msg, 3, 1&#41; != "-"&#41; break;
    // multi-line response
  
&#125;

  
if &#40;$ok == 0&#41; &#123;
    
fputs&#40;$smtp, "QUIT\n"&#41;;
    
fclose&#40;$smtp&#41;;
    
writelog&#40;sprintf&#40;"RCPT TO&#58; reject!"&#41;&#41;;
    
gzclose&#40;$fp&#41;;
    
move_error_msg&#40;basename&#40;$file&#41;&#41;;
    
return 0;
  &
#125;

  
fputs&#40;$smtp, "DATA\n"&#41;;
  // server response
  
while &#40;1&#41; &#123;
    
$msg fgets&#40;$smtp, 256&#41;;
    
if &#40;substr&#40;$msg, 0, 3&#41; != "354"&#41; &#123;
      
writelog&#40;sprintf&#40;"error &#40;354&#41;&#58; %s", chop_newline&#40;$msg&#41;&#41;&#41;;
      
fclose&#40;$smtp&#41;;
      
gzfclose&#40;$fp&#41;;
      
return 0;
    &
#125;
    
if &#40;substr&#40;$msg, 3, 1&#41; != "-"&#41; break;
    // multi-line response
  
&#125;

  
while &#40;gzeof&#40;$fp&#41; == false&#41; &#123;
    
$msg chop_newline&#40;gzgets&#40;$fp, 4096&#41;&#41;;
    
if &#40;$msg == "."&#41;
      
fputs&#40;$smtp, "..\n"&#41;;
    
else
      
fputs&#40;$smtp, "$msg\n"&#41;;
  
&#125;

  
fputs&#40;$smtp, ".\n"&#41;;
  // server response
  
while &#40;1&#41; &#123;
    
$msg fgets&#40;$smtp, 256&#41;;
    
if &#40;substr&#40;$msg, 0, 3&#41; != "250"&#41; &#123;
      
writelog&#40;sprintf&#40;"error &#40;250&#41;&#58; %s", chop_newline&#40;$msg&#41;&#41;&#41;;
      
fclose&#40;$smtp&#41;;
      
gzclose&#40;$fp&#41;;
      
return 0;
    &
#125;
    
if &#40;substr&#40;$msg, 3, 1&#41; != "-"&#41; break;
    // multi-line response
  
&#125;

  
fputs&#40;$smtp, "QUIT\n"&#41;;
  
fclose&#40;$smtp&#41;;

  
gzclose&#40;$fp&#41;;
  
unlink&#40;$file&#41;;

  
writelog&#40;sprintf&#40;"post from %s to %s, size=%d",
               
$from$to$total&#41;&#41;;
  
return 1;
&
#125;

?>



原本是在備份信件的時就直接壓縮存到 NAS 中, 因為 NAS 的運作有點兒慢, 所以就把這個動作分開來處理.

duncanlo

  • SA 苦力組
  • 俺是博士!
  • *****
  • 文章數: 7312
    • 檢視個人資料
備份 ext2/3 filesystem
« 回覆 #2 於: 2003-11-17 20:24 »
我之前的公司是作工程的,
他們對外面寄來的信特別重視,
因為怕某些工程師忘了處理,
所以要求必須要作完整的備份.

假如用sendmail的alias時,
因為信粉多而且通常有附檔,
所以單一MailBox檔案可能會變的非常大,
改用QMail後,
檔案是變小了,
是數量就增加粉多,
超吃inode的.

假如用outlook這類的pop3軟體去收信,
不是軟體當了就是等超久才能找到某封信.

我本來有找到一個perl module,
可以把信轉到mysql內,
可是mysql似乎不是很適合這種資料倉儲的環境.
(雖然有很多商業系統可以作到這些功能)

我想問的是,
貴公司會不會遇到這種問題,
有沒有什麼比較佳解決的方式,
還是貴公司的mail備份機制尚不會遇到這個問題.

twu2

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 5389
  • 性別: 男
    • 檢視個人資料
    • http://blog.teatime.com.tw/1
備份 ext2/3 filesystem
« 回覆 #3 於: 2003-11-17 21:49 »
因為 webmail 用 openwebmail... 所以只能選用一般 unix 的信件格式... 就是一個大大的檔案.
不過沒開放 pop3, 大家都用 imap4 or webmail, 返正信收一收就分到其他的 folder, 對於 inbox, 如果常整理, 並不會太大.

或許等 openwebmail 支援 maildir 格式時, 會想辦法改用 maildir 吧.