Configuring Init Script

使用init脚本,无非就是实现软件服务的开机启动。但是用Debian或Ubuntu时,都是用apt-get来安装软件,而且服务类的软件都自带init脚本,对init脚本变得生疏了。工作中在CentOS上配置了两个开机启动脚本,并发现一个问题。

开机守护进程启动Tomcat6

用了Tomcat这么久,以前居然一直没做个这个配置。Tomcat官方网站推荐用jsvc守护进程来启动Tomcat。

关于jsvc,Apache官网上说得非常清楚了:http://commons.apache.org/proper/commons-daemon/jsvc.html

关于Unix(包括Linux)系统上Tomcat6守护进程配置:https://tomcat.apache.org/tomcat-6.0-doc/setup.html#Unix_daemon

这里的步骤简单为:

1)找到jsvc的源码包tomcat6/bin/commons-daemon-native.tar.gz

2)解压、配置并编译

cd $CATALINA_HOME/bin
tar xvfz commons-daemon-native.tar.gz
cd commons-daemon-1.0.x-native-src/unix
./configure
make
cp jsvc $CATALINA_HOME/bin/

3)配置init脚本。

jsvc源码包里有Tomcat5的init脚本,复制过来,按需要进行修改,并放到/etc/init.d/目录下。例如文件名为tomcatjsvc启动Tomcat后,可能根据Tomcat的启动情况来设置返回值(即通过$?获取的值),导致Tomcat正常启动后,jsvc仍会返回1,而不是0。因此,这里改为Tomcat启动后,通过检测相关端口来判断Tomcat是否启动成功并显示启动后的提示信息。脚本示例如下:

#!/bin/sh 
# 
# Startup Script for Tomcat6 
# 
# chkconfig: 345 98 02 
# description: Tomcat Daemon 
# processname: tomcat 
# pidfile: /var/run/tomcat.pid 
# config: 
# 
# Source function library.
. /etc/rc.d/init.d/functions 
# 
prog=tomcat

JAVA_HOME=/usr/local/jdk1.6.0_45
CATALINA_HOME=/usr/local/apache-tomcat-6.0.35
DAEMON_HOME=$CATALINA_HOME/bin
TOMCAT_USER=tomcat
HTTP_PORT=8080

# for multi instances adapt those lines.
TMP_DIR=$CATALINA_HOME/temp
PID_FILE=/var/run/tomcat.pid
CATALINA_BASE=$CATALINA_HOME

CATALINA_OPTS="-server -Xss512k -Xms64M -Xmx512M"
CLASSPATH=\
$JAVA_HOME/lib/tools.jar:\
$CATALINA_HOME/bin/commons-daemon.jar:\
$CATALINA_HOME/bin/bootstrap.jar

start() {
    echo -n $"Starting $prog: "
    
    #
    # Start Tomcat
    #
    $DAEMON_HOME/jsvc $JSVC_OPTS \
    -user $TOMCAT_USER \
    -home $JAVA_HOME \
    -Dcatalina.home=$CATALINA_HOME \
    -Dcatalina.base=$CATALINA_BASE \
    -Djava.io.tmpdir=$TMP_DIR \
    -wait 10 \
    -pidfile $PID_FILE \
    -outfile $CATALINA_HOME/logs/catalina.out \
    -errfile '&1' \
    $CATALINA_OPTS \
    -cp $CLASSPATH \
    org.apache.catalina.startup.Bootstrap
    #
    # To get a verbose JVM
    #-verbose \
    # To get a debug of jsvc.
    #-debug \

    # Check if Tomcat is running on HTTP_PORT
    lsof -i:$HTTP_PORT > /dev/null
    ret=$?
    if [ $ret -eq 0 ]; then
    echo_success
    else
    echo_failure
    fi
    echo
    return $ret
}

stop() {
    echo -n $"Stopping $prog: "
    
    #
    # Stop Tomcat
    #
    $DAEMON_HOME/jsvc $JSVC_OPTS \
    -stop \
    -pidfile $PID_FILE \
    org.apache.catalina.startup.Bootstrap
    
    ret=$?
    if [ $ret -eq 0 ]; then
    echo_success
    else
    echo_failure
    fi
    echo
    return $ret
}

