LNAMP Shell 部署脚本
学习总结:
这个脚本,早期是出于对个人学习Shell的总结而写,应该有些年头了,目前也在一边学马哥视频的基础上陆续完善,10月初才完成LNAMP环境的分离式部署,并减少整个Shell脚本各部分的依赖关系。
我是网络班13期高级班的学员,因个人做了几年Linux运维,所以目前整个高级班的课程,我是跳着看了集群(LVS + Keepalived)、自动化(Cobbler、Ansible)、监控(Zabbix)、分布式存储(Mogilefs和Glusterfs),系统调优以及Openstack的部分。因目前这几个是我现在这个公司短期内要用的,也是目前我主要关心的几个东西。
7月报的班,8月份岗位变动(被人坑了一把,现在兼了linux 运维的工作,应该也是一种机会吧,可以让我直接把学习的东西,直接用在线上环境上)。
8月底到现在,一直都折腾在之前那个人交接的环境上了(环境相当混乱)。因此,一边看视频,一边就直接用在线上环境了。
Ø 部署了Cobbler的内部源(涉及了CentOS、RedHat、Zabbix、Ubuntu);
Ø 研究了ansible + zabbix,参考了 galaxy上的脚本,在线上部署了zabbix环境;
Ø 修改了早期的LNAMP脚本,调整为可分离式部署,并集成了目前公司在用的个人所写的Git SCM运维方面的脚本。
本来也考虑把Git环境也整进去的,但想想还是算了,折腾不起了,把费脑子的事情还是发在学习上去……
转入主题,Shell脚本的入门是很简单的,但要学好是一个挺长时间的事情的,别把Shell想得太简单,基本的运维脚本,只要是一个会点Linux知识,干过这行的,随便都可以写的出来。一个会写代码,有思想的运维是很可怕的,这也是你的一个竞争力的亮点。
请问以下功能性需求,如果要使用Shell编程,需要界面UI,如何实现?
假设,线上生产环境的一个系统,因早期的开发设计,导致业务层面有很大的BUG问题(比如说,构成数据库唯一键的部分主键冲突),导致整个业务系统,在数据修改、查询操作时,出现数据不一致,冲突性地问题。因此,想用Shell脚本来实现以下功能:
Ø 数据库的修改(需要考虑冲突,界面UI显示,及修正冲突等等)
Ø 数据库的删除
Ø 数据库的备份(提供记录级别、表级别、数据库级别,可以选择性地备份)
Ø 数据库的还原(表级别,没有数据时实现 insert操作,有时实现update操作)
这个需求是我真实碰到的,请问要实现以上功能,需要使用哪些工具?此外,需要保证整个脚本工作地准确性、可靠性及输出的友好性,并且脚本需要尽量避免重复代码。
这篇Blog 分享出来的脚本,我个人认为还是有很大的参考价值的。因他算是我一直以为对学习Shell脚本的一个很好地总结。脚本中,可能会存在部分代码装B的嫌疑,因有些很简单能实现的代码,我可能会有点稍微复杂点的方式来写,主要是怕自己以后不用会忘了。实际上你懂得~~~
功能:

代码说明:
代码使用git 方式管理,代码量(15000+ 行),包括了:
Ø LNAMP环境部署脚本(多套环境,PHP-FPM)
Ø 基础的运维脚本
Ø Git运维脚本(命令的方式)
脚本代码主要涉及的命令工具:
Ø awk、sed:这两个不用说了,都是编程语言,shell 进阶编程必须的
Ø dialog:文本模式下,图形化 UI 设计必须的
Ø tput:也是一个交互性的、控制屏幕输出的工具
脚本演示安装:
使用了 script 命令录制了,整个脚本的安装过程。
在代码包的根目录下有个“demo”的脚本(基于scriptreplay),运行“./demo”即可演示相关安装过程。
本脚本还有很多不完善的地方,另外在分离部署中只对基础的 LNAMP 环境进行测试。仅供学习参考。
下载:百度网盘,链接: http://pan.baidu.com/s/1bnt3uLT,密码: c732。
整个程序分为代码包(30M)和源码包(363M)。
解压运行过程(以 root 执行):
# tar -xvf mallux_nlnamp.tar
# tar -xvf m6-lnamp.tar
# cd lnamp/
# ./pwdHost
使用范围:CentOS 6.x
使用脚本前,本地基于 Cobbler 完成部署的测试 kickstart 文件。
#platform=x86, AMD64, or Intel EM64T
#version=DEVEL
# Firewall configuration
firewall --enabled --ssh
# Install OS instead of upgrade
install
# Use network installation media
url --url=http://192.168.96.98:88/cblr/links/CentOS-6.5-x86_64
# Root password
rootpw --iscrypted $1$GoXayw5C$TlwEAmfGfXIwTeZgseAel0
# System authorization information
auth --useshadow --passalgo=sha512
# Use text mode install
text
# System keyboard
keyboard us
# System language
lang en_US
# SELinux configuration
selinux --permissive
# Do not configure the X Window System
skipx
# Installation logging level
logging --level=info
# Reboot after installation
reboot
# System timezone
timezone --isUtc Asia/Shanghai
# Network information
# Using "old" style networking config. Make sure all MAC-addresses are in cobbler to use the new-style config
network --bootproto=dhcp --device=eth0 --onboot=on
# System bootloader configuration
bootloader --location=mbr --md5pass='$1$8.oYW1$qsN3sdvzytZE0VT/TUph01'
%include /tmp/partitioning
%pre
if grep -q hda$ /proc/partitions
then
HD1st=hda
else
HD1st=sda
fi
echo "bootloader --driveorder=${HD1st}" > /tmp/partitioning
cat >> /tmp/partitioning <<EOF
zerombr yes
part /boot --asprimary --fstype ext4 --ondisk=${HD1st} --size=200
part pv.01 --fstype ext4 --ondisk=${HD1st} --grow --size=1
volgroup mainVG pv.01
logvol swap --vgname=mainVG --fstype swap --size=1024 --name=lv_swap
logvol / --vgname=mainVG --fstype ext4 --size=10000 --name=lv_root
EOF
if [ `grep sd.$ /proc/partitions | wc -l` -gt 1 ]
then
HD2nd=`grep sd.$ /proc/partitions | grep -v $HD1st | awk 'NR==1 {print $NF}'`
cat >> /tmp/partitioning <<-EOF
clearpart --drives=${HD1st},${HD2nd} --all --initlabel
part pv.02 --fstype ext4 --ondisk=${HD2nd} --grow --size=1
volgroup 2ndVG pv.02
logvol /DBHome --vgname=mainVG --fstype ext4 --grow --size=1 --name=lv_DBHome
logvol /home --vgname=2ndVG --fstype ext4 --grow --size=1 --name=lv_home
EOF
else
cat >> /tmp/partitioning <<-EOF
clearpart --drives=${HD1st} --all --initlabel
logvol /home --vgname=mainVG --fstype ext4 --grow --size=1 --name=lv_home
EOF
fi
%packages
@additional-devel
@base
@chinese-support
@development
@hardware-monitoring
@legacy-unix
@network-file-system-client
@network-tools
@performance
@server-platform
@system-admin-tools
@system-management-snmp
cmake
expect
git
ipset
iptraf
iptstate
dstat
lm_sensors
nmap
screen
ftp
telnet
tree
-mysql
-mysql-devel
-mysql-lib
%post
for (( i=0;i<=2;i++ ))
do
ntpdate -b 218.30.114.84 1>>/root/sync_time.log 2>&1
[ $? -eq 0 ] && break
sleep 5
done
hwclock --systohc --utc
Mlux="lnamp_system_v2.0.tar"
wget http://192.168.96.98:88/cblr/links/CentOS-6.5-x86_64/lnamp/$Mlux /root
sed -i '/keepcache/ s;\([[:alpha:]=]*\).*;\11;' /etc/yum.conf
#sed -i '/^#Port 22/aPort 10022' /etc/ssh/sshd_config
#sed -i '/22 / s/22/10022/' /etc/sysconfig/iptables
sed -i "7a alias vi='vim'" /root/.bashrc
sed -i "8a alias ll='ls -al'" /root/.bashrc
sed -i "9a alias grep='grep --color=auto'" /root/.bashrc
sed -i 's;\(^ \{1,\}\)\(\[ "$PS1".*\);\1#\2;' /etc/bashrc
sed -i '/^ \{1,\}#\[ "$PS1" = "\\/a \ [ "$PS1" = "\\\\s-\\\\v\\\\\\$ " ] && PS1="[\\[\\e[0;32;1m\\]\\u\\[\\e[0m\\]@\\[\\e[0;36;1m\\]\\h\\[\\e[0m\\] \\[\\e[0;33;1m\\]\\W\\[\\e[0m\\]]\\\\$ "' /etc/bashrc
grep -q 'md5pass' /boot/grub/grub.conf
if [ $? -gt 0 ]
then
sed -i '/^timeout/a password --md5 $1$8.oYW1$qsN3sdvzytZE0VT/TUph01' /boot/grub/grub.conf
fi
if [ -f '/usr/bin/git' ]
then
cat >>/etc/profile.d/git.sh<<-EOF
# bash completion support for core Git.
if [ -f /etc/bash_completion.d/git ]
then
source /etc/bash_completion.d/git
fi
EOF
fi
[ ! -e "/root/.vimrc" ] && {
cat >>/root/.vimrc<<-EOF
set pastetoggle=<F9>
set nobackup
set noswapfile
set hlsearch
set nonumber
set cindent
set autoindent
set shiftwidth=4
set tabstop=4
set expandtab
set softtabstop=4
set laststatus=2
set ruler
set backspace=indent,eol,start
syntax on
EOF
}
NIC="/etc/sysconfig/network-scripts"
if [ -e "$NIC/ifcfg-em1" ]
then
sed -i "/kernel.*quiet/ s/$/& biosdevname=0/" /boot/grub/grub.conf
rm -rf /etc/udev/rules.d/70-persistent-net.rules
for i in `seq 1 7`
do
emcfg="ifcfg-em$i"
ethcfg="ifcfg-eth$[i-1]"
if [ -e "$NIC/$emcfg" ]
then
mv $NIC/$emcfg $NIC/$ethcfg
sed -i "s/em$i/eth$[i-1]/" $NIC/$ethcfg
fi
done
fi
eject
%end
目录规划:
[root@localhost lnamp]# tree -L 1
.
├── apex.fw ### 目录:存放运维脚本
├── archives ### 目录:git 维护脚本
├── bin ### 目录:存放dialog、tput 等命令
├── conf ### 目录:lnamp 环境部分配置文件
├── etc ### 目录:系统环境脚本、配置之类的
├── fonts ### 目录:Cacti 所需的字体
├── gitclean ### 脚本:git reflog / gc 清理动作
├── gitkeep ### 脚本:空目录下创建.gitkeep文件,防止 git 不提交空目录
├── install ### 脚本:主脚本
├── iptables.recent ### 脚本:iptables recent 模块,防火墙策略相关
├── luxgz ### 目录:lnamp 源码包
├── luxkey ### 目录:ssh 用户 key
├── packages ### 目录:lnamp 源码包解压后的路径
├── pwdHost ### 脚本:linux、mysql用户密码、网络设置
├── README.md ### git 说明性文档
├── RPMs ### 目录:只放了一个YUM epel6 的 RPM 包
├── scripts ### 目录:lnamp 环境安装调用,所有脚本存放位置
├── sql ### 数据库目录:cacti监控系统、system web管理后台
├── timeset ### 脚本:tput控制屏幕输出
├── tmp ### 目录:临时输出文档,工作目录
├── updates ### 目录:存放Yum 自定义的本地源压缩档
└── version ### 脚本:用来修改脚本的作者、E-Mail等信息
14 directories, 8 files
脚本执行流程:“pwdHost”->“install”
首次运行时,请运行“pwdHost”脚本,这个脚本会询问你一些相关设置,并在tmp下生成一些临时文件,脚本最后会调用“install”脚本进入部署lnamp环境的主界面
“pwdHost”脚本会做如下设置:
Ø Linux、MariaDB数据库的root密码
Ø 本地新安装或远程数据库连接设置
Ø 本地网络设置
相关界面:

图1 pwdHost UI
当运行过 pwdHost脚本后,后续就可直接执行“./install”调用程序主脚本了。如果需要重新修改设置,可重新运行pwdHost脚本。
运行“install脚本”时,会显示当前系统的时间(timeset脚本控制)。
如果时间不正确,按下一次“ctrl+c”时,进行设置(如图2)。否则可再次按下“ctrl+c”进入下一个安装环节(如图3)。

图2 timeset 脚本输出

图3 选择应用类型
说明:图3这个界面,是以前残留下来的。因我之前的公司是用PHP开发的,auto4s和dprp5s为两个业务系统的普通账号。这个在后续相关UI的选择操作时,除了会在系统上创建相关用户、拷贝用户密钥(luxkey目录下)以外,还会在部署lnamp环境时,根据这个选择,去修改模板配置文件,生成apache所需的业务系统配置文件。Git 用户同理,但 git 用户会多一个操作,解压“archives”下的 git 运维脚本“repo_sync.tgz”到 git 用户下。
图3选择后,会进入到一个询问你是否要更改“root”用户密码的UI。确认后,正式进入部署lnamp主界面(如图4)。

图4 lnamp 主程界界面
这个不细说的,看着界面上,按相关键进行UI操作进行了,要提的几点如下:
Lnamp环境部署上,如图5所示,每个源码编译的包,都提供了输出编译参数(Debug),编译后可访问的地址(Available URL)、正式编译安装(Install)等选项。

图5 nginx 安装界面
数据库提供了mysql(5.1)和mariadb(5.1和5.5),编译时选择字符校对集时,需要注意一下。一般情况下,选择“utf-8”即可。但是,我们线上的 git环境,申核代码这块用了谷歌的gerrit,测试中发现2.5和2.7版本,gerrit无法在数据库编译时指定“utf-8”下工作,gerrit web UI上会有些操作会报错,即使手工创建修改指定指定字符校对集也不行,不知道怎么回事,所以就引入了默认“latin1”字符校对集的编译一项。
整个 LNAMP 环境部署完毕以后,相关可用的链接地址,就不贴了。相关编译过程中,都有界面可查看。
LNAMP 环境部署,所需的相关脚本(图6),环境都是基于源码编译。

