2012年6月25日月曜日

Linux CentOS 6.2 (x86_64) にて、KVM (Kernel-based Virtual Machine) の xml ファイルと仮想imgファイルをバックアップするスクリプト

1.「kvm-bkonevm.sh」スクリプト概要

Linux CentOS 6.2 (x86_64) にて、KVM (Kernel-based Virtual Machine) の xml ファイルフルパスを指定すると、その KVM の xml ファイル自体と仮想imgファイルをバックアップするスクリプトを作成しました。

  • 「指定された仮想マシンの電源を自動的にシャットダウン、仮想マシンの xml ファイルと仮想 HDD ファイルのバックアップ、バックアップ終了後に仮想マシンの電源をオン」という機能をひと通り備えています。

もちろん事前の動作確認や設定は必要ですが、「毎晩、とある重要な仮想マシン1台を、自動的にシャットダウン、バックアップ、電源をオンにする」という利用方法も可能です。

2.前準備

事前に、cpulimit というソフトをインストールしておく必要があります。

(参考) Linux (CentOS 6.2 x86_64) に、「cpulimit」をインストールして、実行する (= 絶対的な優先度を下げる) 手順

http://hachitaro.blogspot.jp/2012/06/linux-centos-62-x8664-cpulimit.html

3.「kvm-bkonevm.sh」スクリプト利用方法

「kvm-bkonevm.sh」スクリプトの利用方法は以下の通りです。

書式

(this scriptfile) (kvm xml file fullpath) (copy destination directory for copying kvm xml file and hd image file)

利用例

./kvm-bkonevm.sh /etc/libvirt/qemu/pc014.xml /mnt/pc079/d/bak/0101_phasedbak

上のとおりに実行すると、以下の処理を実行します。

  1. スクリプトは、「/etc/libvirt/qemu/pc014.xml」で指定されている仮想マシンの電源がオン(ON) の場合は、シャットダウン処理を開始します。

    kvm-bkonevm.sh を実行した後で「仮想マシンの電源がオンになっている」場合は、この kvm-bkonevm.sh スクリプトが仮想マシンに対してシャットダウン命令 (virsh shutdown) を発行します。

    仮想マシンが何らかの理由で自動的にシャットダウンしない場合は、手作業で仮想マシンをシャットダウン操作をする必要があります。

  2. スクリプトは、シャットダウン処理が完全に終了して、仮想マシンの電源がオフ(OFF) になるまで待機します。
  3. スクリプトは、xml ファイルと、仮想 HDD イメージファイルをバックアップ (コピー) します。

    xml ファイル、仮想 HDD イメージファイルいずれとも、できるかぎり元のディレクトリ構成を保ったままバックアップします。

    • xmlファイルのバックアップ先の例

      「/etc/libvirt/qemu/pc014.xml」

    • 仮想 HDD イメージファイルのバックアップ先の例

      「/var/lib/libvirt/images/pc014.img」

  4. スクリプトは、バックアップ終了後に仮想マシンの電源をオンにします。

4.「kvm-bkonevm.sh」スクリプト本体

スクリプトご利用上の注意」をよくお読みの上、ご了承いただいた方はご利用下さい。

「kvm-bkonevm.sh」スクリプトは以下の通りです。

#!/bin/sh

# usage
# (this scriptfile) (kvm xml file fullpath) (copy destination directory for copying kvm xml file and hd image file)
# example
# ./kvm-bkonevm.sh /etc/libvirt/qemu/pc014.xml /mnt/pc079/d/bak/0101_phasedbak


function funcCPULimit() {
curdttm=`date +%Y%m%d%H%M%S`
msg="cpulimit -e qemu-kvm -l 5 &"
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
cpulimit -e qemu-kvm -l 10 &

curdttm=`date +%Y%m%d%H%M%S`
msg="cpulimit -e rsync -l 10 &"
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
cpulimit -e rsync -l 20 &

curdttm=`date +%Y%m%d%H%M%S`
msg="cpulimit -e mysqldump -l 5 &"
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
cpulimit -e qemu-kvm -l 10 &

return 11
}


# パスの文字列に「//」のように不要な「/ (スラッシュ)」が入っている場合は
# 「//」を「/」へ置き換える。
function FuncReplaceDoubleSlashtoSingle() {
wstr=$1
retstr=`echo "${wstr}" | sed -e 's/\/\//\//g'`
echo ${retstr}
}