restart() {
    stop
    start
}

case "$1" in
    start)
    start
    ;;

    stop)
    stop
    ;;

    restart)
    restart
    ;;

    *)
    echo "Usage $prog start/stop/restart"
    exit 1;;
esac

4)加入开机启动。利用chkconfig命令:

chkconfig --add tomcat
chkconfig tomcat on

所有Java程序都可以用jsvc来启动,但是,启动的类需要实现init(String[] args)、start()、stop()、destroy()这4个方法。服务在启动时会先调用init(String[] args)方法,然后调用start()方法,在服务停止是会首先调用stop()方法,然后调用destroy()方法。

直接启动Tomcat6

其实init脚本只是个含有特定格式(例如要求实现带start和stop参数的功能)的shell脚本。就是说,可以直接执行Tomcat6自带的启动和停止脚本($CATALINA_HOME/bin目录下的startup.shshutdown.sh)。

具体配置参考这个:http://www.cnblogs.com/lianche/p/3154096.html

init脚本的模板如下:(以memcache为例)

#!/bin/sh
#
# Startup Script for memcached
#
# chkconfig: 345 65 35
# description: memcached
# processname: memcached
# pidfile: /var/run/memcached.pid
# config:
#
# Source function library.
. /etc/rc.d/init.d/functions
#
prog=memcached

FILE_HOME=/usr/local/memcache
PID_FILE=/var/run/memcached.pid

start() {
    echo -n $"Starting $prog: "

    $FILE_HOME/bin/memcached -d -m 128 -u root -l 0.0.0.0 -p 11211 -c 512 -P $PID_FILE

    retval=$?
    if [ $retval -eq 0 ]; then
    echo_success
    else
    echo_failure
    fi
    echo
    return $retval
}

stop() {
    echo -n $"Stopping $prog: "

    cat $PID_FILE | xargs kill -9

    ret=$?
    if [ $ret -eq 0 ]; then
    echo_success
    else
    echo_failure
    fi
    echo
    return $ret
}

restart() {
    stop
    start
}

case "$1" in
    start)
    start
    ;;

    stop)
    stop
    ;;

    *)
    echo "Usage $prog start/stop/restart"
    exit 1;;
esac

关于没有生成PID文件的程序

有些程序不像memcached那样把进程id记录到PID_FILE,于是就不能使用kill命令来关闭该进程了。虽然直接调用startup.shshutdown.sh来启动和关闭Tomcat也是没有PID_FILE,但是Tomcat会使用端口来关闭自己进程。遇到既没有PID_FILE,也没有像Tomcat那样有特殊的关闭方法的话,就自能自己用ps命令找到对应的进程id,然后kill掉。

以下以“花生壳(phddns)”为例。其中get_pid函数是获取进程号的。本来ps -C phddns -o pid=就可以获取到进程id了。但是由于启动脚本的文件名也是phddns,ps -C phddns会找到脚本所在的进程id,所以要再加上grep来找到/usr/bin/phddns命令的进程。

#!/bin/sh
#
# Startup Script for phddns
#
# chkconfig: 345 56 44
# description: phddns Daemon
# processname: phddns
# pidfile:
# config:
#
# Source function library.
. /etc/rc.d/init.d/functions
#
prog=phddns

get_pid() {
    #get the process id using ps
    echo $(ps -C phddns -o pid,command | grep '/usr/bin/phddns' | awk '{print $1}')
}

start() {
    echo -n $"Starting $prog: "

    PID_NUM=$(get_pid)

    if [ -n "$PID_NUM" ]; then
    echo_failure
    echo
    echo $prog is already running.
    else
    /usr/bin/phddns -c /etc/phlinux.conf -d > /dev/null

    ret=$?
    if [ $ret -eq 0 ]; then
        echo_success
    else
        echo_failure
    fi
    echo
    fi
    return $ret
}

