figure:first-child { margin-top: -20px; }
#write ol, #write ul { position: relative; }
img { max-width: 100%; vertical-align: middle; }
button, input, select, textarea { color: inherit; font-family: inherit; font-size: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; }
input[type="checkbox"], input[type="radio"] { line-height: normal; padding: 0px; }
*, ::after, ::before { box-sizing: border-box; }
#write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write p, #write pre { width: inherit; }
#write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write p { position: relative; }
h1, h2, h3, h4, h5, h6 { break-after: avoid-page; break-inside: avoid; orphans: 2; }
p { orphans: 4; }
h1 { font-size: 2rem; }
h2 { font-size: 1.8rem; }
h3 { font-size: 1.6rem; }
h4 { font-size: 1.4rem; }
h5 { font-size: 1.2rem; }
h6 { font-size: 1rem; }
.md-math-block, .md-rawblock, h1, h2, h3, h4, h5, h6, p { margin-top: 1rem; margin-bottom: 1rem; }
.hidden { display: none; }
.md-blockmeta { color: rgb(204, 204, 204); font-weight: 700; font-style: italic; }
a { cursor: pointer; }
sup.md-footnote { padding: 2px 4px; background-color: rgba(238, 238, 238, 0.701961); color: rgb(85, 85, 85); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; cursor: pointer; }
sup.md-footnote a, sup.md-footnote a:hover { color: inherit; text-transform: inherit; text-decoration: inherit; }
#write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit; }
figure { overflow-x: auto; margin: 1.2em 0px; max-width: calc(100% + 16px); padding: 0px; }
figure > table { margin: 0px !important; }
tr { break-inside: avoid; break-after: auto; }
thead { display: table-header-group; }
table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; break-inside: auto; text-align: left; }
table.md-table td { min-width: 32px; }
.CodeMirror-gutters { border-right-width: 0px; background-color: inherit; }
.CodeMirror { text-align: left; }
.CodeMirror-placeholder { opacity: 0.3; }
.CodeMirror pre { padding: 0px 4px; }
.CodeMirror-lines { padding: 0px; }
div.hr:focus { cursor: none; }
#write pre { white-space: pre-wrap; }
#write.fences-no-line-wrapping pre { white-space: pre; }
#write pre.ty-contain-cm { white-space: normal; }
.CodeMirror-gutters { margin-right: 4px; }
.md-fences { font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; overflow: visible; white-space: pre; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; position: relative !important; background-position: inherit inherit; background-repeat: inherit inherit; }
.md-diagram-panel { width: 100%; margin-top: 10px; text-align: center; padding-top: 0px; padding-bottom: 8px; overflow-x: auto; }
#write .md-fences.mock-cm { white-space: pre-wrap; }
.md-fences.md-fences-with-lineno { padding-left: 0px; }
#write.fences-no-line-wrapping .md-fences.mock-cm { white-space: pre; overflow-x: auto; }
.md-fences.mock-cm.md-fences-with-lineno { padding-left: 8px; }
.CodeMirror-line, twitterwidget { break-inside: avoid; }
.footnotes { opacity: 0.8; font-size: 0.9rem; margin-top: 1em; margin-bottom: 1em; }
.footnotes + .footnotes { margin-top: 0px; }
.md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; text-decoration: none; text-shadow: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; line-height: normal; font-weight: 400; text-align: left; box-sizing: content-box; direction: ltr; background-position: 0px 0px; background-repeat: initial initial; }
li div { padding-top: 0px; }
blockquote { margin: 1rem 0px; }
li .mathjax-block, li p { margin: 0.5rem 0px; }
li { margin: 0px; position: relative; }
blockquote > :last-child { margin-bottom: 0px; }
blockquote > :first-child, li > :first-child { margin-top: 0px; }
.footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; white-space: normal; }
#write .footnote-line { white-space: pre-wrap; }
@media print {
body, html { border: 1px solid transparent; height: 99%; break-after: avoid-page; break-before: avoid-page; }
#write { margin-top: 0px; padding-top: 0px; border-color: transparent !important; }
.typora-export * { -webkit-print-color-adjust: exact; }
html.blink-to-pdf { font-size: 13px; }
.typora-export #write { padding-left: 32px; padding-right: 32px; padding-bottom: 0px; break-after: avoid-page; }
.typora-export #write::after { height: 0px; }
@page { margin: 20mm 0px; }
}
.footnote-line { margin-top: 0.714em; font-size: 0.7em; }
a img, img a { cursor: pointer; }
pre.md-meta-block { font-size: 0.8rem; min-height: 0.8rem; white-space: pre-wrap; background-color: rgb(204, 204, 204); display: block; overflow-x: hidden; background-position: initial initial; background-repeat: initial initial; }
p > .md-image:only-child:not(.md-img-error) img, p > img:only-child { display: block; margin: auto; }
p > .md-image:only-child { display: inline-block; width: 100%; }
#write .MathJax_Display { margin: 0.8em 0px 0px; }
.md-math-block { width: 100%; }
.md-math-block:not(:empty)::after { display: none; }
[contenteditable="true"]:active, [contenteditable="true"]:focus { outline: 0px; box-shadow: none; }
.md-task-list-item { position: relative; list-style-type: none; }
.task-list-item.md-task-list-item { padding-left: 0px; }
.md-task-list-item > input { position: absolute; top: 0px; left: 0px; margin-left: -1.2em; margin-top: calc(1em - 10px); border: none; }
.math { font-size: 1rem; }
.md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem; border-top-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; }
.md-toc-content { position: relative; margin-left: 0px; }
.md-toc-content::after, .md-toc::after { display: none; }
.md-toc-item { display: block; color: rgb(65, 131, 196); }
.md-toc-item a { text-decoration: none; }
.md-toc-inner:hover { text-decoration: underline; }
.md-toc-inner { display: inline-block; cursor: pointer; }
.md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: 700; }
.md-toc-h2 .md-toc-inner { margin-left: 2em; }
.md-toc-h3 .md-toc-inner { margin-left: 4em; }
.md-toc-h4 .md-toc-inner { margin-left: 6em; }
.md-toc-h5 .md-toc-inner { margin-left: 8em; }
.md-toc-h6 .md-toc-inner { margin-left: 10em; }
@media screen and (max-width: 48em) {
.md-toc-h3 .md-toc-inner { margin-left: 3.5em; }
.md-toc-h4 .md-toc-inner { margin-left: 5em; }
.md-toc-h5 .md-toc-inner { margin-left: 6.5em; }
.md-toc-h6 .md-toc-inner { margin-left: 8em; }
}
a.md-toc-inner { font-size: inherit; font-style: inherit; font-weight: inherit; line-height: inherit; }
.footnote-line a:not(.reversefootnote) { color: inherit; }
.md-attr { display: none; }
.md-fn-count::after { content: "."; }
code, pre, samp, tt { font-family: var(--monospace); }
kbd { margin: 0px 0.1em; padding: 0.1em 0.6em; font-size: 0.8em; color: rgb(36, 39, 41); background-color: rgb(255, 255, 255); border: 1px solid rgb(173, 179, 185); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; box-shadow: rgba(12, 13, 14, 0.2) 0px 1px 0px, rgb(255, 255, 255) 0px 0px 0px 2px inset; white-space: nowrap; vertical-align: middle; background-position: initial initial; background-repeat: initial initial; }
.md-comment { color: rgb(162, 127, 3); opacity: 0.8; font-family: var(--monospace); }
code { text-align: left; }
a.md-print-anchor { white-space: pre !important; border: none !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: 0px !important; text-shadow: initial !important; background-position: 0px 0px !important; background-repeat: initial initial !important; }
.md-inline-math .MathJax_SVG .noError { display: none !important; }
.html-for-mac .inline-math-svg .MathJax_SVG { vertical-align: 0.2px; }
.md-math-block .MathJax_SVG_Display { text-align: center; margin: 0px; position: relative; text-indent: 0px; max-width: none; max-height: none; min-height: 0px; min-width: 100%; width: auto; overflow-y: hidden; display: block !important; }
.MathJax_SVG_Display, .md-inline-math .MathJax_SVG_Display { width: auto; margin: inherit; display: inline-block !important; }
.MathJax_SVG .MJX-monospace { font-family: var(--monospace); }
.MathJax_SVG .MJX-sans-serif { font-family: sans-serif; }
.MathJax_SVG { display: inline; font-style: normal; font-weight: 400; line-height: normal; zoom: 90%; text-indent: 0px; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0px; min-height: 0px; border: 0px; padding: 0px; margin: 0px; }
.MathJax_SVG * { transition: none; }
.MathJax_SVG_Display svg { vertical-align: middle !important; margin-bottom: 0px !important; }
.os-windows.monocolor-emoji .md-emoji { font-family: "Segoe UI Symbol", sans-serif; }
.md-diagram-panel > svg { max-width: 100%; }
[lang="mermaid"] svg, [lang="flow"] svg { max-width: 100%; }
[lang="mermaid"] .node text { font-size: 1rem; }
table tr th { border-bottom-width: 0px; }
video { max-width: 100%; display: block; margin: 0px auto; }
iframe { max-width: 100%; width: 100%; border: none; }
.highlight td, .highlight tr { border: 0px; }

.CodeMirror { height: auto; }
.CodeMirror.cm-s-inner { background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; background-position: inherit inherit; background-repeat: inherit inherit; }
.CodeMirror-scroll { overflow-y: hidden; overflow-x: auto; z-index: 3; }
.CodeMirror-gutter-filler, .CodeMirror-scrollbar-filler { background-color: rgb(255, 255, 255); }
.CodeMirror-gutters { border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; white-space: nowrap; background-position: inherit inherit; background-repeat: inherit inherit; }
.CodeMirror-linenumber { padding: 0px 3px 0px 5px; text-align: right; color: rgb(153, 153, 153); }
.cm-s-inner .cm-keyword { color: rgb(119, 0, 136); }
.cm-s-inner .cm-atom, .cm-s-inner.cm-atom { color: rgb(34, 17, 153); }
.cm-s-inner .cm-number { color: rgb(17, 102, 68); }
.cm-s-inner .cm-def { color: rgb(0, 0, 255); }
.cm-s-inner .cm-variable { color: rgb(0, 0, 0); }
.cm-s-inner .cm-variable-2 { color: rgb(0, 85, 170); }
.cm-s-inner .cm-variable-3 { color: rgb(0, 136, 85); }
.cm-s-inner .cm-string { color: rgb(170, 17, 17); }
.cm-s-inner .cm-property { color: rgb(0, 0, 0); }
.cm-s-inner .cm-operator { color: rgb(152, 26, 26); }
.cm-s-inner .cm-comment, .cm-s-inner.cm-comment { color: rgb(170, 85, 0); }
.cm-s-inner .cm-string-2 { color: rgb(255, 85, 0); }
.cm-s-inner .cm-meta { color: rgb(85, 85, 85); }
.cm-s-inner .cm-qualifier { color: rgb(85, 85, 85); }
.cm-s-inner .cm-builtin { color: rgb(51, 0, 170); }
.cm-s-inner .cm-bracket { color: rgb(153, 153, 119); }
.cm-s-inner .cm-tag { color: rgb(17, 119, 0); }
.cm-s-inner .cm-attribute { color: rgb(0, 0, 204); }
.cm-s-inner .cm-header, .cm-s-inner.cm-header { color: rgb(0, 0, 255); }
.cm-s-inner .cm-quote, .cm-s-inner.cm-quote { color: rgb(0, 153, 0); }
.cm-s-inner .cm-hr, .cm-s-inner.cm-hr { color: rgb(153, 153, 153); }
.cm-s-inner .cm-link, .cm-s-inner.cm-link { color: rgb(0, 0, 204); }
.cm-negative { color: rgb(221, 68, 68); }
.cm-positive { color: rgb(34, 153, 34); }
.cm-header, .cm-strong { font-weight: 700; }
.cm-del { text-decoration: line-through; }
.cm-em { font-style: italic; }
.cm-link { text-decoration: underline; }
.cm-error { color: red; }
.cm-invalidchar { color: red; }
.cm-constant { color: rgb(38, 139, 210); }
.cm-defined { color: rgb(181, 137, 0); }
div.CodeMirror span.CodeMirror-matchingbracket { color: rgb(0, 255, 0); }
div.CodeMirror span.CodeMirror-nonmatchingbracket { color: rgb(255, 34, 34); }
.cm-s-inner .CodeMirror-activeline-background { background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; background-position: inherit inherit; background-repeat: inherit inherit; }
.CodeMirror { position: relative; overflow: hidden; }
.CodeMirror-scroll { height: 100%; outline: 0px; position: relative; box-sizing: content-box; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; background-position: inherit inherit; background-repeat: inherit inherit; }
.CodeMirror-sizer { position: relative; }
.CodeMirror-gutter-filler, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-vscrollbar { position: absolute; z-index: 6; display: none; }
.CodeMirror-vscrollbar { right: 0px; top: 0px; overflow: hidden; }
.CodeMirror-hscrollbar { bottom: 0px; left: 0px; overflow: hidden; }
.CodeMirror-scrollbar-filler { right: 0px; bottom: 0px; }
.CodeMirror-gutter-filler { left: 0px; bottom: 0px; }
.CodeMirror-gutters { position: absolute; left: 0px; top: 0px; padding-bottom: 30px; z-index: 3; }
.CodeMirror-gutter { white-space: normal; height: 100%; box-sizing: content-box; padding-bottom: 30px; margin-bottom: -32px; display: inline-block; }
.CodeMirror-gutter-wrapper { position: absolute; z-index: 4; border: none !important; background-position: 0px 0px !important; background-repeat: initial initial !important; }
.CodeMirror-gutter-background { position: absolute; top: 0px; bottom: 0px; z-index: 4; }
.CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; }
.CodeMirror-lines { cursor: text; }
.CodeMirror pre { border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; border-width: 0px; font-family: inherit; font-size: inherit; margin: 0px; white-space: pre; word-wrap: normal; color: inherit; z-index: 2; position: relative; overflow: visible; background-position: 0px 0px; background-repeat: initial initial; }
.CodeMirror-wrap pre { word-wrap: break-word; white-space: pre-wrap; word-break: normal; }
.CodeMirror-code pre { border-right-width: 30px; border-right-style: solid; border-right-color: transparent; width: fit-content; }
.CodeMirror-wrap .CodeMirror-code pre { border-right-style: none; width: auto; }
.CodeMirror-linebackground { position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; z-index: 0; }
.CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto; }
.CodeMirror-wrap .CodeMirror-scroll { overflow-x: hidden; }
.CodeMirror-measure { position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden; }
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor { position: absolute; visibility: hidden; border-right-style: none; width: 0px; }
.CodeMirror div.CodeMirror-cursor { visibility: hidden; }
.CodeMirror-focused div.CodeMirror-cursor { visibility: inherit; }
.cm-searching { background-color: rgba(255, 255, 0, 0.4); background-position: initial initial; background-repeat: initial initial; }
@media print {
.CodeMirror div.CodeMirror-cursor { visibility: hidden; }
}

