Oracle 笔记

导出一个表的表结构 sql

1
2
3
4
5
6
7
set heading off;
set echo off;
set pages 999;
set long 90000;
spool table_name.sql
select dbms_metadata.get_ddl('TABLE','table_name','user_name') from dual;
spool off;

到处一个用户的全部表结构 sql

1
2
3
4
5
6
7
set pagesize 0
set long 90000
set feedback off
set echo off
spool user_tables.sql
SELECT DBMS_METADATA.GET_DDL('TABLE',t1.table_name) FROM USER_TABLES t1;
spool off;

设置 oracle 客户端的字符集

1
2
3
select * from v$nls_parameters;
-- 在输出中找到 NLS_LANGUAGE、NLS_TERRITORY、NLS_CHARACTERSET 这三个变量的值
-- 环境变量 NLS_LANG 就是由这三个变量组成:NLS_LANG = language_territory.charset

终端连接(ssh) sqlplus 中文乱码

  • 设置该终端与数据库服务器当前字符集编码一致即可

修改数据库字符集

1
2
3
4
5
6
7
8
9
shutdown immediate; (database停了)
startup mount; (database重开去可更改情況)
alter system enable restricted session;
alter system set job_queue_processes=0;
alter system set aq_tm_processes=0;
alter database open;
alter database character set internal_use utf8;
shutdown immediate;
startup; (重开正常oracle)

Oracle 12c PDB 管理

  • 查看当前模式
    1
    
    show con_name; -- 默认 CDB$ROOT
    
  • 查看 CDB$ROOT 下所有 pdbs
    1
    2
    3
    
    select name, open_mode from v$pdbs;
    -- 或者
    show pdbs;
    
  • 创建 PDB 数据库
    1
    2
    3
    4
    5
    
    create pluggable database pdborcl1
        admin user pdborcl1_adm identified by pdborcl1_pass
        roles=(dba,connect,resource)
        file_name_convert=('/opt/oracle/app/oradata/orcl/pdbseed','/opt/oracle/app/oradata/orcl/pdborcl1')
        path_prefix='/opt/oracle/app/oradata/orcl/pdborcl1';
    
  • PDB 数据库创建完成后进入 mount 状态,需手动启动
    1
    
    alter pluggable database {pdborcl1[,pdborcl2]|all [except pdborcl2]} open [read only] [force];
    
  • 进入打开的 PDB 数据库
    1
    
    alter session set container=pdborcl1;
    
  • 切换回 CDB$ROOT
    1
    
    alter session set container=cdb$root;
    
  • 关闭 PDB 数据库
    1
    
    alter pluggable database {pdborcl1[,pdborcl2]|all [except pdborcl2]} close [immediate];
    
  • 删除关闭的 PDB 数据库
    1
    
    drop pluggable database pdborcl1 [including datafiles];
    

sqlplus 到处 csv 文件

1
2
3
sqool /home/oracle/sql_result.csv
select '"' || field1 || '","' || field2 || '","' ... '","' || fieldn || '"' from table1;
spool off

系统变量

常用设置

  • 域输出分隔符
    1
    
    set colsep ' ';
    
  • 设置查询出来的数据分多少页显示,如果需要连续的数据,中间不要出现空行就把newp设置为none,这样输出的数据行都是连续的,中间没有空行之类的
    1
    
    set newp none;
    
  • 显示start启动的脚本中的每个sql命令,缺省为on
    1
    
    set echo off;
    
  • 设置运行命令是是否显示语句
    1
    
    set echo on;
    
  • 设置显示"已选择XX行"
    1
    
    set feedback on;
    
  • 回显本次sql命令处理的记录条数,缺省为on即去掉最后的 “已经选择10000行”
    1
    
    set feedback off;
    
  • 输出域标题,缺省为on 设置为off就去掉了select结果的字段名,只显示数据
    1
    
    set heading off;
    
  • 输出每页行数,缺省为24,为了避免分页,可设定为0。
    1
    
    set pagesize 0;
    
  • 输出一行字符个数,缺省为80
    1
    
    set linesize 80;
    
  • 输出number类型域长度,缺省为10
    1
    
    set numwidth 12;
    
  • 显示脚本中的命令的执行结果,缺省为on
    1
    
    set termout off;
    
  • 去除标准输出每行的拖尾空格,缺省为off
    1
    
    set trimout on;
    
  • 去除重定向(spool)输出每行的拖尾空格,缺省为off
    1
    
    set trimspool on;
    
  • 设置允许显示输出类似dbms_output
    1
    
    set serveroutput on;
    
  • 设置显示已用时间
    1
    
    set timing on;
    
  • 设置允许对执行的sql进行分析
    1
    
    set autotrace on;
    