图6 LNAMP 部署脚本
文件说明:
mlux.pwd:密码定义文件,其它一些数据库、普通用户、web 登陆用户密码设置。
default.pwd:默认linux和mysql的root用户密码,在没有运行“pwdHost”脚本,直接调用“install”脚本时,默认将使用该文件中的root用户默认密码。否则,使用pwdHost脚本设置的密码。
其它文件,_memu 结尾的为 UI上的界面部分,其它 _ins 等都是程序用到的脚本定义部分。这些脚本,都被根目录下的“install”脚本引用了。
源码包(如图7),基本全是官方下载的,不过我有强迫怔。在本地解压后,更改属组用户为 root 后,重新打包了,-_##!
图7 源码包
源码包说明:
php-5.2.17.tar.gz:集成了 php-fpm 补丁。
最后,附上文章开始提到的那个数据库需求的脚本,因涉及到数据库,就只贴代码了,仅供参考。脚本中大量应用了 dialog、sed 和 awk部分,应该算是 dialog 学习的一个好脚本。
#!/usr/bin/env bash
### --------------------------------------------------
### Filename: imgen_update
### Revision: latest stable
### Author: Mallux
### E-mail: gbmagic@aliyun.com
### Blog: blog.mallux.org
### Description: Update IMGEN System Product Information
### --------------------------------------------------
### Copyright © 2014-2015 Mallux
#------------
# Exit Operation
#------
trap "__clean_up" EXIT
__clean_up() {
exec 6>&-
rm -rf $tmp_dir
}
#------------
# Shell - Global Variable and Function Settings
#------
Author="Mallux"
Email="gbmagic@aliyun.com"
pid=$$
tmp_dir="/tmp/imgen_tools/$pid" ; mkdir -p $tmp_dir ; chmod 1777 ${tmp_dir%/*} &> /dev/null
tmp_fifo="$tmp_dir/__$pid.fifo"
mysql_dump="mysqldump"
mysql_bin="mysql"
### Backup level and Operation Table
backup_level=( db_level table_level record_level )
imgen_table=( imgen_product imgen_ref imgen_tac )
backup_dir="./0-bak"
db_level_dir="$backup_dir/db_level"
table_level_dir="$backup_dir/table_level"
### Call mysql Command Function
__d_mysql_do_bin_cmd() {
$mysql_bin -h localhost -u$dbuser -p$dbpass "$@"
[ $? -eq 0 ] && return 0 || return 1
}
### Call mysqldump Command Function
__d_mysql_do_dump_cmd() {
args_1st=$1 ; shift
if [ x"$args_1st" == x"db_level" ]
then
$mysql_dump --opt --master-data=2 --skip-add-drop-table -u$dbuser -p$dbpass "$@"
elif [ x"$args_1st" == x"table_level" ]
then
$mysql_dump --opt --master-data=2 --skip-add-drop-table -c --skip-extended-insert -u$dbuser -p$dbpass "$@"
fi
[ $? -eq 0 ] && return 0 || return 1
}
#------------
# Dialog Unit UI Design
#------
__d_dialog_design_UI() {
mkfifo $tmp_fifo
exec 6<>$tmp_fifo
arch=`arch`
if [ x"$arch" == x"i686" ]
then
dgcmd=`pwd`/bin/dialog32
elif [ x"$arch" == x"x86_64" ]
then
dgcmd=`pwd`/bin/dialog64
else
dgcmd=`which dialog`
fi
[ ! -f "$dgcmd" -o ! -x "$dgcmd" ] && {
echo -e "\e[33;1mFatal:\e[0m The \"dialog\" command not found or does not have execute permission.\n"
exit 1
}
title="IMGEN System Product Update Author: $Author E-mail: $Email"
### Dialog msgbox Unit Function
__d_dialog_design_msgbox_UI() {
unset exit_state
ok_label=$1 ; height=$2 ; width=$3 ; shift 3
$dgcmd --clear \
--backtitle "$title" \
--title "| $sub_title |" \
--colors \
--ok-label " $ok_label " \
--msgbox "$MSG" $height $width
return $?
}
### Dialog yesno Unit Function
__d_dialog_design_yesno_UI() {
unset exit_state
yes_label=$1 ; no_label=$2 ; height=$3 ; width=$4 ; shift 4
$dgcmd --clear \
--backtitle "$title" \
--title "| $sub_title |" \
--colors \
--defaultno \
--yes-label " $yes_label " \
--no-label " $no_label " \
--yesno "$MSG" $height $width
return $?
}
### Dialog password Unit Function
__d_dialog_design_password_UI() {
unset exit_state
ok_label=$1 ; cancel_label=$2 ; height=$3 ; width=$4 ; shift 4
$dgcmd --clear \
--backtitle "$title" \
--title "| $sub_title |" \
--colors \
--ok-label " $ok_label " \
--cancel-label " $cancel_label " \
--passwordbox "$MSG" $height $width \
--output-fd 6
return $?
}
### Dialog inputbox Unit Function
__d_dialog_design_inputbox_UI() {
unset exit_state
ok_label=$1 ;cancel_label=$2 ; height=$3 ; width=$4 ; shift 4
$dgcmd --clear \
--backtitle "$title" \
--title "| $sub_title |" \
--colors \
--ok-label " $ok_label " \
--cancel-label " $cancel_label " \
--inputbox "$MSG" $height $width \
--output-fd 6
return $?
}
### Dialog textbox Unit Function
__d_dialog_design_textbox_UI() {
unset exit_state
file=$1
exit_label=$2 ; height=$3 ; width=$4 ; shift 4
$dgcmd --clear \
--backtitle "$title" \
--title "| $sub_title |" \
--colors \
--exit-label " $exit_label " \
--textbox $file $height $width
return $?
}
### Dialog menu Unit Function
__d_dialog_design_menu_UI() {
unset exit_state
ok_label=$1 ; cancel_label=$2 ; extra_label=$3 ; height=$4 ; width=$5 ; list_height=$6 ; shift 6
$dgcmd --clear \
--backtitle "$title" \
--title "| $sub_title |" \
--colors \
--ok-label " $ok_label " \
--cancel-label " $cancel_label " \
--extra-button \
--extra-label " $extra_label " \
--menu "$MSG" $height $width $list_height \
${list_items[*]} \
--output-fd 6
return $?
}
### Dialog radiolist Unit Function
__d_dialog_design_radiolist_UI() {
unset exit_state
ok_label=$1 ; cancel_label=$2 ; extra_label=$3 ; height=$4 ; width=$5 ; list_height=$6 ; shift 6
$dgcmd --clear \
--backtitle "$title" \
--title "| $sub_title |" \
--colors \
--visit-items \
--ok-label " $ok_label " \
--cancel-label " $cancel_label " \
--extra-button \
--extra-label " $extra_label " \
--radiolist "$MSG" $height $width $list_height \
${list_items[*]} \
--output-fd 6
return $?
}
### Dialog checklist Unit Function
__d_dialog_design_checklist_UI() {
unset exit_state
select_item=$1
ok_label=$2 ; cancel_label=$3 ; extra_label=$4 ; height=$5 ; width=$6 ; list_height=$7 ; shift 7
$dgcmd --clear \
--backtitle "$title" \
--title "| $sub_title |" \
--colors \
--separate-output \
--single-quoted \
--visit-items \
--ok-label " $ok_label " \
--cancel-label " $cancel_label " \
--extra-button \
--extra-label " $extra_label " \
--checklist "$MSG" $height $width $list_height \
${list_items[*]} \
2>$select_item
return $?
}
### Dialog form Unit Function
__d_dialog_design_form_UI() {
### The EOF section include leading TAB characters ( ctrl+v and Tab ), and end with a Space characters.
cat > $dload_form <<-EOF
unset exit_state
$dgcmd --clear \
--backtitle "$title" \
--title "| $sub_title |" \
--colors \
--ok-label " $ok_label " \
--cancel-label " $cancel_label " \
--extra-button \
--extra-label " $extra_label " \
--form "$MSG" $height $width $form_height \
${form_items[*]} \
2>$field_form
EOF
}
}
#------------
# Imgen System Product Database Operation
#------
__o_db_operation_UI() {
### Enter Database Name Function
__o_db_operation_input_dbname_UI() {
sub_title="Welcome to `whoami`"
MSG="\nEnter \Z1Database\Zn name for connect ( Default: \Z1IMGEN\Zn )"
### Call Dialog inputbox UI
__d_dialog_design_inputbox_UI Next Quit 10 70
exit_state=$? ; echo -e "\nexit" >&6
read -u6 dbname ; read -u6 EXIT
### Quit Button
if [ x"$exit_state" == x"1" ]
then
exit 1
### Next Button
elif [ x"$exit_state" == x"0" ]
then
dbname=${dbname:-IMGEN}
__o_db_operation_input_dbuser_UI
fi
}
### Enter Database User Function
__o_db_operation_input_dbuser_UI() {
MSG="\nEnter Database \Z1User\Zn for Login ( Default: \Z1root\Zn )"
### Call Dialog inputbox UI
__d_dialog_design_inputbox_UI Next Previous 10 70
exit_state=$? ; echo -e "\nexit" >&6
read -u6 dbuser ; read -u6 EXIT
### Previous Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_connect_UI
### Next Button
elif [ x"$exit_state" == x"0" ]
then
dbuser=${dbuser:-root}
__o_db_operation_input_dbpass_UI
fi
}
### Enter Database Password Function
__o_db_operation_input_dbpass_UI() {
MSG="\nEnter Database \Z1$dbuser\Zn Password ( Default: \Z1NULL\Zn )"
### Call Dialog password UI
__d_dialog_design_password_UI Next Previous 10 70
exit_state=$? ; echo -e "\nexit" >&6
read -u6 dbpass ; read -u6 EXIT
### Previous Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_input_dbuser_UI
### Next Button
elif [ x"$exit_state" == x"0" ]
then
dbpass=${dbpass:-sqlpass}
fi
}
### Test Database Connection Function
__o_db_operation_connect_UI() {
__o_db_operation_input_dbname_UI
### Call mysql Commamd, test Database connectivity
__d_mysql_do_bin_cmd $dbname -e quit 2>/dev/null
[ $? -eq 0 ] && dbcon_state="success" || dbcon_state="failure"
if [ x"$dbcon_state" == x"success" ]
then
__o_db_operation_main_menu_UI
else
sub_title="$dbname - Database Connection" ; MSG="\nIncorrect configure, Unable to Connect Database."
__d_dialog_design_msgbox_UI Return 7 70
__o_db_operation_connect_UI
fi
}
### Database Operation Menu Type Function
__o_db_operation_menu_type_UI() {
menu_type=$1 ; ok_label=$2 ; cancel_label=$3 ; extra_label=$4 ; shift 4
case $menu_type in
menu)
list_height=${#list_items[*]}
### Call Dialog menu UI
__d_dialog_design_menu_UI $ok_label $cancel_label $extra_label $[list_height+9] 70 $list_height
;;
radiolist)
list_items=( `echo ${list_items[*]} | xargs -n2 | awk '{print $1,$2,"off"}'` )
list_height=`echo ${list_items[*]} | xargs -n3 | wc -l`
### Call Dialog radiolist UI
__d_dialog_design_radiolist_UI $ok_label $cancel_label $extra_label $[list_height+9] 70 $list_height
;;
esac
return $?
}
### Database Operation Main Menu Function
__o_db_operation_main_menu_UI() {
unset list_items ; declare -a list_items
list_items=( "Backup Operation"
"Up-Del Operation"
"Restore Operation" )
list_height=${#list_items[*]}
sub_title="$dbname - Database Operation" ; width=70
MSG="- Select Database (\Z1 $dbname \Zn) Operation -"
MSG=`echo $MSG | sed ':a s/^.\{1,'"$width"'\}$/ & /;ta'`
MSG="\n$MSG"
### Choice Menu Type, menu or radiolist
__o_db_operation_menu_type_UI radiolist Select Re-connect Quit
exit_state=$? ; echo -e "\nexit" >&6
read -u6 operation ; read -u6 EXIT
### Re-connect Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_connect_UI
### Quit Button
elif [ x"$exit_state" == x"3" ]
then
exit 1
### Select Button
elif [ x"$exit_state" == x"0" ]
then
[ -z "$operation" ] && __o_db_operation_main_menu_UI
case "$operation" in
Backup)
__o_db_operation_input_tac_id_UI backup
;;
Up-Del)
__o_db_operation_input_tac_id_UI updel
;;
Restore)
__o_db_operation_restore_UI
;;
esac
fi
}
### Enter Product TAC_ID Function
__o_db_operation_input_tac_id_UI() {
unset product_id tac_id tac_fac tac_ref ref_id product_id_array tac_ref_array tac_id_array
unset operation ; operation=$1 ; shift
if [ x"$operation" == x"backup" ]
then
sub_title="$dbname - Backup Operation"
MSG="\nEnter \Z1TAC_ID(s)\Zn to Backup ( Separate them By \Z1comma\Zn )"
elif [ x"$operation" == x"updel" ]
then
sub_title="$dbname - Retrieve Product"
MSG="\nEnter \Z1TAC_ID\Zn to Retrieve Product ( Default: \Z1NULL\Zn )"
fi
### Call Dialog inputbox UI
__d_dialog_design_inputbox_UI Next Main-menu 10 70
exit_state=$? ; echo -e "\nexit" >&6
read -u6 tac_id ; read -u6 EXIT
### Main-menu Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_main_menu_UI
### Next Button
elif [ x"$exit_state" == x"0" ]
then
[ -z "$tac_id" ] && __o_db_operation_input_tac_id_UI $operation
#tac_id=${tac_id:-014496} ### Conflict - PRODUCT_ID && TAC_REF - 0-sql/imgen_2nd.sql
#tac_id=${tac_id:-867023} ### Conflict - PRODUCT_ID - 0-sql/imgen_1st.sql
#tac_id=${tac_id:-014450} ### Conflict - TAC_REF - 0-sql/imgen_1st.sql
#tac_id=${tac_id:-868858} ### Conflict - TAC_REF - 0-sql/imgen_3rd.sql
#tac_id=${tac_id:-864330} ### Normal
case "$operation" in
backup)
__o_db_operation_backup_UI
;;
updel)
__o_db_operation_query_tac_id_UI
;;
esac
fi
}
### Database TAC_ID Product Information Query Function
__o_db_operation_query_tac_id_info() {
product_info=$1 ; condition=$2 ; shift 2
### Table: imgen_product ( 0 ), imgen_ref ( 1 ) and imgen_tac ( 2 )
product_query="select t.TAC_ID,t.TAC_FAC,p.*,r.TAC_REF,r.REF_ID,r.REF_CREATION_DATE
from ${dbname}.${imgen_table[0]} p left join ${dbname}.${imgen_table[1]} r
on p.PRODUCT_ID=r.PRODUCT_ID left join ${dbname}.${imgen_table[2]} t on t.TAC_REF=r.TAC_REF
where t.TAC_ID=$tac_id"
if [ x"$condition" == x"normal" ]
then
product_query="${product_query}\G"
elif [ x"$condition" == x"tac_ref_conflict" ]
then
product_query="${product_query} and ${query_condition}\G"
fi
### Call mysql Command, generate TAC_ID product information
__d_mysql_do_bin_cmd -e "$product_query" > $product_info
[ -f "$product_info" ] && {
product_id=`awk '/PRODUCT_ID/ { if ( !a[$2]++ ) print $2 }' $product_info | xargs`
product_id_array=( `echo $product_id` )
tac_ref=`awk '/TAC_REF/ {print $2}' $product_info | xargs`
tac_fac=`awk '/TAC_FAC/ { if ( !a[$2]++ ) print $2 }' $product_info | xargs`
ref_id=`awk '/REF_ID/ { if ( !a[$2]++ ) print $2 }' $product_info | xargs`
fline_count=`sed -n '$=' $product_info` ; fline_count=${fline_count:-1}
block_splict=`echo $tac_ref | xargs -n1 | wc -l`
block_height=$[$fline_count/$block_splict]
sed -i '1,'"$block_height"' { /PRODUCT_CODE/ { x;H;d } ; /PRODUCT_REF_COM/ { G } }' $product_info
sed -i ''"$block_height"',$ { /PRODUCT_CODE/ { x;H;d } ; /PRODUCT_REF_COM/ { G } }' $product_info
sed -i -e "1 s/.*/TAC_ID: $tac_id\n------/" -e "1 s/^/\n/ ; $ G" $product_info
sed -i -e "/^\*\{6,\}.*row.*\*\{6,\}$/ s/.*//" $product_info
}
}
### Database TAC_ID Product Information Conflict Detection Function
__o_db_operation_query_tac_id_UI() {
product_info="$tmp_dir/__p_${tac_id}.product_info"
sub_title="$dbname Database - Query Result"
### Retrieve TAC_ID product informatin
__o_db_operation_query_tac_id_info $product_info normal
if [ -z "$tac_id" -o -z "$product_id" -o -z "$ref_id" ]
then
MSG="\nUnable to retrieve TAC_ID (\Z1 $tac_id \Zn) Product information."
__d_dialog_design_msgbox_UI Re-retrieve 7 70
__o_db_operation_input_tac_id_UI updel
fi
for key in ${!product_id_array[*]}
do
if [ x"$key" == x"0" ]
then
query_condition="PRODUCT_ID=${product_id_array[$key]}"
else
query_condition="$query_condition or PRODUCT_ID=${product_id_array[$key]}"
fi
done
### Call mysql Command, retrieve PRODUCT_ID related TAC_REF. Table: imgen_ref ( 1 )
tac_ref_array=( `__d_mysql_do_bin_cmd $dbname -e "select * from ${imgen_table[1]} where ${query_condition}\G" | awk '/TAC_REF: / {print $2}'` )
### TAC_REF Conflict Detection ( imgen_tac major key ), Duplicate TAC_REF
### Retrieve Process: TAC_ID -> TAC_REF -> PRODUCT_ID
if [ ${#product_id_array[*]} -gt 1 -a ${#tac_ref_array[*]} -gt 1 ]
then
### Duplicate TAC_REF Number. Don't use tac_ref_array to filter.
### Because, the system may detect PRODUCT_ID and TAC_REF conflict at the same time.
### The tac_ref value is used to query TAC_REF duplicate items.
unique_tac_ref=( `echo $tac_ref | xargs -n1 | awk '!a[$0]++ { print $0 }'` )
MSG="\nDuplicate TAC_REF ( TAC_ID:\Z1 $tac_id \Zn, TAC_FAC:\Z1 $tac_fac \Zn)"
MSG="$MSG\n\nQuery TAC_ID: \Z1$tac_id\Zn | Conflict TAC_REF:\Z1 ${unique_tac_ref[*]} \Zn"
MSG="$MSG\n\nConflict Major Key Information:\n------"
MSG="$MSG\nPRODUCT_ID: \Z1 $(echo $product_id | xargs -n1 | awk '{ print NR" | "$0,"\\ " }' | xargs) \Zn"
MSG="$MSG\n TAC_REF: \Z1 $(echo $tac_ref | xargs -n1 | awk '{ print NR" | "$0,"\\ " }' | xargs) \Zn"
MSG="$MSG\n REF_ID: \Z1 $(echo $ref_id | xargs -n1 | awk '{ print NR" | "$0,"\\ " }' | xargs) \Zn"
MSG="$MSG\n\nYou need to do the following Operation.\n------"
MSG="$MSG\nStep 1. \Z1insert\Zn new tac informatin into imgen_tac table,"
MSG="$MSG\n and \Z1generate New\Zn TAC_REF automatically.\n"
MSG="$MSG\nStep 2. \Z1update\Zn duplicate TAC_REF items on imgent_ref table,"
MSG="$MSG\n and \Z1relate New\Zn TAC_REF automatically."
### Step 1.1 - Retrieve related TAC_REF, Table: imgen_ref ( 1 )
tac_ref="${unique_tac_ref[0]}"
__d_dialog_design_msgbox_UI Next 23 80
__o_db_operation_conflict_tac_ref_query_UI
### PRODUCT_ID Conflict Detection ( imgen_product major key ), Duplicate PRODUCT_ID
### Retrieve Process: PRODUCT_ID -> TAC_REF -> TAC_ID
elif [ ${#product_id_array[*]} -eq 1 -a ${#tac_ref_array[*]} -gt 1 ]
then
for key in ${!tac_ref_array[*]}
do
if [ x"$key" == x"0" ]
then
query_condition="TAC_REF=${tac_ref_array[$key]}"
else
query_condition="$query_condition or TAC_REF=${tac_ref_array[$key]}"
fi
done
### Step 2.1 - Call mysql Command, Retrieve related TAC_ID. Table: imgen_tac ( 2 )
tac_id_array=( `__d_mysql_do_bin_cmd $dbname -sN -e "select TAC_ID from ${imgen_table[2]} where $query_condition;"` )
conflict_tac_id_file="$tmp_dir/__p_${tac_id}.conflict.tac_id"
echo ${tac_id_array[*]} | xargs -n1 > $conflict_tac_id_file
MSG="\nDuplicate PRODUCT_ID (\Z1 $product_id \Zn, TAC_ID:\Z1 ${tac_id_array[*]} \Zn)"
MSG="$MSG\n\nQuery TAC_ID: \Z1$tac_id\Zn | Conflict TAC_ID: \Z1$(echo ${tac_id_array[*]} | xargs -n1 | grep -v $tac_id)\Zn"
MSG="$MSG\n\nYou need to do the following Operation.\n------"
MSG="$MSG\nStep 1. \Z1insert\Zn new product informatin into imgen_product table,"
MSG="$MSG\n and \Z1generate New\Zn PRODUCT_ID automatically.\n"
MSG="$MSG\nStep 2. \Z1update\Zn duplicate PRODUCT_ID items on imgent_ref table,"
MSG="$MSG\n and \Z1relate New\Zn PRODUCT_ID automatically."
__d_dialog_design_msgbox_UI Next 17 80
__o_db_operation_conflict_product_id_update_UI
### No conflict
else
### Call Dialog textbox UI
__d_dialog_design_textbox_UI $product_info Next $[fline_count+9] 90
exit_state=$? ; #echo $exit_state ; exit
### Next Button
if [ x"$exit_state" == x"0" ]
then
__o_db_operation_menu_updel_UI
fi
fi
}
### Database TAC_REF Conflict Operation - Query Filter
__o_db_operation_conflict_tac_ref_query_UI() {
field_info="$tmp_dir/__p_${tac_id}.conflict.query_field"
field_form="$tmp_dir/__p_${tac_id}.conflict.query_form"
field_data="$tmp_dir/__p_${tac_id}.conflict.query_data"
dload_form="$tmp_dir/__d_${tac_id}.dialog_design_form_UI"
sub_title="$dbname - Query Filter"
MSG="\nQuery TAC_ID: \Z1$tac_id\Zn | Conflict TAC_REF:\Z1 ${unique_tac_ref[*]} \Zn"
unset list_items ; declare -a list_items
list_items=( `cat $product_info | awk -F':' '/PRODUCT_/ { if ( !a[$1]++ ) print $1,"field","off" }' | sed '/PRODUCT_CREATION_DATE/d ; s/^ \{1,\}//'` )
list_height=`echo ${list_items[*]} | xargs -n3 | wc -l`
### Call Dialog checklist UI
__d_dialog_design_checklist_UI $field_info Select Re-Select Main-menu $[list_height+9] 70 $list_height
exit_state=$? ; #echo $exit_state ; exit
query_field=( `cat $field_info` ) ; field_height=${#query_field[*]}
field_max_width=`echo ${query_field[*]} | xargs -n1 | awk '{ if ( w < length($1) ) w = length($1) } END { print w }'`
### Re-Select Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_conflict_tac_ref_query_UI
### Main-menu Button
elif [ x"$exit_state" == x"3" ]
then
__o_db_operation_main_menu_UI
### Select Button
elif [ x"$exit_state" == x"0" ]
then
[ x"$field_height" == x"0" ] && {
MSG="\n Please select at least \Z1One\Zn field to Query."
__d_dialog_design_msgbox_UI Return 7 70
__o_db_operation_conflict_tac_ref_query_UI
}
__o_db_operation_conflict_tac_ref_retrieve_UI
fi
}
### Database TAC_REF Conflict Operation - Retrieve Product
__o_db_operation_conflict_tac_ref_retrieve_UI() {
### The original product information file ( __p_${tac_id}.product_info )
__product_info="$product_info"
unset form_items ; declare -a form_items
### Append field form, the form look like this: [ label y x item y x flen ilen ] ...
for key in ${!query_field[*]}
do
case "${query_field[$key]}" in
PRODUCT_NAME|PRODUCT_CODE)
form_value="5054W"
;;
PRODUCT_DESIGNATION|PRODUCT_REF_COM)
form_value="Pixi3-5.5 4G"
;;
PRODUCT_CREATION_DATE)
form_value=`date '+%Y-%m-%d %T'`
;;
PRODUCT_ID)
form_value="1698"
;;
esac
form_items[$key]="${query_field[$key]}: $[key+1] 1 '$form_value' $[key+1] $[field_max_width+3] 70 200"
done
MSG="\nEnter the following information:"
set -- Retrieve Re-input Return $[field_height+9] 70 $field_height
ok_label=$1 ; cancel_label=$2 ; extra_label=$3 ; height=$4 ; width=$5 ; form_height=$6 ; shift 6
### Call Dialog form UI - load form data
__d_dialog_design_form_UI ; sed -i '1,$ s/ $//' $dload_form ; source $dload_form
exit_state=$? ; #echo $exit_state ; exit
### Re-input Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_conflict_tac_ref_retrieve_UI
### Return Button
elif [ x"$exit_state" == x"3" ]
then
rm -rf $field_info $field_form $dload_form
__o_db_operation_conflict_tac_ref_query_UI
### Retrieve Button
elif [ x"$exit_state" == x"0" ]
then
[ -f "$field_info" ] && extra_comma_row=$[$(sed -n '$=' $field_info)+1]
[ -f "$field_form" ] && {
sed -i 's/ \{1,\}$//' $field_form
awk 'ARGIND==1 { a[FNR]=$0 ; next } ARGIND==2 { print a[FNR]"=""'\''"$0"'\''" }' $field_info $field_form > $field_data
unset query_condition
while read condition
do
if [ -z "$query_condition" ]
then
query_condition="p.$condition"
else
query_condition="$query_condition and p.$condition"
fi
done < $field_data
}
query_msg="$tmp_dir/__p_${tac_id}.conflict.query_msg"
### Step 1.2 - Retrieve TAC_ID product informatin and related PRODUCT_ID ( imgen_ref )
__o_db_operation_query_tac_id_info $query_msg tac_ref_conflict
if [ -z "$tac_id" -o -z "$product_id" -o -z "$ref_id" ]
then
MSG="\nUnable to retrieve TAC_ID (\Z1 $tac_id \Zn) Product information."
### Reuse the original product information file ( __p_${tac_id}.product_info )
### Because there is no query data will cause a script error.
product_info="$__product_info"
__d_dialog_design_msgbox_UI Re-retrieve 7 70
__o_db_operation_conflict_tac_ref_retrieve_UI
fi
### Call Dialog textbox UI
__d_dialog_design_textbox_UI $query_msg Next $[fline_count+9] 90
exit_state=$? ; #echo $exit_state ; exit
### Next Button
if [ x"$exit_state" == x"0" ]
then
__o_db_operation_conflict_tac_ref_update_UI
fi
fi
}
### Database TAC_REF Conflict Operation - Update Product
__o_db_operation_conflict_tac_ref_update_UI() {
tacid_info="$tmp_dir/__p_${tac_id}.tacid_info"
field_info="$tmp_dir/__p_${tac_id}.conflict.insert_field"
field_form="$tmp_dir/__p_${tac_id}.conflict.insert_form"
field_data="$tmp_dir/__p_${tac_id}.conflict.insert_data"
### Call mysql Command, generate TAC_ID tac Field information. Table: imgen_tac ( 2 )
__d_mysql_do_bin_cmd $dbname -e "select * from ${imgen_table[2]} where TAC_REF=$tac_ref\G" | sed '1d' > $tacid_info
awk -F': ' '{print $1}' $tacid_info > $field_info
unset form_items ; declare -a form_items
insert_field=( `cat $tacid_info | awk -F':' '{print $1}'` ) ; field_height=${#insert_field[*]}
field_max_width=`echo ${insert_field[*]} | xargs -n1 | awk '{ if ( w < length($1) ) w = length($1) } END { print w }'`
### Append field form, the form look like this: [ label y x item y x flen ilen ] ...
for key in ${!insert_field[*]}
do
case "${insert_field[$key]}" in
TAC_CREATION_DATE)
form_value=`date '+%Y-%m-%d %T'`
;;
TAC_REF)
### Call mysql Command, Retrieve New TAC_REF. Table: imgen_tac ( 2 )
form_value=`__d_mysql_do_bin_cmd $dbname -sN -e "show create table ${imgen_table[2]}\G" | \
sed -n '/.*ENGINE=.*AUTO_INCREMENT=\([[:digit:]]*\) .*/ s//\1/p'`
new_tac_ref="$form_value"
;;
*)
form_value=`awk -F': ' '/'"${insert_field[$key]}"'/ {print $2}' $tacid_info`
;;
esac
form_items[$key]="${insert_field[$key]}: $[key+1] 1 '$form_value' $[key+1] $[field_max_width+3] 70 200"
done
sub_title="$dbname - TAC_REF Conflict" ; width=70
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn | TAC_REF: \Z1$tac_ref\Zn | REF_ID: \Z1$ref_id\Zn"
MSG=`echo $MSG | sed ':a s/^.\{1,'"$[width-1]"'\}$/ & /;ta'`
MSG="\n$MSG\n\n\Z1Step 1.\Zn insert \Z1New\Zn tac informatin into imgen_tac table."
MSG="$MSG\n The \Z1TAC_REF\Zn ( major Key ) is automatically generated."
set -- Insert Re-input Main-menu $[field_height+12] $width $field_height
ok_label=$1 ; cancel_label=$2 ; extra_label=$3 ; height=$4 ; width=$5 ; form_height=$6 ; shift 6
### Call Dialog form UI
__d_dialog_design_form_UI ; sed -i '1,$ s/ $//' $dload_form ; source $dload_form
exit_state=$? ; #echo $exit_state ; exit
### Re-input Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_conflict_tac_ref_update_UI
### Main-menu Button
elif [ x"$exit_state" == x"3" ]
then
rm -rf $tacid_info $field_info $field_form $dload_form
__o_db_operation_main_menu_UI
### Insert Button
elif [ x"$exit_state" == x"0" ]
then
[ -f "$field_info" ] && extra_comma_row=$[$(sed -n '$=' $field_info)+1]
[ -f "$field_form" ] && {
sed -i 's/ \{1,\}$//' $field_form
awk 'ARGIND==1 { a[FNR]=$0 ; next } ARGIND==2 { print a[FNR]":",$0 }' $field_info $field_form > $field_data
new_tac_id=`awk '/TAC_ID/ {print $2}' $field_data`
new_tac_fac=`awk '/TAC_FAC/ {print $2}' $field_data`
new_tac_ref=`awk '/TAC_REF/ {print $2}' $field_data`
}
insert_sql="$tmp_dir/__p_${tac_id}.conflict.insert_sql"
insert_msg="$tmp_dir/__p_${tac_id}.conflict.insert_msg"
### Related Process: Generate ( SQL ) -> Insert ( imgen_tac )-> Relate ( imgen_ref )
### Step 1.3 - Generate insert DML statement, insert tac informatin into imgen_tac ( 2 ).
awk -F': ' 'BEGIN { print "insert into '${imgen_table[2]}' (" } \
ARGIND==1 { print $0"," ; next } \
ARGIND==2 { a[FNR]=$0 ; b[j++]=FNR } \
END { print ") values (" ; for (i=0;i<j;i++) print "'\''"a[b[i]]"'\''," }' $field_info $field_form | \
sed -e '1,$ s/^ \{1,\}// ; $s/,/ );/' -e ''${extra_comma_row}' s/,$//' > $insert_sql
[ -f "$insert_sql" ] && sed -e '1,$ s/^/| /' -e '1,$ s/$/\\n/' $insert_sql > $insert_msg
msg_height=`sed -n '$=' $insert_msg`
MSG="\nTAC_ID: \Z1$tac_id $tac_fac\Zn -> \Z1$new_tac_id $new_tac_fac\Zn | TAC_REF: \Z1$tac_ref\Zn -> \Z1$new_tac_ref\Zn"
MSG="$MSG\n\n------"
MSG="$MSG\n\Z1WARNING:\Zn Are you sure want to perform \Z1Insert\Zn Operation? ( Default: \Z1No\Zn )"
MSG="$MSG\n\n+------"
MSG="$MSG\n$(cat $insert_msg)+------"
### Call Dialog yesno UI
__d_dialog_design_yesno_UI Continue Cancel $[msg_height+13] 92
exit_state=$? ; #echo $exit_state ; exit
### Cancel Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_input_tac_id_UI updel
### Continue Button
elif [ x"$exit_state" == x"0" ]
then
MSG="\nTAC_ID: \Z1$tac_id\Zn -> \Z1$new_tac_id\Zn | TAC_REF: \Z1$tac_ref\Zn -> \Z1$new_tac_ref\Zn"
MSG="$MSG\n\n\Z1Step 2 :\Zn\n------"
### Step 1.4 - Call mysql Command, Insert New tac informain ( Record - Row level, insert into imgen_tac Table )
__d_mysql_do_bin_cmd $dbname < $insert_sql
[ $? -eq 0 ] && insert_state="Success" || insert_state="Failure"
MSG="$MSG\n imgen_tac \Z1Insert\Zn - [\Z1 $insert_state \Zn]"
### step 1.5 - Call mysql Command, Update old TAC_REF to New TAC_REF ( Record - Row level, update imgen_ref Table )
update_sql="update ${imgen_table[1]} set TAC_REF=$new_tac_ref where PRODUCT_ID=$product_id and TAC_REF=$tac_ref and REF_ID=$ref_id;"
[ x"$insert_state" == x"Success" ] && __d_mysql_do_bin_cmd $dbname -e "$update_sql"
[ $? -eq 0 ] && update_state="Success" || update_state="Failure"
MSG="$MSG\n imgen_ref \Z1Update\Zn - [\Z1 $update_state \Zn]"
MSG="$MSG\n\nIf it was successful, please press the \Z1Re-retrieve\Zn button to continue,"
MSG="$MSG\nand \Z1Update\Zn product information if necessarily.\n"
### Call Dialog msgbox UI
__d_dialog_design_msgbox_UI Re-retrieve 15 80
exit_state=$? ; #echo $exit_state ; exit
### Re-retrieve Button
if [ x"$exit_state" == x"0" ]
then
__o_db_operation_input_tac_id_UI updel
fi
fi
fi
}
### Database PRODUCT_ID Conflict Operation - Retrieve and Update
__o_db_operation_conflict_product_id_update_UI() {
field_info="$tmp_dir/__p_${tac_id}.conflict.insert_field"
field_form="$tmp_dir/__p_${tac_id}.conflict.insert_form"
field_data="$tmp_dir/__p_${tac_id}.conflict.insert_data"
dload_form="$tmp_dir/__d_${tac_id}.dialog_design_form_UI"
### Call mysql Command, generate TAC_ID product Field information. Table: imgen_table ( 0 )
__d_mysql_do_bin_cmd $dbname -e "select * from ${imgen_table[0]} where PRODUCT_ID=$product_id\G" | sed '1d' | awk -F':' '{print $1}' > $field_info
sed -i -e '/PRODUCT_CODE/ { h;d } ; /PRODUCT_REF_COM/ { G }' $field_info
insert_field=( `cat $field_info` ) ; field_height=${#insert_field[*]}
field_max_width=`echo ${insert_field[*]} | xargs -n1 | awk '{ if ( w < length($1) ) w = length($1) } END { print w }'`
unset form_items ; declare -a form_items
### Append field form, the form look like this: [ label y x item y x flen ilen ] ...
for key in ${!insert_field[*]}
do
case "${insert_field[$key]}" in
PRODUCT_NAME|PRODUCT_CODE)
form_value="7048X"
;;
PRODUCT_DESIGNATION|PRODUCT_REF_COM)
form_value="Go play"
;;
PRODUCT_CREATION_DATE)
form_value=`date '+%Y-%m-%d %T'`
;;
PRODUCT_ID)
### Call mysql Command, Retrieve New PRODUCT_ID. Table: imgen_product ( 0 )
form_value=`__d_mysql_do_bin_cmd $dbname -sN -e "show create table ${imgen_table[0]}\G" | \
sed -n '/.*ENGINE=.*AUTO_INCREMENT=\([[:digit:]]*\) .*/ s//\1/p'`
new_product_id="$form_value"
esac
form_items[$key]="${insert_field[$key]}: $[key+1] 1 '$form_value' $[key+1] $[field_max_width+3] 70 200"
done
sub_title="$dbname - PRODUCT_ID Conflict" ; width=70
MSG="- TAC_ID: \Z1$tac_id\Zn -"
MSG=`echo $MSG | sed ':a s/^.\{1,'"$[width-1]"'\}$/ & /;ta'`
MSG="\n$MSG\n\n\Z1Step 1.\Zn insert \Z1New\Zn product informatin into imgen_product table."
MSG="$MSG\n The \Z1PRODUCT_ID\Zn ( major Key ) is automatically generated."
set -- Insert Re-input Main-menu $[field_height+12] $width $field_height
ok_label=$1 ; cancel_label=$2 ; extra_label=$3 ; height=$4 ; width=$5 ; form_height=$6 ; shift 6
### Call Dialog form UI
__d_dialog_design_form_UI ; sed -i '1,$ s/ $//' $dload_form ; source $dload_form
exit_state=$? ; #echo $exit_state ; exit
### Re-input Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_conflict_product_id_update_UI
### Main-menu Button
elif [ x"$exit_state" == x"3" ]
then
rm -rf $field_info $field_form $dload_form
__o_db_operation_main_menu_UI
### Insert Button
elif [ x"$exit_state" == x"0" ]
then
[ -f "$field_info" ] && extra_comma_row=$[$(sed -n '$=' $field_info)+1]
[ -f "$field_form" ] && {
sed -i 's/ \{1,\}$//' $field_form
awk 'ARGIND==1 { a[FNR]=$0 ; next } ARGIND==2 { print a[FNR]":",$0 }' $field_info $field_form > $field_data
new_product_id=`awk '/PRODUCT_ID/ {print $2}' $field_data`
}
insert_sql="$tmp_dir/__p_${tac_id}.conflict.insert_sql"
insert_msg="$tmp_dir/__p_${tac_id}.conflict.insert_msg"
### Related Process: Generate ( SQL ) -> Insert ( imgen_product )-> Relate ( imgen_ref )
### Step 2.2 - Generate insert DML statement, insert product informatin into imgen_product ( 0 ).
awk -F': ' 'BEGIN { print "insert into '${imgen_table[0]}' (" } \
ARGIND==1 { print $0"," ; next } \
ARGIND==2 { a[FNR]=$0 ; b[j++]=FNR } \
END { print ") values (" ; for (i=0;i<j;i++) print "'\''"a[b[i]]"'\''," }' $field_info $field_form | \
sed -e '1,$ s/^ \{1,\}// ; $s/,/ );/' -e ''${extra_comma_row}' s/,$//' > $insert_sql
[ -f "$insert_sql" ] && sed -e '1,$ s/^/| /' -e '1,$ s/$/\\n/' $insert_sql > $insert_msg
msg_height=`sed -n '$=' $insert_msg`
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn -> New PRODUCT_ID: \Z1$new_product_id\Zn"
MSG="$MSG\n\n------"
MSG="$MSG\n\Z1WARNING:\Zn Are you sure want to perform \Z1Insert\Zn Operation? ( Default: \Z1No\Zn )"
MSG="$MSG\n\n+------"
MSG="$MSG\n$(cat $insert_msg)+------"
### Call Dialog yesno UI
__d_dialog_design_yesno_UI Continue Cancel $[msg_height+13] 92
exit_state=$? ; #echo $exit_state ; exit
### Cancel Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_input_tac_id_UI updel
### Continue Button
elif [ x"$exit_state" == x"0" ]
then
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn -> New PRODUCT_ID: \Z1$new_product_id\Zn"
MSG="$MSG\n\n\Z1Step 2 :\Zn\n------"
### Step 2.3 - Call mysql Command, Insert New product informain ( Record - Row level, insert into imgen_product Table )
__d_mysql_do_bin_cmd $dbname < $insert_sql
[ $? -eq 0 ] && insert_state="Success" || insert_state="Failure"
MSG="$MSG\n imgen_product \Z1Insert\Zn - [\Z1 $insert_state \Zn]"
### step 2.4 - Call mysql Command, Update old PRODUCT_ID to New PRODUCT_ID ( Record - Row level, update imgen_ref Table )
update_sql="update ${imgen_table[1]} set PRODUCT_ID=$new_product_id where PRODUCT_ID=$product_id and TAC_REF=$tac_ref and REF_ID=$ref_id;"
[ x"$insert_state" == x"Success" ] && __d_mysql_do_bin_cmd $dbname -e "$update_sql"
[ $? -eq 0 ] && update_state="Success" || update_state="Failure"
MSG="$MSG\n imgen_ref \Z1Update\Zn - [\Z1 $update_state \Zn]"
MSG="$MSG\n\nIf it was successful, please press the \Z1Re-retrieve\Zn button to Re-retrieve.\n"
### Call Dialog msgbox UI
__d_dialog_design_msgbox_UI Re-retrieve 14 80
exit_state=$? ; #echo $exit_state ; exit
### Re-retrieve Button
if [ x"$exit_state" == x"0" ]
then
__o_db_operation_input_tac_id_UI updel
fi
fi
fi
}
### Database Operation Up-Del ( include Update and Delete ) Menu Function
__o_db_operation_menu_updel_UI() {
unset list_items ; declare -a list_items
list_items=( "Update Operation"
"Delete Operation" )
sub_title="$dbname - Database Operation"
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn | TAC_REF: \Z1$tac_ref\Zn | REF_ID: \Z1$ref_id\Zn"
### Choice Menu Type, menu or radiolist
__o_db_operation_menu_type_UI radiolist Select Re-retrieve Main-menu
exit_state=$? ; echo -e "\nexit" >&6
read -u6 operation ; read -u6 EXIT
### Re-retrieve Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_input_tac_id_UI updel
### Main-menu Button
elif [ x"$exit_state" == x"3" ]
then
__o_db_operation_main_menu_UI
### Select Button
elif [ x"$exit_state" == x"0" ]
then
[ -z "$operation" ] && __o_db_operation_menu_updel_UI
case $operation in
Update)
__o_db_operation_update_UI
;;
Delete)
__o_db_operation_delete_UI
;;
esac
fi
}
### Database Update Function
__o_db_operation_update_UI() {
field_info="$tmp_dir/__p_${tac_id}.update_field"
field_form="$tmp_dir/__p_${tac_id}.update_form"
dload_form="$tmp_dir/__d_${tac_id}.dialog_design_form_UI"
update_sql="$tmp_dir/__p_${tac_id}.update_sql"
update_msg="$tmp_dir/__p_${tac_id}.update_msg"
sub_title="$dbname Database - Update Operation"
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn | TAC_REF: \Z1$tac_ref\Zn | REF_ID: \Z1$ref_id\Zn"
unset list_items ; declare -a list_items
list_items=( `cat $product_info | awk -F':' '/PRODUCT_/ {print $1,"Field","off"}' | sed '/PRODUCT_CREATION_DATE/d ; /PRODUCT_ID/d'` )
list_height=`echo ${list_items[*]} | xargs -n3 | wc -l`
### Call Dialog checklist UI
__d_dialog_design_checklist_UI $field_info Select Re-Select Return $[list_height+9] 70 $list_height
exit_state=$? ; #echo $exit_state ; exit
update_field=( `cat $field_info` ) ; field_height=${#update_field[*]}
field_max_width=`echo ${update_field[*]} | xargs -n1 | awk '{ if ( w < length($1) ) w = length($1) } END { print w }'`
### Re-Select Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_update_UI
### Return Button
elif [ x"$exit_state" == x"3" ]
then
__o_db_operation_menu_updel_UI
### Select Button
elif [ x"$exit_state" == x"0" ]
then
[ x"$field_height" == x"0" ] && {
MSG="\n Please select at least \Z1One\Zn field to Updated."
__d_dialog_design_msgbox_UI Return 7 70
__o_db_operation_update_UI
}
### Load field form Data from Database Query
__o_db_operation_update_load_form_UI
fi
}
### Database Update Function - Load form Data
__o_db_operation_update_load_form_UI() {
unset form_items ; declare -a form_items
### Append field form, the form look like this: [ label y x item y x flen ilen ] ...
for key in ${!update_field[*]}
do
form_value=`awk -F': ' '/'"${update_field[$key]}"'/ {print $2}' $product_info`
form_items[$key]="${update_field[$key]}: $[key+1] 1 '$form_value' $[key+1] $[field_max_width+3] 70 200"
done
MSG="\nEnter the following information:"
set -- Update Re-input Return $[field_height+9] 70 $field_height
ok_label=$1 ; cancel_label=$2 ; extra_label=$3 ; height=$4 ; width=$5 ; form_height=$6 ; shift 6
### Call Dialog form UI - load form data
__d_dialog_design_form_UI ; sed -i '1,$ s/ $//' $dload_form ; source $dload_form
exit_state=$? ; #echo $exit_state ; exit
### Re-input Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_update_load_form_UI
### Return Button
elif [ x"$exit_state" == x"3" ]
then
rm -rf $field_info $field_form $dload_form
__o_db_operation_update_UI
### Update Button
elif [ x"$exit_state" == x"0" ]
then
### Generate update DML statement
awk 'ARGIND==1 { a[FNR]=$0 ; next } \
ARGIND==2 { print a[FNR]"='\''"$0"'\''" }' \
$field_info $field_form > $update_sql
[ -f "$update_sql" ] && {
sed -i '$!s/$/,/' $update_sql
sed -i "1 s/^/update ${imgen_table[0]} set\n/" $update_sql
sed -i "$ s/$/\nwhere PRODUCT_ID=$product_id;/" $update_sql
sed -e '1,$ s/^/| /' -e '1,$ s/$/\\n/' $update_sql > $update_msg
}
msg_height=`sed -n '$=' $update_msg`
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn | TAC_REF: \Z1$tac_ref\Zn | REF_ID: \Z1$ref_id\Zn"
MSG="$MSG\n\n------"
MSG="$MSG\n\Z1WARNING:\Zn Are you sure want to perform \Z1Update\Zn Operation? ( Default: \Z1No\Zn )"
MSG="$MSG\n\n+------"
MSG="$MSG\n$(cat $update_msg)+------"
### Call Dialog yesno UI
__d_dialog_design_yesno_UI Continue Cancel $[msg_height+13] 92
exit_state=$? ; #echo $exit_state ; exit
### Cancel Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_update_UI
### Continue Button
elif [ x"$exit_state" == x"0" ]
then
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn | TAC_REF: \Z1$tac_ref\Zn | REF_ID: \Z1$ref_id\Zn"
MSG="$MSG\n\nUpdate STATE :\n------"
### Call mysql Command, Update TAC_ID product informain ( Record - Row level, update imgen_product Table )
__d_mysql_do_bin_cmd $dbname < $update_sql
[ $? -eq 0 ] && update_state="Success" || update_state="Failure"
MSG="$MSG\n imgen_product \Z1Update\Zn - [\Z1 $update_state \Zn]"
MSG="$MSG\n\nIf it was successful, please press the \Z1Re-retrieve\Zn button to Re-retrieve.\n"
### Call Dialog msgbox UI
__d_dialog_design_msgbox_UI Re-retrieve 13 80
exit_state=$? ; #echo $exit_state ; exit
### Re-retrieve Button
if [ x"$exit_state" == x"0" ]
then
__o_db_operation_input_tac_id_UI updel
fi
fi
fi
}
### Database Delete Function
__o_db_operation_delete_UI() {
delete_msg="$tmp_dir/__p_${tac_id}.delete_msg"
sub_title="$dbname Database - Delete Operation"
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn | TAC_REF: \Z1$tac_ref\Zn | REF_ID: \Z1$ref_id\Zn"
MSG="$MSG\n\n------"
MSG="$MSG\n\Z1WARNING:\Zn Are you sure want to perform \Z1Delete\Zn Operation? ( Default: \Z1No\Zn )"
MSG="$MSG\n\n+------"
product_del_sql="delete from imgen_product where PRODUCT_ID=$product_id;"
ref_del_sql="delete from imgen_ref where REF_ID=$ref_id;"
tac_del_sql="delete from imgen_tac where TAC_REF=$tac_ref;"
echo -e "$product_del_sql\n$ref_del_sql\n$tac_del_sql" > $delete_msg
sed -i -e '1,$ s/^/| /' -e '1,$ s/$/\\n/' $delete_msg
msg_height=`sed -n '$=' $delete_msg`
MSG="$MSG\n$(cat $delete_msg)+------"
### Call Dialog yesno UI
__d_dialog_design_yesno_UI Continue Cancel $[msg_height+13] 92
exit_state=$? ; #echo $exit_state ; exit
### Cancel Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_menu_updel_UI
### Continue Button
elif [ x"$exit_state" == x"0" ]
then
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn | TAC_REF: \Z1$tac_ref\Zn | REF_ID: \Z1$ref_id\Zn"
MSG="$MSG\n\nDelete STATE :\n------"
unset delete_state ; declare -a delete_state
### Table: imgen_product ( 0 ) , imgen_ref ( 1 ) and imgen_tac ( 2 )
for key in ${!imgen_table[*]}
do
case ${imgen_table[$key]} in
imgen_product)
query_condition="PRODUCT_ID=$product_id"
delete_sql="$product_del_sql"
;;
imgen_ref)
query_condition="REF_ID=$ref_id"
delete_sql="$ref_del_sql"
;;
imgen_tac)
query_condition="TAC_REF=$tac_ref"
delete_sql="$tac_del_sql"
;;
esac
### Call mysql Command, Delete TAC_ID product information ( Record - Row level )
__d_mysql_do_bin_cmd $dbname -e "$delete_sql"
[ $? -eq 0 ] && delete_state[$key]="Success" || delete_state[$key]="Failure"
if [ x"$key" == x"0" ]
then
MSG="$MSG\n ${imgen_table[$key]} \Z1Delete\Zn - [\Z1 ${delete_state[$key]} \Zn]"
elif [ x"$key" == x"1" -o x"$key" == x"2" ]
then
MSG="$MSG\n ${imgen_table[$key]} \Z1Delete\Zn - [\Z1 ${delete_state[$key]} \Zn]"
fi
done
MSG="$MSG\n\nIf it was successful, please press the \Z1Re-retrieve\Zn button to Re-retrieve.\n"
### Call Dialog msgbox UI
__d_dialog_design_msgbox_UI Re-retrieve 15 80
exit_state=$? ; #echo $exit_state ; exit
### Re-retrieve Button
if [ x"$exit_state" == x"0" ]
then
__o_db_operation_input_tac_id_UI updel
fi
fi
}
### Database Backup Function
__o_db_operation_backup_UI() {
tac_id_array=( `echo $tac_id | awk -v FS=',' '{ $1=$1 ; print $0 }' | xargs -n1 | awk '!a[$0]++ { print $0 }'` )
for tac_id in ${tac_id_array[*]}
do
product_info="$tmp_dir/__p_${tac_id}.product_info"
### Retrieve TAC_ID product informatin
__o_db_operation_query_tac_id_info $product_info normal
if [ -z "$tac_id" -o -z "$product_id" -o -z "$ref_id" ]
then
MSG="\nUnable to retrieve TAC_ID (\Z1 $tac_id \Zn) Product information."
__d_dialog_design_msgbox_UI Return 7 70
__o_db_operation_input_tac_id_UI backup
fi
done
level_info="$tmp_dir/__0_${pid}.backup_level"
MSG="\n- Note: \Z1Restore\Zn operation Provide \Z1Record-level ( Row )\Zn recovery -"
unset list_items ; declare -a list_items
### Backup level: db_level ( 0 ), table_level ( 1 ) and record_level ( 2 )
for key in ${!backup_level[*]}
do
case ${backup_level[$key]} in
db_level)
list_items[$key]="Database Level off"
;;
table_level)
list_items[$key]="Table Level off"
;;
record_level)
list_items[$key]="Record Level on"
;;
esac
done
list_height=${#list_items[*]}
### Call Dialog checklist UI
__d_dialog_design_checklist_UI $level_info Select Re-Select Main-menu $[list_height+9] 70 $list_height
exit_state=$? ; #echo $exit_state ; exit
select_level=( `cat $level_info` ) ; level_count=${#select_level[*]}
### Re-Select Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_backup_UI
### Main-menu Button
elif [ x"$exit_state" == x"3" ]
then
__o_db_operation_main_menu_UI
### Select Button
elif [ x"$exit_state" == x"0" ]
then
[ x"$level_count" == x"0" ] && {
MSG="\n Please select at least \Z1One\Zn Backup level."
__d_dialog_design_msgbox_UI Return 7 70
__o_db_operation_backup_UI
}
echo ${select_level[*]} | grep -qE "Database" ; [ $? -eq 0 ] && is_db_level=true || is_db_level=false
echo ${select_level[*]} | grep -qE "Table" ; [ $? -eq 0 ] && is_table_level=true || is_table_level=false
echo ${select_level[*]} | grep -qE "Record" ; [ $? -eq 0 ] && is_record_level=true || is_record_level=false
date_now=`date +%Y%m%d%H%M.%S`
[ x"$is_db_level" == x"true" ] && mkdir -p $db_level_dir/$date_now
[ x"$is_table_level" == x"true" ] && mkdir -p $table_level_dir/$date_now
MSG="\nBackup DIR :\n------"
MSG="$MSG\n \Z1 Database \Zn - [ $backup_dir/db_level_dir/$date_now ]"
MSG="$MSG\n \Z1 Table \Zn - [ $backup_dir/table_level_dir/$date_now ]"
MSG="$MSG\n \Z1 Record \Zn - [ $backup_dir/record_level_dir/TAC_ID/$date_now ]"
MSG="$MSG\n\nBackup STATE :\n------"
### Call mysqldump Command, Backup IMGEN Database.
[ x"$is_db_level" == x"true" ] && {
__d_mysql_do_dump_cmd db_level $dbname | gzip > $db_level_dir/$date_now/${dbname}.sql.gz
[ $? -eq 0 ] && backup_state="Success" || backup_state="Failure"
MSG="$MSG\n Database Level - [\Z1 $backup_state \Zn]"
}
### Call mysqldump Command, Backup Table Data ( include imgen_product, imgen_ref and imgen_tac ).
[ x"$is_table_level" == x"true" ] && {
__d_mysql_do_dump_cmd table_level $dbname ${imgen_table[*]} | gzip > $table_level_dir/$date_now/${dbname}_table.sql.gz
[ $? -eq 0 ] && backup_state="Success" || backup_state="Failure"
MSG="$MSG\n Table Level - [\Z1 $backup_state \Zn]"
}
### Call mysql Command, export TAC_ID product information ( Record - Row level, include insert and update DML statement ).
[ x"$is_record_level" == x"true" ] && {
for tac_id in ${tac_id_array[*]}
do
product_info="$tmp_dir/__p_${tac_id}.product_info"
### Retrieve TAC_ID product informatin
__o_db_operation_query_tac_id_info $product_info normal
if [ -z "$tac_id" -o -z "$product_id" -o -z "$ref_id" ]
then
MSG="\nUnable to retrieve TAC_ID (\Z1 $tac_id \Zn) Product information."
__d_dialog_design_msgbox_UI Re-retrieve 7 70
__o_db_operation_input_tac_id_UI backup
fi
product_id_array=( `echo $product_id` )
tac_ref_array=( `echo $tac_ref` )
ref_id_array=( `echo $ref_id` )
if [ "${#product_id_array[*]}" -gt 1 -o "${#tac_ref_array[*]}" -gt 1 -o "${#ref_id_array[*]}" -gt 1 ]
then
MSG="$MSG\n Record Level - [\Z1 Failure - $tac_id / Conflict\Zn ]"
else
record_level_dir="$backup_dir/record_level/$tac_id/$date_now" ; mkdir -p $record_level_dir
### Generate insert DML statement
insert_sql() {
table=$1 ; history_data=$2 ; shift 2
extra_comma_row=$[$(sed -n '$=' $history_data)+1]
awk -F': ' 'BEGIN { print "insert into '$table' (" } \
{ a[NR]=$2 ; b[j++]=NR ; print $1","} \
END { print ") values (" ; for (i=0;i<j;i++) print "'\''"a[b[i]]"'\''," }' $history_data | \
sed -e '1,$ s/^ \{1,\}// ; $s/,/ );/' -e ''${extra_comma_row}' s/,$//'
}
### Generate update DML statement
update_sql() {
table=$1 ; history_data=$2 ; shift 2
awk -F': ' '{print $1"='\''"$2"'\''"}' $history_data | \
sed '1,$ s/^ \{1,\}//; $! s/$/,/' | \
sed "1 s/^/update ${imgen_table[$key]} set\n/" | \
sed "$ a where $query_condition;"
}
unset backup_state ; declare -a backup_state
### Table: imgen_product ( 0 ), imgen_ref ( 1 ) and imgen_tac ( 2 )
for key in ${!imgen_table[*]}
do
case ${imgen_table[$key]} in
imgen_product)
query_condition="PRODUCT_ID=$product_id"
;;
imgen_ref)
query_condition="REF_ID=$ref_id"
;;
imgen_tac)
query_condition="TAC_REF=$tac_ref"
;;
esac
history_data="$record_level_dir/${dbname}.${imgen_table[$key]}.history_data"
insert_sql_file="$record_level_dir/${dbname}.${imgen_table[$key]}.sql_insert"
update_sql_file="$record_level_dir/${dbname}.${imgen_table[$key]}.sql_update"
### Call mysql Command, generate history Backup Query Data
__d_mysql_do_bin_cmd $dbname -e "select * from ${imgen_table[$key]} where ${query_condition}\G" | sed '1d' > $history_data
[ $? -eq 0 ] && backup_state[$key]="Success" || backup_state[$key]="Failure"
[ "${imgen_table[$key]}" == "imgen_product" ] && {
sed -i -e '/PRODUCT_CODE/ { h;d } ; /PRODUCT_REF_COM/ { G }' $history_data
}
### Generate insert and update DML statement
insert_sql ${imgen_table[$key]} $history_data > $insert_sql_file
update_sql ${imgen_table[$key]} $history_data > $update_sql_file
done
echo ${backup_state[*]} | grep -q 'Failure' ; [ $? -eq 0 ] && backup_state="Failure" || backup_state="Success"
MSG="$MSG\n Record Level - [\Z1 $backup_state - $tac_id \Zn]"
fi
done
}
__d_dialog_design_msgbox_UI Return $[level_count + ${#tac_id_array[*]} + 13] 80
__o_db_operation_main_menu_UI
fi
}
### Database Restore Function - Retrieve TAC_ID
__o_db_operation_restore_UI() {
record_level_dir="$backup_dir/record_level" ; mkdir -p $record_level_dir
sub_title="$dbname Database - Restore Operation" ; width=70
unset list_items ; declare -a list_items
list_items=( `find $record_level_dir -maxdepth 1 | sed '1d' | awk -F'/' '{print $NF}' | sort` )
list_height=${#list_items[*]}
[ x"$list_height" == x"0" ] && {
MSG="\nThe history Backup Point of TAC_ID \Z1Not found\Zn."
__d_dialog_design_msgbox_UI Return 7 70
__o_db_operation_main_menu_UI
}
list_items=( `echo ${list_items[*]} | xargs -n1 | awk '{print $1,"TAC_ID","off"}'` )
MSG="- Select Backup (\Z1 TAC_ID \Zn) to Restore -"
MSG=`echo $MSG | sed ':a s/^.\{1,'"$width"'\}$/ & /;ta'`
MSG="\n$MSG"
unset product_id tac_id tac_fac tac_ref ref_id product_id_array tac_id_array tac_ref_array
### Call Dialog radiolist UI
__d_dialog_design_radiolist_UI Select Re-select Main-menu $[list_height+9] $width $list_height
exit_state=$? ; echo -e "\nexit" >&6
read -u6 tac_id ; read -u6 EXIT
### Re-select Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_restore_UI
### Main-menu Button
elif [ x"$exit_state" == x"3" ]
then
__o_db_operation_main_menu_UI
### Select Button
elif [ x"$exit_state" == x"0" ]
then
[ -z "$tac_id" ] && __o_db_operation_restore_UI
__o_db_operation_restore_tac_id_UI
fi
}
### Database Restore Function - Restore TAC_ID
__o_db_operation_restore_tac_id_UI() {
MSG1="\n- Note: \Z1Restore\Zn operation Provide \Z1Record-level ( Row )\Zn recovery -"
MSG2="| TAC_ID: \Z1$tac_id\Zn |"
width=70
MSG1=`echo $MSG1 | sed ':a s/^.\{1,'"$[width-1]"'\}$/ & /;ta'`
MSG2=`echo $MSG2 | sed ':a s/^.\{1,'"$[width-1]"'\}$/ & /;ta'`
MSG="$MSG1\n$MSG2"
record_point="$record_level_dir/$tac_id"
### Retrieve TAC_ID Backup Number
history_point=( `find $record_point -maxdepth 1 | sed '1d' | awk -F'/' '{print $NF}' | sort` )
list_height=${#history_point[*]}
[ x"$list_height" == x"0" ] && {
MSG="\nThe TAC_ID (\Z1 $tac_id \Zn) history Backup Point \Z1Not found\Zn."
__d_dialog_design_msgbox_UI Return 7 70
__o_db_operation_main_menu_UI
}
unset list_items ; declare -a list_items
### Retrieve TAC_ID Backup level
for p_key in ${!history_point[*]}
do
unset exist_level ; declare -a exist_level
### Backup level: db_level ( 0 ) , table_level ( 1 ) and record_level ( 2 )
for l_key in ${!backup_level[*]}
do
case ${backup_level[$l_key]} in
db_level)
history_bkdir="$db_level_dir/${history_point[$p_key]}"
[ `ls $history_bkdir | wc -l` -ne 0 ] && exist_level[$l_key]=D
;;
table_level)
history_bkdir="$table_level_dir/${history_point[$p_key]}"
[ `ls $history_bkdir | wc -l` -ne 0 ] && exist_level[$l_key]=T
;;
record_level)
history_bkdir="$record_point/${history_point[$p_key]}"
[ `ls $history_bkdir | wc -l` -ne 0 ] && exist_level[$l_key]=R
;;
esac
done
exist_level=`echo ${exist_level[*]} | awk -v OFS='-' '{ $1=$1 ; print $0 }'`
list_items[$p_key]=`echo ${history_point[$p_key]} | xargs -n1 | awk -F'/' '{print $NF,"'$exist_level'","off"}'`
done
### Call Dialog radiolist UI
__d_dialog_design_radiolist_UI Select Re-select Return $[list_height+10] 70 $list_height
exit_state=$? ; echo -e "\nexit" >&6
read -u6 restore_point ; read -u6 EXIT
### Re-select Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_restore_tac_id_UI
### Return Button
elif [ x"$exit_state" == x"3" ]
then
__o_db_operation_restore_UI
### Select Button
elif [ x"$exit_state" == x"0" ]
then
[ -z "$restore_point" ] && __o_db_operation_restore_tac_id_UI
restore_msg="$tmp_dir/__p_${tac_id}.restore_msg"
restore_bkdir="$record_point/$restore_point"
record_level="$restore_bkdir/$dbname"
### Retrieve TAC_ID history Backup Point ( Record - Row level )
[ `ls ${record_level%/$dbname} | wc -l` -eq 0 ] && {
MSG="\nThe history Backup Point dose not have \Z1Record-level ( Row )\Zn backup.\n"
### Call Dialog msgbox UI
__d_dialog_design_msgbox_UI Return 7 80
exit_state=$? ; #echo $exit_state ; exit
### Return Button
if [ x"$exit_state" == x"0" ]
then
__o_db_operation_restore_tac_id_UI
fi
}
### Display TAC_ID history Backup Point Query Data
result_file=`echo ${imgen_table[*]} | xargs -n1 | \
awk '{print "'$record_level'."$1".history_data"}' | xargs`
field_max_width=`awk -F': ' '{ if ( w < length($1) ) w=length($1) } END { print w } ' $result_file`
sed -i ':a s/^.\{1,'"$[field_max_width-1]"'\}:.*$/ &/;ta' $result_file
tac_point="- TAC_ID: $tac_id | Restore Point: $restore_point -"
tac_point=`echo $tac_point | sed ':a s/^.\{1,82\}$/ & /;ta'`
echo -e "\n $tac_point \n" > $restore_msg ; more $result_file >> $restore_msg
### Call Dialog yesno UI
__d_dialog_design_textbox_UI $restore_msg Next 30 90
exit_state=$? ; #echo $exit_state ; exit
### Next Button
if [ x"$exit_state" == x"0" ]
then
### Table: imgen_product ( 0 ), imgen_ref ( 1 ) and imgen_tac ( 2 )
product_id=`awk '/PRODUCT_ID/ {print $2}' ${record_level}.${imgen_table[0]}.history_data`
ref_id=`awk '/REF_ID/ {print $2}' ${record_level}.${imgen_table[1]}.history_data`
tac_ref=`awk '/TAC_REF/ {print $2}' ${record_level}.${imgen_table[2]}.history_data`
product_info="$tmp_dir/__p_${tac_id}.product_info"
### Retrieve TAC_ID product informatin
__o_db_operation_query_tac_id_info $product_info normal
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn | TAC_REF: \Z1$tac_ref\Zn | REF_ID: \Z1$ref_id\Zn"
MSG="$MSG\n\n------"
MSG="$MSG\n\Z1WARNING:\Zn Are you sure want to perform \Z1Restore\Zn Operation? ( Default: \Z1No\Zn )\n"
MSG="$MSG\nIf the Product information is exists, the \Z1Update\Zn statement will be executed."
MSG="$MSG\nIf not, the \Z1Insert\Zn statement will be executed."
MSG="$MSG\n\n+------"
### Display history Backup Point insert or update DML statement file
if [ x"$fline_count" == x"1" ]
then
echo ${imgen_table[*]} | xargs -n1 | awk '{print "| '$record_level'."$1".sql_insert"}' > $restore_msg
else
echo ${imgen_table[*]} | xargs -n1 | awk '{print "| '$record_level'."$1".sql_update"}' > $restore_msg
fi
sed -i -e '1,$ s/$/\\n/' $restore_msg
msg_height=`sed -n '$=' $restore_msg`
MSG="$MSG\n$(cat $restore_msg)+------"
### Call Dialog yesno UI
__d_dialog_design_yesno_UI Continue Cancel $[msg_height+16] 92
exit_state=$? ; #echo $exit_state ; exit
### Cancel Button
if [ x"$exit_state" == x"1" ]
then
__o_db_operation_restore_UI
### Continue Button
elif [ x"$exit_state" == x"0" ]
then
MSG="\nTAC_ID: \Z1$tac_id\Zn | PRODUCT_ID: \Z1$product_id\Zn | TAC_REF: \Z1$tac_ref\Zn | REF_ID: \Z1$ref_id\Zn"
MSG="$MSG\n\nRestore STATE :\n------"
unset restore_state ; declare -a restore_state
### Table: imgen_product ( 0 ), imgen_ref ( 1 ) and imgen_tac ( 2 )
for key in ${!imgen_table[*]}
do
if [ x"$fline_count" == x"1" ]
then
restore_sql="${record_level}.${imgen_table[$key]}.sql_insert"
else
restore_sql="${record_level}.${imgen_table[$key]}.sql_update"
fi
### Call mysql Command, Restore TAC_ID product informatin ( Record - Row level )
__d_mysql_do_bin_cmd $dbname < $restore_sql
[ $? -eq 0 ] && restore_state[$key]="Success" || restore_state[$key]="Failure"
if [ x"$key" == x"0" ]
then
MSG="$MSG\n ${imgen_table[$key]} \Z1Restore\Zn - [\Z1 ${restore_state[$key]} \Zn]"
elif [ x"$key" == x"1" -o x"$key" == x"2" ]
then
MSG="$MSG\n ${imgen_table[$key]} \Z1Restore\Zn - [\Z1 ${restore_state[$key]} \Zn]"
fi
done
MSG="$MSG\n\nIf it was successful, please press the \Z1Re-retrieve\Zn button to Re-retrieve.\n"
### Call Dialog msgbox UI
__d_dialog_design_msgbox_UI Re-retrieve 15 80
exit_state=$? ; #echo $exit_state ; exit
### Re-retrieve Button
if [ x"$exit_state" == x"0" ]
then
__o_db_operation_input_tac_id_UI updel
fi
fi
fi
fi
}
### __o_db_operation_UI Function - Main Execute Entry
__o_db_operation_connect_UI
}
#------------
# Main
#------
__d_dialog_design_UI
__o_db_operation_UI
原创文章,作者:影·随行,如若转载,请注明出处:http://www.178linux.com/8976


评论列表(5条)
呵!胆大心细,总结出来也一定有不小的收获吧。总结的也非常棒,果断置顶
@stanley:最早写了一版 CentOS 5.5 全自动的,后面因为生产环境上开发环境不一致,所以到 6.X 直接改成半自动化了~~整个脚本加测试,调试UI输出用了整整一个月,-_## 现在不怎么改这个脚本了,越改越多,不敢改了,而且现在没必要用这种脚本来部署其它环境了,直接用 ansilbe/saltstack 就行了
哈,数据库那个,是线上的一个小系统,不过数据是挺重要的,他们设计那种BUG都能出现,而且那个手工去查、修正,太费时了,时间要用在点上,我不关心业务系统,只关心数据库,他们有输出文档,知道怎么回事,就用 shell 直接实现了,业务系统有其它人维护,这种重复性工作还是算了~~不case,测试加写脚本用了一个星期才完成了,脚本用得很好,没问题哈哈
@影·随行:赞 坚持
膜拜中!!!!
真厉害啊