nginx中rewrite指令使用记录

问题背景说明:

某系统发布的Webservice,经过API网关Kong代理后发现WSDL文件无法查看。
经测试发现原因是因为Kong身份验证的需要,在原url增加了apkikey=xxx这样的参数,如:

http://www.companya.com/app/services/orderDataService?wsdl&apkikey=xxx

该系统处理增加参数的请求时,出现下面的错误信息:

Invalid SOAP request.

解决思路:

在不修改应用程序代码的情况,想办法在nginx层做处理,将请求中apikey=xxx的部分过滤掉,再由tomcat服务器处理。
最终测试成功的nginx配置:

        location /api {
            if ($query_string ~ ^(.*)&apikey=(.*)) {
              set $p $1;
              rewrite ^ $p? last;
            }

            proxy_pass   http://tomcat_cluster;
        }

代码虽然看上去很简单,但由于对nginx的配置写法不熟悉,还是费了不少劲,有几个要点:
1. location的匹配对象,只是uri本身,不包括?之后的参数,如果使用的话用$query_string变量。
2. 代码第3行代码是必须的,因为rewrite本身也使用了正则匹配,如果直接使用$1的话,引用的rewrite匹配的结果。
3. 代码第4行$p后面的分号,也是必须,否则nginx会自动将uri之后的参数,附加到rewrite后的地址,在目前的这个配置下造成循环处理报错。
4. rewrite在最后一个参数,有4个可选项,含义如下:
last 相当于发起一个新的请求,nginx会重现根据location指令进行匹配处理
break 直接使用当前资源,不再执行location里余下的语句
permanent HTTP 301重定向
redirect HTTP 302重定向
前两个浏览器中的url地址不变,后两个会变为rewrite后的地址

参考资料: Nginx的rewrite指令官方文档

oracle用户修改口令审计

1、创建存储更改信息的表

create table PW_CHANGE_LOG
(
  username    VARCHAR2(100),
  change_date DATE,
  host        VARCHAR2(100),
  os_user     VARCHAR2(100)
);

2、使用SYS用户执行下面两个语句,使用Resource Manager来记录口令更改记录

CREATE OR REPLACE FUNCTION password_change_log (
  username varchar2,
  password varchar2,
  old_password varchar2
) RETURN boolean
IS
  v_host varchar2(100);
  v_os_user varchar2(100);
BEGIN
  SELECT SYS_CONTEXT('USERENV', 'HOST'), SYS_CONTEXT('USERENV', 'OS_USER')
  INTO v_host, v_os_user
  FROM DUAL;

  INSERT INTO PW_CHANGE_LOG VALUES (USERNAME, SYSDATE, v_host, v_os_user);
  RETURN(TRUE);
END;
/

CREATE PROFILE LOG_PW_CHANGE LIMIT PASSWORD_VERIFY_FUNCTION PASSWORD_CHANGE_LOG;

shell必备利器-fzf 模糊搜索

大家使用Linux命令行中,是否碰到过这样的场景:以前使用过的命令或文件,但时间一长记得不准确了,但有几个关键字还是有印象的,这时候如何能快速、准确的找出当时的命令或文件?

大家肯定会想到,用history | grep的方法,现在给大家介绍一个更简便的方法,就是今天要说的fzf脚本。

1. 安装(使用git的方法)

git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install

2. 快速查找历史命令
fzf安装后,默认会覆盖原有的Ctrl+R的功能。
因此再按Ctrl+R的时候,就会进入fzf的查找界面,查询方式类似于baidu、google等搜索引擎:支持查询多个关键字,默认为AND的关系。
举个例子:如果记得以前启动seafile的命令,按照记忆输入 seafile start,就可以所有包含这两个关键字的历史命令。
候选列表操作方法:
上下移动:箭头键,或Ctrl+/Ctrl+p
选择:回车键,或用鼠标左键单击
退出:ESC或Ctrl+g

3. 快速选择文件
快捷键:Ctrl+t,列出当前文件夹及子文件夹中的文件

4 快速进入文件夹
快捷键:Atl+c,递归列出当前文件家下的所有子文件
按回车键自动进入选中的文件夹