系统变量记录

  • ARRAY[SIZE] {20(默认值)|n} sqlplus 一次从数据库获取的行数,有效值为1至5000. 大的值可提高查询和子查询的有效性,可获取许多行,但也需要更多的内存.当超过1000时,其效果不大.
  • AUTO[COMMIT] {OFF(默认值)|ON|IMM[EDIATE]} 控制ORACLE对数据库的修改的提交. 置ON时,在ORACLE执行每个SQL命令或PL/SQL块后对数据库提交修改;置OFF时则制止自动提交,需要手工地提交修改,例如用SQL的COMMIT命令. IMMEDIATE功能同ON.
  • BLO[CKTERMINATOR] {.(默认值)|C} 置非字母数字字符,用于结束PL/SQL块.要执行块时,必须发出RUN命令或/命令.
  • CMDS[EP] {;|C|OFF(默认值)|ON} 置非字母数字字符,用于分隔在一行中输入的多个SQL/PLUS命令.ON或OFF控制在一行中是否能输入多个命令. ON时将自动地将命令分隔符设为分号(.其中C表示所置字符.
  • COM[PATIBILITY] {V5|V6|V7|NATIVE(默认值)} 指定当前所链接的ORACLE版本.如果当前ORACLE的版本为5,则置COMPATIBILITY为V5; 为版本6时置成V6; 为版本7时置成V7. 如果希望由数据库决定该设置,在置成NATIVE.
  • CON[CAT] {.(默认值)|C|OFF|ON(默认值)} 设置结束一替换变量引用的字符.在中止替换变量引用字符之后可跟所有字符,作为体会组成部分,否则sqlplus将解释为替换变量名的一部分.当CONCAT开关为ON时,sqlplus可重置CONCAT的值为点(.).
  • COPYC[OMMIT] {0(默认值)|n} 控制COPY命令提交对数据库修改的批数.每次拷贝n批后,将提交到目标数据库.有效值为0到5000. 可用变量ARRAYSIZE设置一批的大小.如果置COPYCOMMIT为0,则仅在COPY操作结束时执行一次提交.
  • CRT crt 改变 sqlplus RUNFORM 命令使用的缺省CRT文件.如果置CRT不包含什么,则crt仅包含’’’’.如果在一个Form的系统调用期间,要使用NEW.CRT(缺省CRT是OLD.CRT),可按下列形式调用Form:
    1
    2
    3
    4
    5
    
    SQL>;RUNFORM -C NEW form名
    或者
    SQL>;SET CRT NEW
    SQL>;RUNFORM form名
    # 第二中方法存储CRT选择,以致在下次运行RUNFORM命令(是在同一次sqlplus交互中)时,不需要指定.
    
  • DEF[INE] {&|C|OFF|ON(默认值)} 设置在替换变量时所使用的字符.ON或OFF控制sqlplus是否扫描替换变量的命令及用他们的值代替. DEFINE的ON或OFF的设置控制SCAN变量的设置.
  • ECHO {OFF|ON} 控制START命令是否列出命令文件中的每一命令.为ON时,列出命令;为OFF时,制止列清单.
  • EMBEDDED {OFF(默认值)|ON} 控制每一报表在一页中开始的地方. 为OFF时,迫使每一报表是在新页的顶部开始;为ON时,运行一报表在一页的任何位置开始.
  • ESC[APE] {(默认值)|C|OFF(默认值)|ON} 定义作为Escape字符的字符.为OFF时,使Escape字符不起作用.为ON时,使Escape字符起作用.
  • FEED[BACK] {6(默认值)|n|OFF|ON} 显示由查询返回的记录数.ON和OFF置显示为开或关.置FEEDBACK为ON时,等价于置n为1. 如果置FEEDBACK为0,等价于将它置成OFF.
  • FLU[SH] {OFF|ON(默认值)} 控制输出送至用户的显示设备.为OFF时,运行操作系统做缓冲区输出;为ON时,不允许缓冲. 仅当非交互方式运行命令文件时使用OFF,这样可减少程序I/O总是,从而改进性能.
  • HEA[DING] {OFF|ON(默认值)} 控制报表中列标题的打印.为ON时,在报表中打印列标题;为OFF时禁止打印列标题.
  • HEADS[EP] {|(默认值)|C|OFF|ON(默认值)} 定义标题分隔字符.可在COLUMN命令中使用标题分隔符,将列标题分成多行.ON和OFF将标题分隔置成开或关.当标题分隔为关(OFF)时,sqlplus打印标题分隔符像任何字符一样.
  • LIN[ESIZE] {80(默认值)|n} 置sqlplus在一行中显示的字符总数,它还控制在TTITLE和BTITLE中对准中心的文本和右对齐文本. 可定义LINESIZE为1至最大值,其最大值依赖于操作系统.
  • LONG {80(默认值)|n} 为显示和拷贝LONG类型值的最大宽度的设置. 对于ORACLE7, n的最大值为2G字节;对于版本6,最大值为32767.
  • LONGC[HUNKSIZE] {80(默认值)|n} 为sqlplus检索LONG类型值的增量大小.由于内存的限制,可按增量检索,该变量仅应用于ORACLE7.
  • MAXD[ATA] n 置sqlplus可处理的最大行宽字符数,其缺省值和最大值在不同操作系统中是可变的.
  • NEWP[AGE] {1(默认值)|n} 置每一页的头和顶部标题之间要打印的空行数.如果为0, 在页之间送一换号符,并在许多终端上清屏.
  • NULL text 设置表示空值(null)的文本,如果NULL没有文本,则显示空格(缺省时). 使用COLUMN命令中的NULL子句可控制NULL变量对该列的设置.
  • NUMF[ORMAT] 格式 设置显示数值的缺省格式,该格式是数值格式.
  • NUM[WIDTH] {10(默认值)|n} 对显示数值设置缺省宽度.
  • PAGES[IZE] {14(默认值)|n} 置从顶部标题至页结束之间的行数.在11英寸长的纸上打印报表,其值为54,上下各留一英寸(NEWPAGE值为6).
  • PAU[SE] {OFF(默认值)|ON|text} 在显示报表时,控制终端滚动.在每一暂停时,必须按RETURN键.ON将引起sqlplus在每一报表输出页开始时暂停.所指定的文本是每一次sqlplus暂停时显示的文本.如果要键入多个词,必须用单引号将文本括起来.
  • RECSEP {WRAPPED|EA[CH]|OFF} 指定显示或打印记录分行符的条件.一个记录分行符,是由RECSEPCHAR指定的字符组成的单行.空格为RECSEPCHAR的默认字符.
  • RECSEPCHAR { |C} 告诉sqlplus在哪儿做记录分隔.例如将RECSEP置成WRAPPED,在每一缠绕行之后,打印记录分行符.如果将RECSEP置成EACH,sqlplus在每一行后打印一记录分行符.如果将RECSEP置成OFF, sqlplus不打印分行符.
  • SCAN {OFF|ON(默认值)} 控制对存在的替换变量和值的扫描.OFF禁止替换变量和值的处理; ON则允许正常处理.
  • SERVEROUT[PUT] {OFF|ON} [SIZE n] 控制在sqlplus中的存储过程是否显示输出.OFF时为禁止; ON时则显示输出. SIZE设置缓冲输出的字节数,缺省值为2000, n不能小于2000或大于一百万.
  • SHOW[MODE] {OFF(默认值)|ON} 控制sqlplus在执行SET命令时是否列出其新老值old或new的设置.
  • SPA[CE] {1(默认值)|n} 设置输出列之间空格的数目,其最大值为10.
  • SQLC[ASE] {MIXED|LO[WER]|UP[PER]} 先于执行之前,将SQL命令和PL/SQL块的大小写进行转换. sqlplus将转换命令中的全部文本,包括带引号的直接量和标示符.SQLCASE不改变SQL缓冲区本身.
  • SQLCO[NTINUE] {>;(默认值)|文本} 在一附加行上继续一sqlplus命令时,sqlplus以该设置的字符序列进行提示.
  • SQLN[UMBER] {OFF|ON(默认值)} 为SQL命令和PL/SQL块的第二行和后继行设置提示.为ON时,提示行号;为OFF时,提示设置为SQLPROMPT的值.
  • SQLPER[FIX] {#(默认值)|C} 设置sqlplus前缀字符.在键入一SQL命令或PL/SQL块时,可在单独行上键入一sqlplus命令,由sqlplus的前缀字符做前缀. sqlplus直接执行该命令,不影响SQL命令或PL/SQL块.前缀字符必须是非字母数字字符.
  • SQLP[ROMPT] {SQL>;(默认值)|文本} 设置sqlplus的命令提示符.
    1
    2
    3
    4
    5
    6
    
    11:37:45 SQL> show sqlprompt
    sqlprompt "SQL> "
    11:38:21 SQL> set sqlprompt Jamm>
    11:39:54 Jamm>show sqlprompt
    sqlprompt "Jamm>"
    11:40:03 Jamm>
    
  • SQLT[ERMINATOR] {;(默认值)|C|OFF|ON(默认值)} 设置用于结束和执行SQL命令的字符. OFF意味着sqlplus不识别命令终止符,用键入空行来结束SQL命令. ON重设置终止符为默认的分号.
  • SUF[FIX] {SQL(默认值)|文本} 设置缺省文件的后缀,sqlplus在命令中使用,来引用命令文件. SUFFIX不控制输出(spool)文件的扩展名.
  • TAB {OFF|ON(默认值)} 决定sqlplus在终端输出中如何格式化空白空间. 为OFF时,在输出中使用空格格式化空白空间;为ON时,用TAB字符. TAB的缺省值依赖于系统,用SHOW TAB命令可查看该缺省值.
  • TERM[OUT] {OFF|ON(默认值)} 控制由文件执行命令所产生的输出的显示. OFF禁止显示,以致从一个命令文件假脱机输出,在屏幕上看不到输出. ON时显示输出. TERMOUT OFF 不影响交互地进行命令的输出.
  • TI[ME] {OFF(默认值)|ON} 控制当前日期的显示. ON时,在每条命令提示前显示当前时间; OFF时禁止时间的显示.
    1
    2
    3
    
    11:37:54 SQL> set time off
    SQL> set time on
    11:38:21 SQL>
    
  • TIMI[NG] {OFF(默认值)|ON} 控制时间统计的显示. ON时,显示每一个运行的SQL命令或PL/SQL块的时间统计; OFF时,禁止每一个命令的时间统计.
  • TRIM[OUT] {OFF|ON(默认值)} 决定sqlplus在每一显示行的末端是否允许带空格. ON时将每行尾部的空格去了,特别当从慢速的通信设备存取sqlplus时可改进性能; OFF时允许sqlplus显示尾部的空格.TRIMOUT ON 不影响假脱机输出. 设置TAB ON时,sqlplus忽略TRIMOUT ON.
  • UND[ERLINE] {-(默认值)|C|OFF|ON(默认值)} {-(默认值)|C|OFF|ON(默认值)} 设置用在sqlplus报表中下划线列标题的字符. ON或OFF将下划线置成开或关.
  • VER[IFY] {OFF|ON(默认值)} 控制sqlplus用值替换前、后是否列出命令的文本. ON时显示文本;OFF时禁止列清单.
  • WRA[P] {OFF|ON(默认值)} 控制sqlplus是否截断数据项的显示. OFF时截断数据项;ON时允许数据项缠绕到下一行. 在COLUMN命令中使用WRAPPED和TRUNCATED子句可控制对指定列的WRAP的设置.

参考

Mysql 笔记

MySQL 5.7 配置文件 my.cnf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
[mysqld]
datadir                        = /db/mysql
socket                         = /var/lib/mysql/mysql.sock
symbolic-links                 = 0
log-timestamps                 = SYSTEM
slow-query-log                 = 1
slow-query-log-file            = /var/log/mysqld/slow.log
long-query-time                = 8
#log-queries-not-using-indexes  = 1
log-error                      = /var/log/mysqld/error.log
pid-file                       = /var/run/mysqld/mysqld.pid
max-connections                = 1000
max-connect-errors             = 1000
max-user-connections           = 600
interactive-timeout            = 3600
wait-timeout                   = 3600
skip-name-resolve              = 1
lower-case-table-names         = 1
default-time-zone              = '+08:00'
character-set-server           = utf8mb4
sql-mode                       = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
bind-address                   = 0.0.0.0
table-open-cache               = 2048
default-storage-engine         = innodb
innodb-autoinc-lock-mode       = 2
innodb-flush-log-at-trx-commit = 0
# 建议物理内存一半
innodb-buffer-pool-size        = 8G
innodb-buffer-pool-instances   = 8
max-allowed-packet             = 512M
query-cache-size               = 0
query-cache-type               = 0
# 建议点分 ip 的最后一个数字
server-id                      = 123
# bin log
#binlog-format                  = ROW
#log-bin                        = /var/lib/mysql/mysql-bin
#expire-logs-days               = 3
# relay log
#read-only                      = 1
#replicate-wild-do-table        = db1.%
#relay-log                      = /var/lib/mysql/mysql-relay-bin
#slave-parallel-type            = logical-clock

复制表结构

1
2
create table db1.t1 like db2.t2;
create table db1.t1 select db2.t2 where 1=2;

复制表结构及其数据

1
create table db1.t1 select db2.t2 [where ...]

复制表数据

1
2
insert into db2.t2(column1, column2 ...)
    select column1, column2 ... from db1.t1 [where ...]

通过复制表文件来复制表数据

  • 在db2中创建同结构表

Elasticsearch 笔记

索引

  • 查看某节点的全部索引
    1
    
    curl http://127.0.0.1:9200/_cat/indices?v
    
  • 新建 index
    1
    
    curl -X PUT http://127.0.0.1:9200/index_name
    
  • 删除 index
    1
    
    curl -X DELETE http://127.0.0.1:9200/index_name
    

记录

  • 新增记录(指定记录id)
    1
    2
    3
    4
    5
    
    curl -X PUT -H "Content-Type: application/json" http://127.0.0.1:9200/index_name/doc_id -d '
    {
        "aa": "11",
        "bb": "22"
    }'
    
  • 新增记录(不指定记录id)
    1
    2
    3
    4
    5
    
    curl -X POST -H "Content-Type: application/json" http://127.0.0.1:9200/index_name -d '
    {
        "aa": "11",
        "bb": "22"
    }'
    
  • 查看记录
    1
    
    curl http://127.0.0.1:9200/index_name/doc_id?pretty=true
    
  • 删除记录
    1
    
    curl -X DELETE http://127.0.0.1:9200/index_name/doc_id
    
  • 更新记录
    1
    2
    3
    4
    5
    
    curl -X PUT -H "Content-Type: application/json" http://127.0.0.1:9200/index_name/doc_id -d '
    {
        "aa": "33",
        "bb": "44"
    }'
    

查询

  • 查询所有记录
    1
    
    curl http://127.0.0.1:9200/index_name/_search
    
  • 查询匹配
    1
    2
    3
    4
    
    curl -H "Content-Type: application/json" http://127.0.0.1:9200/index_name/_search -d '
    {
        "query": {"match": {"key_name": "value_pattern"}}
    }'
    
  • 从位置2(默认0)开始查询8(默认10)条记录
    1
    2
    3
    4
    5
    6
    
    curl -H "Content-Type: application/json" http://127.0.0.1:9200/index_name/_search -d '
    {
        "query": {"match": {"key_name": "value_pattern"}},
        "from": 2,
        "size": 8
    }'
    
  • 逻辑 or 查询
    1
    2
    3
    4
    
    curl -H "Content-Type: application/json" http://127.0.0.1:9200/index_name/_search -d '
    {
        "query": {"match": {"key_name": "value_pattern_1 value_pattern_2"}}
    }'
    
  • 逻辑 and 查询
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    curl -H "Content-Type: application/json" http://127.0.0.1:9200/index_name/_search -d '
    {
        "query": {
            "bool": {
                "must": [
                    {"match": {"key_name": "value_pattern_1"}},
                    {"match": {"key_name": "value_pattern_2"}}
                ]
            }
        }
    }'
    
  • 区间查询
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
    set -euo pipefail
    export START_TIME="$(date +%s -d $1)"
    export END_TIME="$(date +%s -d $2)"
    curl -s -H "Content-Type: application/json" -o result.txt \
        http://127.0.0.1:9200/wangmei_raw/_search?pretty -d @- <<EOF
    {
      "_source": [
        "spider_name",
        "spider_time",
        "media_name",
        "publish_time"
      ],
      "query": {
        "bool": {
          "filter": {
            "range": {
              "spider_time": {
                "gt": $START_TIME,
                "lte": $END_TIME
              }
            }
          }
        }
      },
      "size": 10000
    }
    EOF
    

Kibana

  • lucene 正则查询
    1
    2
    
    #查询包含10000-99999毫秒的 message 字段
    { "regexp": { "message": "[0-9]{5}ms" } }
    
  • Dev tool 模拟 pipeline
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    
    POST _ingest/pipeline/_simulate
    {
      "pipeline" : {
        "description": "",
        "processors": [
          {
            "grok": {
              "field": "message",
              "patterns": [
                "",
                ""
              ],
              "ignore_missing": true,
              "ignore_failure": true
            }
          }
        ]
      },
      "docs" : [
        {
          "_source": {
            "message": ""
          }
        },
        {
          "_source": {
            "message": ""
          }
        }
      ]
    }
    

pipeline

filebeat

Nginx 笔记

set

  • set ${变量名} {字符串};

全局变量

  • $args $query_string 请求行中的参数
  • $content_length 请求头里的 Content-length 字段
  • $content_type 请求头里的 Content-type 字段
  • $document_root 请求在 root 指令中指定的值
  • $host 请求头里的 Host 字段,如果没有则是服务器名
  • $http_user_agent 客户端agent信息
  • $http_cookie 客户端cookie信息
  • $limit_rate 这个变量可以限制连接速率
  • $request_method 客户端请求的动作,通常为GET或POST
  • $remote_addr 客户端的IP地址
  • $remote_port 客户端的端口
  • $remote_user 已经经过 Auth Basic Module 验证的用户名
  • $request_filename 请求的文件路径,由 root 或 alias 指令与 URI 请求生成
  • $scheme http 或者 https
  • $server_protocol 请求使用的协议 HTTP/1.0 或 HTTP/1.1
  • $server_addr 服务器地址,在完成一次系统调用后可以确定这个值
  • $server_name 服务器名称
  • $server_port 请求到达服务器的端口号
  • $request_uri 包含请求参数的原始URI,不包含主机名,如"/foo/bar.php?arg=baz"
  • $document_uri $uri 不带请求参数的当前URI,不包含主机名,如"/foo/bar.html"

map

  • 语法

Zabbix 笔记

通过 JavaGateway 监控 tomcat

  • 编译 zabbix server,configure 增加 –enable-java

  • 修改 zabbix_server.conf 文件,配置 JavaGateway 参数

    1
    2
    3
    
    JavaGateway=127.0.0.1
    JavaGatewayPort=10052
    StartJavaPollers=5
    
  • 配置 tomcat catalina 启动参数

    1
    2
    3
    4
    5
    6
    7
    
    export CATALINA_OPTS="
        -Dcom.sun.management.jmxremote
        -Dcom.sun.management.jmxremote.authenticate=false
        -Dcom.sun.management.jmxremote.ssl=false
        -Dcom.sun.management.jmxremote.port=10053
        -Djava.rmi.server.hostname={tomcat_server_ip}
    "
    
  • 重启 tomcat

Ceph 笔记

测试环境

操作系统 主机名 IP OSD 设备 OSD ID 容量 ceph 版本
CentOS7 ceph101 192.168.1.101 /dev/sdb 0 3TB jewel
CentOS7 ceph102 192.168.1.102 /dev/sdb 1 3TB jewel
CentOS7 ceph103 192.168.1.103 /dev/sdb 2 3TB jewel
  • ceph 部署机
    • 操作系统: CentOS7
    • 部署用户: cephdeploy
    • 操作目录: /home/cephdeploy/ceph-cluster
    • IP: 192.168.1.100

新增 OSD

  • 设置 ceph 三个 noflag,禁止 ceph 自动迁移数据
    1
    2
    3
    4
    5
    
    # 在任一节点上执行下面命令即可
    ceph osd set noout
    ceph osd set nobackfill
    ceph osd set norecover
    ceph -s # 此时能看到这三个 flag,而且集群处于不健康状态
    
  • 关闭这三台 ceph 服务器, 加装新的磁盘,个人认为无需配置多盘 raid
  • 启动这三台 ceph 服务器,此时 ceph 自动启动,那三个 noflag 依旧有效
  • 此时查看每台服务器的存储,应该能看到新增的一个或多个裸磁盘
    1
    
    lsblk
    
  • 这里假设每台服务器新增两个磁盘(/dev/sdc,/dev/sdd),都配置成 osd
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    
    # 在 ceph 部署机上执行以下命令
    su - cephdeploy
    cd /home/cephdeploy/ceph-cluster
    # 每次创建一个,别浪 ...
    ceph-deploy osd create ceph101:/dev/sdc
    ceph-deploy osd create ceph101:/dev/sdd
    ceph-deploy osd create ceph102:/dev/sdc
    ceph-deploy osd create ceph102:/dev/sdd
    ceph-deploy osd create ceph103:/dev/sdc
    ceph-deploy osd create ceph103:/dev/sdd
    
  • osd 增加完成后, 取消之前设置的那三个 noflag
    1
    2
    3
    4
    
    # 在任一节点上执行下面命令即可
    ceph osd unset noout
    ceph osd unset nobackfill
    ceph osd unset norecover
    
  • 此时数据向新增的 osd 上均衡,时间不确定 …… 只能等!
    1
    2
    
    # 在任一节点上执行下面命令,观察数据迁移
    ceph -w
    
  • 直至 ceph 恢复健康状态
    1
    2
    
    # 在任一节点上执行下面命令,查看集群状态
    ceph -s
    

删除 OSD

  • 把指定的 osd 踢出集群
    1
    2
    3
    
    # 在任一节点上执行下面命令即可
    ceph osd out {osd-id}
    ceph -s # 此时能看到一个 osd 已经 out
    
  • 此时数据在剩下的几个 osd 上均衡,时间不确定 …… 只能等!
    1
    2
    
    # 在任一节点上执行下面命令,观察数据迁移
    ceph -w
    
  • 直至 ceph 恢复健康状态
    1
    2
    
    # 在任一节点上执行下面命令,查看集群状态
    ceph -s
    
  • 停止该被踢出的 osd
    1
    2
    3
    
    # 在运行该 osd 的节点上执行下面命令
    systemctl stop ceph-osd@{osd-id}
    ceph -s # 此时能看到一个 osd 已经 down
    
  • 删除该被停止的 osd
    1
    2
    3
    4
    5
    6
    7
    8
    
    # 在任一节点上执行下面命令即可
    # 删除 CRUSH 图对应的 osd 条目
    ceph osd crush remove osd.{osd-id}
    # 删除 osd 认证密钥
    ceph auth del osd.{osd-id}
    # 删除 osd
    ceph osd rm {osd-num}
    # 删除各节点的 ceph.conf 可能存在的 osd.{osd-id} 配置
    
  • 设置 ceph 三个 noflag,禁止 ceph 自动迁移数据
    1
    2
    3
    4
    5
    
    # 在任一节点上执行下面命令即可
    ceph osd set noout
    ceph osd set nobackfill
    ceph osd set norecover
    ceph -s # 此时能看到这三个 flag,而且集群处于不健康状态
    
  • 关闭这三台 ceph 服务器,撤掉已被删除 osd 对应的旧磁盘
  • 启动这三台 ceph 服务器,此时 ceph 自动启动,三个 noflag 依旧有效;
  • 取消之前设置的那三个 noflag
    1
    2
    3
    4
    
    # 在任一节点上执行下面命令即可
    ceph osd unset noout
    ceph osd unset nobackfill
    ceph osd unset norecover
    
  • 直至 ceph 恢复健康状态
    1
    2
    
    # 在任一节点上执行下面命令,查看集群状态
    ceph -s
    

OSD 动态配置

  • 查看 osd 当前配置
    1
    
    ceph -n osd.0 --show-config
    
  • 动态修改 osd 某个参数
    1
    
    ceph tell osd.* injectargs '--osd_max_backfills 7'
    

PG 和 PGP

  • 少于 5 个 OSD 时可把 pg_num 设置为 128
  • OSD 数量在 5 到 10 个时,可把 pg_num 设置为 512
  • OSD 数量在 10 到 50 个时,可把 pg_num 设置为 1024
  • OSD 数量大于 50 时,<osd数量> * 100/副本数量(默认3),该值接近的 2 的 N 次方值
  • 存储池的 PG 和 PGP 数量一般相等,都是 2 的 N 次方,只能增加,每次增加为当前的 2 倍
  • 查看存储池的 PG 和 PGP 数量
    1
    2
    
    ceph osd pool get {pool_name} pg_num
    ceph osd pool get {pool_name} pgp_num
    
  • 增加/设置存储池的 PG 和 PGP 数量
    1
    2
    
    ceph osd pool set {pool_name} <cur_pg_num>*2
    ceph osd pool set {pool_name} <cur_pgp_num>*2
    
  • 获取所有卡在某状态的归置组统计信息
    1
    2
    3
    
    ceph pg dump_stuck inactive|unclean|stale|undersized|degraded
    #Inactive (不活跃)归置组不能处理读写,因为它们在等待一个有最新数据的 OSD 复活且进入集群
    #Unclean (不干净)归置组含有复制数未达到期望数量的对象,它们应该在恢复中
    
  • 获取一个具体归置组的归置组图
    1
    
    ceph pg map {pg-id}
    

CEPH 服务器关机维护

  • 设置 ceph 节点 down 后不自动迁移或恢复数据
    1
    2
    3
    
    ceph osd set noout
    ceph osd set nobackfill
    ceph osd set norecover
    
  • 直接关机
  • 下次开机
  • 设置 ceph 节点开始自动迁移或回复数据
    1
    2
    3
    
    ceph osd unset noout
    ceph osd unset nobackfill
    ceph osd unset norecover
    

Websocket 查看实时日志

操作系统

  • CentOS7

下载 websocketd

安装 nc 命令

1
yum install nmap-ncat

创建监听脚本

1
2
3
4
5
6
7
8
cat > cmd.sh <<-END
##!/bin/bash
pkill -x nc
while :; do
    nc -nkl 10088
    sleep 1
done
END

创建 log.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<!DOCTYPE html>
<html>
<head>
    <style>
        body{
            background-color: #0e1012;color: #ffffff;
        }
        *{
            margin: 0; padding: 0;
        }
        #msg{
            overflow:auto; border:2px solid #303030; color:#ffffff; background-color: #2b2b2b; font-size: 13px; position: absolute; left: 8px; right: 8px; bottom: 8px; top: 40px; word-break:
break-all;
        }
        #log{
            position: fixed; top: 0; left: 0; width: 100%; height: 40px; text-align: left; margin: 4px 0 0 8px;
        }
        #log b{
            font-size: 26px;
        }
        #msgBtn{
            padding: 5px 10px; border: none; background: #777; float: right; margin: 0 16px 0 0;
        }
    </style>