stop() {
    echo -n $"Stopping $prog: "

    PID_NUM=$(get_pid)

    if [ -n "$PID_NUM" ]; then
    kill -9 $PID_NUM

    ret=$?
    if [ $ret -eq 0 ]; then
        echo_success
    else
        echo_failure
    fi
    echo
    else
    echo_failure
    echo
    echo $prog is not running.
    fi
    return $ret
}

restart() {
    stop
    start
}

case "$1" in
    start)
    start
    ;;

    stop)
    stop
    ;;

    restart)
    restart
    ;;

    *)
    echo "Usage $prog start/stop/restart"
    exit 1;;
esac

关于启动顺序

开机启动时,如果服务A依赖服务B来运行时,必须要先启动服务B,再启动服务A。通常在init脚本头(注释)中,用chkconfig及其后面3个参数来标记。例如:chkconfig 345 65 35

345表示在init状态为3、4、5时启动,65表示启动顺序(只支持两位数字,数字越小,启动越早),35表示中止顺序(也只支持两位数字,数字越小,中止越早)。

那么,服务A的chkconfig第2个参数要大于服务B的。

生成的启动顺序,可以参照/etc/rc*.d文件夹(*号代表0到6)内的文件名称。其中K开头的表示中止,S开头的表示启动。

PS. 由于工作上用到了CentOS,相关的配置也用得越来越多。这是N年前想不到的事情。

Configuring Iptables

网上看到关于Shadowsocks的优化,觉得有必要设置下自用的VPS。 shadowsocks 公共代理的必要设置 https://gist.github.com/fqrouter/95c037f9a3ba196fd4dd

但是VPS上的Shadowsocks一般只有自己在用,而且服务器限制了最大访问文件数。那么就剩下iptables值得设置了。

关于Debian的iptables,发现跟RedHat(或者CentOS)的不同。最后还是参照了官方Wiki进行了配置。 https://wiki.debian.org/iptables

PS. 本来大学时就学过iptables了,但是现在用来,发现基本忘干净了。

About My Last Job

终于在5月来临前结束了上一份工作。回望过去,刚好满一年。

一年前,眼前一切都安好了,想再次投入到软件公司去做开发。面试多间以后,最后选择了本地数一数二的,而且声称做Java的公司。现在想来,进去也太过于轻松了。

首先是HR招人会有奖金,其次是公司的经营方式--可以理解为人力外包。就是找一些会写代码的程序员,拉到客户那边帮客户做开发。公司赚取客户报价与员工工资之间的差价。这种开发模式,除非客户那边有比较强的技术,并且只需要增加临时的开发人员来完成项目,否则对客户是非常不利的。最简单一点是项目开发过后,就找不到人去维护。实际项目中,也有出现某些代码想修正或者升级,问谁,谁都不知道。

基于这种经营方式,就会导致人员流动性很大。当然,公司只要从客户那边拿到钱,就不用管人员的问题了。更厉害的是,开发工具采用了图形化开发。就是像配置工作流一样去配置业务逻辑。简单直观,开发快,而且不公开技术实现。新人立马就能上手,就算离职也不会学到真正的技术。

这样来看,一个声称是做技术的公司,其实就没有什么核心技术了。进去工作的程序员,也得不到太多的提升。再加上利用晚上不算工资、没有补贴的加班来压缩成本,人就会越做越累。正如某领导所说的,能留下来的都是精英。我的理解,他们都是心态非常好,抗压能力超强的精英。

当然,老板和领导们都应该看到这些问题了(或者看到其它方面),于是踏上了产品研发的道路。我一进去就是投入到新产品的研发,一做就是大半年。然后我们拿着这个半成品,就去给客户做项目开发了。

现在看来,该产品也一样空洞。主要的原因还是缺乏一个技术总监去主导、把控和验收。最后随着产品开发的结束,开发人员的离去(调去其它项目或者离职),产品未能达到预期效果。最TMD的是,有一些东拼西凑的模块,隐含重大问题。例如在Windows上部署Weblogic来运行,核心Jar包会报包名与类名冲突的问题。这样连部署到客户的服务器都成为难题。

