2012年9月12日水曜日

fstab をいじっていたら CentOS が起動しなくなったときの対処 (RAID1を組んでいる場合)

CentOS 6.3 (x86_64) にて /etc/fstab を修正して CentOS を再起動した時に起動途中で止まってしまったことがありました。

対処として、「fstabをいじっていたら起動しなくなったときの対処」を、ほぼそのまま実行して、CentOS が起動するようになりました。

自分の環境では RAID1 を組んでいて、mount のコマンドの引数が上の URL のページと異なったため、メモとしてここに残します。

「『mount -o remount,rw /dev/VolGroup00/LogVol00 /』
を実行しようとしたけれども、/etc/fstab には『/dev/VolGroup00/LogVol00』というデバイスがない・・・」とお困りの方へ。以下の手順が役に立つかもしれません。

  1. まずシングルユーザーモードで起動します。
  2. /etc/fstab で「/」に対応するデバイス名、あるいは UUID を調べる
    vi /etc/fstab

    以下の /etc/fstab を見ると「/」に対応する UUID は「3ffe40ba-4259-48ee-9f04-64a4ad4bbfa7」であることが分かります。

    #
    # /etc/fstab
    # Created by anaconda on Tue Sep 4 19:25:32 2012
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    UUID=3ffe40ba-4259-48ee-9f04-64a4ad4bbfa7 / ext4 defaults 1 1
    UUID=b1ec5276-7cbc-495b-a291-327b052d27c5 /boot ext4 defaults 1 2
    /dev/mapper/sil_biajaecfafccp2 swap swap defaults 0 0
    tmpfs /dev/shm tmpfs defaults 0 0
    devpts /dev/pts devpts gid=5,mode=620 0 0
    sysfs /sys sysfs defaults 0 0
    proc /proc proc defaults 0 0

    (余談) ちなみに・・・この vi を実行している時に、自分が間違えて変更した箇所を修正してなおかつ上書き保存が出来れば何も問題はありませんが、残念ながら読み取り専用モードでのみ開ける状態です。

    試しに、「chmod 777 /etc/fstab」を実行してから vi /etc/fstab を実行したものの、やはり読み取り専用のままでした

  3. vi を終了します。

    vi を終了した時点でも、/etc/fstab の内容が画面に表示されたままなので、UUID をメモに取る必要はありません。

    もし、/etc/fstab の内容が画面に表示されない場合は、vi /etc/fstab を実行して、UUID を紙に手書きで書き写しておく必要があります。

  4. mount を実行する。

    mount を実行します。上で出てきた UUID あるいはデバイス名をキーボードで手入力する必要があります。

    mount -o remount,rw 3ffe40ba-4259-48ee-9f04-64a4ad4bbfa7 /

    これで、/etc/fstab が読み書き可能な状態で開けるようになりました。

  5. vi /etc/fstab

    vi にて、/etc/fstab を開きます。

    読み書き可能な状態になっているはずです。

    必要に応じて修正を行い、保存して vi を終了します。

  6. exit を実行

    exit を実行します。

    exit
  7. exit 実行後、PC が再起動します。CentOS が正常に起動するのを確認します。

2012年8月10日金曜日

CentOS 6.3 (x86_64) に TigerVNC Server をインストールする手順

CentOS 6.3 (x86_64) に TigerVNC Server をインストールしたときの手順を記録のためにここに記す。