</head>
<body>
    <div id="log"><span><b>实时日志</b></span><button id="msgBtn" type="button">清空</button></div>
    <div id="msg"><ul class="list"></ul></div>
    <script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
    <script>
        $(document).ready(function() {
            if (!window.WebSocket) {
                if (window.MozWebSocket) {
                    window.WebSocket = window.MozWebSocket;
                } else {
                    $('#msg').append("<p>你的浏览器不支持websocket</p>");
                }
            }
            var ws = new WebSocket('ws://221.7.197.100:8008/websocket/');
            ws.onopen = function(evt) {
                $('.list').append('<li>websocket连接成功</li>');
            }
            ws.onmessage = function(evt) {
                $('.list').append('<li>' + evt.data + '</li>');
                setTimeout(function(){$('#msg').scrollTop($('.list').height()-$('#msg').height());}, 100)
            }
            $("#msgBtn").click(function(){
                $(".list").html("");
            })
        });
    </script>
</body>
</html>

文件部署位置

1
2
3
4
5
websocketd/
├── [-rwxr-xr-x]  cmd.sh
├── [drwxr-xr-x]  websocket
│   └── [-rw-r--r--]  log.html
└── [-rwxr-xr-x]  websocketd

启动 websocketd

1
2
cd websocketd
./websocketd --port=8008 --staticdir=. ./cmd.sh