啰嗦了一堆问题后,还是总结一下收获吧。

重新投入到软件开发的环境中,感觉还是很好的。一个开发团队里,有问题可以大家一起讨论解决。下班后还能天马行空地讨论各种各样的问题。

不得不说的是,技术老大传授了一些不错的经验。

对于技术的选择,要用自己熟悉的,而不是选择那些吹嘘有多强的新方案。自己熟悉的,遇到问题都好解决。而且成熟稳定的方案会少很多问题,就算有问题,解决方法也比新方案容易找到。

要通过增强代码可复用性来提高开发效率,而不是复制修改代码。其实这个程序员都明白的,但是在开发过程中总是没有做到。

针对问题去解决问题。就是根据问题的提示去找原因,然后解决。

面试的时候,要把话题带到自己熟悉的领域,说出面试官不懂的、不敢反驳的话题。

展望未来,将有更多需要努力和学习的地方。Come on, go ahead!

MySQL Copy Databases

新的工作需要用到MySQL。Leader让我复制一个数据库用来测试。以前用SQL Server都是直接图形化操作,从A数据库导出到B数据库就可以。Oracle就用expdp和impdp命令进行导出导入。MySQL的话,都是导出SQL脚本,再新建个数据库来执行。

网上找个这个教程:MySQL快速复制数据库的方法 http://www.tudaxia.com/archives/357

教程中只需两步:

1)新建数据库

使用mysql命令连上数据库(shell命令):

mysql -uroot -ppassword

执行创建数据库的SQL(SQL语句):

CREATE DATABASE `newdb` DEFAULT CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI;

2)复制数据。通过管道的方式把两条命令合并为一条。(shell命令)

mysqldump db1 -uroot -ppassword --add-drop-table | mysql newdb -uroot -ppassword

当数据很大的时候,建议还是老老实实地先把源数据库的数据备份成文件,再导入新的数据。(shell命令)

mysqldump db1 -uroot -ppassword --add-drop-table --default-character-set=utf8 > /home/db_export/db1.sql
mysql newdb -uroot -ppassword < /home/db_export/db1.sql

Goodbye, Kobo mini

入手Kobo mini一个月后,选择了放弃,把它转手给更需要它的人。

使用时,深深体会到E-ink屏的低功耗,确实很棒。但是机器本身没有良好的系统与开发平台,更没有良好的网络应用,只能离线看书。这不是我想要的。

国外有开发者移植了Debian上去,也写了E-ink屏与多点触控驱动。但是该系统是在旧版fireware上通过Chroot运行的,如要升级最新fireware,需要定制kernel。搞来搞去,搞不成。

最后甚至考虑放在家里,作为留言板、遥控器之类。但是缺乏中文输入,触摸也不好用,而且现在人手一个智能手机,根本不需要这机器。

E-ink屏的低功耗是非常好的优点,但是应用场合太少了。像Yota Phone这种手机,也不能成为主流。如果再不努力,可能会被其它材质取代。

Kobo Mini

入手Kobo mini已经快一个星期了。总结一下这家伙吧。

关于机器本身

入手Kobo mini,最主要是便宜,淘宝300不到就能买到。其次是体积小,5吋屏幕,分辨率是800x600,自带WiFi,并且可以换更大的TF卡来实现扩展存储空间。最后就是可以刷Debian。关于刷Debian,刷过后才感受到不是那么美好,这个后面再说。

缺点,首先是没有背光。然后是系统基于Linux开发的,比Android的(例如:Nook Simple Touch)可玩性差很多,开发的难度也高很多。原系统对中文支持差,可以说是不支持。虽然可以外挂字体显示中文文档,但是自带的浏览器却搞不定。并且没有其它可以很好利用网络的应用软件,自带的WiFi基本是没用了。最后就是不支持外部存储扩展,更换内部TF卡要打开后背,很麻烦。当然从一个角度来说,可以更专心地用来看书。特别是刷上Koreader之后。

