(一)平台所需的环境
OS:CentOS 7.x minimal
elasticsearch :elasticsearch-5.4.0版本
jdk: 1.8已上版本
创建普通用户:appuser
最新的下载路径地址为:https://www.elastic.co/downloads
(二)配置操作系统的环境并安装elasticsearch:
1.ifconifg查看网络的命令无法使用,最后的解决方案为:yum -y install net-tools [[email protected] ~]# ifconifig bash: ifconifig: command not found [[email protected] ~]# ipaddr bash: ipaddr: command not found [[email protected] ~]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000 link/ether 00:15:5d:6e:28:1a brd ff:ff:ff:ff:ff:ff inet 192.168.180.23/24 brd 192.168.180.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::215:5dff:fe6e:281a/64 scope link valid_lft forever preferred_lft forever [[email protected] ~]# yum -y install net-tools #########使用yum安装net-tools工具 Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.163.com * extras: mirrors.163.com * updates: mirrors.163.com Resolving Dependencies --> Running transaction check ---> Package net-tools.x86_64 0:2.0-0.17.20131004git.el7 will be installed --> Finished Dependency Resolution Dependencies Resolved ======================================================================================================================== Package Arch Version Repository Size ======================================================================================================================== Installing: net-tools x86_64 2.0-0.17.20131004git.el7 base 304 k Transaction Summary ======================================================================================================================== Install 1 Package Total download size: 304 k Installed size: 917 k Downloading packages: net-tools-2.0-0.17.20131004git.el7.x86_64.rpm | 304 kB 00:00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : net-tools-2.0-0.17.20131004git.el7.x86_64 1/1 Verifying : net-tools-2.0-0.17.20131004git.el7.x86_64 1/1 Installed: net-tools.x86_64 0:2.0-0.17.20131004git.el7 Complete! [[email protected] ~]# ifconif bash: ifconif: command not found [[email protected] ~]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.180.23 netmask 255.255.255.0 broadcast 192.168.180.255 inet6 fe80::215:5dff:fe6e:281a prefixlen 64 scopeid 0x20<link> ether 00:15:5d:6e:28:1a txqueuelen 1000 (Ethernet) RX packets 26463 bytes 33446022 (31.8 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 10534 bytes 895992 (874.9 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 0 (Local Loopback) RX packets 32 bytes 2724 (2.6 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 32 bytes 2724 (2.6 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
2.安装jdk1.8版本以上的版本,在官网上下好,直接上传。
[[email protected] elk]# rpm -ivh jdk-8u131-linux-x64.rpm Preparing... ################################# [100%] Updating / installing... 1:jdk1.8.0_131-2000:1.8.0_131-fcs ################################# [100%] Unpacking JAR files... tools.jar... plugin.jar... javaws.jar... deploy.jar... rt.jar... jsse.jar... charsets.jar... localedata.jar... [[email protected] elk]# vim /etc/profile #####install for JDK在最下边添加如下 export JAVA_HOME=/usr/java/jdk1.8.0_131/ export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=$JAVA_HOME/lib:.:$CLASSPATH [[email protected] elk]# source /etc/profile [[email protected] elk]# java -version java version "1.8.0_131" Java(TM) SE Runtime Environment (build 1.8.0_131-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)
3.创建appuser普通用户,并安装elasticsearch
[[email protected] elk]# groupadd appuser [[email protected] elk]# useradd -g appuser.appuser [[email protected] elk]# password appuser bash: password: command not found [[email protected] elk]# passwd appuser Changing password for user appuser. New password: Retype new password: passwd: all authentication tokens updated successfully. [[email protected] elk]$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.4.0.tar.gz [[email protected] elk]$ tar xf elasticsearch-5.4.0.tar.gz [[email protected] elk]$ mv elasticsearch-5.4.0 ../ [[email protected] elk]$ cd ../elasticsearch-5.4.0/ [[email protected] elasticsearch-5.4.0]$ mkdir -pv {data,logs} mkdir: created directory ‘data’ mkdir: created directory ‘logs’ [[email protected] elasticsearch-5.4.0]$ vim config/elasticsearch.yml cluster.name: cluster-lqb node.name: node-1 path.data: /home/appuser/elasticsearch-5.4.0/data path.logs: /home/appuser/elasticsearch-5.4.0/logs network.host: 192.168.180.23 http.port: 9200 http.cors.enabled:true http.cors.allow-origin:"*"
4.修改系统参数,用root账号
[[email protected] elasticsearch-5.4.0]# vim /etc/security/limits.conf * soft nproc 65536 * hard nproc 65536 * soft nofile 65536 * hard nofile 65536 [[email protected] elasticsearch-5.4.0]# vim /etc/sysctl.conf vm.max_map_count= 262144 [[email protected] elasticsearch-5.4.0]# sysctl -p vm.max_map_count = 262144
5.启动服务
[[email protected] elasticsearch-5.4.0]$ ./bin/elasticsearch & [1] 2266 [[email protected] elasticsearch-5.4.0]$ [2017-05-27T04:54:06,979][INFO ][o.e.n.Node ] [node-1] initializing ... [2017-05-27T04:54:07,447][INFO ][o.e.e.NodeEnvironment ] [node-1] using [1] data paths, mounts [[/home (/dev/mapper/centos-home)]], net usable_space [145.4gb], net total_space [145.4gb], spins? [possibly], types [xfs] [2017-05-27T04:54:07,451][INFO ][o.e.e.NodeEnvironment ] [node-1] heap size [1.9gb], compressed ordinary object pointers [true] [2017-05-27T04:54:07,459][INFO ][o.e.n.Node ] [node-1] node name [node-1], node ID [fLZy_engTtOA3jBrR-K5Dg] [2017-05-27T04:54:07,461][INFO ][o.e.n.Node ] [node-1] version[5.4.0], pid[2266], build[780f8c4/2017-04-28T17:43:27.229Z], OS[Linux/3.10.0-327.el7.x86_64/amd64], JVM[Oracle Corporation/Java HotSpot(TM) 64-Bit Server VM/1.8.0_131/25.131-b11] [2017-05-27T04:54:12,683][INFO ][o.e.p.PluginsService ] [node-1] loaded module [aggs-matrix-stats] [2017-05-27T04:54:12,685][INFO ][o.e.p.PluginsService ] [node-1] loaded module [ingest-common] [2017-05-27T04:54:12,685][INFO ][o.e.p.PluginsService ] [node-1] loaded module [lang-expression] [2017-05-27T04:54:12,687][INFO ][o.e.p.PluginsService ] [node-1] loaded module [lang-groovy] [2017-05-27T04:54:12,687][INFO ][o.e.p.PluginsService ] [node-1] loaded module [lang-mustache] [2017-05-27T04:54:12,687][INFO ][o.e.p.PluginsService ] [node-1] loaded module [lang-painless] [2017-05-27T04:54:12,689][INFO ][o.e.p.PluginsService ] [node-1] loaded module [percolator] [2017-05-27T04:54:12,689][INFO ][o.e.p.PluginsService ] [node-1] loaded module [reindex] [2017-05-27T04:54:12,689][INFO ][o.e.p.PluginsService ] [node-1] loaded module [transport-netty3] [2017-05-27T04:54:12,691][INFO ][o.e.p.PluginsService ] [node-1] loaded module [transport-netty4] [2017-05-27T04:54:12,694][INFO ][o.e.p.PluginsService ] [node-1] no plugins loaded [2017-05-27T04:54:21,668][INFO ][o.e.d.DiscoveryModule ] [node-1] using discovery type [zen] [2017-05-27T04:54:24,476][INFO ][o.e.n.Node ] [node-1] initialized [2017-05-27T04:54:24,478][INFO ][o.e.n.Node ] [node-1] starting ... [2017-05-27T04:54:25,321][INFO ][o.e.t.TransportService ] [node-1] publish_address {192.168.180.23:9300}, bound_addresses {192.168.180.23:9300} [2017-05-27T04:54:25,364][INFO ][o.e.b.BootstrapChecks ] [node-1] bound or publishing to a non-loopback or non-link-local address, enforcing bootstrap checks [2017-05-27T04:54:28,706][INFO ][o.e.c.s.ClusterService ] [node-1] new_master {node-1}{fLZy_engTtOA3jBrR-K5Dg}{VLbtX7DdQzW51L_GF_nzfA}{192.168.180.23}{192.168.180.23:9300}, reason: zen-disco-elected-as-master ([0] nodes joined) [2017-05-27T04:54:28,812][INFO ][o.e.h.n.Netty4HttpServerTransport] [node-1] publish_address {192.168.180.23:9200}, bound_addresses {192.168.180.23:9200} [2017-05-27T04:54:28,834][INFO ][o.e.n.Node ] [node-1] started [2017-05-27T04:54:28,878][INFO ][o.e.g.GatewayService ] [node-1] recovered [0] indices into cluster_state [[email protected] elasticsearch-5.4.0]$ ps -ef|grep elasticsearch root 2315 2213 0 04:54 pts/1 00:00:00 tail -f /home/appuser/elasticsearch-5.4.0/logs/cluster-lqb.log appuser 2435 2250 99 04:58 pts/0 00:01:12 /usr/java/jdk1.8.0_131//bin/java -Xms2g -Xmx2g -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -server -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -Djdk.io.permissionsUseCanonicalPath=true -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Dlog4j.skipJansi=true -XX:+HeapDumpOnOutOfMemoryError -Des.path.home=/home/appuser/elasticsearch-5.4.0 -cp /home/appuser/elasticsearch-5.4.0/lib/* org.elasticsearch.bootstrap.Elasticsearch appuser 2523 2250 0 04:59 pts/0 00:00:00 grep --color=auto elasticsearch [[email protected] elasticsearch-5.4.0]$ netstat -lntp|grep 9200 (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) tcp6 0 0 192.168.180.23:9200 :::* LISTEN 2435/java
报错:max file descriptors [4096] for elasticsearch process is too low, increase to at least
[65536] 解决方案: cat /etc/security/limits.conf * soft nproc 65536 * hard nproc 65536 * soft nofile 65536 * hard nofile 65536 并重启生效。
(三).安装head插件;由于head插件本质上还是一个nodejs的工程,因此需要安装node,使用npm来安装依赖的包。(npm可以理解为maven)
- 首先安装npm。下载地址(http://nodejs.org/)
[[email protected] elk]# yum -y install xz Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.163.com * extras: mirrors.163.com * updates: mirrors.163.com Resolving Dependencies --> Running transaction check ---> Package xz.x86_64 0:5.1.2-12alpha.el7 will be updated Updated: xz.x86_64 0:5.2.2-1.el7 Dependency Updated: xz-libs.x86_64 0:5.2.2-1.el7 Complete! [[email protected] elk]# wget [[email protected] elk]# xz -d node-v6.10.3-linux-x64.tar.xz [[email protected] elk]# tar xf node-v6.10.3-linux-x64.tar.xz [[email protected] elk]#tar -xvf node-v6.10.3-linux-x64.tar [[email protected] elk]# cd node-v6.10.3-linux-x64 [[email protected] node-v6.10.3-linux-x64]# pwd /tmp/install/elk/node-v6.10.3-linux-x64 [[email protected] elk]# vim /etc/profile ####SET NOD environment export NODE_HOME=/tmp/install/elk/node-v6.10.3-linux-x64 export PATH=$NODE_HOME/bin:$PATH [[email protected] elk]# source /etc/profile [[email protected] node-v6.10.3-linux-x64]# npm -v 3.10.10 [[email protected] node-v6.10.3-linux-x64]# node -v v6.10.3 ###node安装完成
2.安装下载插件包git
[[email protected] elk]# yum install git -y Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.163.com * extras: mirrors.163.com * updates: mirrors.163.com Resolving Dependencies --> Running transaction check ---> Package git.x86_64 0:1.8.3.1-6.el7_2.1 will be installed --> Running transaction check ---> Package libgnome-keyring.x86_64 0:3.8.0-3.el7 will be installed ---> Package perl-Error.noarch 1:0.17020-2.el7 will be installed ---> Package perl-Git.noarch 0:1.8.3.1-6.el7_2.1 will be installed ---> Package perl-TermReadKey.x86_64 0:2.30-20.el7 will be installed ---> Package rsync.x86_64 0:3.0.9-17.el7 will be installed --> Finished Dependency Resolution Installed: git.x86_64 0:1.8.3.1-6.el7_2.1 Dependency Installed: libgnome-keyring.x86_64 0:3.8.0-3.el7 perl-Error.noarch 1:0.17020-2.el7 perl-Git.noarch 0:1.8.3.1-6.el7_2.1 perl-TermReadKey.x86_64 0:2.30-20.el7 rsync.x86_64 0:3.0.9-17.el7 [[email protected] elk]# git clone git://github.com/mobz/elasticsearch-head.git Cloning into ‘elasticsearch-head‘... remote: Counting objects: 4063, done. remote: Total 4063 (delta 0), reused 0 (delta 0), pack-reused 4063 Receiving objects: 100% (4063/4063), 2.10 MiB | 1.02 MiB/s, done. Resolving deltas: 100% (2222/2222), done. Complete!
3.安装解压软件.tar.bz2
[[email protected] phantomjs]# yum install bzip2 phantomjs-2.1.1-linux-x86_64.tar.bz2 Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.163.com * extras: mirrors.163.com * updates: mirrors.163.com No package phantomjs-2.1.1-linux-x86_64.tar.bz2 available. Resolving Dependencies --> Running transaction check ---> Package bzip2.x86_64 0:1.0.6-13.el7 will be installed --> Finished Dependency Resolution Dependencies Resolved ==================================================================================================================================== Package Arch Version Repository Size ==================================================================================================================================== Installing: bzip2 x86_64 1.0.6-13.el7 base 52 k Transaction Summary ==================================================================================================================================== Install 1 Package Total download size: 52 k Installed size: 82 k Is this ok [y/d/N]: y Downloading packages: bzip2-1.0.6-13.el7.x86_64.rpm | 52 kB 00:00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : bzip2-1.0.6-13.el7.x86_64 1/1 Verifying : bzip2-1.0.6-13.el7.x86_64 1/1 Installed: bzip2.x86_64 0:1.0.6-13.el7 Complete!
4.安装grunt。grunt是一个很方便的构建工具,可以进行打包压缩、测试、执行等等的工作,5.X里的head插件就是通过grunt启动的。
[email protected] elk]# cd elasticsearch-head [[email protected] elasticsearch-head]# npm install -g grunt --registry=https://registry.npm.taobao.org /tmp/install/elk/node-v6.10.3-linux-x64/bin/grunt -> /tmp/install/elk/node-v6.10.3-linux-x64/lib/node_modules/grunt/bin/grunt /tmp/install/elk/node-v6.10.3-linux-x64/lib └── [email protected] [[email protected] grunt]# /tmp/install/elk/elasticsearch-head/node_modules/grunt/bin/grunt -V grunt-cli v1.2.0 grunt v1.0.1
5.安装Head
[[email protected] elasticsearch-head]# npm install npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected]^1.0.0 (node_modules/chokidar/node_modules/fsevents): npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"}) npm WARN [email protected] license should be a valid SPDX license expression [[email protected] elasticsearch-head]#
在elasticsearch-head目录下node_modules/grunt下如果没有grunt二进制程序,需要执行:
cd elasticsearch-head npm install grunt --save
由于head的代码还是2.6版本的,直接执行有很多限制,比如无法跨机器访问。因此需要我们需要修改两个文件:
a.修改服务器监听地址( /tmp/install/elk/elasticsearch-head/Gruntfile.js )。b.修改连接地址(/tmp/install/elk/elasticsearch-head/_site/app.js)
6.修改配置
a.修改监听地址Gruntfile.js 。增加hostname属性,设置为*
[[email protected] elasticsearch-head]# vim /tmp/install/elk/elasticsearch-head/Gruntfile.js
tasks: [‘default‘],
options: {
spawn: false
}
},
"grunt": {
files: [ ‘Gruntfile.js‘ ]
}
},
connect: {
server: {
options: {
hostname: ‘*‘,
port: 9100,
base: ‘.‘,
keepalive: true
}
}
}
});
b.修改连接地址:app.js .
[[email protected] elasticsearch-head]# vim /tmp/install/elk/elasticsearch-head/_site/app.js (function( app, i18n ) { var ui = app.ns("ui"); var services = app.ns("services"); app.App = ui.AbstractWidget.extend({ defaults: { base_uri: null }, init: function(parent) { this._super(); this.prefs = services.Preferences.instance(); this.base_uri = this.config.base_uri || this.prefs.get("app-base_uri") || "http://192.168.180.23:9200"; if( this.base_uri.charAt( this.base_uri.length - 1 ) !== "/" ) { // XHR request fails if the URL is not ending with a "/" this.base_uri += "/"; } if( this.config.auth_user ) { var credentials = window.btoa( this.config.auth_user + ":" + this.config.auth_password ); $.ajaxSetup({ headers: { "Authorization": "Basic " + credentials } }); } this.cluster = new services.Cluster({ base_uri: this.base_uri }); this._clusterState = new services.ClusterState({
。大概在4329行把ocalhost修改成你es的服务器地址。his.base_uri = this.config.base_uri || this.prefs.get("app-base_uri") || "http://localhost:9200";
====>this.base_uri = this.config.base_uri || this.prefs.get("app-base_uri") || "http://192.168.180.23:9200";
7.elasticsearch-head启动
[[email protected] elasticsearch-5.4.0]$ cd /home/appuser/elasticsearch-5.4.0/plugins/elasticsearch-head/node_modules/grunt/bin/ [[email protected] bin]$ ./grunt server & [2] 3741 [[email protected] bin]$ Running "connect:server" (connect) task Waiting forever... Started connect web server on http://localhost:9100
至此启动成功,可以在浏览器里查看了
(四).安装bigdesk插件
[email protected] plugins]$ git clone https://github.com/hlstudio/bigdesk Cloning into ‘bigdesk‘... remote: Counting objects: 151, done. remote: Total 151 (delta 0), reused 0 (delta 0), pack-reused 151 Receiving objects: 100% (151/151), 348.16 KiB | 91.00 KiB/s, done. Resolving deltas: 100% (57/57), done. [[email protected] plugins]$ cd bigdesk/_site/ [[email protected] _site]$ python -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ... 192.168.181.231 - - [31/May/2017 03:51:56] "GET / HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /css/reset.css HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /css/CssGrid_2/styles.css HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /css/CssGrid_2/1140.css HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /css/bigdesk.css HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/charts/common.css HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/charts/not-available/not-available-chart.css HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/charts/time-series/time-series-chart.css HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/charts/time-area/time-area-chart.css HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/charts/pack/pack.css HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/lib/css3-mediaqueries/css3-mediaqueries.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/lib/jquery/jquery-1.7.1.min.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/lib/tinysort/jquery.tinysort.min.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/lib/mustache/mustache.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/lib/backbone/backbone-min.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/lib/underscore/underscore-min.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/lib/D3-v2.8.1/d3.v2.min.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/util/bigdesk_extension.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/models/Hello.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/models/cluster/IndicesStatus.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/models/cluster/ClusterHealth.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/models/cluster/ClusterState.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/models/cluster/NodesState.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/models/cluster/NodesStats.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/models/cluster/NodeInfo.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/views/templates.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/views/ClusterHealthView.js HTTP/1.1" 200 - 192.168.181.231 - - [31/May/2017 03:51:56] "GET /js/views/ClusterNodesListView.js HTTP/1.1" 200 -
至此安装完成,见下图