皆さん、プログラムのデプロイはどうしていますか??
通常scpやrsync、その他のデプロイツールを使用すれば、簡単かつ確実に運用サーバにプログラムを配備することが出来ます。
しかし、利用するサーバによって、FTP接続しか出来ない場合があります。
LinuxのFTPコマンドは非常に使い勝手が悪く、ディレクトリ配下を全てアップロードする等という事が出来ません。
また、ソースコードをローカルにダウンロードしてFTPソフトウェアでアップロードする方法は効率が悪く、アップロードしたく無いファイル等は事前に削除するなど、非常にミスを誘発しそうな作業です。
サーバ上のコマンド一発でFTPアップロードが出来たら、確実に便利です。
今回は、サーバ間でFTPアップロードが出来るシェルスクリプトを作成してみました。
NcFTP Clientをインストール
まず、NcFTPという通常のFTPコマンドより使い易いコマンドを利用します。※NcFTPは Download NcFTP Client からインストールしてください。
ソースコードからインストールする場合
# ソースコードをダウンロードします。 [user@centos ~]$ wget ftp://ftp.ncftp.com/ncftp/ncftp-3.2.4-src.tar.gz # tarボールを解凍します。 [user@centos ~]$ tar zxvf ncftp-3.2.4-src.tar.gz # Makeして実行ファイルを生成します。 [user@centos ~]$ cd ncftp-3.2.4 [user@centos ncftp-3.2.4]$ ./configure [user@centos ncftp-3.2.4]$ make # インストールします。 # デフォルトで /usr/local/bin に配置されます。 [user@centos ncftp-3.2.4]$ make install
FTPアップロード シェルスクリプト
このスクリプトは、expectという会話形式通信を自動的に行うことができるコマンドを利用します。rsyncの–exclude-fromオプションのように、アップロードしたくないリストを記述したファイルを外部で管理する事も出来ます。
deploy.sh
#!/bin/bash
#
# deploy.sh
#
# 使用方法 : ./deploy.sh
# 設定ファイル: deploy.exclude.txt (非アップロードファイルがある場合のみ)
#
## Config ------------------------------------------------------
FTP_HOST='ftp.xxxxx.co.jp' # FTPホスト名
FTP_USER='username' # FTPユーザー名
FTP_PASS='password' # FTPパスワード
SRC_DIR='/home/user/appname/' # アップロード元ローカルディレクトリ
DEST_DIR='/' # アップロード先FTPサーバのログインディレクトリ
EXCLUDE_FILE='deploy.exclude.txt' # 非アップロード設定ファイル
## Parse Exclude File -------------------------------------------
parse_exclude_file()
{
if [ ! -f $EXCLUDE_FILE ]; then
return
fi
echo '[ Exclude Pattern ]'
local base_ifs="${IFS}"
IFS='
'
local file=(`cat $EXCLUDE_FILE`)
IFS="${base_ifs}"
local line
for line in "${file[@]}"
do
if echo $line | grep -q '^#'; then
continue
fi
if [ -z "${line}" ]; then
continue
fi
line=`echo $line | awk '{print $1}'`
echo $line
line=`echo $line | \
sed 's:\.:\\\.:' | \
sed 's:\*:\.*:' | \
sed 's:^/:\^/:'`
if [ -n "${EXCLUDE_PATTERN}" ]; then
line=" ${line}"
fi
EXCLUDE_PATTERN="${EXCLUDE_PATTERN}${line}"
done
echo
}
## Create Deploy List ------------------------------------------
create_deploy_list()
{
echo '[ Deploy Target File ]'
local list=`find $SRC_DIR | \
grep -v CVS | \
grep -v .svn | \
grep -v .git`
local file target
for file in $list
do
if [ -d $file ]; then
file="${file}/"
fi
target=`echo $file | sed "s:${SRC_DIR}::"`
if [ -z "${target}" -o "${target}" = '/' ]; then
continue
fi
if is_exclude $target; then
continue
fi
echo $target
echo $target >>$TEMP_FILE
done
echo
}
## Is Exclude ---------------------------------------------------
is_exclude()
{
local target=$1
local pattern
for pattern in $EXCLUDE_PATTERN
do
if echo "/${target}" | grep -q $pattern; then
return 0
fi
done
return 1
}
## FTP Upload --------------------------------------------------
ftp_upload()
{
local base_ifs="${IFS}"
IFS='
'
local list=`cat $TEMP_FILE`
IFS="${base_ifs}"
cd $SRC_DIR
expect - <<EOF
set timeout -1
spawn ncftp -u $FTP_USER -p $FTP_PASS $FTP_HOST
expect "ncftp*>"
send "cd $DEST_DIR\r"
foreach file {$list} {
expect "ncftp*>"
if {[regexp {.*\/\$} \$file]} {
send "mkdir \$file\r"
} else {
send "put -fz \$file \$file\r"
}
}
expect "ncftp*>"
send "exit\r"
EOF
echo
}
## Clean -------------------------------------------------------
clean()
{
if [ -f "${TEMP_FILE}" ]; then
rm -f $TEMP_FILE
fi
}
## Main --------------------------------------------------------
EXCLUDE_PATTERN=''
parse_exclude_file
if [ $? -ne 0 ]; then
echo "[Error] Failed to parse the '${EXCLUDE_FILE}'." >&2
exit $?
fi
TEMP_FILE=`mktemp`
create_deploy_list
if [ $? -ne 0 ]; then
echo '[Error] Failed to create the source list.' >&2
clean
exit $?
fi
echo -n "Do you upload it? [y/n]: "
read ANSWER
if [ "${ANSWER}" != 'y' ]; then
echo 'Canceled the upload.'
exit
fi
ftp_upload
if [ $? -ne 0 ]; then
echo '[Error] Upload failed.' >&2
clean
exit $?
fi
clean
echo '----'
echo "'${FTP_HOST}' deploy success!"
deploy.exclude.txt
# # deploy exclude # # 除外ファイルの設定(除外したいファイルがある場合のみ) # deploy.exclude.txtファイルに除外パターンを記述する # 例) # *.txt *.txt と一致する全てのファイル名を除外 # /foo/ ルートにある foo ディレクトリを除外 # bar/*.log bar ディレクトリ内の *.log に一致するファイルを除外 # # ルートにあるappディレクトリを除外 /app/ # コメントも書けます # ログファイルを除外 *.log
実行例
以下のようなディレクトリ構成があるとします。app/ app/1.txt src/ src/2.txt var/ var/3.log
deploy.sh を実行すると、src/、src/2.txt、var/ のみがアップロード対象となります。
[user@centos ~]$ ./deploy.sh ← プログラムを実行 [ Exclude Pattern ] /app/ *.log [ Deploy Target File ] src/ src/2.txt var/ Do you upload it? [y/n]: y ← アップロードするか質問されます。「y」と応答 ... FTPアップロード ... ... -- deploy success.
ご利用のサーバ環境に合わせて設定を変更すれば、簡単にサーバ間のFTPアップロードが出来るので、参考にして頂ければと思います。

Twitterに投稿