官方介绍机器的详细配置: http://www.kobo.com/kobomini#techspecs Mobile Read的WIKI: http://wiki.mobileread.com/wiki/Kobo_Mini

系统恢复

机器到手后,点了一下factory reset,机器不断重启且不能进入系统。幸好找到img,刷上就好了。刷好后立马备份一个,以防万一。

把img文件刷到TF卡的教程(英文),关键就是改S/N和把4G的镜像刷入2G卡: http://www.mobileread.com/forums/showpost.php?p=2597246&postcount=15 img文件下载地址(Google Driver): https://docs.google.com/file/d/0BxbJNE-fuHAmeGloU3drOXF0WE0/edit

固件升级

这个很简单,机器用USB数据线连上PC,把升级包解压到.kobo目录下,安全断开连接后,系统就自动刷。

固件升级包地址如下(目前mini的最新版本是3.4.1): http://wiki.mobileread.com/wiki/Kobo_Releases Kobo 固件升级详解 http://www.by-smart.com/forum.php?mod=viewthread&tid=2828

添加中文支持

机器连接到电脑,建一个fonts文件夹,把喜欢的中文字体复制进去,然后安全断开连接。原生系统看中文书时,选复制进去的中文字体就可以完美支持中文了。但是浏览器的中文显示问题解决不了。

Kobo系列书库乱码及字体替换解决方案 http://www.by-smart.com/forum.php?mod=viewthread&tid=3776

安装Kobo Start Menu

第三方的系统中,Kobo Start Menu算是兼容性比较好的了。而且界面都是调用sh脚本文件 + html文件的方式,方便修改。缺点是界面比较丑,简直就是没有做界面。

Kobo Start Menu官方介绍(英文): http://www.mobileread.com/forums/showthread.php?t=233259 目前最新版本及安装方法(英文): http://www.mobileread.com/forums/showpost.php?p=2980759&postcount=591

安装Koreader

个人感觉Kobo上,Koreader是最好的阅读软件了(确实也没几个可以选择了)。

Koreader的介绍 http://www.hi-pda.com/forum/viewthread.php?tid=1078988 Koreader的安装使用贴士——该帖适用于Kobo全系列机型 http://bbs.cooldu.net/forum.php?mod=viewthread&tid=1253 Koreader下载地址 https://github.com/koreader/koreader/wiki/Download 字典下载,zh_CN 简体中文词典 http://abloz.com/huzheng/stardict-dic/zh_CN/

安装Vlasovsoftlauncher

Vlasovsoftlauncher集成了几个游戏(数独、国际象棋、国际跳棋、黑白棋、推箱子等),无聊时可以玩玩。还集成了Coolreader。不过已装了Koreader,就对Coolreader不感冒了。

KOBO系列产品CoolReader安装教程(参考方法二) http://www.cooldu.net/forum.php?mod=viewthread&tid=1495&page=1 Vlasovsoftlauncher各版本安装包下载链接 http://vlasovsoft.triolan.com.ua/files/builds_en.html 安装方法原帖链接 http://wiki.vlasovsoft.net/doku.php?id=en:pbchess-1.2.6#dokuwiki__top

刷Debian系统

试着刷上该系统,但发现操作起来各种不适应,系统很多地方都没有针对本机器进行优化。最后还是刷回原版系统。

Kobo as a Linux tablet(系统作者的Blog) https://sites.google.com/site/gibekm/hardware/kobo/kobo-as-tablet 系统作者在论坛上发的帖 http://www.mobileread.com/forums/showthread.php?t=222123 另一个详细安装教程,附Debian镜像下载地址 http://robotsfuckyeahalloneword.svbtle.com/debian-on-kobo-mini

至此,应付看书应该没问题了。但是我希望能运行Debian,或者开发更多的应用。那么,只能继续折腾了。

Oracle Database Export and Import

用Oracle导出导入数据,以前用exp和imp总是报字符集的错误。后来查了下,Oracle 10g新增了expdp(导出)和impdp(导入)两个工具,而它们会自动根据数据库的配置来设置导出文件的字符集,就是可以无视客户端的字符集设置了。但是有个缺点,导出文件只能放在服务器上。这个问题不大,只要设好目录及相关权限就可以了。

