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,测试加写脚本用了一个星期才完成了,脚本用得很好,没问题哈哈
@影·随行:赞 坚持
膜拜中!!!!
真厉害啊