在浏览器中打开日志浏览页面

  • http://{websocket-server}:8008/websocket/log.html

在其他应用服务器,传输实时日志

1
tail -f /tomcat/logs/catalina.out | nc -n {websocket-server} 10088

关闭实时日志

  • 在目标服务器中 kill nc
    1
    
    pkill -x nc
    
  • 在 websocket server 中 kill nc
    1
    
    pkill -x nc
    
  • 直接刷新浏览器的日志浏览页面

Haproxy 笔记

CentOS7 下安装

  • CentOS7 自带的 haproxy 版本太低,这里通过 cheese 源安装最新版本
  • 安装 cheese repo,详细参考这里
    1
    2
    
    wget http://www.nosuchhost.net/~cheese/fedora/packages/epel-7/x86_64/cheese-release-7-1.noarch.rpm
    rpm -Uvh cheese-release-7-1.noarch.rpm
    
  • 安装 haproxy
    1
    
    yum install haproxy
    
  • 修改 sysctl.conf
    1
    2
    3
    4
    5
    6
    7
    8
    
    cat >> /etc/sysctl.conf <<-END
    net.ipv4.ip_forward=1
    net.ipv4.tcp_syncookies = 1
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_tw_recycle = 1
    net.ipv4.tcp_fin_timeout = 8
    END
    sysctl -p
    
  • 禁用 selinux
    1
    2
    
    sed -i '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config
    setenforce 0
    