@charset "utf-8";

:root {
--active-file-bg-color: #dadada;
--active-file-bg-color: rgba(32, 43, 51, 0.63);
--active-file-text-color: white;
--bg-color: #fff;
--text-color: #333;
--side-bar-bg-color: #f5f5f5;
--control-text-color: #666;
}

/* 防止用户自定义背景颜色对网页的影响,添加让用户可以自定义字体 */
html {
color: #333;
background: #fff;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
text-rendering: optimizelegibility;
font-size: 14px;
-webkit-font-smoothing: initial;
}

#write {
max-width: 960px;
padding-top: 2em;
padding-left: 60px;
padding-right: 60px;
min-height: calc(100vh - 6em);
-webkit-font-smoothing: antialiased;
font-size: 16px;
}

.typora-node #write {
min-height: calc(100% - 6em);
}

pre.md-meta-block {
background: #f5f5f5;
padding: 1em;
border-radius: 3px;
font-size: 14px;
}

@media screen and (max-width: 800px) {
html {
font-size: 14px;
}

#write {
padding-left: 30px;
padding-right: 30px;
font-size: 14px;
}
}

@media screen and (min-width: 1100px) {
body, #footer-word-count-info {
background: #f5f5f5;
}

body.pin-outline,
.pin-outline #footer-word-count-info,
.pin-outline footer {
background: #fff;
}

#write {
max-width: 1000px;
padding: 40px 60px;
background: #fff;
margin: 3em auto 3em;
border: 1px solid #ddd;
border-width: 0 1px;
}

.pin-outline #write {
max-width: 1000px;
background: #fff;
margin: 0 0 0;
border: 0;
padding-left: 60px;
padding-right: 60px;
}

footer {
background-color: transparent;
}
}

@media screen and (min-width: 1300px) {
body.pin-outline,
.pin-outline #footer-word-count-info,
.pin-outline footer {
background: #f5f5f5;
}

.pin-outline #write {
max-width: 1000px;
padding: 40px 60px;
background: #fff;
margin: 3em auto 3em;
border: 1px solid #ddd;
border-width: 0 1px;
}

.pin-outline footer {
background-color: transparent;
}

#footer-word-count-info {
background: #f5f5f5;
}
}

/* 如果你的项目仅支持 IE9+ | Chrome | Firefox 等,推荐在 中添加 .borderbox 这个 class */
html.borderbox *, html.borderbox *:before, html.borderbox *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}

/* 内外边距通常让各个浏览器样式的表现位置不同 */
body, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, code, form, fieldset, legend, input, textarea, p, blockquote, th, td, hr, button, article, aside, details, figcaption, figure, footer, header, menu, nav, section {
margin: 0;
padding: 0;
}

/* 重设 HTML5 标签, IE 需要在 js 中 createElement(TAG) */
article, aside, details, figcaption, figure, footer, header, menu, nav, section {
display: block;
}

/* HTML5 媒体文件跟 img 保持一致 */
audio, canvas, video {
display: inline-block;
}

/* 要注意表单元素并不继承父级 font 的问题 */
body, button, input, select, textarea {
font: 300 1em/1.8 "PingFang SC", "Lantinghei SC", "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans;
}

body {
font-family: "PingFang SC", "Lantinghei SC", "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans;
}

h1, h2, h3, h4, h5, h6 {
font-family: "TimesNewRomanPS-ItalicMT", "PingFang SC", "Lantinghei SC", "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans;
/*font-family: "PingFang SC", "Lantinghei SC", "Microsoft Yahei", "Hiragino Sans GB", "Microsoft Sans Serif", "WenQuanYi Micro Hei", sans;*/
-webkit-font-smoothing: initial;
font-weight: 100;
color: var(--text-color);
line-height: 1.35;
font-variant-numeric: lining-nums;
margin-bottom: 1em;
}

em {
font-family: Georgia-Italic, STSongti-SC-Light, serif;
}

strong em,
em strong {
font-family: Georgia-BoldItalic, STSongti-SC-Regular, serif;
}

button::-moz-focus-inner,
input::-moz-focus-inner {
padding: 0;
border: 0;
}

/* 去掉各Table cell 的边距并让其边重合 */
table {
border-collapse: collapse;
border-spacing: 0;
}

/* 去除默认边框 */
fieldset, img {
border: 0;
}

/* 块/段落引用 */
blockquote {
position: relative;
color: #999;
font-weight: 400;
border-left: 1px solid #1abc9c;
padding-left: 1em;
margin: 1em 3em 1em 2em;
}

@media only screen and ( max-width: 640px ) {
blockquote {
margin: 1em 0;
}
}

/* Firefox 以外,元素没有下划线,需添加 */
acronym, abbr {
border-bottom: 1px dotted;
font-variant: normal;
}

/* 添加鼠标问号,进一步确保应用的语义是正确的(要知道,交互他们也有洁癖,如果你不去掉,那得多花点口舌) */
abbr {
cursor: help;
}