参考: 2009年09月19日 vncサーバー構築(CentOS5)

  1. TigerVNCServer をインストール
    yum -y install vnc-server
  2. 「/etc/sysconfig/vncservers」(VNC 用設定ファイルのうちの一つ) をバックアップ
    cp /etc/sysconfig/vncservers /etc/sysconfig/vncservers.bak
  3. 「/etc/sysconfig/vncservers」を vi で編集する。
    # VNCSERVERS="2:myusername"
    # VNCSERVERARGS[2]="-geometry 800x600 -nolisten tcp -localhost"


    VNCSERVERS="3:hachitaro"
    VNCSERVERARGS[3]="-geometry 1024x768 -nolisten tcp"
  4. VNC Viewer で VNC 接続するユーザーのパスワードをセットする。

    su コマンドを実行して、hachitaro ユーザーに切り替える。

    [root@pc101 ~]# su - hachitaro
    [hachitaro@pc101 ~]$
  5. VNC Viewer で VNC 接続するユーザーのパスワードをセットする。

    su コマンドを実行して、hachitaro ユーザーに切り替える。

    [hachitaro@pc101 ~]$ vncpasswd
    Password:
    Verify:
    [hachitaro@pc101 ~]$

    exit コマンドを実行して、元のユーザーに戻る。

    [hachitaro@pc101 ~]$ exit
    logout
    [root@pc101 ~]#
  6. いったん、vncserver サービスを起動して、その後 stop する。

    vncserver サービスを起動する。

    [root@pc101 ~]# service vncserver start
    VNC サーバー を起動中: 3:hachitaro xauth: creating new authority file /home/hachitaro/.Xauthority
    xauth: (stdin):1: bad display name "pc101:3" in "add" command

    New 'pc101:3 (hachitaro)' desktop is pc101:3

    Creating default startup script /home/hachitaro/.vnc/xstartup
    Starting applications specified in /home/hachitaro/.vnc/xstartup
    Log file is /home/hachitaro/.vnc/pc101:3.log

    [ OK ]
    [root@pc101 ~]#

    vncserver サービスを stop する。

    [root@pc101 ~]# service vncserver stop
    VNC サーバー を停止中: 3:hachitaro [ OK ]
    [root@pc101 ~]#
  7. VNC利用ユーザーの、「xstartup」ファイルを編集する。
    vi /home/hachitaro/.vnc/xstartup

    「/home/hachitaro/.vnc/xstartup」のファイル内容 (変更前)

    #!/bin/sh

    [ -r /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n
    export LANG
    export SYSFONT
    vncconfig -iconic &
    unset SESSION_MANAGER
    unset DBUS_SESSION_BUS_ADDRESS
    OS=`uname -s`
    if [ $OS = 'Linux' ]; then
    case "$WINDOWMANAGER" in
    *gnome*)
    if [ -e /etc/SuSE-release ]; then
    PATH=$PATH:/opt/gnome/bin
    export PATH
    fi
    ;;
    esac
    fi
    if [ -x /etc/X11/xinit/xinitrc ]; then
    exec /etc/X11/xinit/xinitrc
    fi
    if [ -f /etc/X11/xinit/xinitrc ]; then
    exec sh /etc/X11/xinit/xinitrc
    fi
    [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
    xsetroot -solid grey
    xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
    twm &

    「/home/hachitaro/.vnc/xstartup」のファイルの一番下の2行を変更して、ファイルを保存する。

    「/home/hachitaro/.vnc/xstartup」のファイル内容 (変更後)

    #!/bin/sh

    [ -r /etc/sysconfig/i18n ] && . /etc/sysconfig/i18n
    export LANG
    export SYSFONT
    vncconfig -iconic &
    unset SESSION_MANAGER
    unset DBUS_SESSION_BUS_ADDRESS
    OS=`uname -s`
    if [ $OS = 'Linux' ]; then
    case "$WINDOWMANAGER" in
    *gnome*)
    if [ -e /etc/SuSE-release ]; then
    PATH=$PATH:/opt/gnome/bin
    export PATH
    fi
    ;;
    esac
    fi
    if [ -x /etc/X11/xinit/xinitrc ]; then
    exec /etc/X11/xinit/xinitrc
    fi
    if [ -f /etc/X11/xinit/xinitrc ]; then
    exec sh /etc/X11/xinit/xinitrc
    fi
    [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
    xsetroot -solid grey
    # xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
    gnome-session &
  8. vncserver サービスを起動する。

    vncserver サービスを起動する。

    [root@pc101 ~]# service vncserver start
    VNC サーバー を起動中: 3:hachitaro xauth: (stdin):1: bad display name "pc101:3" in "add" command

    New 'pc101:3 (hachitaro)' desktop is pc101:3

    Starting applications specified in /home/hachitaro/.vnc/xstartup
    Log file is /home/hachitaro/.vnc/pc101:3.log

    [ OK ]
    [root@pc101 ~]#
  9. iptables の設定を変更 (VNC Server の利用する 5900-5910 のポートを開ける)
    [root@pc101 ~]# vi /etc/sysconfig/iptables
  10. 「/etc/sysconfig/iptables」の、「COMMIT」よりも上の場所に、以下の内容を追加する。追加した後はファイルを保存する。
    -A INPUT -p tcp -m tcp --dport 5900:5910 -j ACCEPT

    (変更前の例)

    # Firewall configuration written by system-config-firewall
    # Manual customization of this file is not recommended.
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A INPUT -p icmp -j ACCEPT
    -A INPUT -i lo -j ACCEPT
    -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
    -A INPUT -j REJECT --reject-with icmp-host-prohibited
    -A FORWARD -j REJECT --reject-with icmp-host-prohibited
    COMMIT

    (変更後の例)

    # Firewall configuration written by system-config-firewall
    # Manual customization of this file is not recommended.
    *filter
    :INPUT ACCEPT [0:0]
    :FORWARD ACCEPT [0:0]
    :OUTPUT ACCEPT [0:0]
    -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    -A INPUT -p icmp -j ACCEPT
    -A INPUT -i lo -j ACCEPT
    -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
    -A INPUT -p tcp -m tcp --dport 5900:5910 -j ACCEPT
    -A INPUT -j REJECT --reject-with icmp-host-prohibited
    -A FORWARD -j REJECT --reject-with icmp-host-prohibited
    COMMIT
  11. 「/etc/sysconfig/iptables」に加えた変更を有効にするために、iptables サービスを再起動する。
    [root@pc101 ~]# service iptables restart
    iptables: ファイアウォールルールを消去中: [ OK ]
    iptables: チェインをポリシー ACCEPT へ設定中filter [ OK ]
    iptables: モジュールを取り外し中: [ OK ]
    iptables: ファイアウォールルールを適用中: [ OK ]
    [root@pc101 ~]#
  12. VNC Viewer (RealVNC など) で、VNC Server へ接続する。
    設定項目名称設定値備考
    IPアドレスとポート番号192.168.1.101::5903VNC Viewer の種類によっては「IPアドレス::ポート番号」「IPアドレス:ポート番号」など記述の方法が異なる場合がある。つながらない場合は記述を変更して試してみる。
    ユーザー名hachitaroVNC Viewer の種類によっては指定が不要な場合がある
    パスワード(上の vncpasswd でセットしたパスワードを入力する)

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 (オン) の状態の画面

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

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