全局配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
global
    log         127.0.0.1 local2 info
    chroot      /var/lib/haproxy # 如果需要外部检查脚本,则需注释该行
    #external-check # 如果需要外部检查脚本,则取消注释
    pidfile     /var/run/haproxy.pid
    maxconn     102400
    user        haproxy
    group       haproxy
    daemon
    stats socket /var/lib/haproxy/stats

默认配置

1
2
3
4
5
6
defaults
    log global
    option dontlognull
    option redispatch
    option abortonclose
    timeout check 8s

tcp 连接多个 ceph-radosgw

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
frontend  ceph-radosgw
    bind *:7480
    timeout client 8s
    default_backend ceph-radosgw
backend ceph-radosgw
    mode tcp
    balance roundrobin
    timeout connect 8s
    timeout server 8s
    retries 2
    #option external-check
    #external-check command /var/lib/haproxy/health_check.sh
    server cpeh240 10.9.10.234:7480 check
    server ceph241 10.9.10.235:7480 check
    server ceph243 10.9.10.236:7480 check

tcp 连接 mysql galera cluster

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
frontend mysql
    bind *:3306
    timeout client 1800s
    default_backend mysql
backend mysql
    balance source
    option tcpka
    timeout connect    8s
    timeout server     1800s
    retries 2
    server  mysql231   10.9.10.231:3306 check inter 4s
    server  mysql232   10.9.10.232:3306 check inter 4s
    server  mysql233   10.9.10.233:3306 check inter 4s