address, caption, cite, code, dfn, th, var {
font-style: normal;
font-weight: 400;
}

/* 去掉列表前的标识, li 会继承,大部分网站通常用列表来很多内容,所以应该当去 */
ul, ol {
list-style: none;
}

/* 对齐是排版最重要的因素, 别让什么都居中 */
caption, th {
text-align: left;
}

q:before, q:after {
content: '';
}

/* 统一上标和下标 */
sub, sup {
font-size: 75%;
line-height: 0;
position: relative;
}

:root sub, :root sup {
vertical-align: baseline; /* for ie9 and other modern browsers */
}

sup {
top: -0.5em;
}

sub {
bottom: -0.25em;
}

/* 让链接在 hover 状态下显示下划线 */
a {
color: #1abc9c;
}

a:hover {
text-decoration: underline;
}

#write a {
border-bottom: 1px solid #1abc9c;
}

#write a:hover {
border-bottom-color: #555;
color: #555;
text-decoration: none;
}

/* 默认不显示下划线,保持页面简洁 */
ins, a {
text-decoration: none;
}

/* 标记,类似于手写的荧光笔的作用 */
mark {
background: #fffdd1;
border-bottom: 1px solid #ffedce;
padding: 2px;
margin: 0 5px;
}

/* 代码片断 */
pre, code, pre tt {
font-family: Courier, 'Courier New', monospace;
}

#write .md-fences {
border: 1px solid #ddd;
padding: 1em 0.5em;
display: block;
-webkit-overflow-scrolling: touch;
}

/* 一致化 horizontal rule */
hr {
border: none;
border-bottom: 1px solid #cfcfcf;
margin-bottom: 0.8em;
height: 10px;
}

#write strong {
font-weight: bolder;
color: #000;
}

.code-tooltip.md-hover-tip strong {
color: white;
}

/* 保证块/段落之间的空白隔行 */
#write p, #write .md-fences, #write ul, #write ol, #write dl, #write form, #write hr, #write figure,
#write-p, #write-pre, #write-ul, #write-ol, #write-dl, #write-form, #write-hr, #write-table, blockquote {
margin-bottom: 1.2em
}

html {
font-family: PingFang SC, Verdana, Helvetica Neue, Microsoft Yahei, Hiragino Sans GB, Microsoft Sans Serif, WenQuanYi Micro Hei, sans-serif;
}

/* 标题应该更贴紧内容,并与其他块区分,margin 值要相应做优化 */
#write h1, #write h2, #write h3, #write h4, #write h5, #write h6,
#write-h1, #write-h2, #write-h3, #write-h4, #write-h5, #write-h6 {
margin-top: 1.2em;
margin-bottom: 0.6em;
line-height: 1.35;
color: #000;
}

#write h1, #write-h1 {
font-size: 2.4em;
padding-bottom: 1em;
border-bottom: 3px double #eee;
}

#write h2, #write-h2 {
font-size: 1.8em;
}

#write h3, #write-h3 {
font-size: 1.6em;
}

#write h4, #write-h4 {
font-size: 1.4em;
}

#write h5, #write h6, #write-h5, #write-h6 {
font-size: 1.2em;
}

/* 在文章中,应该还原 ul 和 ol 的样式 */
#write ul, #write-ul {
margin-left: 1.3em;
list-style: disc;
}

#write ol, #write-ol {
list-style: decimal;
margin-left: 1.9em;
}

#write li ul, #write li ol, #write-ul ul, #write-ul ol, #write-ol ul, #write-ol ol {
margin-bottom: 0.8em;
margin-left: 2em;
}

#write li ul, #write-ul ul, #write-ol ul {
list-style: circle;
}

#write table th, #write table td {
border: 1px solid #ddd;
padding: 0.5em 1em;
color: #666;
}

#write table .md-table-edit th {
border: none;
padding: 0;
color: inherit;
}

#write table th, #write-table th {
background: #fbfbfb;
}

#write table thead th, #write-table thead th {
background: #f1f1f1;
}

#write table caption {
border-bottom: none;
}

#write em {
font-weight: inherit;
font-style: inherit;
}

li>p {
margin-bottom: 0 !important;
}

/* Responsive images */
#write img {
max-width: 100%;
}

a.md-toc-inner {
border-bottom: 0 !important;
}

.md-toc-h1:first-of-type:last-of-type{
display: none;
}

.md-toc {
font-size: inherit;
}

.md-toc-h1 .md-toc-inner {
font-weight: normal;
}

.md-table-edit th {
padding: 0 !important;
border: 0 !important;
}

.mac-seamless-mode #write {
min-height: calc(100vh - 6em - 20px);
}

.typora-quick-open-item.active {
color: var(--active-file-text-color);
}

*.in-text-selection, ::selection {
background: var(--active-file-bg-color);
text-shadow: none;
color: white;
}

.btn-primary {
background-color: #2d2d2d;
border-color: #020202;
}

.btn-primary:hover, .btn-primary:focus, .btn-primary.focus, .btn-primary:active, .btn-primary.active, .open > .dropdown-toggle.btn-primary {
background-color: #4e4c4e;
border: #4e4c4e;
}

