awk 系列:如何使用 awk 的特殊模式 BEGIN 和 END

在 awk 系列的第八节,我们介绍了一些强大的 awk 命令功能,它们是变量、数字表达式和赋值运算符。

本节我们将学习更多的 awk 功能,即 awk 的特殊模式:BEGIN 和 END。

学习 awk 的模式 BEGIN 和 END

随着我们逐渐展开,并探索出更多构建复杂 awk 操作的方法,将会证明 awk 的这些特殊功能的是多么强大。

开始前,先让我们回顾一下 awk 系列的介绍,记得当我们开始这个系列时,我就指出 awk 指令的通用语法是这样的:

# awk 'script' filenames  

在上述语法中,awk 脚本拥有这样的形式:

/pattern/ { actions } 

你通常会发现脚本中的模式(/pattern/)是一个正则表达式,此外,你也可以在这里用特殊模式 BEGIN 和 END。因此,我们也能按照下面的形式编写一条 awk 命令:

awk '
BEGIN { actions } 
/pattern/ { actions }
/pattern/ { actions }
……….
END { actions } 
' filenames

假如你在 awk 脚本中使用了特殊模式:BEGIN 和 END,以下则是它们对应的含义:

  • BEGIN 模式:是指 awk 将在读取任何输入行之前立即执行 BEGIN 中指定的动作。
  • END 模式:是指 awk 将在它正式退出前执行 END 中指定的动作。

含有这些特殊模式的 awk 命令脚本的执行流程如下:

  1. 当在脚本中使用了 BEGIN 模式,则 BEGIN 中所有的动作都会在读取任何输入行之前执行。
  2. 然后,读入一个输入行并解析成不同的段。
  3. 接下来,每一条指定的非特殊模式都会和输入行进行比较匹配,当匹配成功后,就会执行模式对应的动作。对所有你指定的模式重复此执行该步骤。
  4. 再接下来,对于所有输入行重复执行步骤 2 和 步骤 3。
  5. 当读取并处理完所有输入行后,假如你指定了 END 模式,那么将会执行相应的动作。

当你使用特殊模式时,想要在 awk 操作中获得最好的结果,你应当记住上面的执行顺序。

为了便于理解,让我们使用第八节的例子进行演示,那个例子是关于 Tecmint 拥有的域名列表,并保存在一个叫做 domains.txt 的文件中。

news.tecmint.com
tecmint.com
linuxsay.com
windows.tecmint.com
tecmint.com
news.tecmint.com
tecmint.com
linuxsay.com
tecmint.com
news.tecmint.com
tecmint.com
linuxsay.com
windows.tecmint.com
tecmint.com
$ cat ~/domains.txt

未分类

在这个例子中,我们希望统计出 domains.txt 文件中域名 tecmint.com 出现的次数。所以,我们编写了一个简单的 shell 脚本帮助我们完成任务,它使用了变量、数学表达式和赋值运算符的思想,脚本内容如下:

#!/bin/bash
for file in $@; do
if [ -f $file ] ; then
### 输出文件名
echo "File is: $file"
### 输出一个递增的数字记录包含 tecmint.com 的行数
awk '/^tecmint.com/ { counter+=1 ; printf "%sn", counter ; }' $file
else
### 若输入不是文件,则输出错误信息
echo "$file 不是一个文件,请指定一个文件。" >&2 && exit 1
fi
done
### 成功执行后使用退出代码 0 终止脚本
exit 0

现在让我们像下面这样在上述脚本的 awk 命令中应用这两个特殊模式:BEGIN 和 END:

我们应当把脚本:

awk '/^tecmint.com/ { counter+=1 ; printf "%sn", counter ; }' $file

改成:

awk ' BEGIN {  print "文件中出现 tecmint.com 的次数是:" ; }
/^tecmint.com/ {  counter+=1  ;  }
END {  printf "%sn",  counter  ; } 
'  $file

在修改了 awk 命令之后,现在完整的 shell 脚本就像下面这样:

#!/bin/bash
for file in $@; do
if [ -f $file ] ; then
### 输出文件名
echo "File is: $file"
### 输出文件中 tecmint.com 出现的总次数
awk ' BEGIN {  print "文件中出现 tecmint.com 的次数是:" ; }
/^tecmint.com/ {  counter+=1  ;  }
END {  printf "%sn",  counter  ; } 
'  $file
else
### 若输入不是文件,则输出错误信息
echo "$file 不是一个文件,请指定一个文件。" >&2 && exit 1
fi
done
### 成功执行后使用退出代码 0 终止脚本
exit 0

未分类

当我们运行上面的脚本时,它会首先输出 domains.txt 文件的位置,然后执行 awk 命令脚本,该命令脚本中的特殊模式 BEGIN 将会在从文件读取任何行之前帮助我们输出这样的消息“文件中出现 tecmint.com 的次数是:”。

接下来,我们的模式 /^tecmint.com/ 会在每个输入行中进行比较,对应的动作 { counter+=1 ; } 会在每个匹配成功的行上执行,它会统计出 tecmint.com 在文件中出现的次数。

最终,END 模式将会输出域名 tecmint.com 在文件中出现的总次数。

$ ./script.sh ~/domains.txt 

未分类

最后总结一下,我们在本节中演示了更多的 awk 功能,并学习了特殊模式 BEGIN 和 END 的概念。

Centos7部署Kubernetes集群

一、环境介绍及准备:

1、物理机操作系统

物理机操作系统采用Centos7.3 64位,细节如下。

[root@localhost ~]# uname -a
Linux localhost.localdomain 3.10.0-514.6.1.el7.x86_64 #1 SMP Wed Jan 18 13:06:36 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
[root@localhost ~]# cat /etc/redhat-release 
CentOS Linux release 7.3.1611 (Core)

2、主机信息

本文准备了三台机器用于部署k8s的运行环境,细节如下:

未分类

设置三台机器的主机名:

Master上执行:

[root@localhost ~]#  hostnamectl --static set-hostname  k8s-master

Node1上执行:

[root@localhost ~]# hostnamectl --static set-hostname  k8s-node-1

Node2上执行:

[root@localhost ~]# hostnamectl --static set-hostname  k8s-node-2

在三台机器上设置hosts,均执行如下命令:

echo '10.0.251.148    k8s-master
10.0.251.148   etcd
10.0.251.148   registry
10.0.251.153   k8s-node-1
10.0.251.155    k8s-node-2' >> /etc/hosts

3、关闭三台机器上的防火墙

systemctl disable firewalld.service
systemctl stop firewalld.service

二、部署etcd

k8s运行依赖etcd,需要先部署etcd,本文采用yum方式安装:

[root@localhost ~]# yum install etcd -y

未分类

yum安装的etcd默认配置文件在/etc/etcd/etcd.conf。编辑配置文件,更改以下带颜色部分信息:

[root@localhost ~]# vi /etc/etcd/etcd.conf

# [member]
ETCD_NAME=master
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
#ETCD_WAL_DIR=""
#ETCD_SNAPSHOT_COUNT="10000"
#ETCD_HEARTBEAT_INTERVAL="100"
#ETCD_ELECTION_TIMEOUT="1000"
#ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379,http://0.0.0.0:4001"
#ETCD_MAX_SNAPSHOTS="5"
#ETCD_MAX_WALS="5"
#ETCD_CORS=""
#
#[cluster]
#ETCD_INITIAL_ADVERTISE_PEER_URLS="http://localhost:2380"
# if you use different ETCD_NAME (e.g. test), set ETCD_INITIAL_CLUSTER value for this name, i.e. "test=http://..."
#ETCD_INITIAL_CLUSTER="default=http://localhost:2380"
#ETCD_INITIAL_CLUSTER_STATE="new"
#ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://etcd:2379,http://etcd:4001"
#ETCD_DISCOVERY=""
#ETCD_DISCOVERY_SRV=""
#ETCD_DISCOVERY_FALLBACK="proxy"
#ETCD_DISCOVERY_PROXY=""

启动并验证状态

[root@localhost ~]# systemctl start etcd
[root@localhost ~]#  etcdctl set testdir/testkey0 0
0
[root@localhost ~]#  etcdctl get testdir/testkey0 
0
[root@localhost ~]# etcdctl -C http://etcd:4001 cluster-health
member 8e9e05c52164694d is healthy: got healthy result from http://0.0.0.0:2379
cluster is healthy
[root@localhost ~]# etcdctl -C http://etcd:2379 cluster-health
member 8e9e05c52164694d is healthy: got healthy result from http://0.0.0.0:2379
cluster is healthy

扩展:Etcd集群部署参见——http://www.cnblogs.com/zhenyuyaodidiao/p/6237019.html

三、部署master

1、安装Docker

[root@k8s-master ~]# yum install docker

未分类

配置Docker配置文件,使其允许从registry中拉取镜像。

[root@k8s-master ~]# vim /etc/sysconfig/docker

# /etc/sysconfig/docker

# Modify these options if you want to change the way the docker daemon runs
OPTIONS='--selinux-enabled --log-driver=journald --signature-verification=false'
if [ -z "${DOCKER_CERT_PATH}" ]; then
    DOCKER_CERT_PATH=/etc/docker
fi
OPTIONS='--insecure-registry registry:5000'

设置开机自启动并开启服务

[root@k8s-master ~]# chkconfig docker on
[root@k8s-master ~]# service docker start

2、安装kubernets

[root@k8s-master ~]# yum install kubernetes

未分类

3、配置并启动kubernetes

在kubernetes master上需要运行以下组件:

  • Kubernets API Server

  • Kubernets Controller Manager

  • Kubernets Scheduler

相应的要更改以下几个配置中带颜色部分信息:

3.1 /etc/kubernetes/apiserver

[root@k8s-master ~]# vim /etc/kubernetes/apiserver

###
# kubernetes system config
#
# The following values are used to configure the kube-apiserver
#

# The address on the local server to listen to.
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"

# The port on the local server to listen on.
KUBE_API_PORT="--port=8080"

# Port minions listen on
# KUBELET_PORT="--kubelet-port=10250"

# Comma separated list of nodes in the etcd cluster
KUBE_ETCD_SERVERS="--etcd-servers=http://etcd:2379"

# Address range to use for services
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"

# default admission control policies
#KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"

# Add your own!
KUBE_API_ARGS=""

3.2 /etc/kubernetes/config

[root@k8s-master ~]# vim /etc/kubernetes/config

###
# kubernetes system config
#
# The following values are used to configure various aspects of all
# kubernetes services, including
#
#   kube-apiserver.service
#   kube-controller-manager.service
#   kube-scheduler.service
#   kubelet.service
#   kube-proxy.service
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"

# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"

# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"

# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://k8s-master:8080"

启动服务并设置开机自启动

[root@k8s-master ~]# systemctl enable kube-apiserver.service
[root@k8s-master ~]# systemctl start kube-apiserver.service
[root@k8s-master ~]# systemctl enable kube-controller-manager.service
[root@k8s-master ~]# systemctl start kube-controller-manager.service
[root@k8s-master ~]# systemctl enable kube-scheduler.service
[root@k8s-master ~]# systemctl start kube-scheduler.service

四、部署node

1、安装docker

参见3.1

2、安装kubernets

参见3.2

3、配置并启动kubernetes

在kubernetes node上需要运行以下组件:

  • Kubelet

  • Kubernets Proxy

相应的要更改以下几个配置文中带颜色部分信息:

3.1 /etc/kubernetes/config

[root@K8s-node-1 ~]# vim /etc/kubernetes/config

###
# kubernetes system config
#
# The following values are used to configure various aspects of all
# kubernetes services, including
#
#   kube-apiserver.service
#   kube-controller-manager.service
#   kube-scheduler.service
#   kubelet.service
#   kube-proxy.service
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"

# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"

# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=false"

# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://k8s-master:8080"

3.2 /etc/kubernetes/kubelet

[root@K8s-node-1 ~]# vim /etc/kubernetes/kubelet

###
# kubernetes kubelet (minion) config

# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
KUBELET_ADDRESS="--address=0.0.0.0"

# The port for the info server to serve on
# KUBELET_PORT="--port=10250"

# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=k8s-node-1"

# location of the api-server
KUBELET_API_SERVER="--api-servers=http://k8s-master:8080"

# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container-image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"

# Add your own!
KUBELET_ARGS=""

启动服务并设置开机自启动

[root@k8s-master ~]# systemctl enable kubelet.service
[root@k8s-master ~]# systemctl start kubelet.service
[root@k8s-master ~]# systemctl enable kube-proxy.service
[root@k8s-master ~]# systemctl start kube-proxy.service

4、查看状态

在master上查看集群中节点及节点状态

[root@k8s-master ~]#  kubectl -s http://k8s-master:8080 get node
NAME         STATUS    AGE
k8s-node-1   Ready     3m
k8s-node-2   Ready     16s
[root@k8s-master ~]# kubectl get nodes
NAME         STATUS    AGE
k8s-node-1   Ready     3m
k8s-node-2   Ready     43s

至此,已经搭建了一个kubernetes集群,但目前该集群还不能很好的工作,请继续后续的步骤。

五、创建覆盖网络——Flannel

1、安装Flannel

在master、node上均执行如下命令,进行安装

[root@k8s-master ~]# yum install flannel

未分类

版本为0.0.5

2、配置Flannel

master、node上均编辑/etc/sysconfig/flanneld,修改红色部分

[root@k8s-master ~]# vi /etc/sysconfig/flanneld

# Flanneld configuration options

# etcd url location.  Point this to the server where etcd runs
FLANNEL_ETCD_ENDPOINTS="http://etcd:2379"

# etcd config key.  This is the configuration key that flannel queries
# For address range assignment
FLANNEL_ETCD_PREFIX="/atomic.io/network"

# Any additional options that you want to pass
#FLANNEL_OPTIONS=""

3、配置etcd中关于flannel的key

Flannel使用Etcd进行配置,来保证多个Flannel实例之间的配置一致性,所以需要在etcd上进行如下配置:(‘/atomic.io/network/config’这个key与上文/etc/sysconfig/flannel中的配置项FLANNEL_ETCD_PREFIX是相对应的,错误的话启动就会出错)

[root@k8s-master ~]# etcdctl mk /atomic.io/network/config '{ "Network": "10.0.0.0/16" }'
{ "Network": "10.0.0.0/16" }

4、启动

启动Flannel之后,需要依次重启docker、kubernete。

在master执行:

systemctl enable flanneld.service 
systemctl start flanneld.service 
service docker restart
systemctl restart kube-apiserver.service
systemctl restart kube-controller-manager.service
systemctl restart kube-scheduler.service

在node上执行:

systemctl enable flanneld.service 
systemctl start flanneld.service 
service docker restart
systemctl restart kubelet.service
systemctl restart kube-proxy.service

Apache优化:修改最大并发连接数

Apache是一个跨平台的web服务器,由于其简单高效、稳定安全的特性,被广泛应用于计算机技术的各个领域。现在,Apache凭借其庞大的用户数,已成为用户数排名第一的web服务器。

尽管如此,在实际的生产环境中,我们仍然不可能直接使用默认配置的Apache来充当服务器。毕竟,为了更充分合理地利用Apache服务器,我们都应该根据自己的实际需要对Apache的默认配置作出一些必要的调整。而针对Apache的优化配置过程中,修改Apache的最大并发连接数就显得尤为重要。

在修改Apache的最大并发连接数之前,我们需要预先了解一些Apache的相关知识。

众所周知,Apache是一个跨平台的、采用模块化设计的服务器。为了应对不同的平台和不同的环境产生的各种不同的需求,也为了在具体的平台或环境下达到最佳的效果,Apache在web服务器的基础功能方面(端口绑定、接收请求等)也同样采用了模块化设计,这个Apache的核心模块就叫做多路处理模块(Multi-Processing Module,简称MPM)。

Apache针对不同的操作系统提供了多个不同的MPM模块,例如:mpm_beos、mpm_event、mpm_netware、mpmt_os2、mpm_prefork、mpm_winnt、mpm_worker。如果条件允许,我们可以根据实际需求将指定的MPM模块编译进我们自己的Apache中(Apache的源码是开放的,允许用户自行编译)。不过,如果在编译时我们没有选择,Apache将按照如下表格根据不同的操作系统自行选择对应的MPM模块,这也是Apache针对不同平台推荐使用的MPM模块。

未分类

mpm_event模块可以看作是mpm_worker模块的一个变种,不过其具有实验性质,一般不推荐使用。

当然,Apache在其官方网站上也提供了根据不同操作系统已经编译好对应MPM模块的成品Apache。你可以点击此处进入Apache官方网站下载。

此外,如果我们想要知道某个Apache内部使用的是何种MPM模块,我们可以以命令行的方式进入Apache安装目录bin,然后键入命令httpd -l,即可查看到当前Apache内部使用的何种MPM模块。

未分类

由于在平常的开发工作中,BeOS、NetWare、OS/2等操作系统并不常见,这里我们主要针对Windows和Unix/Linux操作系统上的MPM模块进行讲解。在Windows和Unix/Linux操作系统上,MPM模块主要有mpm_winnt、mpm_prefork、mpm_worker三种。

mpm_prefork模块

mpm_prefork模块主要应用于Unix/Linux平台的Apache服务器,其主要工作方式是:当Apache服务器启动后,mpm_prefork模块会预先创建多个子进程(默认为5个),当接收到客户端的请求后,mpm_prefork模块再将请求转交给子进程处理,并且每个子进程同时只能用于处理单个请求。如果当前的请求数将超过预先创建的子进程数时,mpm_prefork模块就会创建新的子进程来处理额外的请求。Apache总是试图保持一些备用的或者是空闲的子进程用于迎接即将到来的请求。这样客户端的请求就不需要在接收后等候子进程的产生。

由于在mpm_prefork模块中,每个请求对应一个子进程,因此其占用的系统资源相对其他两种模块而言较多。不过mpm_prefork模块的优点在于它的每个子进程都会独立处理对应的单个请求,这样,如果其中一个请求出现问题就不会影响到其他请求。同时,mpm_prefork模块可以应用于不具备线程安全的第三方模块(比如PHP的非线程安全版本),且在不支持线程调试的平台上易于调试。此外,mpm_prefork模块还具有比mpm_worker模块更高的稳定性。

mpm_worker模块

mpm_worker模块也主要应用于Unix/Linux平台的Apache服务器,它可以看作是mpm_prefork模块的改进版。mpm_worker模块的工作方式与mpm_prefork模块类似。不过,由于处理相同请求的情况下,基于进程(例如mpm_prefork)比基于线程的处理方式占用的系统资源要多。因此,与mpm_prefork模块不同的是,mpm_worker模块会让每个子进程创建固定数量的服务线程和一个监听线程,并让每个服务线程来处理客户端的请求,监听线程用于监听接入请求并将其传递给服务线程处理和应答。Apache总是试图维持一个备用或是空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理。

与mpm_prefork模块相比,mpm_worker模块可以进一步减少系统资源的开销。再加上它也使用了多进程,每个进程又有多个线程,因此它与完全基于线程的处理方式相比,又增加了一定的稳定性。

mpm_winnt模块

mpm_winnt模块是专门针对Windows操作系统而优化设计的MPM模块。它只创建一个单独的子进程,并在这个子进程中轮流产生多个线程来处理请求。

修改MPM模块配置

在对Apache的MPM模块具备一定了解后,我们就可以针对不同的MPM模块来修改Apache的最大并发连接数配置了。

1. 启用MPM模块配置文件

在Apace安装目录/conf/extra目录中有一个名为httpd-mpm.conf的配置文件。该文件主要用于进行MPM模块的相关配置。不过,在默认情况下,Apache的MPM模块配置文件并没有启用。因此,我们需要在httpd.conf文件中启用该配置文件,如下所示:

# Server-pool management (MPM specific)
Include conf/extra/httpd-mpm.conf (去掉该行前面的注释符号"#")

2. 修改MPM模块配置文件中的相关配置

在启动MPM模块配置文件后,我们就可以使用文本编辑器打开该配置文件,我们可以看到,在该配置文件中有许多配置节点,如下图所示:

未分类

此时,我们就需要根据当前Apache服务器所使用的MPM模块,来修改对应节点下的参数配置。首先,我们来看看mpm_winnt模块下的默认配置:

#由于mpm_winnt模块只会创建1个子进程,因此这里对单个子进程的参数设置就相当于对整个Apache的参数设置。

<IfModule mpm_winnt_module>
ThreadsPerChild      150 #推荐设置:小型网站=1000 中型网站=1000~2000 大型网站=2000~3500
MaxRequestsPerChild    0 #推荐设置:小=10000 中或大=20000~100000
</IfModule>

对应的配置参数作用如下:

ThreadsPerChild

每个子进程的最大并发线程数。

MaxRequestsPerChild

每个子进程允许处理的请求总数。如果累计处理的请求数超过该值,该子进程将会结束(然后根据需要确定是否创建新的子进程),该值设为0表示不限制请求总数(子进程永不结束)。

该参数建议设为非零的值,可以带来以下两个好处:

  1. 可以防止程序中可能存在的内存泄漏无限进行下去,从而耗尽内存。

  2. 给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。

注意:在以上涉及到统计请求数量的参数中,对于KeepAlive的连接,只有第一个请求会被计数。

接着,我们再来看看mpm_perfork模块和mpm_worker模块下的默认配置:

#mpm_perfork模块

<IfModule mpm_prefork_module>
StartServers          5 #推荐设置:小=默认 中=20~50 大=50~100
MinSpareServers       5 #推荐设置:与StartServers保持一致
MaxSpareServers      10 #推荐设置:小=20 中=30~80 大=80~120 
MaxClients          150 #推荐设置:小=500 中=500~1500 大型=1500~3000
MaxRequestsPerChild   0 #推荐设置:小=10000 中或大=10000~500000
(此外,还需额外设置ServerLimit参数,该参数最好与MaxClients的值保持一致。)
</IfModule>
#mpm_worker模块

<IfModule mpm_worker_module>
StartServers          2 #推荐设置:小=默认 中=3~5 大=5~10
MaxClients          150 #推荐设置:小=500 中=500~1500 大型=1500~3000
MinSpareThreads      25 #推荐设置:小=默认 中=50~100 大=100~200
MaxSpareThreads      75 #推荐设置:小=默认 中=80~160 大=200~400 
ThreadsPerChild      25 #推荐设置:小=默认 中=50~100 大型=100~200
MaxRequestsPerChild   0 #推荐设置:小=10000 中或大=10000~50000
(此外,如果MaxClients/ThreadsPerChild大于16,还需额外设置ServerLimit参数,ServerLimit必须大于等于 MaxClients/ThreadsPerChild 的值。)
</IfModule>

对应的配置参数作用如下:

StartServers

启动Apache时创建的子进程数。

MinSpareServers

处于空闲状态的最小子进程数。

所谓空闲子进程是指没有正在处理请求的子进程。如果当前空闲子进程数少于MinSpareServers,那么Apache将以最大每秒一个的速度产生新的子进程。只有在非常繁忙机器上才需要调整这个参数。此值不宜过大。

MaxSpareServers

处于空闲状态的最大子进程数。

只有在非常繁忙机器上才需要调整这个参数。此值不宜过大。如果你将该指令的值设置为比MinSpareServers小,Apache将会自动将其修改成MinSpareServers+1。

MaxClients

允许同时连接的最大请求数量。

任何超过MaxClients限制的请求都将进入等待队列,直到达到ListenBacklog指令限制的最大值为止。

对于非线程型的MPM(也就是mpm_prefork),MaxClients表示可以用于处理客户端请求的最大子进程数量,默认值是256。要增大这个值,你必须同时增大ServerLimit。

对于线程型或者混合型的MPM(也就是mpm_beos或mpm_worker),MaxClients表示可以用于处理客户端请求的最大线程数量。线程型的mpm_beos的默认值是50。对于混合型的MPM默认值是16(ServerLimit)乘以25(ThreadsPerChild)的结果。因此要将MaxClients增加到超过16个进程才能提供的时候,你必须同时增加ServerLimit的值。

MinSpareThreads

处于空闲状态的最小线程数。

不同的MPM对这个指令的处理是不一样的:

mpm_worker的默认值是75。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太少,子进程将产生新的空闲线程。mpm_netware的默认值是10。既然这个MPM只运行单独一个子进程,此MPM当然亦基于整个服务器监视空闲线程数。mpm_beos和mpmt_os2的工作方式与mpm_netware差不多,mpm_beos的默认值是1;mpmt_os2的默认值是5。

MaxSpareThreads

处于空闲状态的最大线程数。

不同的MPM对这个指令的处理是不一样的:

mpm_worker的默认值是250。这个MPM将基于整个服务器监视空闲线程数。如果服务器中总的空闲线程数太多,子进程将杀死多余的空闲线程。mpm_netware的默认值是100。既然这个MPM只运行单独一个子进程,此MPM当然亦基于整个服务器监视空闲线程数。mpm_beos和mpmt_os2的工作方式与mpm_netware差不多,mpm_beos的默认值是50;mpmt_os2的默认值是10。

备注:ServerLimit表示Apache允许创建的最大进程数。 值得注意的是,Apache在编译时内部有一个硬限制ServerLimit 20000(对于mpm_prefork模块为ServerLimit 200000)。你不能超越这个限制。
使用这个指令时要特别当心。如果将ServerLimit设置成一个高出实际需要许多的值,将会有过多的共享内存被分配。如果将ServerLimit和MaxClients设置成超过系统的处理能力,Apache可能无法启动,或者系统将变得不稳定。

注意:在配置相关参数时,请先保证服务器具备足够的硬件性能(例如:CPU、内存等)。 如果发现自启动后,随着服务器的运行时间增加,服务器的内存占用也随之增加,可能是程序中出现内存泄露,请向下调整参数MaxRequestsPerChild的值以降低内存泄露带来的影响,然后尽快找出程序中的问题之所在。

【工作】Nginx 实现域名的登录验证功能

背景说明

研发有个需求,访问公司某个域名下的某个url时候需要认证,只有输入正确的用户密码才允许访问web内容。

实现思路

Nginx服务中的”ngx_http_auth_basic_module”模块可以实现此要求,默认情况下编译安装完nginx后,就已经安装启用了ngx_http_auth_basic_module模块,如果不需要这个模块,可以加上 –without-http_auth_basic_module关闭。

ngx_http_auth_basic_module模块指令:

语法: auth_basic string | off;
默认值: auth_basic off;
作用:默认表示不开启认证,后面如果跟上字符,这些字符会在弹窗中显示。
配置段: http, server, location, limit_except

语法: auth_basic_user_file file;
默认值: 无
作用:指定密码文件的位置,可以是相对路径或者绝对路径
配置段: http, server, location, limit_except

实现过程

下面以我的网站www.jiagoumi.com来演示此功能的实现过程,需求是仅当访问http://www.jiagoumi.com/test/时候输入密码才能访问

1. 使用openssl生成密码文件

# printf "test:$(openssl passwd -crypt 123123)n" >> /usr/local/nginx/conf/htpasswd.auth
[root@160719 nginx]# cat /usr/local/nginx/conf/htpasswd
test:bFJVr/zQWK60.

2.修改虚拟主机配置文件

下面红色部分为添加实现的代码

server {
    listen       80;
    server_name    www.jiagoumi.com;
    access_log    logs/www.jiagoumi.com.access.log;
    error_log     logs/www.jiagoumi.com.error.log;

    location /test {
     auth_basic "Authorization Required";
     auth_basic_user_file /usr/local/nginx/conf/htpasswd.auth;
     index  index.php index.html index.htm;
     root   /data/nginx/site/www.jiagoumi.com;
     }

    location /
    {
        proxy_set_header        Host  $host;
        proxy_set_header        X-Real-IP  $remote_addr;
        proxy_set_header        REMOTE-HOST $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass              http://192.168.1.1:8080;
    }

验证配置文件,重启Nginx服务:

# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/nginx.conf test is successful

# /usr/local/nginx/sbin/nginx -s reload

3.验证效果

访问http://www.jiagoumi.com/test/会提示输入密码,输入上面创建的账号密码即可登录查看内容。

注意:此功能需要使用IE兼容模式访问,使用chrome内核的浏览器无法正常访问。

未分类

[译]Linux:25个有用的iptables防火墙规则

管理网络流量是系统管理员需要处理的最棘手的工作之一。

管理员配置防火墙时需要同时满足系统和用户对于传出和传入连接的要求,而且要避免系统遭受攻击。

这就是iptables有用的地方。iptables是一个linux命令行防火墙,它允许系统管理员通过一系列可配置的规则来控制传出和传入的流量。

iptables使用一系列具有链结构的表,这些链包含内建的规则或用户定义的规则。多亏于此,系统管理员可以恰当地过滤系统的网络流量。

iptables中有以下三种类型的表:

  • FILTER表,默认的表,包含以下三种内建链:
    • INPUT链,发给本地sockets的包
    • FORWARD链,经由系统发送的包
    • OUTPUT链,本地生成并发出的包
  • NAT表,当一个包试图创建新连接时将访问该表,该表包含以下内建链:
    • PREROUTING链,更改刚接收到的包
    • OUTPUT链,更改本地产生的包
    • POSTROUTING链,更改即将发出的包
  • MANGLE表,用于包的更改:
    • PREROUTING链:更改传入连接
    • OUTPUT链:更改本地产生的包
    • INPUT链:更改传入的包
    • POSTROUTING链:更改即将发出的包
    • FORWARD链:更改经过的包

在这篇文章中,你将会看到一些有用的命令,帮助你使用iptables来管理你的Linux防火墙。

1. 开始/停止/重启iptables防火墙

首先,你应该知道如何在不同发行版的Linux系统中管理iptables服务。

基于SystemD的linux发行版

------------ On Cent/RHEL 7 and Fedora 22+ ------------
# systemctl start iptables
# systemctl stop iptables
# systemctl restart iptables

基于SysVinit的linux发行版

------------ On Cent/RHEL 6/5 and Fedora ------------
# /etc/init.d/iptables start
# /etc/init.d/iptables stop
# /etc/init.d/iptables restart

2. 查看所有iptables规则

# iptables -L -n -v

输出示例:

Chain INPUT (policy ACCEPT 1129K packets, 415M bytes)
pkts bytes target prot opt in out source destination 
0 0 ACCEPT tcp -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
0 0 ACCEPT udp -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 ACCEPT tcp -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:67
0 0 ACCEPT udp -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:67

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination 
0 0 ACCEPT all -- * lxcbr0 0.0.0.0/0 0.0.0.0/0 
0 0 ACCEPT all -- lxcbr0 * 0.0.0.0/0 0.0.0.0/0

Chain OUTPUT (policy ACCEPT 354K packets, 185M bytes)
pkts bytes target prot opt in out source destination

如果你想要查看某个表的规则,可以使用-t选项,后面跟上你想要查看的表。例如,要查看NAT表的规则,可以输入以下命令:

# iptables -t nat -L -v -n

3. 屏蔽某个IP地址

如果你发现一个来自某个IP的异常活动,你可以屏蔽这个IP地址:

# iptables -A INPUT -s xxx.xxx.xxx.xxx -j DROP

将“xxx.xxx.xxx.xxx”改为想要屏蔽的IP地址。需要注意的是,你有可能会意外屏蔽自己的IP地址。 -A 选项会将规则添加到指定的链中。

如果你只想要屏蔽来自某个IP地址的TCP流量,你可以使用 -p 选项来指定协议。这种情况下命令如下:

# iptables -A INPUT -p tcp -s xxx.xxx.xxx.xxx -j DROP

4. 取消屏蔽某个IP地址

如果你想取消对某个IP地址的屏蔽,可以删除对应的屏蔽规则:

# iptables -D INPUT -s xxx.xxx.xxx.xxx -j DROP

选项 -D 用于从选定的链中删除一条或多条规则,你也可以使用 –delete 选项。

5. 屏蔽某个端口

有时候我们会想要屏蔽基于某个端口的传出或传入连接,这是一个良好的安全措施,当你要设定防火墙时,应该认真考虑这措施。

屏蔽基于某个端口的传出连接:

# iptables -A OUTPUT -p tcp --dport xxx -j DROP

允许基于某个端口的传入连接:

# iptables -A INPUT -p tcp --dport xxx -j ACCEPT

将上面例子中的“xxx”修改为想要屏蔽或允许的端口号。如果你想要屏蔽UDP流量而不是TCP流量,只需简单地将上述规则中的 tcp 修改为 udp 即可。

6. 使用Multiport允许多个端口

你可以通过使用multiport来同时允许多个端口,你可以在下面找到适用于传入和传出的规则:

# iptables -A INPUT  -p tcp -m multiport --dports 22,80,443 -j ACCEPT
# iptables -A OUTPUT -p tcp -m multiport --sports 22,80,443 -j ACCEPT

7. 允许基于某个端口的指定范围的网络

你可能想限制一些基于某个端口的连接访问特定网络。比方说你想要允许基于22端口的传出连接访问192.168.100.0/24网络,可以通过以下命令实现:

# iptables -A OUTPUT -p tcp -d 192.168.100.0/24 --dport 22 -j ACCEPT

8. 屏蔽Facebook网站

有一些雇主喜欢屏蔽员工对于Facebook网站的访问权限,下面是一个屏蔽Facebook流量的示例。

首先找到Facebook使用的IP地址:

# host facebook.com
facebook.com has address 66.220.156.68

# whois 66.220.156.68 | grep CIDR
CIDR: 66.220.144.0/20

接下来你就可以屏蔽Facebook网站了:

# iptables -A OUTPUT -p tcp -d 66.220.144.0/20 -j DROP

注意,Facebook网站使用的IP地址范围可能因国家而异。

9. 设置端口转发

有时你可能想要将某个服务的流量转发到另一个端口,命令如下:

# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j REDIRECT --to-port 2525

以上命令会将所有来自eth0接口的传入流量,由25端口转发到2525端口。你可以根据自己的需要来修改端口号。

10. 屏蔽Apache端口的网络洪水

有些IP地址可能会对网站的web端口请求过多的连接,这可能导致一些问题。要避免这些问题,你可以使用以下规则:

# iptables -A INPUT -p tcp --dport 80 -m limit --limit 100/minute --limit-burst 200 -j ACCEPT

上述命令中 –limit 100/minute 表示将传入连接限制为100个每分钟,–limit-burst 200 表示仅当连接总数达到200个以后才开始限制连接数。

11. 屏蔽传入Ping请求

基于安全考虑,有些系统管理员喜欢屏蔽传入ping请求。虽然威胁并不大,不过了解如何屏蔽这样的请求还是有好处的:

# iptables -A INPUT -p icmp -i eth0 -j DROP

12. 允许loopback权限

loopback权限(来自127.0.0.1的权限)是非常重要的,你应该总是将其设为激活状态。

# iptables -A INPUT -i lo -j ACCEPT
# iptables -A OUTPUT -o lo -j ACCEPT

13. 记录丢弃的网络包

如果你想要记录eth0接口所丢弃的网络包,可以使用以下命令:

# iptables -A INPUT -i eth0 -j LOG --log-prefix "IPtables dropped packets:"

你可以改变 –log-prefix 选项后面所跟的内容。日志将被记录到 /var/log/messages 文件中,你可以通过以下命令来搜索日志:

# grep "IPtables dropped packets:" /var/log/messages

14. 屏蔽某个MAC地址

你可以屏蔽来自特定MAC地址的访问权限:

# iptables -A INPUT -m mac --mac-source 00:00:00:00:00:00 -j DROP

当然,你需要将“00:00:00:00:00:00”改为你想屏蔽的MAC地址。

15. 限制每个IP的并发连接数

如果你不想同一个IP地址在某个端口同时建立太多连接,你可以通过以下方式进行限制:

# iptables -A INPUT -p tcp --syn --dport 22 -m connlimit --connlimit-above 3 -j REJECT

上述命令允许每个客户端同时建立最多3个连接。当然,你可以改变端口号来匹配不同的服务。

16. 搜索IPtables规则

一旦你定义了自己的iptables规则,你可能经常需要进行搜索或修改操作。一种简单的搜索方式如下:

# iptables -L $table -v -n | grep $string

在上述示例中,你需要将 $table 改为你想搜索的表,并将 $string 改为你想搜索的字符串。

示例如下:

# iptables -L INPUT -v -n | grep 192.168.0.100

17. 定义新的链

你可以定义自己的链,并在其中存放自定义的规则。

定义一个链:

# iptables -N custom-filter

现在你可以查看你定义的过滤规则了:

# iptables -L

示例输出:

Chain INPUT (policy ACCEPT)
target prot opt source destination

Chain FORWARD (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Chain custom-filter (0 references)
target prot opt source destination

18. 删除所有链或规则

删除所有自定义链:

# iptables -F

清除某个表中的所有链:

# iptables -t nat -F

你可以将“nat”改为想要清除的链所在的表。

19. 保存IPtables规则到文件

如果你想保存你的防火墙规则,可以使用 iptables-save 命令:

# iptables-save > ~/iptables.rules

20. 从文件恢复IPtables规则

如果你想要恢复一个列表的规则,可以使用 iptables-restore 命令:

# iptables-restore < ~/iptables.rules

21. 设置符合PCI的规则

有一些系统管理员可能被要求将服务器按PCI要求进行配置。不同的PCI提供商有许多不同的要求,但也有一些共同的要求。

在很多情况下,你需要拥有多于一个的IP地址。你需要将以下规则应用到网站的IP地址中。请特别注意,使用下面的命令时你应该清楚自己在做什么。

# iptables -I INPUT -d SITE -p tcp -m multiport --dports 21,25,110,143,465,587,993,995 -j DROP

如果你使用cPanel或者类似的控制面板,你可能还需要屏蔽它的端口。示例如下:

# iptables -I in_sg -d DEDI_IP -p tcp -m multiport --dports  2082,2083,2095,2096,2525,2086,2087 -j DROP

注意:为了确保你满足PCI供应商的要求,请认真查看他们的报告,并应用要求的规则。在一些情况下你可能还需要屏蔽基于特定端口的UDP流量。

22. 允许已建立的和相关联的连接

正如网络流量被分为传入和传出,你可能想要允许已建立的和相关联的传入流量。

对于传入连接:

# iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

对于传出连接:

# iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT

23. 丢弃无效的包

我们可以将某些网络包标记为无效。一些人可能喜欢记录这些包,但另一些人喜欢丢弃它们。要丢弃无效的包,可以执行以下命令:

# iptables -A INPUT -m conntrack --ctstate INVALID -j DROP 

24. 屏蔽某个网络接口的连接

有些系统可能具有不止一个的网络接口。你可以限制某个网络接口的访问权限,或者屏蔽来自特定IP地址的连接。

例如:

# iptables -A INPUT -i eth0 -s xxx.xxx.xxx.xxx -j DROP

将“xxx.xxx.xxx.xxx”改为你想屏蔽的IP地址。

25. 禁止传出邮件

如果你的系统不应该发送任何电子邮件,你可以屏蔽SMTP传出端口。

示例:

# iptables -A OUTPUT -p tcp --dports 25,465,587 -j REJECT

总结

IPtables是一个强大而又易用的防火墙。学习IPtables的基本使用,对于每个Linux系统管理员而言都是非常重要的。如果你想要了解更多关于iptables命令及其选项的详细内容,建议你阅读它的手册:

# man iptables

Linux CentOS 7 重置root用户密码

在Centos 7以前的发行版中,只需要在vmlinuz行末尾添加“1”或“single”后按b重新引导即可。Linux Centos 7系列发行版系统,若是忘记超级用户root密码,破解起来相当费事。而且重置Centos 7 Root密码的方法和Centos 6系列完全不同。

接下来我将以2种解决方案破解Centos 7 Root密码。

第一种解决方案

1. 进入单用户模式

在系统启动读秒的时候,按下任意键,会出现选择内核启动项,选择第一个按下e编辑当前内核。

在以下选项中,添加“rd.break”红色标注部分:

linux16 /vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/cl-root ro cra
shkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet LANG=en_US.UTF-8 rd.break

添加完成,然后按 “ctrl+x” 或 “F10” 启动。

2. 以读写权限挂载文件系统

switch_root # mount -o rw,remount /sysroot/
switch_root # chroot /sysroot/

3. 修改root用户密码

sh-4.2 # echo NewRenwole123 | passwd --stdin root
Changing password for user root.
passwd:all authentication tokens updated successfully.

或:

sh-4.2 # passwd root (输入两次密码回车即可)

4. 重载SElinux并退出单用户模式

sh-4.2 # touch /.autorelabel
sh-4.2 # exit
switch_root # reboot

重新启动后,可以使用新密码 “NewRenwole123” 登录。

第二种解决方案

1. 进入单用户模式

系统启动读秒的时候,按下e编辑当前内核:

linux16 /vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/cl-root ro cra
shkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet LANG=en_US.UTF-8

修改为:

linux16 /vmlinuz-3.10.0-514.el7.x86_64 root=/dev/mapper/cl-root ro cra
shkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap init=/bin/sh

将“rhgb quiet LANG=zh_CN.UTF-8”替换为“init=/bin/sh”,按“ctrl+x”或“F10”引导系统。

2. 挂载并使文件系统为可写

sh-4.2 # mount -o remount,rw /
sh-4.2 # passwd root (回车后需输入两次密码,成功后出现如下提示):
passwd:all authentication tokens updated successfully.

3. 加载 SELinux 策略,并重启系统

sh-4.2 # touch /.autorelabel
sh-4.2 # exec /sbin/init

系统初始化完毕后会自动重启,用新密码登录即可。

centos vsftp下修改默认端口21

常规下21端口容易遭到别人的扫描、带来了一定程度的不安全。所以,最好的就是把21端口修改掉。默认修改为2121

一、修改vsftp的配置文件

vi /etc/vsftpd/vsftpd.conf

在原来的基础上加上:

listen_port=2121
pasv_enable=YES
pasv_min_port=1050
pasv_max_port=1060
pasv_promiscuous=YES

二、修改防火墙规则

如果防火墙开启、并且做了端口限制、请添加这两条规则。

vi /etc/sysconfig/iptables
-A INPUT -p tcp -m state --state NEW -m tcp --dport 1050:1060 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 2121 -j ACCEPT
service iptables restart

三、通过客户端ftp连接(选择被动模式连接)

docker环境搭建ELK

ELK是开源日志界的三大剑客,本文主要讲怎么在docker里头跑起来这一套东东。

镜像

这里采用docker-elk的镜像。

运行

cd docker-elk
eval "$(docker-machine env default)"
docker-compose up -d
...
Successfully built 68f1e0777077
Creating dockerelk_kibana_1
Attaching to dockerelk_elasticsearch_1, dockerelk_logstash_1, dockerelk_kibana_1
kibana_1        | Stalling for Elasticsearch
kibana_1        | Starting Kibana
elasticsearch_1 | [2016-02-03 12:01:46,067][INFO ][node                     ] [Caretaker] version[2.2.0], pid[1], build[8ff36d1/2016-01-27T13:32:39Z]
elasticsearch_1 | [2016-02-03 12:01:46,068][INFO ][node                     ] [Caretaker] initializing ...
elasticsearch_1 | [2016-02-03 12:01:46,615][INFO ][plugins                  ] [Caretaker] modules [lang-expression, lang-groovy], plugins [], sites []
elasticsearch_1 | [2016-02-03 12:01:46,635][INFO ][env                      ] [Caretaker] using [1] data paths, mounts [[/usr/share/elasticsearch/data (/dev/sda1)]], net usable_space [14gb], net total_space [18.1gb], spins? [possibly], types [ext4]
elasticsearch_1 | [2016-02-03 12:01:46,635][INFO ][env                      ] [Caretaker] heap size [1015.6mb], compressed ordinary object pointers [true]
elasticsearch_1 | [2016-02-03 12:01:49,038][INFO ][node                     ] [Caretaker] initialized
elasticsearch_1 | [2016-02-03 12:01:49,040][INFO ][node                     ] [Caretaker] starting ...
elasticsearch_1 | [2016-02-03 12:01:49,120][INFO ][transport                ] [Caretaker] publish_address {172.17.0.6:9300}, bound_addresses {[::]:9300}
elasticsearch_1 | [2016-02-03 12:01:49,130][INFO ][discovery                ] [Caretaker] elasticsearch/jOBlX_T5TYmgeE6jHP-z0Q
elasticsearch_1 | [2016-02-03 12:01:52,207][INFO ][cluster.service          ] [Caretaker] new_master {Caretaker}{jOBlX_T5TYmgeE6jHP-z0Q}{172.17.0.6}{172.17.0.6:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
elasticsearch_1 | [2016-02-03 12:01:52,250][INFO ][http                     ] [Caretaker] publish_address {172.17.0.6:9200}, bound_addresses {[::]:9200}
elasticsearch_1 | [2016-02-03 12:01:52,251][INFO ][node                     ] [Caretaker] started
elasticsearch_1 | [2016-02-03 12:01:52,259][INFO ][gateway                  ] [Caretaker] recovered [0] indices into cluster_state
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["warning","config"],"pid":1,"key":"bundled_plugin_ids","val":["plugins/dashboard/index","plugins/discover/index","plugins/doc/index","plugins/kibana/index","plugins/markdown_vis/index","plugins/metric_vis/index","plugins/settings/index","plugins/table_vis/index","plugins/vis_types/index","plugins/visualize/index"],"message":"Settings for "bundled_plugin_ids" were not applied, check for spelling errors and ensure the plugin is loaded."}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:sense","info"],"pid":1,"name":"plugin:sense","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:kibana","info"],"pid":1,"name":"plugin:kibana","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:elasticsearch","info"],"pid":1,"name":"plugin:elasticsearch","state":"yellow","message":"Status changed from uninitialized to yellow - Waiting for Elasticsearch","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:kbn_vislib_vis_types","info"],"pid":1,"name":"plugin:kbn_vislib_vis_types","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:markdown_vis","info"],"pid":1,"name":"plugin:markdown_vis","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:metric_vis","info"],"pid":1,"name":"plugin:metric_vis","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:spyModes","info"],"pid":1,"name":"plugin:spyModes","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:statusPage","info"],"pid":1,"name":"plugin:statusPage","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["status","plugin:table_vis","info"],"pid":1,"name":"plugin:table_vis","state":"green","message":"Status changed from uninitialized to green - Ready","prevState":"uninitialized","prevMsg":"uninitialized"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:44+00:00","tags":["listening","info"],"pid":1,"message":"Server running at http://0.0.0.0:5601"}
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:49+00:00","tags":["status","plugin:elasticsearch","info"],"pid":1,"name":"plugin:elasticsearch","state":"yellow","message":"Status changed from yellow to yellow - No existing Kibana index found","prevState":"yellow","prevMsg":"Waiting for Elasticsearch"}
elasticsearch_1 | [2016-02-03 13:21:50,104][INFO ][cluster.metadata         ] [Caretaker] [.kibana] creating index, cause [api], templates [], shards [1]/[1], mappings [config]
elasticsearch_1 | [2016-02-03 13:21:50,489][INFO ][cluster.routing.allocation] [Caretaker] Cluster health status changed from [RED] to [YELLOW] (reason: [shards started [[.kibana][0]] ...]).
kibana_1        | {"type":"log","@timestamp":"2016-02-03T13:21:53+00:00","tags":["status","plugin:elasticsearch","info"],"pid":1,"name":"plugin:elasticsearch","state":"green","message":"Status changed from yellow to green - Kibana index ready","prevState":"yellow","prevMsg":"No existing Kibana index found"}

查看kibana

http://192.168.99.100:5601/
未分类

查看sense

http://192.168.99.100:5601/app/sense
未分类

默认端口

  • 5000: Logstash TCP input.

  • 9200: Elasticsearch HTTP

  • 9300: Elasticsearch TCP transport

  • 5601: Kibana

CentOS 7 修改内核启动顺序

1. 查看当前 grub2 的启动项:

cat /boot/grub2/grub.cfg

menuentry 后面的就是启动项。

例如改为 ‘CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)’

2. 一条命令:

grub2-set-default 'CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)'

例如

grub2-set-default 'CentOS Linux (3.10.0-327.36.3.el7.x86_64) 7 (Core)'

3. 验证一下是否有用:

grub2-editenv list

将会返回:

saved_entry=CentOS Linux (3.10.0-327.el7.x86_64) 7 (Core)

4. 重启即可。

docker环境搭建elasticsearch

本文主要讲如何使用使用docker搭建elasticsearch。

下载镜像

这里利用hangxin1940搭好的镜像,不过是es的1.4.2版本。

docker pull hangxin1940/docker-elasticsearch-cn:v1.6.0

启动容器

docker run -d -p 9200:9200 -p 9300:9300 --name es hangxin1940/docker-elasticsearch-cn:v1.6.0

查看es(这里的ip是docker的default machine的ip)

访问http://192.168.99.100:9200/

{
status: 200,
name: "node1",
cluster_name: "cn-out-of-box",
version: {
number: "1.6.0",
build_hash: "cdd3ac4dde4f69524ec0a14de3828cb95bbb86d0",
build_timestamp: "2015-06-09T13:36:34Z",
build_snapshot: false,
lucene_version: "4.10.4"
},
tagline: "You Know, for Search"
}

查看集群状态

http://192.168.99.100:9200/_plugin/head/

未分类

也可以用命令行

curl -XGET http://192.168.99.100:9200/_cluster/health?pretty

返回

{
  "cluster_name" : "cn-out-of-box",
  "status" : "yellow",
  "timed_out" : false,
  "number_of_nodes" : 1,
  "number_of_data_nodes" : 1,
  "active_primary_shards" : 1,
  "active_shards" : 1,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 1,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0
}

这里目前只是单节点的,后续弄成集群看看。

查看插件

http://192.168.99.100:9200/_plugin/oob

未分类

增删改查

增加

curl -XPUT 'http://192.168.99.100:9200/twitter/tweet/1' -d '{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elastic Search"
}'

返回

{"_index":"twitter","_type":"tweet","_id":"1","_version":1,"created":true}%

查询

curl -XGET 'http://192.168.99.100:9200/twitter/tweet/1'

返回

{"_index":"twitter","_type":"tweet","_id":"1","_version":1,"found":true,"_source":{
    "user" : "kimchy",
    "post_date" : "2009-11-15T14:12:12",
    "message" : "trying out Elastic Search"
}}%

未分类

高级查询:选择字段

curl -XGET 'http://192.168.99.100:9200/twitter/tweet/1?fields=message,user&pretty=true'

返回

{
  "_index" : "twitter",
  "_type" : "tweet",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "fields" : {
    "message" : [ "trying out Elastic Search" ],
    "user" : [ "kimchy" ]
  }
}

高级查询:选择格式

curl -XGET 'http://192.168.99.100:9200/twitter/tweet/1?fields=message,user&format=yaml'

返回

---
_index: "twitter"
_type: "tweet"
_id: "1"
_version: 1
found: true
fields:
  message:
  - "trying out Elastic Search"
  user:
  - "kimchy"

更新

curl -X PUT http://192.168.99.100:9200/twitter/tweet/1 -d '{"message": "hello world", "user": "patterncat"}'

返回

{"_index":"twitter","_type":"tweet","_id":"1","_version":2,"created":false}%

这个是覆盖更新,不是局部更新:

 ~  curl -XGET 'http://192.168.99.100:9200/twitter/tweet/1'
{"_index":"twitter","_type":"tweet","_id":"1","_version":2,"found":true,"_source":{"message": "hello world", "user": "patterncat"}}%

删除

curl -XDELETE 'http://192.168.99.100:9200/twitter/tweet/1'

返回

{"found":true,"_index":"twitter","_type":"tweet","_id":"1","_version":3}%

查看mapping

{
    "twitter": {
        "mappings": {
            "tweet": {
                "properties": {
                    "message": {
                        "type": "string"
                    }, 
                    "post_date": {
                        "type": "date", 
                        "format": "dateOptionalTime"
                    }, 
                    "user": {
                        "type": "string"
                    }
                }
            }
        }
    }
}

索引分析

http://192.168.99.100:9200/twitter/_analyze?field=message&text=hello%20world

{
    "tokens": [
        {
            "token": "hello", 
            "start_offset": 0, 
            "end_offset": 5, 
            "type": "<ALPHANUM>", 
            "position": 1
        }, 
        {
            "token": "world", 
            "start_offset": 6, 
            "end_offset": 11, 
            "type": "<ALPHANUM>", 
            "position": 2
        }
    ]
}