tcp 连接 redis 主库

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
frontend redis
    bind *:6379
    timeout client 1800s
    default_backend redis
backend redis
    balance roundrobin
    timeout connect 8s
    timeout server 1800s
    retries 2
    option tcp-check
    tcp-check connect
    tcp-check send PING\r\n
    tcp-check expect string +PONG
    tcp-check send info\ replication\r\n
    tcp-check expect string role:master
    tcp-check send QUIT\r\n
    tcp-check expect string +OK
    server redis87 10.1.14.87:6379 check inter 4s
    server redis88 10.1.14.88:6379 check inter 4s
    server redis89 10.1.14.89:6379 check inter 4s

状态页面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
listen admin_stats
    bind 0.0.0.0:10080
    mode http
    maxconn 100
    timeout client 1m
    timeout connect 4s
    timeout server 4s
    stats refresh 30s
    stats uri /
    stats auth username:password
    stats realm haproxy for private user, enter username/password
    stats hide-version

通过 rsyslog 生成日志

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
sed -i -e '/ModLoad imudp/s/^#//' \
    -e '/UDPServerRun 514/s/^#//' /etc/rsyslog.conf
cat > /etc/rsyslog.d/haproxy.conf <<EOF
## haproxy log
template(name="HaproxyTime" type="list"){
    property(name="timereported" dateformat="year")
    constant(value="-")
    property(name="timereported" dateformat="month")
    constant(value="-")
    property(name="timereported" dateformat="day")
    constant(value=" ")
    property(name="timereported" dateformat="hour")
    constant(value=":")
    property(name="timereported" dateformat="minute")
    constant(value=":")
    property(name="timereported" dateformat="second")
    constant(value=" ")
    property(name="msg" droplastlf="on")
    constant(value="\n")
}
template(name="DynFile" type="list"){
    constant(value="/var/log/haproxy/haproxy-")
    property(name="timereported" dateformat="year")
    property(name="timereported" dateformat="month")
    property(name="timereported" dateformat="day")
    constant(value=".log")
}
local2.* action(type="omfile" dynaFile="DynFile" template="HaproxyTime")
EOF
systemctl restart rsyslog
systemctl restart haproxy