#preference-dialog .modal-content{
background: #6e757a;
--bg-color: #6e757a;
--text-color: #f1f1f1;
color: #f1f1f1;
}

#typora-source,
.typora-sourceview-on {
--bg-color: #eee;
background: #eee;
}

.cm-s-typora-default .cm-header, .cm-s-typora-default .cm-property {
color: #116098;
}

.cm-s-typora-default .cm-link {
color: #11987d;
}

.cm-s-typora-default .cm-em {
font-family: Georgia-Italic, STSongti-SC-Light, serif;
color: #6f6400;
}

.cm-s-typora-default .cm-em{
color: rgb(0, 22, 45);
}

.CodeMirror.cm-s-typora-default div.CodeMirror-cursor{
border-left: 3px solid #6e757a;
}

.cm-s-typora-default .CodeMirror-selectedtext,
.typora-sourceview-on .CodeMirror-focused .CodeMirror-selected {
background: #6e757a;
color: white;
}

.file-node-icon.fa.fa-folder:before {
color: rgba(32, 43, 51, 0.49);
}

#preference-dialog .megamenu-menu-panel h1 {
margin-bottom: 1em;
}

::-webkit-scrollbar-corner {
display: none;
background: transparent;
}

/*.file-node-icon.fa.fa-folder:before {
content: "\f114";
}

#typora-sidebar {

}*/

/*.cm-s-typora-default .cm-header, .cm-s-typora-default .cm-property {
color: #fffff1;
}

.cm-s-typora-default .cm-link {
color: #86f9e2;
color: #e5f7eb;
}

.cm-s-typora-default .cm-comment, .cm-s-typora-default .cm-code {
color: rgb(255, 199, 199);
}

.cm-s-typora-default .cm-atom, .cm-s-typora-default .cm-number {
color: #dec4c7;
}

.cm-s-typora-default .cm-em {
font-family: Georgia-Italic, STSongti-SC-Light, serif;
color: #f3ff7e;
}

.typora-sourceview-on .CodeMirror-cursor {
border-left: 3px solid #ffffd6;
}

.typora-sourceview-on #toggle-sourceview-btn {
background: #505050;
}

.typora-sourceview-on .cm-s-inner .cm-variable,
.typora-sourceview-on .cm-s-inner .cm-operator,
.typora-sourceview-on .cm-s-inner .cm-property {
color: #b8bfc6;
}

.typora-sourceview-on .cm-s-inner .cm-keyword {
color: #C88FD0;
}

.typora-sourceview-on .cm-s-inner .cm-tag {
color: #7DF46A;
}

.typora-sourceview-on .cm-s-inner .cm-attribute {
color: #7575E4;
}

.typora-sourceview-on .cm-s-inner .cm-string {
color: #D26B6B;
}

.typora-sourceview-on .cm-s-inner .cm-comment,
.typora-sourceview-on .cm-s-inner.cm-comment {
color: #DA924A;
}

.typora-sourceview-on .cm-s-inner .cm-header,
.typora-sourceview-on .cm-s-inner .cm-def,
.typora-sourceview-on .cm-s-inner.cm-header,
.typora-sourceview-on .cm-s-inner.cm-def {
color: #8d8df0;
}

.typora-sourceview-on .cm-s-inner .cm-quote,
.typora-sourceview-on .cm-s-inner.cm-quote {
color: #57ac57;
}

.typora-sourceview-on .cm-s-inner .cm-hr {
color: #d8d5d5;
}

.typora-sourceview-on .cm-s-inner .cm-link {
color: #d3d3ef;
}

.typora-sourceview-on .cm-s-inner .cm-negative {
color: #d95050;
}

.typora-sourceview-on .cm-s-inner .cm-positive {
color: #50e650;
}

.typora-sourceview-on .cm-s-inner .cm-string-2 {
color: #f50;
}

.typora-sourceview-on .cm-s-inner .cm-meta,
.typora-sourceview-on .cm-s-inner .cm-qualifier {
color: #b7b3b3;
}

.typora-sourceview-on .cm-s-inner .cm-builtin {
color: #f3b3f8;
}

.typora-sourceview-on .cm-s-inner .cm-bracket {
color: #997;
}

.typora-sourceview-on .cm-s-inner .cm-atom,
.typora-sourceview-on .cm-s-inner.cm-atom {
color: #84B6CB;
}

.typora-sourceview-on .cm-s-inner .cm-number {
color: #64AB8F;
}

.typora-sourceview-on .cm-s-inner .cm-variable {
color: #b8bfc6;
}

.typora-sourceview-on .cm-s-inner .cm-variable-2 {
color: #9FBAD5;
}

.typora-sourceview-on .cm-s-inner .cm-variable-3 {
color: #1cc685;
}

.typora-sourceview-on .CodeMirror div.CodeMirror-cursor {
border-left: 1px solid #b8bfc6;
z-index: 3;
}

.cm-s-typora-default .CodeMirror-selectedtext,
.typora-sourceview-on .CodeMirror-focused .CodeMirror-selected {
background: #212324;
}

.typora-sourceview-on .CodeMirror-linenumber {
color: rgb(255, 255, 255);
}*/

