2010年12月2日木曜日

[SA-4-6] FTPによるファイル送信(Shell Script)

バックアップしたファイルは,そのままサーバ上に保管するのではなく,ロケーションの異なるサーバにコピーすると,より安全である(ディザスタリカバリ).
そこで,定期的にファイルの転送をサーバに行わせるために,ファイルの転送を自動的に行うShellScriptを作成する.

内部でFTPクライアントを使用しているため,事前にFTPクライアントをインストール
#yum install ftp

また,ファイルの送信先サーバがFTPサーバとしてもどう際してる必要がある為,ローカルで動作確認を行う為には,FTPサーバをインストールする必要がある.
#yum install vsftpd
#service vsftpd start
#chkconfig vsftpd on

転送試験に使用するファイル用意
$vi ~/script/test.txt

転送試験の際の受信用ディレクトリ用意
$mkdir ~/script/receive


ftp_put.bash
#!/bin/bash

################################################
# 設定
################################################
# 送信するファイル
L_FILE="/home/(ユーザー名)/script/test.txt"
# 送信先ホスト
R_HOST="localhost"
# 送信先ディレクトリ
R_DIR="/home/(ユーザー名)/script/receive"

################################################
# 関数
################################################
# ファイルを FTP で送信する
# 入力
#   $1: 送信するファイル名
#   $2: 送信先ホスト名
#   $3: 送信先ディレクトリ
#   $4: 一時作業ディレクトリ
# 終了ステータス
#   0: 成功
#   1: 失敗
ftp_put_file () {
    local l_file="$1"
    local r_host="$2"
    local r_dir="$3"
    local tmpdir="$4"

    local filename="${l_file##*/}"
    local r_file="${r_dir}/${filename}"
    local log="${tmpdir}/ftp_put.log"

    local status

    # FTP を実行
    ftp -v -g "${r_host}" <<-EOF > "${log}" 2>&1
 quote NOOP
 put "${l_file}" "${r_file}"
 quote NOOP
 EOF

    # 結果チェック(1)
    status=$?
    if [ "${status}" -ne 0 ]; then
 return "${status}"
    fi

    # 結果チェック(2)
    ftp_chk_transfer "${log}"

    # 失敗した場合にはエラーメッセージ(かもしれないもの)
    # の最後の3行を標準エラー出力に表示
    if [ $? -ne 0 ]; then
 grep -v '^[123][0-9][0-9]' "${log}" | tail -3 1>&2
 return 1
    fi

    return 0
}

# FTP によるファイル送受信を、ログからチェックする
# 入力
#   $1: 転送ログ
# 終了ステータス
#   0: 転送成功
#   1: 転送失敗
ftp_chk_transfer () {
    local state="START"
    local code
    local msg_first
    local msg_rest

    # ログファイルを読みながらのループ
    while read code msg_first msg_rest; do
 case "${state}" in
 # 最初の NOOP 実行前
 START)
     if [ "${code} ${msg_first}" == "200 NOOP" ]; then
  state=TRANS_START
     fi
     ;;
        # PASV/PORT でのコネクション確立中
 TRANS_START)
     case "${code}" in
     125 | 150)
  state=TRANS_DATA
  ;;
     200)
  if [ "${msg_first}" == NOOP ]; then
      # 想定外
      state="ERROR"
      break
  fi
  ;;
     esac
     ;;
 # データ転送中
 TRANS_DATA)
     case "${code}" in
     226 | 250)
  # 転送成功
  state=SUCCESS
  break
  ;;
     200)
  if [ "${msg_first}" == NOOP ]; then
      # 想定外
      state="ERROR"
      break
  fi
  ;;
     esac
     ;;
 esac
    done < "$1"

    # 以下の test の結果が関数の終了ステータス
    [ "${state}" == "SUCCESS" ]
    return
}

################################################
# メイン処理
################################################
# util_common.bash を読み込む(make_tmp_dir/clean_tmp_dir)
FILE_UTIL=util_common.bash
. "${FILE_UTIL}" 2> /dev/null \
    || . "${0%/*}/${FILE_UTIL}" 2> /dev/null
if [ $? -ne 0 ]; then
    echo "Can't load ${FILE_UTIL}!" 1>&2
    exit 1
fi

# 作業ディレクトリの作成
tmpdir=$(make_tmp_dir 2>/dev/null)
if [ $? -ne 0 ]; then
    echo "Can't create temporary directory!" 1>&2
    exit 2
fi

# trap の設定
SIGNALS="HUP INT QUIT PIPE TERM"
trap "{ clean_tmp_dir; exit; }" ${SIGNALS}

ftp_put_file \
    "${L_FILE}" \
    "${R_HOST}" \
    "${R_DIR}" \
    "${tmpdir}"

status=$?

# 作業ディレクトリの削除と trap 解除
clean_tmp_dir
trap ${SIGNALS}

# スクリプトの終了ステータスを
#  ftp_put_file の終了ステータスに
exit ${status}

.netrc(設定ファイル)
machine localhost login <ユーザー名> password <パスワード>

0 件のコメント: