Redis 主从+哨兵+监控 (centos7.2 + redis 3.2.9 )
环境准备:
192.168.0.2 redis01 主
192.168.0.3 redis02 从
192.168.0.4 redis03 从
Redis 主从搭建
一:下载并安装redis软件(以192.168.0.2为例)
192.168.0.2:
1.安装依赖包:yum install -y wget gcc make tcl
2.进入src目录并下载redis软件
cd /usr/local/src
wget http://download.redis.io/releases/redis-3.2.9.tar.gz
3.解压并安装
tar -zxvf redis-3.2.9.tar.gz
cd redis-3.2.9
make && make install
4.目录配置
mkdir -p /usr/local/redis
mkdir -p /usr/local/redis/data
mkdir -p /usr/local/redis/conf
mkdir -p /usr/local/redis/bin
5.配置目录文件
cp /data/redis-3.2.9/src/redis* bin/
cd bin/
rm -f *.c
rm -f *.o
rm -f *.h
cp /data/redis-3.2.9/redis.conf /usr/local/redis/conf/6379.conf
另外两个服务器下载安装一致,不再重复
二:配置conf文件:
master库 6379.conf:
bind 192.168.0.2 ##主库地址
protected-mode no ##一般均为内网,可以关闭保护模式
port 6379 ##端口
timeout 30 ##超时时间限制
daemonize yes ##后台运行
pidfile "/usr/local/redis/redis_6379.pid" ## 执行PID文件的路径
logfile "/usr/local/redis/redis.log" ## 指定log日志的路径
dir "/usr/local/redis/data" ## 指定数据文件的目录
masterauth "redis" ## 指定认证密码
slave-serve-stale-data yes ## 设置成 NO 如果slave 无法与master 同步,设置成slave不可读,方便监控脚本发现问题;此处设置为yes 继续提供查询服务
slave-read-only yes ## 指定从库只读
requirepass "redis" ## 指定登录密码
appendonly yes ## 指定aof增量持久化
appendfsync always ## 指定增量同步
slave库 6379.conf:
bind 192.168.0.3 ##主库地址
protected-mode no ##一般均为内网,可以关闭保护模式
port 6379 ##端口
timeout 30 ##超时时间限制
daemonize yes ##后台运行
pidfile "/usr/local/redis/redis_6379.pid" ## 执行PID文件的路径
logfile "/usr/local/redis/redis.log" ## 指定log日志的路径
dir "/usr/local/redis/data" ## 指定数据文件的目录
masterauth "redis" ## 指定认证密码
slave-serve-stale-data yes ##
slave-read-only yes ## 指定从库只读
requirepass "redis" ## 指定登录密码
appendonly yes ## 指定aof增量持久化
appendfsync always ## 指定增量同步
slaveof 192.168.0.2 6379 ## 指定主库的IP 端口
192.168.0.4从库的conf文件配置与192.168.0.3的配置除了bind不一样,其它完全一致
三、启动服务
启动主库:
[root@redis01 /]# redis-server /usr/local/redis/conf/6379.conf
[root@redis01 /]# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 00:48 ? 00:00:00 /usr/sbin/init
root 17 1 0 00:48 ? 00:00:00 /usr/lib/systemd/systemd-journald
root 28 1 0 00:48 ? 00:00:00 /usr/lib/systemd/systemd-udevd
dbus 57 1 0 00:48 ? 00:00:00 /bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
root 58 1 0 00:48 ? 00:00:00 /usr/lib/systemd/systemd-logind
root 77 0 0 00:48 ? 00:00:00 bash
root 253 0 0 03:06 ? 00:00:00 redis-server 192.168.0.2:6379
root 256 77 0 03:06 ? 00:00:00 ps -ef
启动从库:
[root@redis02 conf]# redis-server /usr/local/redis/conf/6379.conf
[root@redis02 conf]# ps -ef | grep redis
root 535 0 0 00:54 ? 00:00:00 redis-server 192.168.0.3:6379
root 540 113 0 00:54 ? 00:00:00 grep --color=auto redis
[root@redis03 conf]# redis-server /usr/local/redis/conf/6379.conf
[root@redis03 conf]# ps -ef | grep redis
root 457 0 0 00:55 ? 00:00:04 redis-server 192.168.0.4:6379
root 496 78 0 02:40 ? 00:00:00 grep --color=auto redis
四、查看info信息
登录主库:
[root@redis01 /]# redis-cli -h 192.168.0.2 -p 6379 -a redis
192.168.0.2:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.0.4,port=6379,state=online,offset=2648162,lag=1
slave1:ip=192.168.0.3,port=6379,state=online,offset=2648162,lag=1
master_repl_offset:2648162
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1599587
repl_backlog_histlen:1048576
登录从库:
[root@redis02 redis]# redis-cli -h 192.168.0.3 -p 6379 -a redis
192.168.0.3:6379> info replication
# Replication
role:slave
master_host:192.168.0.2
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:2658326
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
至此redis的一主两从已经搭建完毕
哨兵集群搭建
分别在三个节点启动哨兵
一:哨兵sentinel.conf文件的配置:
bind 192.168.0.2 ## 绑定IP
protected-mode no ## 关闭保护模式
port 26379 ## 端口
dir "/usr/local/redis/data" ## 配置工作目录
logfile "/usr/local/redis/sentinel.log" ## 指定log日志的地址
sentinel monitor mymaster 192.168.0.2 6379 2 ## mymaster 为集群名称; 192.168.0.2为主库IP 从库自动获取 无需配置 ;数字2,是指当有两个及以上的sentinel服务检测到master宕机,才会去执行主从切换的功能。
sentinel auth-pass mymaster redis ## 设置master和slaves验证密码
sentinel down-after-milliseconds redis1 10000 ## master或slave多长时间(默认30秒)不能使用后标记为s_down状态。
sentinel failover-timeout redis1 60000 ## 若sentinel在该配置值内未能完成failover操作(即故障时master/slave自动切换),则认为本次failover失败。
sentinel can-failover mymaster yes ## 在sentinel检测到O_DOWN后,是否对这台redis启动failover机制 ,设置为NO 时 只有仲裁权 没有当选权
sentinel parallel-syncs mymaster 1 ## 执行故障转移时,最多可以有多少个从服务器同时对新的主服务器进行同步,这个数字越小,完成故障转移所需的时间就越长,但越大就意味着越多的从服务器因为复制而不可用。可以通过将这个值设为 1 来保证每次只有一个从服务器处于不能处理命令请求的状态。
sentinel notification-script master1/data/scripts/send_mail.sh ##当sentinel触发时,切换主从状态时,需要执行的脚本。当主down的时候可以通知当事人,
注意:
1.应用程序连接到哨兵端口,通过指定不同的master名称连接到具体的主副本。
2.哨兵配置文件中只需要配置主从复制中的主副本ip和端口即可,当主从进行切换时哨兵会自动修改哨兵配置文件中的主副本ip为新在主副本ip。
3.一个哨兵配置文件中可以同时配置监控多个主从复制。
4.单个哨兵就可以用来进行主从故障监控,但是如果只有一个sentinel进程,如果这个进程运行出错,或者是网络堵塞,那么将无法实现redis集群的主备切换(单点问题);<quorum>这个2代表投票数,当2个sentinel认为一个master已经不可用了以后,将会触发failover,才能真正认为该master已经不可用了。(sentinel集群中各个sentinel也有互相通信,通过gossip协议);所以合理的配置应该是同时启动多个哨兵进程,并且最好是在不同的服务器中启动。
5.注意mymaster的需要在整个网络环境都是唯一的,哨兵之间会自动通过mastername去建立关联关系只要网络环境是相通的。
另外两台配置基本一致(bind地址根据实际填写)
二、启动哨兵进程
[root@redis01 /]# redis-sentinel /usr/local/redis/conf/sentinel.conf
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.9 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 247
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
247:X 10 Sep 02:52:37.578 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
247:X 10 Sep 02:52:37.578 # Sentinel ID is 71b6ecdcc24ecdac45b6a9473716f67fc654f331
247:X 10 Sep 02:52:37.578 # +monitor master mymaster 192.168.0.2 6379 quorum 2
247:X 10 Sep 02:52:37.578 * +slave slave 192.168.0.3:6379 192.168.0.3 6379 @ mymaster 192.168.0.2 6379
247:X 10 Sep 02:54:25.135 * +sentinel sentinel f6d139040d2ec105d721b5aa738ba7ef4c9d3ab0 192.168.0.3 26379 @ mymaster 192.168.0.2 6379
247:X 10 Sep 02:58:35.764 * +sentinel sentinel 6e565fad2dab08a0df9bc74e06eebfc901c9b20a 192.168.0.4 26379 @ mymaster 192.168.0.2 6379
[root@redis02 redis]# redis-sentinel /usr/local/redis/conf/sentinel.conf
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.9 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 627
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
627:X 10 Sep 03:21:26.126 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
627:X 10 Sep 03:21:26.126 # Sentinel ID is f6d139040d2ec105d721b5aa738ba7ef4c9d3ab0
627:X 10 Sep 03:21:26.126 # +monitor master mymaster 192.168.0.3 6379 quorum 2
627:X 10 Sep 03:21:26.126 * +slave slave 192.168.0.2:6379 192.168.0.2 6379 @ mymaster 192.168.0.3 6379
627:X 10 Sep 03:21:26.127 * +slave slave 192.168.0.4:6379 192.168.0.4 6379 @ mymaster 192.168.0.3 6379
627:X 10 Sep 03:21:27.966 * +sentinel sentinel 71b6ecdcc24ecdac45b6a9473716f67fc654f331 192.168.0.2 26379 @ mymaster 192.168.0.3 6379
三、查看info信息
四、模拟主库宕机,验证哨兵是否自动切换
手动kill 主库192.168.0.2 redis进程
[root@redis02 redis]# redis-sentinel /usr/local/redis/conf/sentinel.conf
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.9 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 583
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
583:X 10 Sep 01:38:17.492 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
583:X 10 Sep 01:38:17.493 # Sentinel ID is f6d139040d2ec105d721b5aa738ba7ef4c9d3ab0
583:X 10 Sep 01:38:17.493 # +monitor master mymaster 192.168.0.2 6379 quorum 2
583:X 10 Sep 01:38:17.493 * +slave slave 192.168.0.3:6379 192.168.0.3 6379 @ mymaster 192.168.0.2 6379
583:X 10 Sep 01:38:17.493 * +slave slave 192.168.0.4:6379 192.168.0.4 6379 @ mymaster 192.168.0.2 6379
583:X 10 Sep 01:38:18.216 * +sentinel sentinel 71b6ecdcc24ecdac45b6a9473716f67fc654f331 192.168.0.2 26379 @ mymaster 192.168.0.2 6379
583:X 10 Sep 01:41:52.390 # +sdown master mymaster 192.168.0.2 6379
583:X 10 Sep 01:41:52.481 # +new-epoch 1
583:X 10 Sep 01:41:52.482 # +vote-for-leader 71b6ecdcc24ecdac45b6a9473716f67fc654f331 1
583:X 10 Sep 01:41:52.893 # +config-update-from sentinel 71b6ecdcc24ecdac45b6a9473716f67fc654f331 192.168.0.2 26379 @ mymaster 192.168.0.2 6379
583:X 10 Sep 01:41:52.893 # +switch-master mymaster 192.168.0.2 6379 192.168.0.4 6379
583:X 10 Sep 01:41:52.893 * +slave slave 192.168.0.3:6379 192.168.0.3 6379 @ mymaster 192.168.0.4 6379
583:X 10 Sep 01:41:52.893 * +slave slave 192.168.0.2:6379 192.168.0.2 6379 @ mymaster 192.168.0.4 6379
583:X 10 Sep 01:42:22.905 # +sdown slave 192.168.0.2:6379 192.168.0.2 6379 @ mymaster 192.168.0.4 6379
583:X 10 Sep 01:46:12.219 # -sdown slave 192.168.0.2:6379 192.168.0.2 6379 @ mymaster 192.168.0.4 6379
583:X 10 Sep 01:46:22.170 * +convert-to-slave slave 192.168.0.2:6379 192.168.0.2 6379 @ mymaster 192.168.0.4 6379
583:X 10 Sep 01:57:31.160 # +sdown sentinel 71b6ecdcc24ecdac45b6a9473716f67fc654f331 192.168.0.2 26379 @ mymaster 192.168.0.4 6379
583:X 10 Sep 01:58:45.313 # -sdown sentinel 71b6ecdcc24ecdac45b6a9473716f67fc654f331 192.168.0.2 26379 @ mymaster 192.168.0.4 6379
583:X 10 Sep 02:21:19.500 * +convert-to-slave slave 192.168.0.2:6379 192.168.0.2 6379 @ mymaster 192.168.0.4 6379
自动选举 192.168.0.4 作为主库并且在192.168.0.2恢复后 自动加入并设置为slave
五、sentinel一些命令介绍
[root@idxs21-108 redis]# redis-cli -h 192.168.0.2 -p 26379
①INFO sentinel的基本状态信息
②SENTINEL masters 列出所有被监视的主服务器,以及这些主服务器的当前状态
③SENTINEL slaves 列出给定主服务器的所有从服务器,以及这些从服务器的当前状态
④SENTINEL get-master-addr-by-name 返回给定名字的主服务器的 IP 地址和端口号
⑤SENTINEL reset 重置所有名字和给定模式 pattern 相匹配的主服务器。重置操作清除主服务器目前的所有状态, 包括正在执行中的故障转移, 并移除目前已经发现和关联的, 主服务器的所有从服务器和 Sentinel 。
⑥SENTINEL failover 当主服务器失效时, 在不询问其他 Sentinel 意见的情况下, 强制开始一次自动故障迁移,但是它会给其他sentinel发送一个最新的配置,其他sentinel会根据这个配置进行更新
Sentinel的工作方式:
1):每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令
2):如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被 Sentinel 标记为主观下线。
3):如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
4):当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线
5):在一般情况下, 每个 Sentinel 会以每 10 秒一次的频率向它已知的所有Master,Slave发送 INFO 命令
6):当Master被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次
7):若没有足够数量的 Sentinel 同意 Master 已经下线, Master 的客观下线状态就会被移除。
若 Master 重新向 Sentinel 的 PING 命令返回有效回复, Master 的主观下线状态就会被移除。
至此 哨兵集群搭建完毕
redis监控平台搭建
GITHUB开源:https://github.com/LittlePeng/redis-monitor
下载软件:https://codeload.github.com/LittlePeng/redis-monitor/zip/master
mv master redis-monitor-master.zip
一、安装(pip)
首先安装epel扩展源:
yum -y install epel-release
更新完成之后,就可安装pip:
yum -y install python-pip
安装完成之后清除cache:
yum clean all
二、安装依赖包
cd redis-monitor-master
pip install -r requirements.txt
三、配置redis_live.conf
{
"master_slave_sms": "1,1",
"RedisStatsServer": {
"port": 6379,
"server": "192.168.0.2",
"password": "redis"
},
"sms_alert": "192.168.110.207:9999",
"DataStoreType": "redis",
"RedisServers": [{
"instance": "Master1",
"group": "Test1",
"port": 6379,
"server": "192.168.0.2",
"password" : "redis"
}, {
"instance": "Slave1",
"group": "Test1",
"port": 6379,
"server": "192.168.0.3",
"password": "redis"
}, {
"instance": "Slave2",
"group": "Test1",
"port": 6379,
"server": "192.168.0.4",
"password": "redis"
}]
}
四、启动进程
python src/redis_monitor_daemon.py
python src/redis_live_daemon.py
前端访问地址:http://10.1.12.123:8888/index.html#
参考来源:
https://www.cnblogs.com/chenmh/p/5578376.html
https://blog.csdn.net/lifupingcn/article/details/68942133
https://segmentfault.com/a/1190000002680804 Redis Sentinel机制与用法(一)
https://segmentfault.com/a/1190000002685515 Redis Sentinel机制与用法(二)
https://www.linuxidc.com/Linux/2017-08/146375.htm
https://blog.csdn.net/dc_726/article/details/47699739
Redis 主从+哨兵+监控 (centos7.2 + redis 3.2.9 )的更多相关文章
- Redis主从&哨兵集群搭建
主从集群 在搭建主从集群前,我们先把Redis安装起来: #解压Redis压缩包 [root@master lf]# tar -zxvf redis-6.2.1.tar.gz -- #安装gcc [r ...
- redis主从+ 哨兵模式(sentinel)+漂移VIP实现高可用系统
原文:https://www.jianshu.com/p/c2ab606b00b7 客户端程序 客户端程序(如PHP程序)连接redis时需要ip和port,但redis-server进行故障转移时, ...
- 新手之:SpringBoot ——Reids主从哨兵整合(CentOS7)
一.Redis主从搭建(一台服务器模拟多个端口) 结构图:) 1.确保安装了Redis,我装在了/opt/redis目录下.可通过"whereis redis-cli"命令查看是否 ...
- Redis主从哨兵和集群搭建
主从配置 哨兵配置 集群配置 1.主从: 国王和丞相,国王权力大(读写),丞相权利小(读) 2.哨兵: 国王和王子,国王死了(主服务挂掉),王子继位(从服务变主服务) 3.集群: 国王和国王,一个国王 ...
- redis 主从 哨兵
数据库为什么要读写分离 写代码好多年了,大家先抛弃在代码框架里面各种花哨的设计之外,写的代码到最后无非就是为了增删查改数据库.一般项目数据库刚开始只是但一个库,随着数据量的增大,就开始优化数据库(抛开 ...
- redis 主从哨兵01
主从复制过程 1.从服务器开始连接主服务器时,会向主服务器发送一个SYNC同步命令 2.主服务器接收到命令后,执行BGSAVE,异步的将写命令保存到一个缓冲区里 3.主服务器执行完BGSAVE之后,就 ...
- 【Redis学习专题】- Redis主从+哨兵集群部署
集群版本: redis-4.0.14 集群节点: 节点角色 IP redis-master 10.100.8.21 redis-slave1 10.100.8.22 redis-slave2 10.1 ...
- 三千字介绍Redis主从+哨兵+集群
一.Redis持久化策略 1.RDB 每隔几分钟或者一段时间会将redis内存中的数据全量的写入到一个文件中去. 优点: 因为他是每隔一段时间的全量备份,代表了每个时间段的数据.所以适合做冷备份. R ...
- redis主从+哨兵模式
主从模式配置分为手动和配置文件两种方式进行配置,我现在有192.168.238.128(CentOS1).192.168.238.131(CentOS3).192.168.238.132(CentOS ...
随机推荐
- 新安装的win7/win10系统,所有驱动都没安装,插入U盘也无法识别解决方法
我是使用老毛挑安装的系统,结果安装好之后,才发现所有驱动都没有安装,例如usb,网卡驱动等 解决方法就是先把驱动下载到系统安装盘里面,然后再次进入安装系统界面,相当于重新安装系统,但实际上我们不需要. ...
- Java中的权限学习笔记
1.Java中的权限有两个层次,一个是类这一层,另一个是类成员那一层. 类这一层: public class可以在本包内被访问,也可以在包外被访问.而没有被public修饰的class只能在本包内被调 ...
- 关于kafka的新的group无法订阅到topic中历史消息的问题
今天在写kafka的java api例子时候,遇到一个问题,比如我创建了一个test主题,往里面写了1,2,3,4,5条消息,在这个时候,我用一个新的group启动了一个消费者,发现该消费者只能读到5 ...
- 使用 --image-repository 解决kubeadm 安装k8s 集群 谷歌镜像墙的问题
从网上我们看到的好多kubeadm 安装k8s 的时候都说需要下拉取镜像,然后修改,实际上 我们可以使用配置参数,快速的跳过墙的问题 说明: 基础镜像,我们仍然存在,拉取的问题,但是dockerhub ...
- IBM websphere MQ使用说明
百度文库: IBM websphere MQ使用说明 IBM MQ安装和配置
- Python __slots__的使用
每个类在实例化时都会被分配一个dict,通过 实例.__dict__来访问,dict记录了实例的所有属性 如: class Man(object): pass man = Man()print(man ...
- 曾经很强大的免费 ERP 2BizBox
曾经很强大的免费 ERP 2BizBox 整个功能很强大,特别是生产,工单也很完善,有损耗,有反冲等功能. 流程比较规矩,需要先采购后才能使用,只有生产后才能销售,工单有组装和拆装,工程有工程更改,也 ...
- day 31 进程的其他方法 进程锁 进程队列
一.进程的其他方法 1. .name 进程名 (可指定) 2. .pid 进程号 3. os.getpid 在什么位置就是什么的进程号 4. .is ...
- 通过plsql develop查看建表语句
右键--查看 右下角 如下显示,找出ddl语句 可以看到索引等
- webpack 4:默认配置
webpack 4:默认配置 entry 默认: ./src/index.js(注意: 路径必须带上./): entry: './src/index.js', output 默认最后路径: ./dis ...