.typora-export li, .typora-export p, .typora-export, .footnote-line {white-space: normal;}
-->

1. 需求是这样的

一台机器上有两种不同类型的日志数据,且是按天存储的。目录结构是这样的:

 
 
 
 
 
 
 
 
--/data/log
  --/access_log
    --190101.txt
    --190102.txt
    ...
  --/click_log
    --190101.txt
    --190102.txt
    ... 
 
 

access_log每行是一个JSON字符串,长得像这样:

 
 
 
xxxxxxxxxx
 
 
 
 
{
    "url": "index", 
    "server": {
        ...
    }, 
    "timestamp": 1551369609, 
    "ip": "188.138.188.34", 
    "session_id": "l9tooea23s6mjlid1q01svmc80", 
    "method": "GET", 
    "request_id": "a7ce6bc3e6c39e65eb5d11c979956acf"
}
 
 

click_log每行也是一个JSON字符串,长得像这样:

 
 
 
xxxxxxxxxx
 
 
 
 
{
    "click_id": "474b927e12731128579b8100f4f8918b", 
    "click_obj": [
        ...
    ], 
    "data": {
        ...
    }
}
 
 

需求比较简单,提供一个可查功能就可以了:

  • 针对access_log,需要解析其中timestamp,方便按时间筛选日志;
  • access_log和click_log都需要解析JSON;

2. 调研与实施

在百度一搜,就是ELK,社区又比较火,索性就直接上吧。

2.1 搭建ES集群

比较简单,照着官网来即可,不想英文的,就百度吧,前人已经出了很多案例了。列几个比较好的参考吧: http://jiangew.me/es-deploy-proxy/ https://www.cnblogs.com/leeSmall/p/9189078.html https://www.cnblogs.com/leeSmall/p/9220535.html 我搭建的集群是6节点的,配置如下:

 
 
 
xxxxxxxxxx
 
 
 
 
cluster.name: myname
node.name: 192-168-0-106
node.master: false
node.data: false
path.data: /data/es/data
path.logs: /data/es/log
network.host: 192.168.0.106
http.port: 9200
discovery.zen.ping.unicast.hosts: ["192.168.0.106", "192.168.0.107", "192.168.0.108", "192.168.0.109", "192.168.0.110", "192.168.0.111"]
discovery.zen.minimum_master_nodes: 3
 
 
2.2 搭建kibana

直接用192.168.0.106那个节点,下包、解压、改配置,配置如下:

 
 
 
xxxxxxxxxx
 
 
 
 
server.host: "192.168.0.106"
elasticsearch.hosts: ["http://192.168.0.106:9200"]
 
 
2.3 搭建FileBeat

网上说logstash较重,FileBeat比较轻量,想想,我的需求这么简单就从了。 轻量是轻量,但搭建过程,对于新手来说,还是不容易,中间遇到了很多问题,弯路就不提了,只提两个重要的。

2.3.1 如何解析JSON

