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 <パスワード>

[卒業研究] 卒業論文の書き方

卒業論文は卒業研究の単なる作業メモではなく,文章として「読める」ものでなければならない.

つまり,行った事や結果の羅列ではなく,まず卒業研究として行った事の,そもそもの妥当性や事情を説明した上で,内容の説明を行い,最後に結果や今後の展望について纏める必要がある.

これによって卒業研究が世の中でどのような位置付けにあるかが,読者に伝わる.

具体的には,起承転結を意識して記述すると良い.

また論文を書く際の心構えについては,こちらのサイトが参考になる.

2010年12月1日水曜日

[SA-4-5] ファイル差分バックアップ(Shell Script)

内部でrcsコマンドを使用しているため,事前にrcsをインストール
#yum install rcs

backup_etc.bash
#!/bin/bash
# usage:
# 1. BACKUP_ROOT(/var/tmp/backup) に、バックアップをとりたいファイルへの
#    シンボリックリンクを張ります
#    例: cd ${BACKUP_ROOT}; ln -s /etc/nsswitch.conf
# 2. backup_etc.bash を引数なしで実行します

# バックアップ作成用ディレクトリ
BACKUP_ROOT="/var/tmp/backup"

# バックアップ作成用ディレクトリ内の最大の深さ
MAX_DEPTH=2

# RCS のチェックインメッセージ(空白/タブを入れないこと)
CHECKIN_MSG="Automatic_RCS_backup"

# 引数に応じて、
#   「ディレクトリの深さ + 1」
# を表す glob パターンを生成する
# usage: make_pattern <depth>
# ex. make_pattern 1 → "*/*"
make_pattern () {
    local -i i=$1
    local pattern="*"

    while [ $i -gt 0 ]; do
        pattern="${pattern}/*"
        let "i--"
    done

    echo "${pattern}"
}

# RCS の ci (チェックイン)コマンドを使って差分バックアップをとります
# 引数: なし
make_rcs_backup () {
    local dir
    local pattern=$(make_pattern ${MAX_DEPTH})
    local lock_user
    local file
    local msg

    # CHECKIN_MSG が設定されている場合だけ
    # msg 変数の内容を -m"メッセージ" とします
    msg=${CHECKIN_MSG:+"-m${CHECKIN_MSG}"}

    # BACKUP_ROOT に移動
    pushd "${BACKUP_ROOT}" > /dev/null

    # RCS という名前以外のディレクトリを探す
    # ※BSDシステムでは find -x . -type d ... とすること
    find . -xdev -type d \( -name RCS -prune -o -print \) | \
        while read dir; do
            case "${dir}" in
                ${pattern})
                    # MAX_DEPTH を越えたものは対象外
                    continue
                    ;;
            esac

     # 対象ディレクトリに移動
            cd "${BACKUP_ROOT}/${dir}"
     if [ ! -d RCS ]; then
  mkdir RCS
            fi

     # ファイルごとに ci を実行
            for file in *; do
  if [ -d "${file}" ]; then
      continue
  fi

  ci ${msg} -l "${file}" < /dev/null > /dev/null 2>&1
  if [ $? -ne 0 ]; then
      echo "backup FAIL: ${file}" 1>&2
  fi
     done
        done            

    # 最初いたディレクトリに戻る
    popd > /dev/null
}

make_rcs_backup

もしくは,rsyncを用いて差分バックアップを取る方法もある.
この場合,変更なきファイルはハードリンクとし,前回のバックアップから変更があったファイルのみ実際のコピーを行う為,バックアップの容量圧縮する事が可能となる.
rsync -av --delete --link-dest=../[過去] [現在]/ [保存名]

[MA-11-1] 新uploader

今後は,こちらのアップローダーを利用してください.

[memo] 安全なSQLの呼び出し方 (IPA)

情報処理推進機構(IPA)が公開している,SQLインジェクション攻撃等を回避する為のWebアプリケーションの安全な実装方法を解説した資料をベースに,深刻な被害が発生しがちなSQLインジェクション等について解説する.

ダウンロード(PDF)