以下例子,假设把USER_A的数据库,复制成USER_B的数据库。

首先,看一下已定义好的目录。如果有需要就新增一个。新增前要授权用户拥有“create any directory”的权限。

-- 查看已定义的文件夹
select * from dba_directories;

-- 查看用户“USER_A”的权限
select * from dba_sys_privs where grantee='USER_A';

-- 授创建文件夹的权限
grant create any directory to USER_A;

-- 创建目录
create or replace directory NEW_DIR as '/tmp';

进行导入导出之前,要授权相关用于拥有读写文件夹的权限。USER_A要导出数据,那他应该有“写”文件夹的权限;USER_B要导入数据,他要有“读”文件夹的权限。嫌麻烦的话,可以同时赋予文件夹的读写权限。

-- 授权用户“USER_A”拥有文件夹“NEW_DIR”的读写权限
grant read,write on directory NEW_DIR to USER_A;

-- 授权用户“USER_A”只有文件夹“NEW_DIR”的写权限
grant write on directory NEW_DIR to USER_A;

-- 授权用户“USER_B”只有文件夹“NEW_DIR”的读权限
grant read on directory NEW_DIR to USER_B;

导出导入的相关参数,查一下就知道了,这里只是操作该用户的所有对象。其中impdp的参数中,remap_schema是把源用户转换成目标用户(格式是 源用户:目标用户),remap_tablespace是把源表空间转换为目标表空间(格式是 源表空间:目标表空间)。以下命令需要在服务器的命令窗口执行。

--导出备份文件,USER_A的数据库
expdp USER_A/PASSWORD@sid schemas=USER_A directory=NEW_DIR dumpfile=user_a_backup.dmp

--导入备份文件,把USER_A的数据库导入到USER_B的数据库
impdp USER_B/PASSWORD@sid remap_schema=USER_A:USER_B remap_tablespace=USER_A_TS:USER_B_TS directory=NEW_DIR dumpfile=user_a_backup.dmp

参考资料:

Install OwnCloud 7

在“搬瓦工”上部署了“ownCloud 7”,记录一下相关的东西吧。采用“Debian 7 x86_64” + “Nginx”部署。

服务器安装

由于“ownCloud 7”的官方文档很齐全,所以基本按照教程就能顺利部署了。

1)在apt配置增加分发包安装地址,然后用apt安装。会提示相关依赖包,一并安装。命令如下:

sudo echo "deb http://download.opensuse.org/repositories/isv:/ownCloud:/community/Debian_7.0/ /" >> /etc/apt/sources.list.d/owncloud.list
apt-get update
apt-get install owncloud

apt的好处是,升级方便。

2)Nginx配置。这个我找了好久,原来官方文档就已经说明清楚了。

Nginx Configuration — ownCloud Administrators Manual 7.0 documentation 按照文档内容部署好,重启一下Nginx就可以了。由于StartSSL的证书申请失败,只能先放弃https。

3)初次配置。登录部署好的OwnCloud,按照提示操作即可。

客户端安装

我的移动设备就只有Android手机和平板了。虽然Android客户端是开源的,但是官方提供的下载地址是Google Play的收费版。由于不能付费购买,就只好自己编译。但我比较懒,幸好网上有提供编译好的版本。链接如下: ownCloud Synchronization client - F-Droid

总结

部署个ownCloud也纯粹是玩玩而已。对于一个国外(速度慢)廉价(空间小)VPS来说,实用性还是不大。但是ownCloud支持Google Drive(15GB免费)、Dropbox(2GB免费)、FTP等扩展,其实用性大大提升!

Git Tutorial

前段时间把自己的小玩意迁移到GitHub,于是学了一下git。把相关的教程整理一下。

1)git - 简明指南 http://rogerdudler.github.io/git-guide/index.zh.html 这个教程应该是最简单明了,没有之一。几分钟就看完。还有多国语言版。