参考官网这一页:https://www.elastic.co/guide/en/beats/filebeat/6.6/filebeat-input-log.html 就这两行代码:

 
 
 
xxxxxxxxxx
 
 
 
 
filebeat.inputs:
- type: log
  paths:
    - /data/log/access_log/*   -- 日志路径
  json.keys_under_root: true   -- 把JSON中key移到根上(日志JSON只是beat上传数据的一项)
  json.add_error_key: true     -- 解析失败,把错误放出来
 
 
2.3.2 ES 的mapping设置与输出设置
 
 
 
xxxxxxxxxx
 
 
 
 
setup.template.fields: "access_fields.yml"
setup.template.pattern: "access*"
setup.template.name: "access"
output.elasticsearch:
  hosts: ["192.168.0.106:9200"]
  index: "access_%{[dissect.key4]}"
  pipeline: "log_pipeline"
processors:
  - add_host_metadata: ~
  - add_cloud_metadata: ~
  - dissect:
      tokenizer: "%{key1}/%{key2}/%{key3}/%{key4}"
      field: "source"
      target_prefix: "dissect"
 
 

A. 没有用默认的fields.yml,在里面加了一个log_time,且要定义成date类型,需要从数据中的timestamp解析出来,用的pipeline。在kibana上的dev tools功能中console,贴入这段代码,并执行。

 
 
 
xxxxxxxxxx
 
 
 
 
PUT _ingest/pipeline/log_pipeline
{
    "description": "log processor", 
    "processors": [
        {
            "date": {
                "field": "timestamp", 
                "target_field" : "log_time",
                "formats": [
                    "UNIX"
                ], 
                "timezone":"Asia/Shanghai",
                "on_failure": [
                    {
                        "set": {
                            "field": "date_processor_error", 
                            "value": "{{ _ingest.on_failure_message }}"
                        }
                    }
                ]
            }
        }
    ]
}
 
 

B. 由于每天的数据要单独建索引,而且只能从文件名中提取年月日,所以用了dissect processor。

2.3.2 一个filebeat发一类索引,还是发多类索引

我用的后者,不知道会不会有什么问题,从运行来看,没出什么错。

3. 总结

不得不说,ES的文档写得真详细,搭个demo非常快,但要用好,还是有很多值得探索的地方,抽空再研究一下吧。

一个ELK日志检索实施案例的更多相关文章

  1. ELK日志检索并邮件微信通知

    简介 脚本为通过api检索日志内容,并通过邮件或者微信发送出来. 脚本 index检索脚本 #!/usr/bin/env python # coding:utf-8 from elasticsearc ...

  2. ELK日志监控平台安装部署简介--Elasticsearch安装部署

    最近由于工作需要,需要搭建一个ELK日志监控平台,本次采用Filebeat(采集数据)+Elasticsearch(建立索引)+Kibana(展示)架构,实现日志搜索展示功能. 一.安装环境描述: 1 ...

  3. 创业公司做数据分析(四)ELK日志系统 (转)

    http://blog.csdn.net/zwgdft/article/details/53842574 作为系列文章的第四篇,本文将重点探讨数据采集层中的ELK日志系统.日志,指的是后台服务中产生的 ...

  4. ELK日志分析 学习笔记

    (贴一篇之前工作期间整理的elk学习笔记) ELK官网 https://www.elastic.co   ELK日志分析系统 学习笔记 概念:ELK = elasticsearch + logstas ...

  5. 创业公司做数据分析(四)ELK日志系统

      作为系列文章的第四篇.本文将重点探讨数据採集层中的ELK日志系统.日志.指的是后台服务中产生的log信息,一般会输入到不同的文件里.比方Django服务下,一般会有nginx日志和uWSGI日志. ...

  6. TKE 用户故事 - 作业帮 PB 级低成本日志检索服务

    作者 吕亚霖,2019年加入作业帮,作业帮架构研发负责人,在作业帮期间主导了云原生架构演进.推动实施容器化改造.服务治理.GO微服务框架.DevOps的落地实践. 莫仁鹏,2020年加入作业帮,作业帮 ...

  7. ELK 日志分析系统概述及部署

    ELK 日志分析系统概述及部署 1.ELK概述: ELK简介 : ELK平台是一套完整的日志集中处理解决方案,将 ElasticSearch.Logstash 和 Kiabana 三个开源工具配合使用 ...

  8. ELK日志分析系统搭建(转)

    摘要: 前段时间研究的Log4j+Kafka中,有人建议把Kafka收集到的日志存放于ES(ElasticSearch,一款基于Apache Lucene的开源分布式搜索引擎)中便于查找和分析,在研究 ...

  9. ELK 日志分析体系

    ELK   日志分析体系 ELK 是指 Elasticsearch.Logstash.Kibana三个开源软件的组合. logstash                       负责日志的收集,处 ...

随机推荐

  1. golang 变量定义

    package main import "fmt" var luckyNum = 6 var luckyStr = "love" //myNum := 6 // ...

  2. .NET Core微服务之基于Ocelot实现API网关服务

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.啥是API网关? API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口.这样就可以明显的简化客户端 ...

  3. Kubernetes知识小普及

    大部分概念Kubernetes官网都有详细介绍,Kubernetes中文官网 https://kubernetes.io/zh/docs/tutorials/kubernetes-basics/ 官网 ...

  4. Python实战171203统计

    统计序列中元素出现的频次 如何统计出某一个随机数列的元素出现的次数是多少? import randomdata=[random.randint(0,7) for _ in range(15)]c=di ...

  5. django-restframework 处理跨域问题

    django-restframework 处理跨域问题 一 前言 想要处理跨域问题,首先需要了解同源策略. 二 同源策略 同源策略(Same origin policy)是一种约定,它是浏览器最核心也 ...

  6. 杭电ACM2020--绝对值排序

    输入n(n<=100)个整数,按照绝对值从大到小排序后输出.题目保证对于每一个测试实例,所有的数的绝对值都不相等.   Input 输入数据有多组,每组占一行,每行的第一个数字为n,接着是n个整 ...

  7. MVC开发模式简述

    了解MVC开发模式,首先我们要了解一下发展趋势 一.什么是软件设计 Jack W.Reeves 于14年前(1992年),就在其撰写的论文——<What is Software Design&g ...

  8. 关于jQuery中的选择器

    1:选择器的作用 获取网页的上面的标签元素等等,然后对他进行一些列的操作(添加样式,添加行为...) 2:选择器有哪些 基本选择器,层次选择器,过滤选择器,表单选择器 一:基本选择器 基本选择器是jq ...

  9. mysql命令查看表结构及注释

    使用如下命令:select table_schema,table_name,column_name,column_type,column_key,is_nullable,column_default, ...

  10. 第五章:shiro密码加密

    在涉及到密码存储问题上,应该加密/生成密码摘要存储,而不是存储明文密码.比如之前的600w csdn账号泄露对用户可能造成很大损失,因此应加密/生成不可逆的摘要方式存储. 5.1 编码/解码 Shir ...