参考

Ansible

CentOS7 安装 ansible

1
yum install ansible

修改配置文件 /etc/ansible/ansible.conf

1
2
3
4
## 取消 ssh key 验证
host_key_checking = False
## 改用 debug 输出模式
stdout_callback = debug

修改配置文件 hosts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
## 增加 tomcat 服务器组
[tomcat]
tomcat101 ansible_ssh_host=192.168.1.101
tomcat102 ansible_ssh_host=192.168.1.102
tomcat103 ansible_ssh_host=192.168.1.103
## 增加 mysql 服务器组
[mysql]
mysql201 ansible_ssh_host=192.168.1.201 ansible_ssh_pass=111111
mysql202 ansible_ssh_host=192.168.1.202
mysql203 ansible_ssh_host=192.168.1.203
## 全局设置全部服务器的默认设置
[all:vars]
ansible_ssh_port=22
ansible_ssh_user=root
ansible_ssh_pass=123456

authorized_key 模块

1
2
## 分发密钥
ansible all -m authorized_key -a "user=root key='{{ lookup('file', '/root/.ssh/id_rsa.pub') }}'"

简单使用

  • 批量设置主机名为资产名
    1
    2
    
    ansible all -m shell -a 'hostnamectl set-hostname {{inventory_hostname}}'
    ansible all -m shell -a 'echo "{{ansible_ssh_host}} {{inventory_hostname}}" >> /etc/hosts'
    