function FuncRemoveRightSlash() {
wstr=$1

# wstr の最後の一文字を抜き出す。
wstrlenall=`echo $((${#wstr}))`
lastchar=${wstr:${wstrlenall}:${wstrlenall}}

if [[ ${lastchar} = "/" ]]
then
# 一番右端の一文字が「/」なら
# 「/」を削除する。
retstr=${wstr##*/}
else
# 一番右端の一文字が「/」以外なら
# 削除処理は不要
retstr=${wstr}
fi

echo ${retstr}

}

function FuncAddRightSlash() {
wstr=$1

# wstr の最後の一文字を抜き出す。
wstrlenall=`echo $((${#wstr}))`
lastchar=${wstr:${wstrlenall}:${wstrlenall}}

if [[ ${lastchar} = "/" ]]
then
# 一番右端の一文字が「/」なら
# 「/」を追加する必要はない。
retstr=${wstr}
else
# 一番右端の一文字が「/」以外なら
# 「/」を追加する。
retstr=${wstr}'/'
fi

echo ${retstr}

}

function FuncGetStrQuotedWithDifferentStr() {

# getting kvm sv251.xml information
# wallstr=`virsh domxml-to-native qemu-argv /etc/libvirt/qemu/sv251.xml`

# 第1引数は、
# 「virsh domxml-to-native qemu-argv (kvm の xml ファイルフルパス)」
# の値。
# wallstr=$1
# wallstr=`virsh domxml-to-native qemu-argv /etc/libvirt/qemu/sv251.xml`

# echo '${1}..........'$1
wallstr=$1
# echo '${wallstr}..........'${wallstr}

wallstrlen=`echo ${#wallstr}`

# echo 'wallstrlen is '${wallstrlen}

# searchtarget_leftstr='-drive file='
searchtarget_leftstr=$2
searchtarget_leftstrlen=`echo ${#searchtarget_leftstr}`
# searchtarget_rightstr=','
searchtarget_rightstr=$3


tempstr[0]=`echo "${wallstr##*${searchtarget_leftstr}}"`
# echo '${tempstr[0]} is '${tempstr[0]}
tempstrlen[0]=`echo ${#tempstr[0]}`
# echo '${tempstrlen[0]} is '${tempstrlen[0]}

targetstr_startpos=`expr ${wallstrlen} - ${tempstrlen[0]}`
# echo '${targetstr_startpos} is '${targetstr_startpos}
targetstr_startpos_fixed=`expr ${targetstr_startpos} + 1`

tempstr[1]=`echo "${tempstr[0]#*${searchtarget_rightstr}}"`
# echo '${tempstr[1]} is '${tempstr[1]}
tempstrlen[1]=`echo ${#tempstr[1]}`
# echo '${tempstrlen[1} is '${tempstrlen[1]}

targetstr_endpos=`expr ${wallstrlen} - ${tempstrlen[1]}`
# echo '${targetstr_endpos} is '${targetstr_endpos}
targetstr_endpos_fixed=`expr ${targetstr_endpos} - 1`
# echo '${targetstr_endpos_fixed} is '${targetstr_endpos_fixed}


# retstr=`echo ${wallstr} | cut -c ${targetstr_startpos}-${targetstr_endpos_fixed}`
retstr=`echo ${wallstr} | cut -c ${targetstr_startpos_fixed}-${targetstr_endpos_fixed}`

echo ${retstr}


}


function funcGetKVMInfo() {
# getting KVM xml file copy source, destination,
# and getting KVM hd file copy source, destination

# getting KVM HDD information
# wstr=`virsh domxml-to-native qemu-argv /etc/libvirt/qemu/sv251.xml`


wstr=`virsh domxml-to-native qemu-argv ${kvmxml_fullpath_src}`

# KVM の 仮想マシン名を取得する。
# 左側が「'-name '」で、(一番右端に半角スペースを含める)
leftstr='-name '
# 右側が「' -uuid'」で、(一番左端に半角スペースを含める)
# rightstr=' -uuid'
rightstr=' '
# 囲まれた文字列を、${wstr} から探し出して、
# kvm_hd_fullpath_src に代入する。
# 引数 ${wstr} の内容が半角スペースを含むため、"" でくくる。
targetvmname=`FuncGetStrQuotedWithDifferentStr "${wstr}" "${leftstr}" "${rightstr}"`
# echo '${targetvmname} is "'${targetvmname}'"'

curdttm=`date +%Y%m%d%H%M%S`
msg='${targetvmname} is "'${targetvmname}'"'
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}


# KVM の 仮想 HDD のフルパスを取得する。
# 左側が「'-drive file='」で、
leftstr='-drive file='
# 右側が「','」で、
rightstr=','
# 囲まれた文字列を、${wstr} から探し出して、
# kvm_hd_fullpath_src に代入する。
# 引数 ${wstr} の内容が半角スペースを含むため、"" でくくる。
kvm_hd_fullpath_src=`FuncGetStrQuotedWithDifferentStr "${wstr}" "${leftstr}" "${rightstr}"`
# echo '${kvm_hd_fullpath_src} is '${kvm_hd_fullpath_src}
curdttm=`date +%Y%m%d%H%M%S`
msg='${kvm_hd_fullpath_src} is '${kvm_hd_fullpath_src}
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

# kvm_hd_dir_src=`echo ${kvm_hd_fullpath_src%/*}`
kvm_hd_dir_src=${kvm_hd_fullpath_src%/*}
# echo '${kvm_hd_dir_src} is '${kvm_hd_dir_src}
curdttm=`date +%Y%m%d%H%M%S`
msg='${kvm_hd_dir_src} is '${kvm_hd_dir_src}
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

# echo '${kvmxml_fullpath_src} is '${kvmxml_fullpath_src}
curdttm=`date +%Y%m%d%H%M%S`
msg='${kvmxml_fullpath_src} is '${kvmxml_fullpath_src}
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

kvm_xml_dir_src=${kvmxml_fullpath_src%/*}
# echo '${kvm_xml_dir_src} is '${kvm_xml_dir_src}
curdttm=`date +%Y%m%d%H%M%S`
msg='${kvm_xml_dir_src} is '${kvm_xml_dir_src}
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

# echo '${copybasedir_dest} is '${copybasedir_dest}
curdttm=`date +%Y%m%d%H%M%S`
msg='${copybasedir_dest} is '${copybasedir_dest}
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

curdttm=`date +%Y%m%d%H%M%S`
curdt=`date +%Y%m%d`

thispchostname=`hostname -s`

kvmxml_copydir_dest=`FuncAddRightSlash ${copybasedir_dest}`
# kvmxml_copydir_dest=${kvmxml_copydir_dest}`FuncAddRightSlash ${curdt}`
kvmxml_copydir_dest=${kvmxml_copydir_dest}`FuncAddRightSlash ${curdttm}`
kvmxml_copydir_dest=${kvmxml_copydir_dest}`FuncAddRightSlash ${thispchostname}`
kvmxml_copydir_dest=${kvmxml_copydir_dest}`FuncRemoveRightSlash ${kvm_xml_dir_src}`
kvmxml_copydir_dest=`FuncReplaceDoubleSlashtoSingle ${kvmxml_copydir_dest}`
curdttm=`date +%Y%m%d%H%M%S`
msg='${kvmxml_copydir_dest} is '${kvmxml_copydir_dest}
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
kvmhd_copydir_dest=`FuncAddRightSlash ${copybasedir_dest}`
# kvmhd_copydir_dest=${kvmhd_copydir_dest}`FuncAddRightSlash ${curdt}`
kvmhd_copydir_dest=${kvmhd_copydir_dest}`FuncAddRightSlash ${curdttm}`
kvmhd_copydir_dest=${kvmhd_copydir_dest}`FuncAddRightSlash ${thispchostname}`
kvmhd_copydir_dest=${kvmhd_copydir_dest}`FuncRemoveRightSlash ${kvm_hd_dir_src}`
kvmhd_copydir_dest=`FuncReplaceDoubleSlashtoSingle ${kvmhd_copydir_dest}`
# echo '${kvmhd_copydir_dest} is '${kvmhd_copydir_dest}
curdttm=`date +%Y%m%d%H%M%S`
msg='${kvmhd_copydir_dest} is '${kvmhd_copydir_dest}
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

}

function funcWaitWithCountDown() {
wWaitSecCount=$1
wBaseMsg=$2
curdttm=`date +%Y%m%d%H%M%S`
msg="${wWaitSecCount} ${wBaseMsg}"
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
until [ ${wWaitSecCount} -eq 0 ]
do
curdttm=`date +%Y%m%d%H%M%S`
msg="${wWaitSecCount}"
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
wWaitSecCount=`expr ${wWaitSecCount} - 1`
sleep 1
done

}

function funcKVM_VM_PowerOnProcStart() {
# echo "now start vm "${targetvmname}
curdttm=`date +%Y%m%d%H%M%S`
msg="Now PowerOn the vm "${targetvmname}
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

curdttm=`date +%Y%m%d%H%M%S`
msg=`virsh start ${targetvmname}`
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

curdttm=`date +%Y%m%d%H%M%S`
msg="The PowerOn Process has finished. Please wait for OS to start."${targetvmname}
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

}

function funcKVM_VM_ShutdownStart() {
curdttm=`date +%Y%m%d%H%M%S`
msg="starting to shutdown ${targetvmname}..."
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
# echo ${targetvmname}"shutdown starting..."
# ssh -t -t root@${targetvmname} shutdown -h now
curdttm=`date +%Y%m%d%H%M%S`
# msg=`ssh -t -t root@${targetvmname} shutdown -h now`
msg=`virsh shutdown ${targetvmname}`
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

curdttm=`date +%Y%m%d%H%M%S`
msg="shutdown process of ${targetvmname} has started..."
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
}

function funcKVM_VM_ShutdownFinishWait() {
while [ 1 -eq 1 ]
do
curvmdomstat=`virsh domstate ${targetvmname}`
# echo "curent ${targetvmname} status is ${curvmdomstat}"
curdttm=`date +%Y%m%d%H%M%S`
msg="curent ${targetvmname} status is ${curvmdomstat}. Now waiting for shut off..."
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
sleep 1
if [ `echo ${curvmdomstat} | grep シャットオフ` ]; then
break
fi
if [ `echo ${curvmdomstat} | grep "shut off"` ]; then
break
fi
done

curdttm=`date +%Y%m%d%H%M%S`
msg="curent ${targetvmname} status is ${curvmdomstat}"
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
curdttm=`date +%Y%m%d%H%M%S`
msg="Now ${targetvmname} is confirmed to be ${curvmdomstat}"
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

}


function funcKVM_VM_XML_backup() {
curdttm=`date +%Y%m%d%H%M%S`
msg=`mkdir -p -m +w ${kvmxml_copydir_dest} 2>&1`
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

curdttm=`date +%Y%m%d%H%M%S`
msg=`rsync -avvv --delete --timeout=3600 --bwlimit=8192 ${kvmxml_fullpath_src} ${kvmxml_copydir_dest} 2>&1`
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
return 11
}

# rsync option
# --bwlimit=8192 --timeout=3600
# is added to avoid the following error
# rsync: connection unexpectedly closed
#
# reference
# http://kawama.jp/archives/2007/12/rsyncssh.html
function funcKVM_VM_HDImgFile_backup() {
curdttm=`date +%Y%m%d%H%M%S`
msg=`mkdir -p -m +w ${kvmhd_copydir_dest} 2>&1`
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}

curdttm=`date +%Y%m%d%H%M%S`
msg=`rsync -avvv --delete --timeout=3600 --bwlimit=8192 ${kvm_hd_fullpath_src} ${kvmhd_copydir_dest} 2>&1`
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}


return 11
}

function funcDispFinishedMessage() {
curdttm=`date +%Y%m%d%H%M%S`
msg="${targetvmname} backup process has finished. Thank you for your cooperation."
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${logdirfilename}
return 11
}

function funcMainProc() {
# funcWaitWithCountDown 30 " now waiting for starting a process of KVM xml and hd file backup... If you want to stop, Ctrl+C"
funcCPULimit
funcGetKVMInfo
funcWaitWithCountDown 30 " now waiting for shutdown ${targetvmname}... If you want to stop, Ctrl+C"
funcKVM_VM_ShutdownStart
funcKVM_VM_ShutdownFinishWait
funcWaitWithCountDown 30 " now waiting for staring file copy of ${targetvmname} files... If you want to stop, Ctrl+C"
funcKVM_VM_XML_backup
funcKVM_VM_HDImgFile_backup
funcKVM_VM_PowerOnProcStart
funcDispFinishedMessage
}

function funcMain() {
funcMainProc
}


curdttm=`date +%Y%m%d%H%M%S`
curdt=`date +%Y%m%d`
# ログファイル名を決定する。
curdttmforlogfilename=${curdttm}
logdir='/var/log/1050/'
mkdir -p -m +w ${logdir} 2>&1
logfilename_suffix='_log_'
shfilename=`basename $0`
logfilename_ext='.txt'
quotstr='"'
logdirfilename=${logdir}${curdttmforlogfilename}${logfilename_suffix}${shfilename}${logfilename_ext}


kvmxml_fullpath_src=$1
copybasedir_dest=$2
# funcMain ${kvmxml_fullpath_src} ${copydir_dest}
funcMain ${kvmxml_fullpath_src} ${copydir_dest}

Linux (CentOS 6.2 x86_64 用) スクリプトご利用上の注意点、免責事項

このブログで公開されている、Linux (CentOS 6.2 x86_64 用) スクリプトをご利用になる場合の注意点、免責事項を以下のとおりお伝えいたします。

  • Linux (CentOS 6.2 x86_64 含む) で利用される場合は、以下のスクリプトをコピーしてテキストエディタに貼り付けて、「UTF-8(BOM無)」「改行コード(LFのみ)」でファイル名は「mybackup01.sh」と、拡張子は「.sh」にする点にご留意下さい。
  • 私のマシンでは特に問題なく動作していることを確認していますが、他のマシンでも必ず意図通りに動作するという保証はいたしかねます。
  • 以下のスクリプトを利用したことによるあらゆる障害 (データの消失、破損、時間的損害、金銭的損害につながる障害を含めた障害) が発生した場合、私は一切の責任を負いかねます。その点をご了承の上でご利用をお願い致します。
  • もし誤りやお気づきの点がありましたらお知らせくださると幸いです。
  • 恐れ入りますが、このスクリプトに関してのサポートは控えさせて頂きます。
  • 商用、非商用に限らずご利用はご自由にどうぞ。

linux (CentOS 6.2 x86_64) で、「cpulimit」と --bwlimit を使って、マシン負荷を減らしネットワーク負荷を減らして rsync を実行する方法

1.rsync の高負荷を減らすには

Linux の rsync (Windows の robocopy に相当) は非常に便利です。ただしマシンやネットワークにとって高い負荷がかかって困る場合もあります。

  • rsync を実行すると、マシンに高い負荷がかかりの動作が重たくなる
  • rsync を実行すると、ネットワークに高い負荷がかかり、Web サイトの読み込みが遅くなる、あるいはエラーが発生する。

ここでは、「Linux (CentOS 6.2 x86_64 ディストリビューション)」の場合を例に、「マシンにとって低負荷、ネットワークにとっても低負荷」な rsync を実行する手順を説明します。

2.前準備

事前に、cpulimit というソフトをインストールしておきます。

(参考) Linux (CentOS 6.2 x86_64) に、「cpulimit」をインストールして、実行する (= 絶対的な優先度を下げる) 手順

http://hachitaro.blogspot.jp/2012/06/linux-centos-62-x8664-cpulimit.html

3.rsync スクリプトの例

私が作成した、「マシンとネットワークに低負荷の rsync」スクリプトを以下に記します。

スクリプトご利用上の注意」をよくお読みの上、ご了承いただいた方はご利用下さい。

「mybackup01.sh」

#!/bin/sh

# clamproc1501

# 実行中のスクリプトのディレクトリを取得
# CURDIR=`pwd`
CURDIR=`dirname $0`
# echo ${CURDIR}
thispchostname=`hostname -s`
echo ${thispchostname}


curdttmforlogfilename=`date +%Y%m%d%H%M%S`

logfilesdir='/var/log/1050/'
rsynclogdir='/var/log/1050/'
rsynclogfilename_suffix='rsynclog'

mkdir -m 777 -p ${logfilesdir}
mkdir -m 777 -p ${rsynclogdir}

shfilename=`basename $0`
logfilename_ext='.txt'
quotstr=



rsynclogdirfilename=${rsynclogdir}${curdttmforlogfilename}_${thispchostname}_${shfilename}_${rsynclogfilename_suffix}${logfilename_ext}


# 関数の戻り値
RETNOTSET=1
RETTRUE=11
RETFALSE=12

popd
wScriptDir=$(cd $(dirname $0) && pwd)
pushd

. ${wScriptDir}'/../0000_com/'com_proc.sh

PATH=/usr/bin:/bin


# syncing nas252 to nas253

func_check_other_proc() {
func_check_other_highload_process_running
rtn=$?
if [ "$rtn" -ne 11 ]
then
return ${rtn}
fi

return 11
}

func_rsync() {
# コピー元ディレクトリの指定
#
# 「hachitaro」ディレクトリごと、rsync するので、
# 「/mnt/nas123/usr/hachitaro/」
# ではなく
# 「/mnt/nas123/usr/hachitaro」
# を指定する。
rsync_sourcedir_file="mnt/nas123/usr/hachitaro"

# コピー先ディレクトリの指定
# rsync_dest_dir="/mnt/nas456/bk/server1001/pc/usr/"
rsync_dest_dir="/mnt/nas456/bk/server1001/pc/usr/"

# rsync の CPU 最大使用率を50%に制限。(CPUの優先度ではない)
cpulimit -e rsync -l 50 &

# rsync 実行
# rsync -avvv --stats ${rsync_sourcedir_file} ${rsync_dest_dir} | tee -a ${rsynclogdirfilename}

# rsync 実行
# --bwlimit=()KBytes
# 「 --bwlimit=1000」は、 1000KB/s (= 1MB/s) の意味
# 「 --bwlimit=10000」は、 10000KB/s (= 10MB/s) の意味
# 「 --bwlimit=50000」は、 20000KB/s (= 20MB/s) の意味
# 「 --bwlimit=50000」は、 50000KB/s (= 50MB/s) の意味
# 「--bwlimit=100000」は、100000KB/s (=100MB/s) の意味
rsync -avvv --stats --bwlimit=20000 ${rsync_sourcedir_file} ${rsync_dest_dir} | tee -a ${rsynclogdirfilename}


return 11
}


func_main() {
local -i rtn
rtn=1

func_check_other_proc
func_check_other_proc
rtn=$?
if [ "$rtn" -ne 11 ]; then return ${rtn}; fi


# rcync
func_rsync
rtn=$?
if [ "$rtn" -ne 11 ]; then return ${rtn}; fi

# すべての処理が終了して、ここまで処理がすすんだ場合、「処理はすべて正常終了」
# とみなす。

rtn=11
return ${rtn}


}



func_main
rtn=$?

curdttm=`date +%Y%m%d%H%M%S`
if [ "$rtn" -ne 11 ]
then
# 処理で以上が発生したため、これより以下の処理は続行はしない。
curdttm=`date +%Y%m%d%H%M%S`
msg="処理途中で異常が発生したため、処理を途中で中断しました。"' 2>&1'
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${thispchostname}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${clamproclogdirfilename}
else
# 処理が正常終了したため、次の処理へ進む
curdttm=`date +%Y%m%d%H%M%S`
msg="処理がすべて正常に終了しました。"' 2>&1'
echo "${quotstr}${curdttm}${quotstr} ${quotstr}${thispchostname}${quotstr} ${quotstr}${msg}${quotstr}" | tee -a ${clamproclogdirfilename}
fi


Linux (CentOS 6.2 x86_64) に、「cpulimit」をインストールして、実行する (= 絶対的な優先度を下げる) 手順

1.「cpulimit」概要 nice コマンドとは別の方法で優先度を強制的に下げるソフト

Linux には、nice コマンドを使って相対優先度を変更することができます。Windows 7 ではタスクマネージャーの「プロセス」タブの「基本優先度」 に相当するものです。(低、通常以下、通常、通常以上、高、リアルタイム)

Linux で 「nice コマンドを利用して、とあるプロセス (例えば rsync や FaHCore_a4.exe など) の優先度を可能な限り下げたけれども、マシンの動作が重たくて、kill をすると軽くなる」という場合があります。

この場合は、「cpulimit」というソフトをインストールすることで、その重たいプロセスの絶対的な優先度を下げることができます。

原理は単純で、cpulimit がそのプロセスを定期的に頻繁に sleep させるというものです。

Linux (CentOS などの Redhat Enterprise Linux 系ディストリビューション) で「nice コマンドをつかってもマシンが重たくて困っている」という方は、「cpulimit」をインストールする手順を説明します。

ちなみに、Ubuntu は、別のインストール手順があります。そちらは恐れ入りますが、別の Web ページをご参照をお願い致します。

2.「cpulimit」インストール

cpulimit インストールの手順です。インストールとは言ってもソースコードをダウンロードして make します。難しくはないかと思います。

ここでは「cpulimit-1.1」のバージョンを例に上げて説明します。もしバージョンの数値が変わったら数値を読み替えて実行して下さい。

# wget http://downloads.sourceforge.net/cpulimit/cpulimit-1.1.tar.gz
# tar zxvf cpulimit-1.1.tar.gz
# cd cpulimit-1.1
# make
# cp cpulimit /usr/bin/

以上でインストールが完了です。

3.「cpulimit」ごく簡単な実行例

rsync の CPU 最大使用率を 50% に制限する例です。

一番最後に「&」をつけるのをお忘れなく。

cpulimit -e rsync -l 50 &

2012年6月20日水曜日

ウィルコム WX01 キーロック ON/OFF (オン/オフ) の切替手順、利用するボタンはどれ

「ウィルコム WX01 キーロック ON/OFF (オン/オフ)の切替手順、利用するボタンはどれかわからない」と、お困りの方もいらっしゃるかと思います。

理由は 2 つです。

  1. 本体の箱に取扱説明書が入っていなかった。
  2. 説明書を、メーカーのサイトからダウンロードして説明書通りに「* ロック」キーを押しても、ロックされない

    まずは「*」キーに「ロック」と書かれていません。それならばと他のキーを探しても「ロック」と書かれてあるキーは見当たりません。「安全運転モード」キーは見つかりますが、キーロックとは別の機能です。

ボタンの表記と、実際の製品の表記が異なっています。表記だけではなく機能や手順も異なっているということです。

WX01 の出荷時期によって、仕様変更が行われているのかもしれません。

「WX01 を、取扱手順書通りに操作をしてもキーロックできない」方は、以下のいずれかでキーロックが出来ると思われます。一つずつ試すことをおすすめします。

  • 「* ロック」と書かれたボタンを長押しする

    操作手順書の 27 ページには、「* ロック」キーを長押しするようにと、説明が書かれています。

  • 「OK」と書かれたボタンを長押しする

    ウィルコムのページで紹介されている、WX01 には「OK」と書かれたボタンがあります。筆者の手元にある WX01 には、同じ位置にボタンはありますが「OK」とは書かれていません。

    出荷時期によって、ボタンの表記などに差異があるかもしれません。

  • 「(OKという文字が書かれていないが、上下左右を操作するキーの中央にあるキー)」を長押しする

    以下のキーです

以下、画面例です。

  1. 画面例その1.キーロックOFF (オフ) の状態の画面

    「キー」のアイコンが画面に表示されていない

    アイコンが、3つ表示されています。

    なお、「メールアイコン」、「『MENU』アイコン」、「電話帳アイコン」は、筆者が作成したいわゆる造語です。取扱説明書には特に説明が書かれていなかったため、説明の便宜上、名前を付けさせて頂きました。

  2. 画面例その2.キーロックON (オン) の状態の画面

    「キー」のアイコンが画面に表示されている

    以下は、上の拡大画像です。

ウィルコム WX01 マナーモード ON/OFF の切替手順、利用するボタンはどれ

ウィルコム WX01 マナーモード ON/OFF の切替手順、利用するボタンはどれか?

WX01UT の取扱説明書 (参照: ) 27ページの「マナーモード」の項目によると、以下のように説明されています。

「0(数字のゼロ) わ マナー」のボタンを長押しすれば、マナーモードに入ります。
(中略)
マナーモードを解除するには、もう一度「0(数字のゼロ) わ マナー」を押します。

これは、皆様が実際にお手持ちの WX01 の種類によって、若干異なる可能性があります。(私は WX01NX です)

「* マナー」というように、「とにかく『マナーと書かれたボタンを長押し』」すれば、マナーモードの ON/OFF を切り替えることができます。

2012年6月19日火曜日

ウィルコム WX01 製品情報、取扱説明書ダウンロードの URL

Google の検索のテキストボックスに「ウィルコム」と入力をすると「ウィルコム 解約」という検索候補が一番先頭に来るようになってどれくらいの時間がたったでしょうか・・・

このブログでは、ウィルコムの1ユーザーとして筆者が淡々とウィルコム(willcom) についても書いていきます。

ウィルコムの「もう1台無料」キャンペーンで「WX01 (機種名)」を入手された方もいらっしゃるかと思います。

「取扱説明書が同梱されていると外箱には記載されているのに同梱されていない」とお困りの方、ウィルコム WX01 製品情報、取扱説明書ダウンロードの URL は、以下の通りです。

2012年6月14日木曜日

自分のブログ、Webページを Google にクロールしてもらうには

Google 社の人が、カメラを搭載した車であちこち出かけて風景を撮影するなど必要な作業を行います。すると、Google map のストリートビューでその風景が見えるようになります。

Google 社のクローラーが、ブログ、Web ページを自動的にクロールしてなおかつプログラムが「この ブログ、Web ページは、ブログ読者、Webページ読者にとってどれだけ有益か」なども自動的に判断して、検索用のインデックスをつくります。

そして、Google で検索をすると、ブログや Web ページが表示されるようになります。

基本的にはブログや Web ページを作ると、(よほどのことが無い限り) しばらく待つだけで、Google で検索できるようになります。

  • 「自分でブログを書いた。きっと他の人にも役に立つ内容だと思う。Google で検索をしたら、自分のブログが検索結果に出るようにして欲しい」
  • 「自分では無いが、知人がブログ、Web ページを書いた。きっと他の人にも役に立つ内容だと思う。Google で検索をしたら、自分のブログが検索結果に出るようにして欲しい」
  • 「自分では無いが、Google 検索ではなく別の方法で、非常に有用な Web ページを見つけた。きっと他の人にも役に立つ内容だと思う。Google で検索をしたら、自分のブログが検索結果に出るようにして欲しい」

という場合、普通はしばらく待てば Google の検索結果に表示される (= ヒットする) ようになります。 google 社のクローラーが自動的にクロールしてくれます。

人間が、Google に「クロール依頼」を出すこともできます。

「Web ページを見に来て、Google 検索をした時に、検索できるようにして欲しい」と、クローラ (クロールするプログラム) に依頼を出すということです。

「クロールの依頼を出すと、google 社のクローラが Web ページ、ブログをクロールしてくれる」のは確かです。ただし、クロール依頼を出してもGoogle で検索して検索できるようになるとは限りません。あくまで Google 社が有用だと認めた Web ページなりブログが、検索できるようになります。

逆に、「クロール依頼を出してもいつまでたっても Google で検索できるようにならない」ページもあります。一言で言うと「内容がない」ページです。

今、この文章を書いていて何か胸が痛いような気がするのですが・・・。

例を挙げると・・・

  • 背景の色と同じ色の文字色で、人間の目で見て一見してわかりづらいが、検索エンジンでヒットするような単語をたくさん書いてある。しかも Web サイトの内容に無関係。
  • リンク集

    「リンク集」自体は特に悪くないです。Google で検索してもヒットしにくい傾向があるというだけのことです。

本題に戻ります。

もし「google 社のクローラーにクロールして欲しい」と言う方は、まず以下をご覧の上で・・

Google へのクロールのリクエスト (ヘルプ)

http://support.google.com/webmasters/bin/answer.py?hl=ja&answer=1352276

以下のページでクロールのリクエストを依頼できます。

ウェブマスタツール (クロールのリクエスト依頼の Web ページ)

https://www.google.com/webmasters/tools/submit-url

Linux CentOS 6.2 x86_64 にて、rpm で epel リポジトリをインストールする手順

Linux CentOS 6.2 x86_64 にて、rpm で epel リポジトリをインストールする手順のメモです。

epel リポジトリは、CentOS をどの方法でインストールしても、自動的にはインストールされません。(自動的にインストールする方法があったらぜひ教えて下さい) これは、CentOS インストーラーに epel リポジトリが含まれていないためと思われます。詳しい方、教えて下さると幸いです。

CentOS インストール後に、手作業で rpm で epel リポジトリをインストールする必要があります。

rpm で epel リポジトリをインストールしておくと、「yum で ClamAV (無料オープンソースのウィルススキャンソフト) をインストールできるようになる」などの利点があります。

筆者がインストールするときにお恥ずかしながら手こずりました。自戒の念を込めつつ、備忘録としてこの投稿を書いています。

  1. (前準備) yum-priorities のインストール

    epel をインストールする前に、yum-prioritiesインストールを行います。

    yum -y install yum-plugin-priorities
  2. (前準備) 標準リポジトリ設定ファイル (CentOS-Base.repo) 編集

    標準リポジトリ設定ファイル (.repo) の編集を行います。

    「/etc/yum.repos.d/CentOS-Base.repo」を vi などのテキストエディタで開いて、「priority=1」という行を 3 箇所に追加します。

    見て予想がつくかとは思いますが、「#」で始まる行はコメントです。以下はあくまでも例なのでご自身にわかりやすいようにしてもらえればとおもいます。例えば「# added」の代わりに「# 追加した」にする。あるいは「# #######」の代わりに「# ------」とするなど。

    vi /etc/yum.repos.d/CentOS-Base.repo
    [base]
    name=CentOS-$releasever - Base
    mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
    #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
    gpgcheck=1

    gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
    # ###########################################
    # added
    priority=1
    # ###########################################


    #released updates
    [updates]
    name=CentOS-$releasever - Updates
    mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
    #baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
    gpgcheck=1

    gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
    # ###########################################
    # added
    priority=1
    # ###########################################


    #additional packages that may be useful
    [extras]
    name=CentOS-$releasever - Extras
    mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras
    #baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
    gpgcheck=1

    gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-CentOS-6
    # ###########################################
    # added
    priority=1
    # ###########################################
  3. EPELリポジトリインストール

    ようやく前準備が終わりました。epel リポジトリをインストールします。・・・がその前に、epel の URL を確認します。重要です。

    Web ブラウザで、以下の URL を開きます (x86_64版の場合)

    http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/

    「epel-release-6-x.noarch.rpm」

    を含んでいるファイル名を Webページ内で検索します。

    xはバージョン、リビジョンの数字です。

    時期によって、バージョン、リビジョンの数字が上がっている場合があります。

    rpm 実行前に、バージョン、リビジョン番号の確認を必ず確認することをおすすめします。

    筆者は、rpm 実行時にエラーが発生して、お恥ずかしながら解決するまでに非常に手こずりました。

    なので、自戒を込めて、ここで一句。

        rpm(あーるぴーえむ)?
        ちょっと待て
        その URL 大丈夫?
    
    
    

    上の一句で、網羅はしているのですが、範囲が広めです。

    自分のように、rpmを使い始めて間もない人にとってはあまり役に立ちません。

    漠然としていて、言われた方は「なら、どうすればいいのさ?」と、途方に暮れるだけです。

        rpm(あーるぴーえむ)?
        ちょっと待て
        バージョン、リビジョン番号は?
    
    
    
        rpm(あーるぴーえむ)?
        ちょっと待て
        その URL 古くない?
    
    
    
        ちょっと待て
        それは PowerPC 版だ。
    
    
    
        64(※)が、
        欲しい時には x86_64 だ。
    
    
    

    ※「64」 この場合「ろくよん」と読みます。ここでは 64bit版の意味です。「64bit」だと、どうしても一句を作れないのでこの場合のみ便宜上「ろくよん」と呼んで下さるとありがたいです。

        i686?
        それは32bit版だ。
    
    
    

    稚拙な句をつらつらと並べましたが、私だけではなく皆様が rpm 実行する時にも「ああ、そういえば気をつけなければ」と、留意していただけると rpm のエラー、トラブルをより回避しやすくなるかと思います。

    上の句を見ていると、「Alpha版? ほんとにそれで合ってるの?」などの句も思い浮かんだりしますが、きりがないので句の話はここで終わりにします。

    検索の話に戻ります。

    実際に検索する時は

    「epel-release-6」

    で Web ページ内の検索をします。

    2012/05/17 時点では、

    「epel-release-6-6.norach.rpm」

    がファイル名です。

    6-6が、バージョン、リビジョン番号を表しています。

    「epel-release-6-6.norach.rpm」

    を右クリックして、「URL をクリップボードにコピー」を実行します。

    (参考) 上記の場合、クリップボードにコピーされた URL は以下のとおりとなります。

    http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-6.noarch.rpm

    rpm -Uvh を実行します。

    キーボードで「rpm -Uvh 」と入力します。最後の一文字、半角スペースを忘れずに。

    引き続き、先ほどクリップボードにコピーしておいた URL を貼り付けます

    実行例

    rpm -Uvh http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-6.noarch.rpm
  4. epel-release アップデート

    epel-release をインストールしたあとで、アップデートを行います。

    yum -y update epel-release

以上で、rpm で epel リポジトリをインストール完了です。

(参考)

http://centossrv.com/epel.shtml

2012年6月13日水曜日

KVM (Kernel-based Virtual Machine) の仮想PC、仮想マシン (仮想PC の OS は CentOS 6.2 x86_64) をコピーして、新しい仮想PCを作る手順


KVM (Kernel-based Virtual Machine) の仮想PC、仮想マシン (仮想PC の OS は CentOS 6.2 x86_64) をコピーして、新しい仮想PCを作る手順


ここでは、pc100 を pc200 にコピーする場合を例に説明します。


◆手順1.仮想HD ファイルのコピー

仮想HD ファイルをコピーします。
cp コマンドでも、GNOME のファイルブラウザを利用してコピーしても
どちらでも構いません。
必要に応じてリネームします。

コピー元
/var/lib/libvirt/images/pc100.img

コピー先
/var/lib/libvirt/images/

コピー終了後、以下の 2 つのファイルが存在する状態が正しい状態です。
/var/lib/libvirt/images/pc100.img
/var/lib/libvirt/images/pc200.img


◆手順2.xml ファイルのコピー
cp コマンドでも、GNOME のファイルブラウザを利用してコピーしても
どちらでも構いません。
必要に応じてリネームします。


コピー終了後、以下の 2 つのファイルが存在する状態が正しい状態です。
/etc/libvirt/qemu/pc100.xml
/etc/libvirt/qemu/pc200.xml


◆手順3.pc200.xml の編集
vi や gedit などのテキストエディタで「pc200.xml」を編集します。


変更1箇所目...name
変更前
 <name>pc100</name>
変更後
 <name>pc200</name>


変更2箇所目...uuid (コメント化する)
変更前(例)
 <uuid>dc182d1a-44f2-bc49-5b0e-xxxxxxxxxxxx</uuid>

変更後
<!--
 <uuid>dc182d1a-44f2-bc49-5b0e-xxxxxxxxxxxx</uuid>
-->

変更3箇所目...仮想HD イメージファイルのフルパスの修正
変更前
     <source file='/var/lib/libvirt/images/pc100.img'/>
変更前
     <source file='/var/lib/libvirt/images/pc200.img'/>


変更3箇所目...MACアドレスの修正
変更前
     <mac address='52:54:xx:xx:xx:a5'/>
変更後 (例)
     <mac address='52:54:xx:xx:xx:a6'/>

他のPCのMACアドレスと重複しないMACアドレスを指定します。
具体的には、一番右側の2桁の16進数を修正します。
上の説明の例ではa5に+1して、a6に変更しています。


上の修正が終了したら、ファイルを保存します。

◆手順4.「virsh define」
コンソールを起動します。

以下のように入力します。
virsh define /etc/libvirt/qemu/pc200.xml


◆手順5.仮想マシンマネージャーを一旦終了して、再度起動する

仮想マシンマネージャーを起動します。
もし仮想マシンマネージャーを実行中の場合はいったん終了してから、もう一度起動します。


仮想マシンの一覧に、pc200 が存在することを確認します。





◆手順6.仮想マシン(pc200) の起動
仮想マシンを起動します。

◆手順7.仮想マシン(pc200) のホスト名 (Linuxの場合。Windows の場合はコンピュータ名に相当)、IPアドレスの変更

ホスト名と、IP アドレスを変更します。



# vi /etc/sysconfig/network

変更前
HOSTNAME=pc100

変更後
HOSTNAME=pc100



# vi /etc/sysconfig/network-scripts/ifcfg-eth0

変更前
IPADDR=192.168.1.100

変更後
IPADDR=192.168.1.200



◆手順8.同仮想PCの再起動
ホスト名の変更を有効にするために、PC200を再起動します。

# shutdown -r now

◆手順9.再起動後の動作確認
再起動後、必要に応じて動作確認を行います。

ファイルサーバー(CIFS、NFS) を利用している場合は、そのファイルサーバーをマウントできていること
Webブラウザで、www.google.co.jp や www.yahoo.co.jp へ接続して、ページが表示されること