5. 不使用快捷键的方式触发fzf
在cd vi等命令中选择文件或文件夹的时候,输入**,按TAB,将使用fzf进行查找

参考资料
Shell脚本:模糊搜索神器

曲折的Seafile安装过程

嗯,我得承认,这次安装Seafile折腾的事情,完全是因为最初想偷个懒:申请的vps是centos 6.9 64位,不是Seafile官方推荐的centos 7,所以在网上找了个安装教程开始安装,于是开始了漫长的折腾。

参考文章:
CentOS6.8安装seafile
官方文档: 部署 Seafile 服务器(使用 SQLite)

1、因文件数量不会太多,不想再安装mysql,想用个sqlite算了。结果在安装seafile的时候,报错找不到sqllite3模块。查资料下载源代码编译sqlite3,又重新编译python2.7,算是安装上了。

2、安装完成后启动,一切正常,但访问seahub的时候,出现Internal Error 500的错误。诡异的是,所有日志文件中均没有报错,查了N多资料,最大的可能说是python依赖的包没安装全,但实在没头绪找出缺少哪些包。

3、当时心里不忿,难道6.9就装不上?VPS重新安装了同样的操作系统,按照步骤重新一步一步来,到seafile启动时候,出现和第一个参考资料出现了同样的错误: ”libc.so.6: version `GLIBC_2.14′ not found”.

按照文章中给出的方法,下载新版本的glibc编译安装后,想把lib64/libc.so.6的软链接,修改为编译后libc文件。先把源文件重命名,然后建立新的软连接,居然报错了:

ls: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory

不得已,查资料修改,按照下面的方法改过来:

LD_PRELOAD=/lib64/libc-2.14.so ln -s /lib64/libc-2.14.so /lib64/libc.so.6

可惜的是,软链接修改后,seafile仍然无法启动。
更悲催的是,中间参考一篇文章,建议将新版本的libc编译覆盖到原位置。尝试了一下,在make或make install中间出错后,出现N多loading shared libraries的问题,基本上这个操作系统的命令都不能用了,连恢复的方法想不到了。

4、幸亏吃饭后脑子清醒了一些:既然操作系统已经坏了,干脆按照官方建议在centos 7下安装吧。
没有再找其他资料,按照官方安装文档一步步执行,顺顺当当的安装成功后,使用也一切正常。

后记:
官方6.1版本的客户端,不支持windows xp操作系统。所幸的是服务器端兼容性比较好,在网上找5.X版本安装后也能正常使用。
吐个槽就是官方的下载页面, 服务器端和客户端都只有最新版本,要是有历史版本的下载链接就更方便了。

zsh使用小记

知乎上关于zsh亮点的文章,我是看了这个介绍才对zsh有了兴趣:为什么说 zsh 是 shell 中的极品?

安装过程

yum -y install git zsh

# 安装oh-my-zsh
wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh

# 安装插件autojump

git clone git://github.com/joelthelion/autojump.git ~/.oh-my-zsh/custom/plugins/autojump
cd  ~/.oh-my-zsh/custom/plugins/autojump
./install.py

# 安装其他插件
git clone https://github.com/zsh-users/zsh-completions ~/.oh-my-zsh/custom/plugins/zsh-completions
git clone https://github.com/zsh-users/zsh-autosuggestions $ZSH_CUSTOM/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM}/plugins/zsh-syntax-highlighting

# 修改~/.zshrc
# 加到最后一行
[[ -s ~/.autojump/etc/profile.d/autojump.sh ]] && . ~/.autojump/etc/profile.d/autojump.sh
# 启用插件
plugins=(
  git autojump zsh-completions zsh-autosuggestions zsh-syntax-highlighting
)
# 修改插件主题
ZSH_THEME="ys"

# 重新加载配置文件
source ~/.zshrc
autoload -U compinit && compinit

# 打开新的terminal, 验证新的插件功能是否已经生效

zsh的插件列表:
awesome-zsh-plugins
oh-my-zsh Plugins Overview

另外记录两个其他的命令

# 修改时区
echo "export TZ='Asia/Shanghai'" >> /etc/profile
source /etc/profile

# 查看历史操作,去重
history | awk '{$1=""; print $0;}' | uniq

Tmux学习记录

一、安装
高版本的centos可以用yum直接安装,我用5.9 64位版本还不行,需要从源代码编译,且需要先编译依赖的libevent包
参考文章:Tmux学习笔记
有几个补充:
1. 首先需安装gcc
2. ncurses安装的是6.1版本,5.9版本在make的时候会报错
3. tmux安装版本为2.6
4. tmux的configure语句需修改

yum install gcc ncurses-devel

wget https://cloud.github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz
tar zxvf libevent-2.0.21-stable.tar.gz
cd libevent-2.0.21-stable
./configure --prefix=/usr/local/libevent
make && make install

wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.1.tar.gz
tar xf ncurses-6.1.tar.gz
cd ncurses-6.1
./configure --prefix=/usr/local/ncurses
make && make install

wget https://github.com/tmux/tmux/releases/download/2.6/tmux-2.6.tar.gz
tar xf tmux-2.6.tar.gz
cd /opt/tmux-2.6
./configure CFLAGS="-I/usr/local/libevent/include -I/usr/local/ncurses/include" LDFLAGS="-L/usr/local/libevent/lib -L/usr/local/ncurses/lib" --prefix=/usr/local/tmux

cp /usr/local/libevent/lib/libevent-2.0.so.5 /usr/lib64
cp /usr/local/tmux/bin/tmux /usr/local/bin/

tmux -V

二、使用教程的参考文章:
Tmux使用手册
tmux-Productive-Mouse-Free-Development_zh
上面的文章已经讲的非常全面了,在实际测试过程中,记录几个实用的小Tips:
1、我是在windows上使用ssh的方式连接linux服务器上,如果想把Tmux窗口中文本复制到windows上,可以使用Shift+鼠标左键选择的方式。使用shift+insert的快捷键,可以将windows操作系统的剪贴板内容复制到tmux中。
2、快捷键Crtl+d可以直接关闭当前窗口
3、Tmux的窗口是没有滚动条的,如果想查看屏幕以前输出的内容,需要先进入复制模式,按照vi的方式进行上下滚动(j/k按行滚动,Crtl+b/Ctrl+f按屏幕滚动)
4、快捷键Prefix+=,列出所有粘贴缓存区并粘贴选中的缓存内容,可以在不同的session、窗口之间共享数据,相当于windows中的多重剪贴板功能,非常实用。

===update 2018-04-06===

为了让tmux中vi正常显示中文,需要设置环境变量
export LANG=”zh_CN.utf8″
export LC_ALL=”zh_CN.utf8″

superset安装记录

由于不熟悉python,踩了不少坑,仅以此文记录

1. centos 5.8 32位,更新及安装基本的编译环境

sudo yum upgrade python-setuptools
sudo yum install gcc gcc-c++ libffi-devel python-devel python-pip python-wheel openssl-devel libsasl2-devel openldap-devel

2. 安装Python 3.4.8,注意要使用altinstall,否则后面的安装过程会出现找不到python 2 module的错误

wget https://www.python.org/ftp/python/3.4.8/Python-3.4.8.tgz
tar xvf Python-3.4.8.tgz
cd Python-3.4.8

/configure --prefix=/usr/local
make
make altinstall

创建python3和pip的链接

cd /usr/bin
ln -s /usr/local/python3/bin/python3.4 ./python3
ln -s /usr/local/python3/bin/pip3.4 ./pip

不建议将python3设置默认的python执行程序,否则执行后续的yum操作会报错,当然可以用下面的脚本执行yum,但毕竟麻烦。

cd /usr/bin
python2.6 yum list installed

3. 修改环境变量,
当前目录增加到PATH中,设置语言为UTF-8,否则执行fabmanager会报错

vi ~/.bash_profile
将最后几行修改为:

PATH=.:$PATH:$HOME/bin
export PATH
export LC_ALL=en_US.utf-8
export LANG=en_US.utf-8export LANG=en_US.utf-8

4. 安装superset

pip install --upgrade setuptools pip

pip install superset

cd /usr/local/python3.4 /bin
python3 fabmanager create-admin --app superset
python3 superset db upgrade
python3 superset load_examples
python3 superset init
python3 superset runserver

5. 访问superset

http://localhost:8088

用户名为admin,口令是fabmanger中设置的口令

参考资料;
官方安装文档

oracle expdp impdp使用记录

查询系统中的Directory

SELECT * FROM dba_directories

创建新的Directory

CREATE DIRECTORY dmpdir AS '/opt/oracle';
Directory created.

GRANT read, write ON DIRECTORY dmpdir TO scott;
Grant succeeded.

su – oracle

expdp user/password@oracle_sid parfile=ecc_fms_exp.par

impdp user/password@oracle_sid parfile=ecc_fms_imp.par

ecc_fms_exp.par
schemas=ECC_FMS_01
directory=DATA_PUMP_DIR
dumpfile=ecc_fms_without_srpcell.dmp
logfile=ecc_fms_without_srpcell_exp.log
exclude=table:”like ‘SRP_SHEET_CELL__’”
exclude=table:”like ‘SRP_SHEET_CELL___’”

ecc_fms_imp.par
directory=DATA_PUMP_DIR
dumpfile=ecc_fms_without_srpcell.dmp
logfile=ecc_fms_without_srpcell_imp.log
remap_schema=ECC_FMS_01:ECC_FMS_03
# include=TYPE_SPEC
transform=oid:n

[转]Mysql中模拟递归查询

众所周知,目前的mysql版本中并不支持直接的递归查询,但是通过递归到迭代转化的思路,还是可以在一句SQL内实现树的递归查询的。这个得益于Mysql允许在SQL语句内使用@变量。以下是示例代码。

创建表格

CREATE TABLE `treenodes` (
`id` int , -- 节点ID
`nodename` varchar (60), -- 节点名称
`pid` int  -- 节点父ID
);

插入测试数据

INSERT INTO `treenodes` (`id`, `nodename`, `pid`) VALUES
('1','A','0'),('2','B','1'),('3','C','1'),
('4','D','2'),('5','E','2'),('6','F','3'),
('7','G','6'),('8','H','0'),('9','I','8'),
('10','J','8'),('11','K','8'),('12','L','9'),
('13','M','9'),('14','N','12'),('15','O','12'),
('16','P','15'),('17','Q','15'),('18','R','3'),
('19','S','2'),('20','T','6'),('21','U','8');

查询语句

SELECT id AS ID,pid AS 父ID ,levels AS 父到子之间级数, paths AS 父到子路径 FROM (
    SELECT id, pid,
        @le:= IF (pid = 0 ,0,
        IF( LOCATE( CONCAT('|',pid,':'),@pathlevel) > 0  ,
					SUBSTRING_INDEX( SUBSTRING_INDEX(@pathlevel,CONCAT('|',pid,':'),-1),'|',1) +1
					,@le+1) ) levels,
        @pathlevel:= CONCAT(@pathlevel,'|',id,':', @le ,'|') pathlevel,
        @pathnodes:= IF( pid =0,',0',
        CONCAT_WS(',',
        IF( LOCATE( CONCAT('|',pid,':'),@pathall) > 0  ,
					SUBSTRING_INDEX( SUBSTRING_INDEX(@pathall,CONCAT('|',pid,':'),-1),'|',1)
					,@pathnodes ) ,pid  ) )paths,
        @pathall:=CONCAT(@pathall,'|',id,':', @pathnodes ,'|') pathall
    FROM  treenodes,
    (SELECT @le:=0,@pathlevel:='', @pathall:='',@pathnodes:='') vv
    ORDER BY  pid,id
) src
ORDER BY id

Mysql的行锁只锁一行记录吗?

InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。
InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁,会把所有扫描过的行都锁定!

在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。
由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。
当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;

另外间隙锁也会锁多行,InnoDB除了通过范围条件加锁时使用间隙锁外,如果使用相等条件请求给一个不存在的记录加锁,InnoDB也会使用间隙锁!

当发生死锁的时候,Innodb目前处理死锁的方法是将持有最少行级排他锁的事务进行回滚。

查看INNODB中可能存在的死锁情况:
SHOW ENGINE INNODB STATUS