使用awk来统计访问站点的响应状态码

使用awk来通知nginx的日志来实现对某站点响应状态码的统计

代码:

awk 'BEGIN{
        print "状态码t比例"
    }
    {
        if ($11 ~ /http://blog.longway.pw/) {
            count+=1;
            item[$9]+=1
        }
    }
    END{
        for(i in item) 
            print i,"t",item[i]/count * 100
    }' /usr/local/nginx/logs/access.log | sort -nk2

awk中引用变量的两种方式

结合编辑数据文件的shell脚本学习awk传参方式,该脚本功能:

  • 取VIDEOUSR_11082017_0102_ONLINE_STASTIC.dat文件中第87个字段的低8位;

  • 将每行数据的第3列和第87列对调;

  • 修改后的数据生成到最新时间戳文件中。

1、常规用法

#!/usr/bin/bash

if [[ $# -eq 2 ]];then
  srcfile="$1" #文件名
  bit=$2 #低bit位
  filetimetmp=${srcfile#*_}
  filetime=${filetimetmp%%_*} #截取文件中时间戳,日+月+年
  realtime=`date +"%d%m%Y"` #生成最新时间戳,日+月+年
  let databit="2**$bit" #低bit位对应的值,通过取余截取第低bit位数值
  if [[ -f $srcfile ]];then
    newfile=${srcfile//$filetime/$realtime} #生成最新时间戳对应的文件
    if [[ -f $newfile && $newfilew =~ ".dat" ]];then
       rm -rf $newfile
    fi
       cat $srcfile|sed 's/ /#/'|awk -v mod=$databit -F ',' '{predata=$87%mod;$87=$3;$3=predata;print $0}'|sed 's/ /,/g'|sed 's/#/ /' >>$newfile
       ##其中sed 's/ /#/'和sed 's/#/ /'是对数据中带有空格时间(2017-08-11 17:30:21)做保护(编辑前空格替换为#看,编辑完后#替换为空格)
  fi
fi

调用方式:

sh datatransfomate.sh VIDEOUSR_11082017_0102_ONLINE_STASTIC.dat 8

awk传参:awk -v mod=$databit,之后可以在‘{}’中使用mod变量。

但字段值不能通过变量方式进行修改,即$87和$3如何使用外部变量进行传参。

2、${}变量传参

#!/usr/bin/bash

if [[ $# -eq 4 ]];then
  srcfile="$1" #文件名
  exchghead=$2 #对应第3个字段
  exchgtail=$3 #对应第87个字段
  bit=$4 #低bit位
  filetimetmp=${srcfile#*_}
  filetime=${filetimetmp%%_*} #截取文件中时间戳,日+月+年
  realtime=`date +"%d%m%Y"` #生成最新时间戳,日+月+年
  let databit="2**$bit" #低bit位对应的值,通过取余截取第低bit位数值
  if [[ -f $srcfile ]];then
     newfile=${srcfile//$filetime/$realtime} #生成最新时间戳对应的文件

    if [[ -f $newfile && $newfilew =~ ".dat" ]];then
       rm -rf $newfile
    fi
       cat $srcfile|sed 's/ /#/'|awk -v mod=$databit -F ',' "{predata=$${exchgtail}%mod;$${exchgtail}=$${exchghead};$${exchghead}=predata;print $0}"|sed 's/ /,/g'|sed 's/#/ /' >>$newfile
       ##其中sed 's/ /#/'和sed 's/#/ /'是对数据中带有空格时间(2017-08-11 17:30:21)做保护(编辑前空格替换为#看,编辑完后#替换为空格)
  fi
fi

调用方式:

sh datatransfomate.sh VIDEOUSR_11082017_0102_ONLINE_STASTIC.dat 3 87 8

awk传参:由于使用了“”,shell会对“”中$进行索引替换,因此需要对部分$进行转译。

awk中“”经过shell处理后会转换:

awk -v mod=$databit -F ',' "{predata=$${exchgtail}%mod;$${exchgtail}=$${exchghead};$${exchghead}=predata;print $0}"

                                                    ==》awk -v mod=$databit -F ',' ‘{predata=$87%mod;$87=$3;$3=predata;print $0}’

3、使用总结

  • 常规使用 -v 即可传参,awk -v innerpara=$outerpara -F ‘,’ ‘{print innerpara,$0}’

  • 通过变量方式传参,awk -v -F ‘,’ “{print $${outerpara},$0}” ##注意使用转译符即可

  • 以上两种传参方式可以同时使用

解决apache中403 Forbidden的问题

今天刚编译安装了httpd2.2.34,绑定域名后发现

未分类

检查了目录,也不是权限的问题,检查了N遍httpd.conf才找到是什么问题,默认

<Directory />
Options FollowSymLinks
AllowOverride None
Order deny,allow
Deny from all  ------就这段
</Directory>

无条件禁止任何访问
想要正常把

Deny from all注释掉或者改成allow from all就可以正常访问了。

如果你的服务器也出现了403错误,不防注意下httpd.conf 配置文件Deny from all

开启Apache的PATHINFO模式以支持ThinkPHP

前言

刚开始运行一个基于Think PHP开发的网站源码时(第一次接触ThinkPHP),在本地访问时一直出现404错误,检查地址也没有错误。后来查了很多资料后才发现,Think PHP的默认URL模式是PATHINFO模式,而我本地的Apache没有开启这个模式(ಥ _ ಥ),所以一直报错。在这里记录一下如何开启Apache的PATHINFO模式。

注释:本地服务器使用的是WAMPServer集成安装环境,安装路径为E:Wamp。

正文

第一步:在Apache安装目录的conf文件夹下的httpd.conf文件116行里找到:

#LoadModule rewrite_module modules/mod_rewrite.so

将前面的#去掉,改为:

LoadModule rewrite_module modules/mod_rewrite.so

注:我的路径是:E:WampwampbinapacheApache2.2.21conf,httpd.conf这个文件在其它目录也有,注意只有改动这个目录的文件才有效。

第二步:还是在该文件里进行修改,在118行找到:

Options FollowSymLinks

AllowOverride None

Order deny,allow

Deny from all

AcceptPathInfo On    //加入这行代码就OK了

之后在本地浏览器可以正常访问,不出现404错误了。

mysqldump导出备份数据库报Table ‘performance_schema.session_variables‘ doesn‘t exist

当你在mysql5.6或者5.7中进行备份数据库的时候可能会出现以下这个错误:

例如输入命令:

mysqldump -u root -p test > test.sql

出现的问题:

mysqldump: Couldn‘t execute ‘SHOW VARIABLES LIKE ‘gtid_mode‘‘: Table ‘performance_schema.session_variables‘ doesn‘t exist (1146)

网上说了好多解决方法,例如:使用“–set-gtid-grupe=off”参数等,试了结果并没什么用。

其实具体的解决方法是:

mysql_upgrade -u root -p –force #更新
service mysql restart #restart mysql service
mysqldump -u root -p test > test.sql #重新备份数据

Mysqldump的导出技巧

Mysqldump 是我们经常要用到的命令,Mysqldump 与Mysql 关于连接信息的参数是一致的。

  • -h 主机地址
  • -u 用户名
  • -P 端口
  • -p 密码

命令格式:

mysqldump -h 主机地址 -P 端口 -u 数据库用户名 -p密码  目标数据库名 表名 --where "" > dump.sql

主要看如何限定要导出的数据集范围:

目标数据库名 > 表名 > 表中某个字段的限定条件

三个限定条件,越往后条件越精确,除数据库名以外后面的两个条件都是可选的。这种参数设计思想值得借鉴。

例句:

mysqldump -p123456 cms content --where "date>'2017-08-30 00:00:00'" > dump.sql

上面的命令表示,导出cms数据库下面的content 表中字段 date 大于 2017-08-30 00:00:00 的数据。

UBUNTU 16.04 APACHE2开启HTTP2支持

UBUNTU 16.04默认源里的APACHE2没有HTTP2模块,如果启用HTTP2模块一般会报错找不到模块.

a2enmod http2
ERROR: Module http2 does not exist!

所以如果要启用HTTP2模块,需要从源码从头编一个APACHE2.不过编译好的HTTP2模块可以直接拷贝出来使用,所以已经安装过APACHE2了也不需要担心.
首先将源码源加入源列表之中:

vi /etc/apt/sources.list

添加以下:

deb-src http://archive.ubuntu.com/ubuntu/ xenial main universe restricted multiverse
deb-src http://security.ubuntu.com/ubuntu xenial-security main universe restricted multiverse
deb-src http://archive.ubuntu.com/ubuntu/ xenial-updates main universe restricted multiverse

然后刷新源,如果有需要更新的包,顺便升下级:

apt update
apt upgrade

然后安装依赖:

apt install curl devscripts build-essential fakeroot libnghttp2-dev

创建一个工作的编译目录:

cd ~
mkdir apache2
cd apache2

从源里下载APACHE2的源码然后编译:

apt source apache2
apt build-dep apache2
cd apache2-2.4.18
apt install curl devscripts build-essential fakeroot
fakeroot debian/rules binary

将编译的好的HTTP2模块拷贝到APACHE2模块目录中:

cp debian/apache2-bin/usr/lib/apache2/modules/mod_http2.so /usr/lib/apache2/modules/

然后为HTTP2模块编写一个配置文件:

vim /etc/apache2/mods-available/http2.load

在其中写入以下:

LoadModule http2_module /usr/lib/apache2/modules/mod_http2.so

<IfModule http2_module>  
LogLevel http2:info  
</IfModule>

最后启用HTTP2模块:

service apache2 restart
a2enmod http2
service apache2 restart

编辑网站配置文件,加入HTTP2协议:

vim /etc/apache2/sites-enabled/default-ssl.conf

在默认配置文件的SERVERNAME下添加一行:

Protocols h2 http/1.1

如果没有默认配置文件,可参考以下配置文件:

<IfModule mod_ssl.c>  
 <VirtualHost _default_:443>
 ServerAdmin webmaster@localhost
 ServerName your-domain.com
 Protocols h2 http/1.1
 DocumentRoot /var/www/html

 ErrorLog ${APACHE_LOG_DIR}/error.log
 CustomLog ${APACHE_LOG_DIR}/access.log combined

 SSLEngine on

 SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
 SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

 <FilesMatch ".(cgi|shtml|phtml|php)$">
 SSLOptions +StdEnvVars
 </FilesMatch>
 <Directory /usr/lib/cgi-bin>
 SSLOptions +StdEnvVars
 </Directory>

 </VirtualHost>
</IfModule>

然后还需要将HTTP2协议加入APACHE2配置文件中:

vim /etc/apache2/apache2.conf

加入以下行:

Protocols h2 http/1.1

最后重启APACHE2

service apache2 restart

python flask-sqlalchemy如何设置使自动建的mysql表字符集charset为utf8

问题

发现flask-sqlalchemy自动创建的mysql表为默认的latin1,如何不更改mysql服务器的默认字符集,直接在flask里配置自动建的mysql表字符集为utf8?

最佳答案

配置table_args就可以了,如:

class Foo(Base):
    __tablename__ = "foo"
    __table_args__ = {'mysql_collate': 'utf8_general_ci'}

    ...

    column = db.Column(db.String(500))

MySQL InnoDB Cluster环境搭建和简单测试

InnoDB Cluster初印象

记得MySQL Group Replicatioin 刚开始的时候,MySQL界很是轰动,等待了多年,终于有了官方的这个高可用解决方案。你要说还有一些方案补充,比如MySQL Cluster,MySQL Proxy,这些的使用率个人感觉还是不高,也就是经受的考验还不够,原因有很多,就不赘述了。

不久,我和一个MySQL DBA有了下面的一个基本对话。

我: MySQL GR GA之后,里面的自动切换功能确实很赞,能够做到读写分离,原本MHA的方案现在MGR也可以做了。

MySQL DBA:如果数据库发生了故障,这个自动切换的过程,其实对于应用不是透明的,因为读写节点相当于漂移到了另外一台服务器上,除非再做个中间件。

我:单纯MGR目前还做不了这个,它目前只是保证数据库层面的这种切换和高可用。

MySQL DBA:所以说MGR的企业级应用还是需要一些辅助,这样才算是一个完整的解决方案。

不久,MySQL InnoDB Cluster推出,我觉得这个方案想比原来的MGR更进一步,说实话,我很看好这个方案,尽管目前愿意真正去用的用户确实不多。

如果你看一下官方的这个架构图,就会发现,MGR本身就是Innodb Cluster的一部分,还有两个组件,MySQL Shell,MySQL Router,这三板斧就是InnoDB Cluster的一个核心组件,而正如我之前所说,可以看到MySQL的一个格局和定位,他正在很努力去解决以前诟病的问题。

未分类

安装前先保证Python满足要求

要安装InnoDB Cluster,环境的一个基本要求就是Python,我看了下,很多默认的系统版本是2.6,而它的最低要求是2.7及以上,所以还是需要提前准备下这个部分。

如果你的系统是Python 2.6版本的,可以考虑升级到2.7,参考如下的方法。

下载安装包,部署

wget http://python.org/ftp/python/2.7/Python-2.7.tar.bz2     --no-check-certificate
./configure
make all
make install
make clean
make distclean

查看Python的版本

# /usr/local/bin/python2.7 -V
Python 2.7

做基本的环境设置,替换旧的Python

mv /usr/bin/python /usr/bin/python2.6
ln -s /usr/local/bin/python2.7 /usr/bin/python

sandbox安装部署InnoDB Cluster

搭建InnoDB Cluster显而易见需要多台服务器,而如果在一台服务器上练习测试,也是全然没有问题,如果想更快更方便的测试模拟,还可以使用sandbox来做,首先你得有sandbox,接着InnoDB Cluster的三大组件是MGR,MySQL Shell,MySQL Router,所以你可以从官网直接下载下来。

然后我们开启安装之旅。

使用MySQL Shell的命令mysqlsh开始部署,创建一个端口为3310的实例

mysql-js> dba.deploySandboxInstance(3310)
A new MySQL sandbox instance will be created on this host in
/root/mysql-sandboxes/3310

输入密码之后,一个3310端口的MySQL服务就启动了。

Please enter a MySQL root password for the new instance:
Deploying new MySQL instance...
Instance localhost:3310 successfully deployed and started.
Use shell.connect('root@localhost:3310'); to connect to the instance.

接着创建另外两个节点 3320,3330

dba.deploySandboxInstance(3320)
dba.deploySandboxInstance(3330)

我们切换到3310的MySQL实例,准备开始创建Cluster

mysql-js>  connect root@localhost:3310
Creating a Session to 'root@localhost:3310'
Enter password:
Closing old connection...
Classic Session successfully established. No default schema selected.

定义一个Cluster变量,节点1就开启了Cluster创建之旅,可以从下面的信息看出,至少需要3个节点

mysql-js>  var cluster = dba.createCluster('testCluster')
A new InnoDB cluster will be created on instance 'root@localhost:3310'.
Creating InnoDB cluster 'testCluster' on 'root@localhost:3310'...
Adding Seed Instance...
Cluster successfully created. Use Cluster.addInstance() to add MySQL instances.
At least 3 instances are needed for the cluster to be able to withstand up to  one server failure.

接着把另外两个节点加入进来,先加入端口为3320的节点

mysql-js> cluster.addInstance('root@localhost:3320')
A new instance will be added to the InnoDB cluster. Depending on the amount of
data on the cluster this might take from a few seconds to several hours.
Please provide the password for 'root@localhost:3320':
Adding instance to the cluster ...加入端口为3330的节点,日志和节点2相似。

mysql-js> cluster.addInstance('root@localhost:3330')

这个时候Cluster就创建好了。

这个时候,我们再配置一下MySQL Router,创建个软链接,保证能够正常调用。

# ln -s /home/innodb_cluster/mysql-router-2.1.3-linux-glibc2.12-x86-64bit/bin/mysqlrouter   /usr/bin/mysqlroute
# which mysqlroute
/usr/bin/mysqlroute

配置MySQL Router的启动节点为端口3310的实例

# mysqlrouter –bootstrap root@localhost:3310 –user=mysql

这个时候还是要输入密码,成功之后,这个绑定就打通了。

Please enter MySQL password for root:
Bootstrapping system MySQL Router instance...
MySQL Router  has now been configured for the InnoDB cluster 'testCluster'.
The following connection information can be used to connect to the cluster.
Classic MySQL protocol connections to cluster 'testCluster':
- Read/Write Connections: localhost:6446
- Read/Only Connections: localhost:6447
X protocol connections to cluster 'testCluster':
- Read/Write Connections: localhost:64460
- Read/Only Connections: localhost:64470

可以从上面的日志看出来,分配的读写端口是6446,只读端口是6447,还有x协议连接的端口为64460,64470

启动MySQL Router

# mysqlrouter &
[1] 2913

如果对MySQL Router还有些疑问,可以看看安装目录下,会生成下面的配置文件,我们就看里面的.conf文件,里面的一部分内容如下:

[routing:testCluster_default_rw]
bind_address=0.0.0.0
bind_port=6446
destinations=metadata-cache://testCluster/default?role=PRIMARY
mode=read-write
protocol=classic

验证测试

我们尝试使用6446来连接登录,这个时候就通过MySQL Shell开启了连接入口,MySQL Router做了转接,连接到了里面的读写节点3310

# mysqlsh --uri root@localhost:6446
Creating a Session to 'root@localhost:6446'
Enter password:
Classic Session successfully established. No default schema selected.
Welcome to MySQL Shell 1.0.9

切换到sql模式,查看端口就知道是哪个节点了。

mysql-js> sql
Switching to SQL mode... Commands end with ;
mysql-sql> select @@port;
+--------+
| @@port |
+--------+
|   3310 |
+--------+
1 row in set (0.00 sec)

如果切换为脚本模式查看实例的状态,可以使用里面定义的API来做,输出都是JSON串。

mysql-js> dba.configureLocalInstance('[email protected]:3310')
Please provide the password for '[email protected]:3310':
Detected as sandbox instance.
Validating MySQL configuration file at: /root/mysql-sandboxes/3310/my.cnf
Validating instance...
The instance '127.0.0.1:3310' is valid for Cluster usage
You can now use it in an InnoDB Cluster.
{
"status": "ok"
}如果查看Cluster的信息,可以看到下面的读写节点,只读节点的状态信息

mysql-js> dba.getCluster()
<Cluster:testCluster>

得到Cluster的信息

var cluster = dba.getCluster()
mysql-js> cluster.status()
{
"clusterName": "testCluster",
"defaultReplicaSet": {
"name": "default",
"primary": "localhost:3310",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"localhost:3310": {
"address": "localhost:3310",
"mode": "R/W",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
},
"localhost:3320": {
"address": "localhost:3320",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
},
"localhost:3330": {
"address": "localhost:3330",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
}
}
}
}

也可以使用describe得到一些基本的信息

mysql-js> cluster.describe();
{
"clusterName": "testCluster",
"defaultReplicaSet": {
"instances": [
{
"host": "localhost:3310",
"label": "localhost:3310",
"role": "HA"
},
{
"host": "localhost:3320",
"label": "localhost:3320",
"role": "HA"
},
{
"host": "localhost:3330",
"label": "localhost:3330",
"role": "HA"
}
],
"name": "default"
}
}

切换测试

当然光看不练还是假把式,我们切换一下,看看好使不?

模拟一个节点出现问题,可以使用killSandboxInstance方法。

mysql-js> dba.killSandboxInstance(3310)
The MySQL sandbox instance on this host in
/root/mysql-sandboxes/3310 will be killed
Killing MySQL instance...
Instance localhost:3310 successfully killed.

节点被清理了,没有任何进程存在。

# ps -ef|grep mysql|grep 3310
#

我们还是使用6446的端口来统一连接,这个时候就切换到了端口3320的MySQL服务

# mysqlsh --uri root@localhost:6446
mysql-js> sql
Switching to SQL mode... Commands end with ;
mysql-sql> select @@port;
+--------+
| @@port |
+--------+
|   3320 |
+--------+
1 row in set (0.00 sec)

所以切换的部分没有问题,我们再次把“迷失”的节点启动起来。

# mysqlsh --uri root@localhost:6446
mysql-js> dba.startSandboxInstance(3310)
The MySQL sandbox instance on this host in
/root/mysql-sandboxes/3310 will be started
Starting MySQL instance...
Instance localhost:3310 successfully started.

这个时候再次查看Cluster的状态,3320就是主了,3310就是只读节点了。

mysql-js> dba.getCluster()
<Cluster:testCluster>

把节点2纳入到Cluster中

mysql-js> cluster.rejoinInstance('root@localhost:3310')
Rejoining the instance to the InnoDB cluster. Depending on the original
problem that made the instance unavailable, the rejoin operation might not be
successful and further manual steps will be needed to fix the underlying
problem.
Please monitor the output of the rejoin operation and take necessary action if
the instance cannot rejoin.
Please provide the password for 'root@localhost:3310':
Rejoining instance to the cluster ...
The instance 'root@localhost:3310' was successfully rejoined on the cluster.
The instance 'localhost:3310' was successfully added to the MySQL Cluster.
mysql-js>

可以想象如果是一个生产系统,这么多的日志,这个过程真是让人纠结。
最后来一个切换后的Cluster状态

mysql-js> cluster.status()
{
"clusterName": "testCluster",
"defaultReplicaSet": {
"name": "default",
"primary": "localhost:3320",
"status": "OK",
"statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
"topology": {
"localhost:3310": {
"address": "localhost:3310",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
},
"localhost:3320": {
"address": "localhost:3320",
"mode": "R/W",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
},
"localhost:3330": {
"address": "localhost:3330",
"mode": "R/O",
"readReplicas": {},
"role": "HA",
"status": "ONLINE"
}
}
}
}

解决jenkins启动结束时保留衍生进程

在jenkins中配置自动更新部署项目时,如果采取用execute shell启动/关闭tomcat,会发现可以进行关闭tomcat,但是无法启动tomcat,虽然构建会显示执行成功,但是查看进程,tomcat是没有启动的。这是因为Jenkins默认会在Build结束后Kill掉所有的衍生进程。需要进行以下配置,才能避免此类情况发生:

1、重设环境变量build_id

在execute shell输入框中加入BUILD_ID=DONTKILLME,即可防止jenkins杀死启动的tomcat进程

未分类

2、在启动jenkins 的时候禁止jenkins杀死衍生进程

修改/etc/sysconfig/jenkins配置,在JENKINS_JAVA_OPTIONS中加入-Dhudson.util.ProcessTree.disable=true。需要重启jenkins生效

此方法配置一次后,所有的job都无需设置BUILD_ID,就能够防止jenkins杀死启动的tomcat进程。