2)Learn Git Branching http://pcottle.github.io/learnGitBranching/ 在线学习并操作git命令。图形化界面,非常适合初学者。

3)Git教程 - 廖雪峰的官方网站 http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 篇幅不长的教程,号称“史上最浅显易懂的Git教程”。教程中,作者把git相关的问题,该说的都说清楚了。

4)Pro Git中文版 https://www.progit.cn/ 基本上关于Git的详细内容都在这本书了。如果看了上面的教程,仍有疑问,那么这本书应该都能解决。

Daily Backup VPS with Google Drive

现在最方便最便宜的存储,当属网盘了。于是想,是否可以利用来作为VPS的日常备份?Google了一下,很多教程。本来想用百度盘,毕竟2TB的免费空间肯定用不完。但是想想,还是用国外的吧,速度会更快。Google Drive的免费空间有15GB,而且已有了开源的同步工具,就选它了。

这个教程已经说得很详细了:VPS每日自动备份到Google Drive

按照教程去配置同步工具grive,修改了一下备份脚本,如下(主要是去掉了数据库文件的加密操作):

#### begin file autobackup.sh ##########################
#!/bin/bash
# from http://eamin.net/vps%E6%AF%8F%E6%97%A5%E8%87%AA%E5%8A%A8%E5%A4%87%E4%BB%BD%E5%88%B0google-drive/
# begin settings
# MySQL user
MYSQL_USER=ro
# MySQL password
MYSQL_PASS=123
# backup directory
BACKUPDIR=/opt/backup
# grive directory
GDRIVEDIR=/opt/grive/
# website directory
WEB_DATA=/opt/www/
# the password file for encrypting the database backup files
#PASSWDFILE=/home/passwd
# end settings

# naming rule of backup files
DataBakName=mysql_$(date +"%Y%m%d").tar.gz
WebBakName=www_$(date +%Y%m%d).tar.gz
# delete files three weeks ago
OldData=mysql_$(date -d -21day +"%Y%m%d").tar.gz
OldWeb=www_$(date -d -21day +"%Y%m%d").tar.gz

# Create the directory when not existed
if [ ! -d $BACKUPDIR ]; then
    mkdir -p $BACKUPDIR
fi

cd $BACKUPDIR

# begin backup database
DATABASES=`mysql -h "127.0.0.1" -u $MYSQL_USER -p$MYSQL_PASS -Bse 'show databases'`

for DB in $DATABASES; do

# ignore system tables
if [ "$DB" == "information_schema" -o "$DB" == "performance_schema" -o "$DB" == "mysql" ]; then
    continue
fi

# export data to backup file
SQLFILE="$BACKUPDIR/$DB.sql.gz"
#ENCFILE="$BACKUPDIR/$DB.sql.gz.enc"
mysqldump -h "127.0.0.1" -u $MYSQL_USER -p$MYSQL_PASS $DB | gzip -9 > $SQLFILE

# encrypt database backup file
#openssl des3 -in $SQLFILE -out $ENCFILE -pass file:$PASSWDFILE
# decrypt database backup file
#openssl des3 -d -in $ENCFILE -out $SQLFILE -pass file:$PASSWDFILE

# delete the file without encryption
#rm $SQLFILE
done
# end backup database

# compress and merge all the backup files
#tar zcf $BACKUPDIR/$DataBakName $BACKUPDIR/*.sql.gz.enc
#rm $BACKUPDIR/*.sql.gz.enc
tar zcf $BACKUPDIR/$DataBakName $BACKUPDIR/*.sql.gz
rm $BACKUPDIR/*.sql.gz

# backup website files
tar zcpf $BACKUPDIR/$WebBakName $WEB_DATA

cd $GDRIVEDIR
grive
rm $OldData
rm $OldWeb

# move the files to grive directory
mv $BACKUPDIR/$WebBakName $GDRIVEDIR/bwg01_backup
mv $BACKUPDIR/$DataBakName $GDRIVEDIR/bwg01_backup
grive

#### end file autobackup.sh ##########################