ansible 常用 roles

Redis Sentinel

环境

主机名 地址 操作系统 初始状态
sentinel86 10.1.14.86 CentOS7.4 null
redis87 10.1.14.87 CentOS7.4 master
redis88 10.1.14.88 CentOS7.4 slave
redis89 10.1.14.89 CentOS7.4 slave

安装 redis

  • 在全部服务器上安装 redis
    1
    2
    
    yum install epel-release
    yum install redis
    

redis master 配置

  • 在 redis87 上修改 /etc/redis.conf
    1
    
    bind 0.0.0.0
    

redis slave 配置

  • 在 redis88 和 redis89 上修改 /etc/redis.conf
    1
    2
    
    bind 0.0.0.0
    slaveof 10.1.14.87 6379
    

redis sentinel 配置

  • 在 sentinel86 上创建三个 sentinel 配置文件
    1
    2
    3
    4
    5
    
    cd /etc/
    cp redis-sentinel.conf redis-sentinel-16379.conf
    cp redis-sentinel.conf redis-sentinel-26379.conf
    mv redis-sentinel.conf redis-sentinel-36379.conf
    chown redis.root redis-sentinel-?6379.conf
    
  • 修改 /etc/redis-sentinel-16379.conf
    1
    2
    3
    4
    5
    6
    
    bind 0.0.0.0
    port 16379
    dir /var/log/redis/16379
    sentinel monitor mymaster 10.1.14.87 6379 2
    sentinel down-after-milliseconds mymaster 8000
    logfile /var/log/redis/16379/sentinel.log
    
  • 修改 /etc/redis-sentinel-26379.conf
    1
    2
    3
    4
    5
    6
    
    bind 0.0.0.0
    port 26379
    dir /var/log/redis/26379
    sentinel monitor mymaster 10.1.14.87 6379 2
    sentinel down-after-milliseconds mymaster 8000
    logfile /var/log/redis/26379/sentinel.log
    
  • 修改 /etc/redis-sentinel-36379.conf
    1
    2
    3
    4
    5
    6
    
    bind 0.0.0.0
    port 36379
    dir /var/log/redis/36379
    sentinel monitor mymaster 10.1.14.87 6379 2
    sentinel down-after-milliseconds mymaster 8000
    logfile /var/log/redis/36379/sentinel.log
    
  • 创建日志目录
    1
    2
    3
    
    cd /var/log/redis/
    mkdir 16379 26379 36379
    chown redis.redis ?6379 -R
    
  • 创建两个 sentinel service 文件
    1
    2
    3
    4
    
    cd /usr/lib/systemd/system/
    cp redis-sentinel.service redis-sentinel-16379.service
    cp redis-sentinel.service redis-sentinel-26379.service
    mv redis-sentinel.service redis-sentinel-36379.service
    
  • 修改 /usr/lib/systemd/system/redis-sentinel-16379.service
    1
    2
    
    ExecStart=/usr/bin/redis-sentinel /etc/redis-sentinel-16379.conf --daemonize no
    ExecStop=/usr/libexec/redis-shutdown redis-sentinel-16379
    
  • 修改 /usr/lib/systemd/system/redis-sentinel-26379.service
    1
    2
    
    ExecStart=/usr/bin/redis-sentinel /etc/redis-sentinel-26379.conf --daemonize no
    ExecStop=/usr/libexec/redis-shutdown redis-sentinel-26379
    
  • 修改 /usr/lib/systemd/system/redis-sentinel-36379.service
    1
    2
    
    ExecStart=/usr/bin/redis-sentinel /etc/redis-sentinel-36379.conf --daemonize no
    ExecStop=/usr/libexec/redis-shutdown redis-sentinel-36379
    
  • 更新服务
    1
    
    systemctl daemon-reload
    

启动 redis 服务

  • 在 redis87、redis88 和 redis89 上启动 redis 服务
    1
    2
    3
    
    systemctl start redis
    # 查看当前节点主从信息
    redis-cli info replication
    

启动 redis sentinel 监控

  • 在 sentinel86 上启动 sentinel 监管程序
    1
    2
    3
    
    systemctl start redis-sentinel-16379
    systemctl start redis-sentinel-26379
    systemctl start redis-sentinel-36379