-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
549 lines (329 loc) · 149 KB
/
atom.xml
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Renqiang</title>
<icon>https://www.gravatar.com/avatar/80b72ea0d3710afada9d5b05e6477caa</icon>
<subtitle>码码工</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="https://renqiangme.github.io/"/>
<updated>2019-04-27T02:25:09.841Z</updated>
<id>https://renqiangme.github.io/</id>
<author>
<name>Renqiang</name>
<email>[email protected]</email>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>Mac下IDEA部分快捷键</title>
<link href="https://renqiangme.github.io/2019/04/27/Mac%E4%B8%8BIDEA%E9%83%A8%E5%88%86%E5%BF%AB%E6%8D%B7%E9%94%AE/"/>
<id>https://renqiangme.github.io/2019/04/27/Mac下IDEA部分快捷键/</id>
<published>2019-04-27T02:17:05.000Z</published>
<updated>2019-04-27T02:25:09.841Z</updated>
<content type="html"><![CDATA[<h2 id="编辑"><a href="#编辑" class="headerlink" title="编辑"></a>编辑</h2><ul><li><p>⌥↩︎ ,option键+Enter键,自动导入类,每按一次自动导入一个类,需要结合F2来自动跳动到没有导入该类的那一行,如何有多个类会弹出框供选择。</p></li><li><p>⌘P ,command键+P,显示方法的参数信息</p></li><li><p>⌃J ,control键+J,快速查看当前所选类、方法的文档</p></li><li><p>⌘N, command键+N,弹出生成代码(getter、setter、构造函数、hashCode/equals,toString)</p></li><li><p>⌃O ,control键+O,覆盖方法(重写父类方法)</p></li><li><p>⌃I ,control键+I,实现方法(实现接口中的方法)</p></li><li><p>⌘⌥T ,command键+option键+T,包围代码(使用if..else, try..catch, for, synchronized等包围选中的代码)</p></li><li><p>⌘/ ,command键+/,注释/取消注释与行注释</p></li><li><p>⌘⌥/ ,command键+option键+/,注释/取消注释与块注释</p></li><li><p>⌥↑ ,option键+上箭头键,连续选中代码块</p></li><li><p>⌥↓ ,option键+下箭头键,减少当前选中的代码块</p></li><li><p>⇥ / ⇧⇥ ,按右制表符缩进代码 / shift+右制表符反缩进代码</p></li><li><p>⌘⌥L ,command键+option键+L,格式化代码</p></li><li><p>⌃⌥O ,control键+option键+O,优化import,比如属于同一个包的引入进来的类不是挨着的,使用这个优化之后会让他们挨着一起。</p></li><li><p>⌘X ,command键+X,剪切当前行或选定的块到剪贴板</p></li><li><p>⌘C ,command键+C,复制当前行或选定的块到剪贴板</p></li><li><p>⌘V ,command键+V,从剪贴板粘贴</p></li><li><p>⌘⇧V ,command键+shift键+V,从最近的缓冲区粘贴</p></li><li><p>⌘D ,command键+D,复制当前行或选定的块</p></li><li><p>⌘⌫ ,command键+删除键,删除当前行或选定的块的行</p></li><li><p>⇧↩ ,shift键+回车键,开始新的一行</p></li><li><p>⌘+ / ⌘- ,command键 + +键,展开 / ,command键 + -键,折叠代码块</p></li><li><p>⌘⇧+ ,command键 + shift + +键,展开所以代码块</p></li><li><p>⌘⇧- ,command键 + shift + -键,折叠所有代码块</p></li></ul><h2 id="查询-替换"><a href="#查询-替换" class="headerlink" title="查询/替换"></a>查询/替换</h2><ul><li><p>⌘F ,command键 + F,在文件内查找,比如搜索hello,在当前文件中找到了五个hello,可以通过上下方向箭头来向上或向下。</p></li><li><p>⌘R ,command键 + R,在文件内替换。</p></li><li><p>⌘⇧F ,command键 + shift + F,全局查找</p></li><li><p>⌘⇧R ,command键 + shift + R,全局替换</p></li></ul><h2 id="编译和运行"><a href="#编译和运行" class="headerlink" title="编译和运行"></a>编译和运行</h2><ul><li><p>⌃⌥R ,control键 + option键+ R,弹出 Run 的可选择菜单</p></li><li><p>⌃⌥D ,control键 + option键+ D,弹出 Debug 的可选择菜单</p></li><li><p>⌃R ,control键 + R,运行</p></li><li><p>⌃D ,control键 + D,运行调试</p></li></ul><h2 id="Debug调试"><a href="#Debug调试" class="headerlink" title="Debug调试"></a>Debug调试</h2><ul><li><p>F8 进入下一步,如果当前行断点是一个方法,则不进入当前方法体内。</p></li><li><p>F7 进入下一步,如果当前行断点是一个方法,则进入当前方法体内,如果该方法体还有方法,则不会进入该内嵌的方法中。</p></li><li><p>⇧F7 ,shift键 + F7,智能步入,断点所在行上有多个方法调用,会弹出进入哪个方法。</p></li><li><p>⇧F8 ,shift键 + F8,跳出</p></li><li><p>⌥F9 ,option键 + F9,运行到光标处,如果光标前有其他断点会进入到该断点</p></li><li><p>⌥F8 ,option键 + F8,计算表达式(可以更改变量值使其生效)</p></li><li><p>⌘⌥R ,command键+option键 + R,恢复程序运行,如果该断点下面代码还有断点则停在下一个断点上</p></li><li><p>⌘F8 ,command键+ F8,切换断点(若光标当前行有断点则取消断点,没有则加上断点) </p></li><li><p>⌘⇧F8 ,command键 + shift键 + F8,查看断点信息</p></li></ul><h2 id="Navigation(导航)"><a href="#Navigation(导航)" class="headerlink" title="Navigation(导航)"></a>Navigation(导航)</h2><ul><li><p>⌘O ,command键 + 字母o,查找类文件</p></li><li><p>⌘⇧O ,command键 +shift键+ 字母o,查找所有类型文件、打开文件、打开目录,打开目录需要在输入的内容前面或后面加一个反斜杠/</p></li><li><p>⌘⌥O ,command键 + option键+ 字母o,前往指定的变量或方法</p></li><li><p>⌘L 在当前文件跳转到某一行的指定处,会弹出一个框来输入行号,跟vim里面的<code>:xxline</code>作用一样。</p></li><li><p>⌘F12 ,command键 + F12,弹出当前文件结构层,可以在弹出的层上直接输入进行筛选(可用于搜索类中的方法)</p></li><li><p>⌃H ,command键 + H,显示当前类的层次结构</p></li><li><p>⌘⇧H ,command键 +shift+ H,显示方法层次结构</p></li><li><p>⌃⌥H ,command键 +option+ H,显示调用层次结构</p></li></ul><h2 id="Refactor重构"><a href="#Refactor重构" class="headerlink" title="Refactor重构"></a>Refactor重构</h2><ul><li><p>F5 复制文件到指定目录</p></li><li><p>F6 移动文件到指定目录</p></li><li><p>⇧F6 ,shift键+ F6,选择当前文件类名,会弹出重命名文件</p></li></ul><h2 id="General通用"><a href="#General通用" class="headerlink" title="General通用"></a>General通用</h2><ul><li><p>⌘1…⌘9 ,command键+ 1…9,打开相应编号的工具窗口</p></li><li><p>⌃⌘F ,control键+command键+F,切换全屏模式</p></li><li><p>⌘, ,command键+, 打开IDEA系统设置</p></li><li><p>⌘; ,command键+; 打开项目结构对话框</p></li></ul>]]></content>
<summary type="html">
<h2 id="编辑"><a href="#编辑" class="headerlink" title="编辑"></a>编辑</h2><ul>
<li><p>⌥↩︎ ,option键+Enter键,自动导入类,每按一次自动导入一个类,需要结合F2来自动跳动到没有导入该类的那一行,
</summary>
<category term="开发工具" scheme="https://renqiangme.github.io/categories/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
<category term="IDEA" scheme="https://renqiangme.github.io/tags/IDEA/"/>
</entry>
<entry>
<title>kubernetes的kubeconfig配置文件及contexts切换</title>
<link href="https://renqiangme.github.io/2019/04/24/kubernetes%E7%9A%84kubeconfig%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E5%8F%8Acontexts%E5%88%87%E6%8D%A2/"/>
<id>https://renqiangme.github.io/2019/04/24/kubernetes的kubeconfig配置文件及contexts切换/</id>
<published>2019-04-24T04:18:19.000Z</published>
<updated>2019-04-24T04:20:34.712Z</updated>
<content type="html"><![CDATA[<h2 id="Kubeconfig"><a href="#Kubeconfig" class="headerlink" title="Kubeconfig"></a>Kubeconfig</h2><p>Kubernetes的kubeconfig配置文件用于使用<code>kubectl CLI</code>,并允许您通过kubeconfig配置文件远程连接,控制群集。kubeconfig配置文件是存储在每个群集的<code>kubectl-configs</code>中。</p><h3 id="基本用法"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法</h3><p>要将<code>kubectl</code>与没有任何配置的集群一起使用,只需使用<code>--kubeconfig</code>选项。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">kubectl --kubeconfig kubectl-configs/<config-file> get pods</div></pre></td></tr></table></figure><h3 id="高级用法"><a href="#高级用法" class="headerlink" title="高级用法"></a>高级用法</h3><p>为每个命令手动指定配置文件可能会有的麻烦。</p><p>可以将<code>KUBECONFIG</code>环境变量设置为以下格式的配置文件列表:<code>config-1:config-2:config-3</code></p><p>现在,所有文件都已合并,您可以通过上下文在它们之间切换。 例如:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line"># 显示当前使用的context</div><div class="line">kubectl config current-context</div><div class="line"></div><div class="line"># 比如切换到使用aliyun-k8s,就会本地kubectl cli连接到aliyun-k8s集群</div><div class="line">kubectl config use-context aliyun-k8s</div><div class="line"></div><div class="line"># 显示aliyun-k8s集群的pods</div><div class="line">kubectl get pods</div></pre></td></tr></table></figure></p><p>更多命令可以通过<code>kubectl config --help</code> 查看。</p><p>通常情况下,我们本地开发机器会搭建kubernets,同时本地的测试机器环境也会搭建kubernets,线上也会搭建很多个kubernets集群环境。</p><p>因为kubernets去读取context的时候,如果设置了全局环境变量<code>KUBECONFIG</code>,他就会优先使用这个全局环境变量对应的配置文件,如果没有设置就会去找<code>$HOME/.kube/config</code> 这个配置文件。</p><p>如果需要在本地管理连接这些kubernets,那么可以把对应的kubernets的配置文件:<code>$HOME/.kube/config</code> 导出来,下载导本地,再跟本地的配置文件合并。</p><p>以本地测试机器为例子:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line">#登录到测试机器,导出配置文件</div><div class="line">kubectl config view --raw > office-test.conf</div><div class="line"></div><div class="line"># 下载office-test.conf到本地电脑,然后修改环境变量配置文件,比如:vim ~/.bash_profile</div><div class="line"></div><div class="line">export KUBECONFIG=/Users/xx/.kube/office-test.conf:/Users/xx/.kube/config</div><div class="line"></div><div class="line"># 更新环境变量文件</div><div class="line"></div><div class="line">source ~/.bash_profile</div><div class="line"></div><div class="line"># 新开一个命令行终端,执行导入合并文件</div><div class="line">kubectl config view --raw > combined.conf</div><div class="line"></div><div class="line"># 注释掉KUBECONFIG这个环境变量并source更新,然后再把combined.conf复制到$HOME/.kube/config`</div><div class="line"></div><div class="line">#可以看到最新的合并了的contexts</div><div class="line">kubectl config get-contexts</div><div class="line"></div><div class="line">#切换context为 office-test</div><div class="line"></div><div class="line">kubectl config set-context office-test</div><div class="line"></div><div class="line">#获取对应的pods,校验是否切换连接成功</div><div class="line">kubectl get pods</div></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<h2 id="Kubeconfig"><a href="#Kubeconfig" class="headerlink" title="Kubeconfig"></a>Kubeconfig</h2><p>Kubernetes的kubeconfig配置文件用于使用<code>kub
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Kubernetes" scheme="https://renqiangme.github.io/tags/Kubernetes/"/>
<category term="k8s" scheme="https://renqiangme.github.io/tags/k8s/"/>
</entry>
<entry>
<title>安装kubernetes-dashboard</title>
<link href="https://renqiangme.github.io/2019/04/24/%E5%AE%89%E8%A3%85kubernetes-dashboard/"/>
<id>https://renqiangme.github.io/2019/04/24/安装kubernetes-dashboard/</id>
<published>2019-04-24T04:15:23.000Z</published>
<updated>2019-04-24T04:20:54.133Z</updated>
<content type="html"><![CDATA[<h2 id="kubernetes-Dashboard"><a href="#kubernetes-Dashboard" class="headerlink" title="kubernetes Dashboard"></a>kubernetes Dashboard</h2><p>作为Kubernetes的Web用户界面,用户可以通过Dashboard在Kubernetes集群中部署容器化的应用,对应用进行问题处理和管理,并对集群本身进行管理。通过Dashboard,用户可以查看集群中应用的运行情况,同时也能够基于Dashboard创建或修改部署、任务、服务等Kubernetes的资源。通过部署向导,用户能够对部署进行扩缩容,进行滚动更新、重启Pod和部署新应用。当然,通过Dashboard也能够查看Kubernetes资源的状态。</p><p>Kubernetes Dashboard <a href="https://github.com/kubernetes/dashboard" target="_blank" rel="external">Github地址</a></p><h3 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml</div></pre></td></tr></table></figure><p>安装部署成功之后执行:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">kubectl proxy</div></pre></td></tr></table></figure><p>打开<a href="http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login" target="_blank" rel="external">:http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login</a><br>就可以通过UI来管理了。</p><h3 id="kubernetes-Dashboard访问权限问题"><a href="#kubernetes-Dashboard访问权限问题" class="headerlink" title="kubernetes Dashboard访问权限问题"></a>kubernetes Dashboard访问权限问题</h3><p>现在新版的kubernetes Dashboard似乎都没有了跳过这个button.</p><p><img src="https://note.youdao.com/yws/public/resource/d48e73f7c3726b842a8ccc4f0166348f/xmlnote/544F88A12CE744E0B1CD5B5807446A46/4154" alt="image"></p><p>点击跳过进入dashboard 使用的是默认的 kubernetes-dashboard 角色,比如Azure的AKS就是直接没有登录界面,直接进入主页。可能有很多黄色警告:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">configmaps is forbidden: User "system:serviceaccount:kube-system:kubernetes-dashboard" cannot list configmaps in the namespace "default"</div><div class="line"></div><div class="line">persistentvolumeclaims is forbidden: User "system:serviceaccount:kube-system:kubernetes-dashboard" cannot list persistentvolumeclaims in the namespace "default"</div><div class="line"></div><div class="line">secrets is forbidden: User "system:serviceaccount:kube-system:kubernetes-dashboard" cannot list secrets in the namespace "default"</div><div class="line"></div><div class="line">services is forbidden: User "system:serviceaccount:kube-system:kubernetes-dashboard" cannot list services in the namespace "default"</div><div class="line">....</div></pre></td></tr></table></figure></p><p>说明 kubernetes-dashboard权限不足。</p><h4 id="法一:创建一个管理员权限的用户,生成Token访问dashboard"><a href="#法一:创建一个管理员权限的用户,生成Token访问dashboard" class="headerlink" title="法一:创建一个管理员权限的用户,生成Token访问dashboard"></a>法一:创建一个管理员权限的用户,生成Token访问dashboard</h4><p>参考自:<a href="https://github.com/kubernetes/dashboard/wiki/Creating-sample-user" target="_blank" rel="external">Creating-sample-user</a></p><h5 id="创建一个管理员Service-Account文件"><a href="#创建一个管理员Service-Account文件" class="headerlink" title="创建一个管理员Service Account文件"></a>创建一个管理员Service Account文件</h5><p>在本地创建一个dashboard-adminuser.yaml,内容是:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line">apiVersion: v1</div><div class="line">kind: ServiceAccount</div><div class="line">metadata:</div><div class="line"> name: admin-user</div><div class="line"> namespace: kube-system</div><div class="line">---</div><div class="line">apiVersion: rbac.authorization.k8s.io/v1</div><div class="line">kind: ClusterRoleBinding</div><div class="line">metadata:</div><div class="line"> name: admin-user</div><div class="line">roleRef:</div><div class="line"> apiGroup: rbac.authorization.k8s.io</div><div class="line"> kind: ClusterRole</div><div class="line"> name: cluster-admin</div><div class="line">subjects:</div><div class="line">- kind: ServiceAccount</div><div class="line"> name: admin-user</div><div class="line"> namespace: kube-system</div></pre></td></tr></table></figure><p>然后执行:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">kubectl apply -f dashboard-adminuser.yaml</div></pre></td></tr></table></figure><h5 id="生成Bearer-Token"><a href="#生成Bearer-Token" class="headerlink" title="生成Bearer Token"></a>生成Bearer Token</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')</div></pre></td></tr></table></figure><p>然后复制粘贴token,就能进入kubernetes Dashboard的管理界面了。</p><h5 id="查看所有的ServiceAccount"><a href="#查看所有的ServiceAccount" class="headerlink" title="查看所有的ServiceAccount"></a>查看所有的ServiceAccount</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">kubectl get serviceaccount --all-namespaces</div></pre></td></tr></table></figure><h4 id="法二:也可以把kubernetes-dashboard-用户的权限绑定成-admin-的权限"><a href="#法二:也可以把kubernetes-dashboard-用户的权限绑定成-admin-的权限" class="headerlink" title="法二:也可以把kubernetes-dashboard 用户的权限绑定成 admin 的权限"></a>法二:也可以把kubernetes-dashboard 用户的权限绑定成 admin 的权限</h4><p>直接执行下面命令:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">kubectl create clusterrolebinding kubernetes-dashboard -n kube-system --clusterrole=cluster-admin --serviceaccount=kube-system:kubernetes-dashboard</div></pre></td></tr></table></figure></p><p>或者创建一个文件然后再create:</p><p><code>vi kube-dashboard-access.yaml</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">apiVersion: rbac.authorization.k8s.io/v1</div><div class="line">kind: ClusterRoleBinding</div><div class="line">metadata:</div><div class="line"> name: kubernetes-dashboard</div><div class="line"> labels:</div><div class="line"> k8s-app: kubernetes-dashboard</div><div class="line">roleRef:</div><div class="line"> apiGroup: rbac.authorization.k8s.io</div><div class="line"> kind: ClusterRole</div><div class="line"> name: cluster-admin</div><div class="line">subjects:</div><div class="line">- kind: ServiceAccount</div><div class="line"> name: kubernetes-dashboard</div><div class="line"> namespace: kube-system</div></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">kubectl create -f kube-dashboard-access.yaml</div></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="kubernetes-Dashboard"><a href="#kubernetes-Dashboard" class="headerlink" title="kubernetes Dashboard"></a>kubernetes Dashboard</h2><
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Kubernetes" scheme="https://renqiangme.github.io/tags/Kubernetes/"/>
<category term="k8s" scheme="https://renqiangme.github.io/tags/k8s/"/>
<category term="kubernetes-dashboard" scheme="https://renqiangme.github.io/tags/kubernetes-dashboard/"/>
</entry>
<entry>
<title>kubernetes简单安装笔记</title>
<link href="https://renqiangme.github.io/2019/04/24/kubernetes%E7%AE%80%E5%8D%95%E5%AE%89%E8%A3%85%E7%AC%94%E8%AE%B0/"/>
<id>https://renqiangme.github.io/2019/04/24/kubernetes简单安装笔记/</id>
<published>2019-04-24T04:13:48.000Z</published>
<updated>2019-04-24T04:20:28.422Z</updated>
<content type="html"><![CDATA[<h2 id="安装Kubernetes"><a href="#安装Kubernetes" class="headerlink" title="安装Kubernetes"></a>安装Kubernetes</h2><h3 id="线上的云环境"><a href="#线上的云环境" class="headerlink" title="线上的云环境"></a>线上的云环境</h3><p>我们可以使用云平台的Kubernetes Service来管理部署我们的服务。</p><h3 id="本地开发测试环境:"><a href="#本地开发测试环境:" class="headerlink" title="本地开发测试环境:"></a>本地开发测试环境:</h3><h4 id="Linux系统(单个节点Kubernetes)"><a href="#Linux系统(单个节点Kubernetes)" class="headerlink" title="Linux系统(单个节点Kubernetes)"></a>Linux系统(单个节点Kubernetes)</h4><p>可以通过 microk8s可以非常快速的搭建起一个 Kubernetes 单机环境,安装极其非常方便。<br>ubuntu 自带 snap 命令,可以直接执行,centos 需要先安装 snap。</p><h5 id="centos安装-snap"><a href="#centos安装-snap" class="headerlink" title="centos安装 snap"></a>centos安装 snap</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">yum copr enable ngompa/snapcore-el7</div><div class="line">yum -y install snapd</div><div class="line">yum copr enable ngompa/snapcore-el7</div><div class="line">yum install epel-release</div><div class="line">yum install yum-plugin-copr</div><div class="line">yum copr enable ngompa/snapcore-el7</div><div class="line">yum -y install snapd</div><div class="line">systemctl enable --now snapd.socket</div><div class="line">ln -s /var/lib/snapd/snap /snap</div></pre></td></tr></table></figure><h5 id="snap安装Kubernetes"><a href="#snap安装Kubernetes" class="headerlink" title="snap安装Kubernetes"></a>snap安装Kubernetes</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">snap install microk8s --classic</div><div class="line"></div><div class="line">#开启 DNS 服务</div><div class="line">microk8s.enable dns dashboard</div></pre></td></tr></table></figure><h5 id="microk8s-常用操作"><a href="#microk8s-常用操作" class="headerlink" title="microk8s 常用操作"></a>microk8s 常用操作</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line"># 1. 启动 </div><div class="line">microk8s.start</div><div class="line"></div><div class="line"># 2. 关闭</div><div class="line">microk8s.stop</div><div class="line"></div><div class="line"># 3. 状态</div><div class="line">microk8s.status</div><div class="line"></div><div class="line"># 4. kubectl 操作</div><div class="line"></div><div class="line"># 查看 cluster</div><div class="line">microk8s.kubectl cluster-info</div><div class="line"></div><div class="line"># 查看 nodes</div><div class="line">microk8s.kubectl get nodes</div><div class="line"></div><div class="line"># 查看 pods</div><div class="line">microk8s.kubectl get pods</div><div class="line"></div><div class="line"># docker 操作</div><div class="line">microk8s.docker ps</div><div class="line">microk8s.docker images</div></pre></td></tr></table></figure><h5 id="为microk8s-kubectl取别名"><a href="#为microk8s-kubectl取别名" class="headerlink" title="为microk8s.kubectl取别名"></a>为microk8s.kubectl取别名</h5><p>可以看到,在 microk8s 环境中执行 kubectl 时,需要在 kubectl 命令前添加前缀 microk8s.。为了跟其他系统环境统一我们可以取个别名<code>kubectl</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">snap alias microk8s.kubectl kubectl</div></pre></td></tr></table></figure><h5 id="查看节点和集群信息"><a href="#查看节点和集群信息" class="headerlink" title="查看节点和集群信息"></a>查看节点和集群信息</h5><p>使用 <code>kubectl get -h</code> 可以看到更多关于<code>kubectl get</code>的用法,下面列举查看用得比较多的指令:</p><ul><li>查看node信息: <code>kubectl get nodes</code></li><li>查看services信息: <code>kubectl get services</code></li><li>查看deployment信息: <code>kubectl get deployments</code></li><li>查看pod信息: <code>kubectl get pods</code></li></ul><p>执行<code>kubectl get nodes</code>可以看到只会有1个master节点。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">$ kubectl get nodes</div><div class="line"></div><div class="line">NAME STATUS ROLES AGE VERSION</div><div class="line">docker-for-desktop Ready master 1d v1.10.11</div><div class="line"></div><div class="line">$ kubectl get services</div><div class="line">NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE</div><div class="line">kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d</div><div class="line"></div><div class="line">$ kubectl get deployments</div><div class="line">No resources found.</div><div class="line">$ kubectl get pods</div><div class="line">No resources found.</div></pre></td></tr></table></figure></p><p>因为是本地运行minikube,所以只会有一个主节点,这个以后也不会改变,默认会有一个名为kubernetes的服务,注意其类型是 ClusterIP ,只能从集群内部访问,且其访问端口为443,而真正的部署和pod(类似于容器)现在都还是空的.</p><h4 id="Linux系统(多个节点Kubernetes)"><a href="#Linux系统(多个节点Kubernetes)" class="headerlink" title="Linux系统(多个节点Kubernetes)"></a>Linux系统(多个节点Kubernetes)</h4><p>我们也可以使用<a href="https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/" target="_blank" rel="external">kubeadm</a> 来安装k8s集群,可以参照官方文档一步一步安装。</p><p>安装完成之后,多个节点,执行<code>kubectl get nodes</code>可以看到会有多个节点。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">$ kubectl get nodes</div><div class="line"></div><div class="line">NAME STATUS ROLES AGE VERSION</div><div class="line">k8s-2-master-01 Ready master 34d v1.13.4</div><div class="line">k8s-2-node-02 Ready <none> 34d v1.13.4</div><div class="line">k8s-2-node-03 Ready <none> 34d v1.13.4</div><div class="line">k8s-2-node-04 Ready <none> 33d v1.13.4</div></pre></td></tr></table></figure><h4 id="Mac-windows系统"><a href="#Mac-windows系统" class="headerlink" title="Mac / windows系统"></a>Mac / windows系统</h4><p>可以使用<a href="https://kubernetes.io/docs/setup/minikube/" target="_blank" rel="external">Minikube</a>,最新版的docker for mac已经自带了。<br>界面可视化安装,就不写步骤了。</p>]]></content>
<summary type="html">
<h2 id="安装Kubernetes"><a href="#安装Kubernetes" class="headerlink" title="安装Kubernetes"></a>安装Kubernetes</h2><h3 id="线上的云环境"><a href="#线上的云环境"
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Kubernetes" scheme="https://renqiangme.github.io/tags/Kubernetes/"/>
<category term="k8s" scheme="https://renqiangme.github.io/tags/k8s/"/>
</entry>
<entry>
<title>Linux设置Swap交换分区</title>
<link href="https://renqiangme.github.io/2018/08/21/Linux%E8%AE%BE%E7%BD%AESwap%E4%BA%A4%E6%8D%A2%E5%88%86%E5%8C%BA/"/>
<id>https://renqiangme.github.io/2018/08/21/Linux设置Swap交换分区/</id>
<published>2018-08-21T05:12:51.000Z</published>
<updated>2019-03-18T04:49:17.638Z</updated>
<content type="html"><![CDATA[<p>有时,服务器上面程序跑多了,受限于内存不够,会出现程序被kill掉或者起不来的情况。</p><p>这个时候我们可以设置下Swap(交换分区)。Swap(交换分区),类似于 Windows 的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。</p><a id="more"></a><h5 id="1-检查-Swap-空间"><a href="#1-检查-Swap-空间" class="headerlink" title="1.检查 Swap 空间"></a>1.检查 Swap 空间</h5><p>在设置 Swap 文件之前,有必要先检查一下系统里有没有既存的 Swap 文件。</p><p>运行命令:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">swapon -s</div></pre></td></tr></table></figure></p><p>如果返回的信息概要是空的,则表示 Swap 文件不存在。</p><p>然后我们还需要检查下需要把Swap(交换分区)设置的那个目录所在的磁盘是否还有剩余空间,可以使用:<code>df -lh</code></p><h5 id="2-创建-Swap-文件"><a href="#2-创建-Swap-文件" class="headerlink" title="2.创建 Swap 文件"></a>2.创建 Swap 文件</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">dd if=/dev/zero of=/tmp/swapfile bs=1024 count=1024k</div></pre></td></tr></table></figure><p>这样就建立一个/tmp/swapfile的分区文件,大小为1G。</p><p>参数解读:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">if=文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file ></div><div class="line">of=文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file ></div><div class="line">bs=bytes:同时设置读入/输出的块大小为bytes个字节</div><div class="line">count=blocks:仅拷贝blocks个块,块大小等于bs指定的字节数。</div></pre></td></tr></table></figure></p><h5 id="3-格式化并激活-Swap-文件"><a href="#3-格式化并激活-Swap-文件" class="headerlink" title="3.格式化并激活 Swap 文件"></a>3.格式化并激活 Swap 文件</h5><p>创建好 Swap 文件,还需要格式化后才能使用。运行命令:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mkswap /tmp/swapfile</div></pre></td></tr></table></figure><p>激活 Swap ,运行命令:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">swapon /tmp/swapfile</div></pre></td></tr></table></figure></p><p>如果以上在空间足够的情况下,应该就成功了,可以运行命令:<code>swapon -s</code> 或者 <code>free -m</code> 检查下。</p><p>如果要机器重启的时候自动挂载 Swap ,那么还需要修改 fstab 配置。</p><p>用 vim 打开 /etc/fstab 文件,在其最后添加如下一行:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">/tmp/swapfile swap swap defaults 0 0</div></pre></td></tr></table></figure></p><p>赋予 Swap 文件适当的权限:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">chown root:root /tmp/swapfile </div><div class="line">chmod 600 /tmp/swapfile</div></pre></td></tr></table></figure></p><h5 id="4-修改swappiness"><a href="#4-修改swappiness" class="headerlink" title="4.修改swappiness"></a>4.修改swappiness</h5><p>同时,我们还可以修改 Linux Swap 空间的 swappiness ,调整对硬盘的缓存。</p><p>Linux会使用硬盘的一部分做为 Swap 分区,用来进行进程调度–进程是正在运行的程序–把当前不用的进程调成等待(standby),甚至睡眠(sleep),一旦要用,再调成活动(active),睡眠的进程就会在 Swap 分区,把内存空出来让给活动的进程。</p><p>如果内存够大,应当告诉 Linux 不必太多的使用 Swap 分区,可以通过修改 swappiness 的参数来设置。swappiness=0 的时候表示最大限度使用物理内存,然后才是 Swap 空间,swappiness=100 的时候表示积极的使用 Swap 分区,并且把内存上的数据及时的搬运到 Swap 空间里面。</p><p>一般swappiness 的默认值是60。</p><p>通过以下命令可以查看swappiness的值:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">cat /proc/sys/vm/swappiness</div></pre></td></tr></table></figure></p><p>使用 sysctl 临时性的修改,重启系统会恢复成系统默认,命令:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sysctl vm.swappiness=10</div></pre></td></tr></table></figure></p><p>永久设置,还需要<code>vi /etc/sysctl.conf</code>,在这个文档的最后加上这样一行:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">vm.swappiness=10 #可以是其他值,:wq保存后Swap分区在系统重启后都会生效了</div></pre></td></tr></table></figure></p><h5 id="其他,删除某swap分区"><a href="#其他,删除某swap分区" class="headerlink" title="其他,删除某swap分区"></a>其他,删除某swap分区</h5><p>a.先停止正在使用swap分区:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">swapoff /tmp/swapfile</div></pre></td></tr></table></figure></p><p>b. 删除swap分区文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">rm -rf /tmp/swapfile</div></pre></td></tr></table></figure></p><p>c.删除掉我们之前在fstab文件里追加的开机自动挂载配置内容:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">/tmp/swapfile swap swap defaults 0 0</div></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<p>有时,服务器上面程序跑多了,受限于内存不够,会出现程序被kill掉或者起不来的情况。</p>
<p>这个时候我们可以设置下Swap(交换分区)。Swap(交换分区),类似于 Windows 的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。</p>
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Linux" scheme="https://renqiangme.github.io/tags/Linux/"/>
<category term="Swap" scheme="https://renqiangme.github.io/tags/Swap/"/>
</entry>
<entry>
<title>给MongoDB新增一个readWriteAnyDatabase的角色账户</title>
<link href="https://renqiangme.github.io/2018/05/01/%E7%BB%99MongoDB%E6%96%B0%E5%A2%9E%E4%B8%80%E4%B8%AAreadWriteAnyDatabase%E7%9A%84%E8%A7%92%E8%89%B2%E8%B4%A6%E6%88%B7/"/>
<id>https://renqiangme.github.io/2018/05/01/给MongoDB新增一个readWriteAnyDatabase的角色账户/</id>
<published>2018-05-01T09:18:01.000Z</published>
<updated>2019-03-18T04:48:54.833Z</updated>
<content type="html"><![CDATA[<p>安装好MongoDB时,通常开了一个最高管理权限的root账户来方便我们管理数据库,实际开发中并一般不使用这个账户,我们可以单独添加一个账户来连接数据库。</p><a id="more"></a><h5 id="MongoDB的账户角色:"><a href="#MongoDB的账户角色:" class="headerlink" title="MongoDB的账户角色:"></a>MongoDB的账户角色:</h5><p>数据库用户角色:read、readWrite</p><p>数据库管理角色:dbAdmin、dbOwner、userAdmin</p><p>集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManage</p><p>备份恢复角色:backup、restore</p><p>所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase</p><p>超级用户角色:root</p><p>内部角色:__system</p><p><code>Read</code>:允许用户读取指定数据库</p><p><code>readWrite</code>:允许用户读写指定数据库</p><p><code>dbAdmin</code>:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile</p><p><code>userAdmin</code>:允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户</p><p><code>clusterAdmin</code>:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。</p><p><code>readAnyDatabase</code>:只在admin数据库中可用,赋予用户所有数据库的读权限</p><p><code>readWriteAnyDatabase</code>:只在admin数据库中可用,赋予用户所有数据库的读写权限</p><p><code>userAdminAnyDatabase</code>:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限</p><p><code>dbAdminAnyDatabase</code>:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。</p><p><code>root</code>:只在admin数据库中可用。超级账号,超级权限</p><h5 id="新增一个readWriteAnyDatabase的角色账户"><a href="#新增一个readWriteAnyDatabase的角色账户" class="headerlink" title="新增一个readWriteAnyDatabase的角色账户"></a>新增一个readWriteAnyDatabase的角色账户</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line">#以root登录(这个root的角色是userAdminAnyDatabase)</div><div class="line">./mongo --port 27017 -u "root" -p "xxx" --authenticationDatabase "admin" </div><div class="line"></div><div class="line">#切换到admin db</div><div class="line">use admin</div><div class="line"></div><div class="line">#查看所有用户</div><div class="line">db.system.users.find()</div><div class="line"></div><div class="line">#新增用户,并授予readWriteAnyDatabase的角色</div><div class="line">db.createUser({user:"mongodb-admin",pwd:"123456",roles:[{role:"readWriteAnyDatabase", db:"admin"}]})</div><div class="line"></div><div class="line">#新增xxxx角色</div><div class="line">#db.grantRolesToUser("mongodb-admin",[{role:"xxx",db:"admin"}])</div><div class="line"></div><div class="line">#以mongodb-admin登录</div><div class="line">mongo --port 27017 -u mongodb-admin -p '123456' --authenticationDatabase 'admin'</div><div class="line"></div><div class="line">#测试创建集合和查询,如果没有报错,说明权限已经ok</div><div class="line">use test</div><div class="line">db.createCollection("Account")</div><div class="line">db.Account.find()</div></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>安装好MongoDB时,通常开了一个最高管理权限的root账户来方便我们管理数据库,实际开发中并一般不使用这个账户,我们可以单独添加一个账户来连接数据库。</p>
</summary>
<category term="MongoDB" scheme="https://renqiangme.github.io/categories/MongoDB/"/>
<category term="MongoDB" scheme="https://renqiangme.github.io/tags/MongoDB/"/>
</entry>
<entry>
<title>使用Systemd部署管理SpringBoot应用</title>
<link href="https://renqiangme.github.io/2018/04/17/%E4%BD%BF%E7%94%A8System%E9%83%A8%E7%BD%B2SpringBoot%E5%BA%94%E7%94%A8/"/>
<id>https://renqiangme.github.io/2018/04/17/使用System部署SpringBoot应用/</id>
<published>2018-04-17T05:28:12.000Z</published>
<updated>2019-04-24T10:03:15.321Z</updated>
<content type="html"><![CDATA[<p>如果不使用<code>Docker</code>和<code>Kubernets</code>部署管理<code>SpringBoot</code>应用,可以选择<code>Systemd</code>。</p><p>因为SpringBoot自带Tomcat之类的Web应用服务器,可以直接<code>java -jar xxx.jar</code>的方式启动起来。</p><p>如果我们直接使用<code>nohup java -jar xxx.jar &</code> 之类的虽然也可以实现后台运行,但是是有可能因为某些原因挂掉的,所以我们需要找到一种工具让应用可以重启或者开机启动。</p><p>我们可以使用Python的<code>Supervisor</code>,也有盆友说可以使用Node的<code>pm2</code>,但是我一般都是选择<code>Systemd</code>,现在Linux系统都是自带这个的。</p><a id="more"></a><h5 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h5><p>生成jar包:进入到SpringBoot项目的目录,然后执行:<code>mvn clean package</code>,找到target目录里面的jar包。</p><p>上传jar包:scp -P xx_port xxx.jar username@host:./</p><p>SSH登录进入服务器之后,首先需要安装JDK,然后把jar包复制到/home/www/applications</p><p>在/etc/systemd/system/目录下面新建一个service的配置,配置内容参考:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">[Unit]</div><div class="line">Description=service-test</div><div class="line">After=syslog.target</div><div class="line"></div><div class="line">[Service]</div><div class="line">User=root</div><div class="line">WorkingDirectory=/home/www/applications</div><div class="line">Restart=always</div><div class="line">ExecStart=/usr/local/jdk1.8.0_161/bin/java -jar /home/www/applications/service-test-1.0.jar</div><div class="line">ExecStop=/usr/bin/kill -15 $MAINPID</div><div class="line">SuccessExitStatus=143</div><div class="line"></div><div class="line">[Install]</div><div class="line">WantedBy=multi-user.target</div></pre></td></tr></table></figure><p>新增一个新的service之后,需要让配置生效,如果修改配置文件,需要reload。</p><p>使xx service生效:<br><code>systemctl enable xx.service</code></p><p>刷新配置:<br><code>systemctl daemon-reload</code></p><p>启动xx service:</p><p><code>systemctl start xx.service</code></p><p>查看xx service的status:</p><p><code>systemctl status xx.service</code></p><p>重启xx service:</p><p><code>systemctl restart xx.service</code></p><p>看xx service日志,按住shift+g可以跳转到最后一行:</p><p><code>journalctl -u xx.service</code></p><p>动态像<code>tail -f xxfile</code>一样查看对应service的日志:</p><p><code>journalctl -f xx.service</code></p>]]></content>
<summary type="html">
<p>如果不使用<code>Docker</code>和<code>Kubernets</code>部署管理<code>SpringBoot</code>应用,可以选择<code>Systemd</code>。</p>
<p>因为SpringBoot自带Tomcat之类的Web应用服务器,可以直接<code>java -jar xxx.jar</code>的方式启动起来。</p>
<p>如果我们直接使用<code>nohup java -jar xxx.jar &amp;</code> 之类的虽然也可以实现后台运行,但是是有可能因为某些原因挂掉的,所以我们需要找到一种工具让应用可以重启或者开机启动。</p>
<p>我们可以使用Python的<code>Supervisor</code>,也有盆友说可以使用Node的<code>pm2</code>,但是我一般都是选择<code>Systemd</code>,现在Linux系统都是自带这个的。</p>
</summary>
<category term="JAVA" scheme="https://renqiangme.github.io/categories/JAVA/"/>
<category term="JAVA" scheme="https://renqiangme.github.io/tags/JAVA/"/>
<category term="SpringBoot" scheme="https://renqiangme.github.io/tags/SpringBoot/"/>
<category term="Systemd" scheme="https://renqiangme.github.io/tags/Systemd/"/>
</entry>
<entry>
<title>Log4j2日志->Kafka->LogStash->ElasticSearch并邮件报警</title>
<link href="https://renqiangme.github.io/2018/01/21/Log4j2%E6%97%A5%E5%BF%97-%3EKafka-%3ELogstash-%3EElasticsearch%E5%B9%B6%E9%82%AE%E4%BB%B6%E6%8A%A5%E8%AD%A6/"/>
<id>https://renqiangme.github.io/2018/01/21/Log4j2日志->Kafka->Logstash->Elasticsearch并邮件报警/</id>
<published>2018-01-21T11:08:28.000Z</published>
<updated>2019-03-29T06:38:57.810Z</updated>
<content type="html"><![CDATA[<p>SpringBoot项目中需要把日志记录到<a href="https://www.elastic.co/cn/products/elasticsearch" target="_blank" rel="external">:ElasticSearch</a> 并使用 <a href="https://www.elastic.co/cn/products/kibana" target="_blank" rel="external">:Kibana</a> 搜索、展示、查看日志。</p><h4 id="修改SpringBoot中的配置"><a href="#修改SpringBoot中的配置" class="headerlink" title="修改SpringBoot中的配置"></a>修改SpringBoot中的配置</h4><p>因为SpringBoot默认使用的日志框架是:<a href="http://logback.qos.ch/" target="_blank" rel="external">:Logback</a>,但是<a href="https://logging.apache.org/log4j/2.x/" target="_blank" rel="external">:Log4j2</a> 性能可能更高就打算替换掉。</p><a id="more"></a><p>替换方法,修改项目maven的pom.xml配置文件:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><dependency></div><div class="line"> <groupId>org.springframework.boot</groupId></div><div class="line"> <artifactId>spring-boot-starter</artifactId></div><div class="line"> <exclusions></div><div class="line"> <exclusion></div><div class="line"> <groupId>org.springframework.boot</groupId></div><div class="line"> <artifactId>spring-boot-starter-logging</artifactId></div><div class="line"> </exclusion></div><div class="line"> </exclusions></div><div class="line"></dependency></div><div class="line"><dependency></div><div class="line"> <groupId>org.springframework.boot</groupId></div><div class="line"> <artifactId>spring-boot-starter-log4j2</artifactId></div><div class="line"></dependency></div></pre></td></tr></table></figure><p>因为需要把日志记录到Kafka,所以引入org.apache.kafka kafka-clients到项目中:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><dependency></div><div class="line"> <groupId>org.apache.kafka</groupId></div><div class="line"> <artifactId>kafka-clients</artifactId></div><div class="line"> <version>0.10.0.0</version></div><div class="line"></dependency></div></pre></td></tr></table></figure><p>因为日志在本地测试和线上的kafka的服务器需要分开,通常我们可以在resources目录下面创建:</p><ul><li>本地的log4j2的配置文件名叫log4j2-dev.xml</li><li>正式线上的log4j2的配置文件名叫log4j2-prd.xml</li></ul><p>然后我们可以修改SpringBoot的bootstrap.properties,<code>ACTIVE_ENVIRONMENT</code>为环境变量。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">spring.profiles.active=${ACTIVE_ENVIRONMENT:dev}</div><div class="line">logging.config=classpath:log4j2-${ACTIVE_ENVIRONMENT}.xml</div></pre></td></tr></table></figure></p><p>log4j2-xxx.xml的内容例子如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><?xml version="1.0" encoding="UTF-8"?></div><div class="line"><Configuration status="warn"></div><div class="line"> <Properties></div><div class="line"> </Properties></div><div class="line"> <Appenders></div><div class="line"> <Console name="STDOUT" target="SYSTEM_OUT"></div><div class="line"> <PatternLayout pattern="%d %p %c{1.} %t %m%n"/></div><div class="line"> </Console></div><div class="line"> <Kafka name="KAFKA-LOGGER" topic="service-logs-test"><!--kafka topic--></div><div class="line"> <JsonLayout/> <!--JsonLayout:日志格式为json,方便在Elastic中处理--></div><div class="line"> <Property name="bootstrap.servers">10.2.200.26:9092</Property><!--kafka server的ip:port--></div><div class="line"> <Property name ="retries" >3</Property></div><div class="line"> <Property name ="linger.ms" >1000</Property></div><div class="line"> <Property name ="buffer.memory" > 10485760</Property></div><div class="line"> </Kafka></div><div class="line"> <Async name="ASYNC-KAFKA-LOGGER"></div><div class="line"> <AppenderRef ref="KAFKA-LOGGER"/></div><div class="line"> <LinkedTransferQueue/></div><div class="line"> </Async></div><div class="line"> </Appenders></div><div class="line"> <Loggers></div><div class="line"> <logger name="demo.xx.com.test" level="info" additivity="false"><!--日志级别大于info都会被记录到Kafka--></div><div class="line"> <AppenderRef ref="KAFKA-LOGGER"/></div><div class="line"> </logger></div><div class="line"> <!-- Root表示所有Logger用Root中的Appender打印日志 --></div><div class="line"> <Root level="info"></div><div class="line"> <AppenderRef ref="STDOUT"/></div><div class="line"> <AppenderRef ref="ASYNC-KAFKA-LOGGER"/></div><div class="line"> </Root></div><div class="line"> </Loggers></div><div class="line"></Configuration></div></pre></td></tr></table></figure></p><h4 id="在LogStash中的配置"><a href="#在LogStash中的配置" class="headerlink" title="在LogStash中的配置"></a>在LogStash中的配置</h4><p>LogStash组成结构:<br>Logstash 通过管道进行运作,管道有两个必需的元素,输入和输出,还有一个可选的元素,过滤器。输入插件从数据源获取数据,过滤器插件根据用户指定的数据格式修改数据,输出插件则将数据写入到目的地。<br>因此,需要一个配置文件管理输入、过滤器和输出相关的配置。配置文件内容格式如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"># 输入</div><div class="line">input {</div><div class="line"> ...</div><div class="line">}</div><div class="line"></div><div class="line"># 过滤器</div><div class="line">filter {</div><div class="line"> ...</div><div class="line">}</div><div class="line"></div><div class="line"># 输出</div><div class="line">output {</div><div class="line"> ...</div><div class="line">}</div></pre></td></tr></table></figure></p><p>所以我们创建一个文件到LogStash的配置文件:logstash.yml中path.config配置的扫描目录。</p><p>service-logs.conf配置文件内容如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div></pre></td><td class="code"><pre><div class="line">input {</div><div class="line"> kafka {</div><div class="line"> topics_pattern => ["service-logs-.*"]</div><div class="line"> bootstrap_servers => "10.1.220.27:9092"</div><div class="line"> group_id => "local-logstash"</div><div class="line"> decorate_events => true</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">filter {</div><div class="line"> json {</div><div class="line"> source => "message"</div><div class="line"> }</div><div class="line"> mutate {</div><div class="line"> add_field => {</div><div class="line"> "kafka_topic" => "%{[@metadata][kafka][topic]}"</div><div class="line"> "kafka_consumer_group" => "%{[@metadata][kafka][consumer_group]}"</div><div class="line"> "kafka_partition" => "%{[@metadata][kafka][partition]}"</div><div class="line"> "kafka_offset" => "%{[@metadata][kafka][offset]}"</div><div class="line"> "kafka_timestamp" => "%{[@metadata][kafka][timestamp]}"</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">output {</div><div class="line"> if [level] == "ERROR" {</div><div class="line"> http {</div><div class="line"> url => "http://localhost:8088/send/mail"</div><div class="line"> http_method => "post"</div><div class="line"> automatic_retries => 0</div><div class="line"> connect_timeout => 6</div><div class="line"> keepalive => false</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> elasticsearch {</div><div class="line"> hosts => ["127.0.0.1:9200"]</div><div class="line"> action => "index"</div><div class="line"> index => "logstash-%{[kafka_topic]}"</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure><p>我们可以看到上面output针对日志级别是ERROR的会发送一个HTTP请求到一个发邮件的服务器,因为LogStash自带的邮件发不出来,所以单独用了nodejs写了一个发邮件接口。</p><p>如果使用LogStash自带的配置如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line">output {</div><div class="line"> if [level] == "ERROR" {</div><div class="line"> email {</div><div class="line"> debug => true</div><div class="line"> to => "[email protected]"</div><div class="line"> from => "[email protected]"</div><div class="line"> subject => 'Alert - Error'</div><div class="line"> codec => "plain"</div><div class="line"> contenttype => "text/html; charset=UTF-8"</div><div class="line"> body => "Tags: %{tags}\\n\\Content:\\n%{message}"</div><div class="line"> username => "[email protected]"</div><div class="line"> password => "xxx"</div><div class="line"> address => "smtp.126.com"</div><div class="line"> domain => "smtp.126.com"</div><div class="line"> port => 25</div><div class="line"> use_tls => false</div><div class="line"> via => "smtp"</div><div class="line"> }</div><div class="line"> }</div><div class="line"> }</div></pre></td></tr></table></figure><p>LogStash的功能很强大,更多可以阅读官方的文档。</p>]]></content>
<summary type="html">
<p>SpringBoot项目中需要把日志记录到<a href="https://www.elastic.co/cn/products/elasticsearch">:ElasticSearch</a> 并使用 <a href="https://www.elastic.co/cn/products/kibana">:Kibana</a> 搜索、展示、查看日志。</p>
<h4 id="修改SpringBoot中的配置"><a href="#修改SpringBoot中的配置" class="headerlink" title="修改SpringBoot中的配置"></a>修改SpringBoot中的配置</h4><p>因为SpringBoot默认使用的日志框架是:<a href="http://logback.qos.ch/">:Logback</a>,但是<a href="https://logging.apache.org/log4j/2.x/">:Log4j2</a> 性能可能更高就打算替换掉。</p>
</summary>
<category term="JAVA" scheme="https://renqiangme.github.io/categories/JAVA/"/>
<category term="JAVA" scheme="https://renqiangme.github.io/tags/JAVA/"/>
<category term="Kafka" scheme="https://renqiangme.github.io/tags/Kafka/"/>
<category term="LogStash" scheme="https://renqiangme.github.io/tags/LogStash/"/>
<category term="ElasticSearch" scheme="https://renqiangme.github.io/tags/ElasticSearch/"/>
</entry>
<entry>
<title>Git的一些操作记录</title>
<link href="https://renqiangme.github.io/2018/01/12/Git%E7%9A%84%E4%B8%80%E4%BA%9B%E6%93%8D%E4%BD%9C%E8%AE%B0%E5%BD%95/"/>
<id>https://renqiangme.github.io/2018/01/12/Git的一些操作记录/</id>
<published>2018-01-12T01:30:28.000Z</published>
<updated>2019-03-18T04:47:46.288Z</updated>
<content type="html"><![CDATA[<h4 id="Git撤销某个commit"><a href="#Git撤销某个commit" class="headerlink" title="Git撤销某个commit"></a>Git撤销某个commit</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">git reset –mixed:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,同时清空了暂存区(回退commit和index信息)</div><div class="line">git reset –soft:回退到某个版本,只回退了commit的信息,git不会清除你的暂存区。如果还要提交,直接commit即可</div><div class="line">git reset –hard:彻底回退到某个版本,直接覆盖工作区,暂存区,本地的源码所有的内容也会变为上一个版本的内容</div><div class="line"></div><div class="line">Git撤销命令后面的可选参数:</div><div class="line">HEAD 最近一个提交</div><div class="line">HEAD^ 上一次</div><div class="line"><commit_id> 每次commit的SHA1值. 可以用git log 看到,也可以在页面上commit标签页里找到</div></pre></td></tr></table></figure><a id="more"></a><p>如果本地的源码彻底回退到某个版本,并希望远程Git仓库的记录也回滚的话。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">git reset --hard <commit_id></div><div class="line">git push origin HEAD --force</div></pre></td></tr></table></figure><p>如果本地的源码彻底回退到某个版本,又想回滚到回滚前的某个版本。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git reflog</div></pre></td></tr></table></figure><p>git reflog 可以查看所有分支的所有操作记录(包括commit和reset的操作),包括已经被删除的commit记录,git log则不能察看已经删除了的commit记录。</p><h4 id="修改Git使用的远程仓库"><a href="#修改Git使用的远程仓库" class="headerlink" title="修改Git使用的远程仓库"></a>修改Git使用的远程仓库</h4><p>三种方式:</p><p>1:修改命令 git remte origin set-url url</p><p>2:先删后加 git remote rm origin && git remote add origin url</p><p>3:直接修改文件: .git/config</p><h4 id="打包出Git两个commit之间提交过的文件"><a href="#打包出Git两个commit之间提交过的文件" class="headerlink" title="打包出Git两个commit之间提交过的文件"></a>打包出Git两个commit之间提交过的文件</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">git diff xxx xxx --name-only | xargs tar -cvzf update.tar.gz</div></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="Git撤销某个commit"><a href="#Git撤销某个commit" class="headerlink" title="Git撤销某个commit"></a>Git撤销某个commit</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">git reset –mixed:此为默认方式,不带任何参数的git reset,即时这种方式,它回退到某个版本,只保留源码,同时清空了暂存区(回退commit和index信息)</div><div class="line">git reset –soft:回退到某个版本,只回退了commit的信息,git不会清除你的暂存区。如果还要提交,直接commit即可</div><div class="line">git reset –hard:彻底回退到某个版本,直接覆盖工作区,暂存区,本地的源码所有的内容也会变为上一个版本的内容</div><div class="line"></div><div class="line">Git撤销命令后面的可选参数:</div><div class="line">HEAD 最近一个提交</div><div class="line">HEAD^ 上一次</div><div class="line">&lt;commit_id&gt; 每次commit的SHA1值. 可以用git log 看到,也可以在页面上commit标签页里找到</div></pre></td></tr></table></figure>
</summary>
<category term="Git" scheme="https://renqiangme.github.io/categories/Git/"/>
<category term="Git" scheme="https://renqiangme.github.io/tags/Git/"/>
</entry>
<entry>
<title>Ubuntu安装Elastic Stack</title>
<link href="https://renqiangme.github.io/2018/01/02/Ubuntu%E5%AE%89%E8%A3%85Elastic%20Stack/"/>
<id>https://renqiangme.github.io/2018/01/02/Ubuntu安装Elastic Stack/</id>
<published>2018-01-02T08:18:08.000Z</published>
<updated>2019-03-18T04:47:30.235Z</updated>
<content type="html"><![CDATA[<h4 id="1-首先安装python-software-properties"><a href="#1-首先安装python-software-properties" class="headerlink" title="1.首先安装python-software-properties"></a>1.首先安装python-software-properties</h4><p>该程序将安装add-apt-repository的应用程序,更加方便的添加和使用PPA软件库。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sudo apt-get update</div><div class="line">sudo apt-get install -y python-software-properties software-properties-common apt-transport-https</div></pre></td></tr></table></figure><a id="more"></a><h4 id="2-安装java8"><a href="#2-安装java8" class="headerlink" title="2.安装java8"></a>2.安装java8</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">sudo add-apt-repository ppa:webupd8team/java -y</div><div class="line">sudo apt-get update</div><div class="line">sudo apt-get install -y oracle-java8-installer</div></pre></td></tr></table></figure><p>打印java的版本信息:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">java -version</div></pre></td></tr></table></figure><h4 id="3-安装elastic"><a href="#3-安装elastic" class="headerlink" title="3.安装elastic"></a>3.安装elastic</h4><h5 id="3-1:安装之前先添加elastic-repository-key-到server"><a href="#3-1:安装之前先添加elastic-repository-key-到server" class="headerlink" title="3.1:安装之前先添加elastic repository key 到server"></a>3.1:安装之前先添加elastic repository key 到server</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -</div></pre></td></tr></table></figure><h5 id="3-2:找到当前的文档版本,导入当前的repository到sources-list-d:"><a href="#3-2:找到当前的文档版本,导入当前的repository到sources-list-d:" class="headerlink" title="3.2:找到当前的文档版本,导入当前的repository到sources.list.d:"></a>3.2:找到当前的文档版本,导入当前的repository到sources.list.d:</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list</div></pre></td></tr></table></figure><h4 id="4-安装elasticsearch"><a href="#4-安装elasticsearch" class="headerlink" title="4:安装elasticsearch"></a>4:安装elasticsearch</h4><p>Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。</p><p>但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。</p><p>Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。</p><p>不过,Elasticsearch不仅仅是Lucene和全文搜索,我们还能这样去描述它:</p><p>分布式的实时文件存储,每个字段都被索引并可被搜索</p><p>分布式的实时分析搜索引擎</p><p>可以扩展到上百台服务器,处理PB级结构化或非结构化数据</p><p>而且,所有的这些功能被集成到一个服务里面,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互<br>。</p><h5 id="4-1-安装及修改配置文件"><a href="#4-1-安装及修改配置文件" class="headerlink" title="4.1:安装及修改配置文件"></a>4.1:安装及修改配置文件</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sudo apt-get update</div><div class="line">sudo apt-get install -y elasticsearch</div></pre></td></tr></table></figure><p>配置文件路径:/etc/elasticsearch/elasticsearch.yml </p><p>可以修改host,port….</p><h5 id="4-2-加入开机自启动服务"><a href="#4-2-加入开机自启动服务" class="headerlink" title="4.2:加入开机自启动服务"></a>4.2:加入开机自启动服务</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">sudo systemctl daemon-reload</div><div class="line">sudo systemctl enable elasticsearch</div><div class="line">sudo systemctl start elasticsearch</div></pre></td></tr></table></figure><h5 id="4-3-通过system进行管理elasticsearch"><a href="#4-3-通过system进行管理elasticsearch" class="headerlink" title="4.3:通过system进行管理elasticsearch"></a>4.3:通过system进行管理elasticsearch</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">systemctl status elasticsearch</div><div class="line"></div><div class="line">systemctl start elasticsearch</div><div class="line"></div><div class="line">systemctl stop elasticsearch</div><div class="line"></div><div class="line">systemctl restart elasticsearch</div></pre></td></tr></table></figure><h5 id="4-4-查看运行情况"><a href="#4-4-查看运行情况" class="headerlink" title="4.4:查看运行情况"></a>4.4:查看运行情况</h5><p>查看端口:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">netstat -plntu</div></pre></td></tr></table></figure><p>查看elasticsearch的cluster,版本..相关信息:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">curl -XGET 'localhost:9200/?pretty'</div></pre></td></tr></table></figure><p>查看集群健康情况:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">curl 'localhost:9200/_cat/health?v'</div></pre></td></tr></table></figure><p>查看集群中的节点列表:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">curl 'localhost:9200/_cat/nodes?v'</div></pre></td></tr></table></figure><p>查看index情况:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">curl 'localhost:9200/_cat/indices?v'</div></pre></td></tr></table></figure><h5 id="4-4-参考文档"><a href="#4-4-参考文档" class="headerlink" title="4.4:参考文档"></a>4.4:参考文档</h5><p><a href="https://www.elastic.co/guide/cn/elasticsearch/guide/cn/index.html" target="_blank" rel="external">Elasticsearch: 权威指南</a></p><h4 id="5-安装Kibana"><a href="#5-安装Kibana" class="headerlink" title="5:安装Kibana"></a>5:安装Kibana</h4><p>Kibana是一个为Elasticsearch平台分析和可视化的开源平台,使用Kibana能够搜索、展示存储在Elasticsearch中的索引数据。使用它可以很方便用图表、表格、地图展示和分析数据。<br>Kibana能够轻松处理大量数据,通过浏览器接口能够轻松的创建和分享仪表盘,通过改变Elasticsearch查询时间,可以完成动态仪表盘。</p><h5 id="5-1-通过apt安装及配置"><a href="#5-1-通过apt安装及配置" class="headerlink" title="5.1:通过apt安装及配置"></a>5.1:通过apt安装及配置</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo apt-get install -y kibana</div></pre></td></tr></table></figure><p>配置文件路径:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">/etc/kibana/kibana.yml</div></pre></td></tr></table></figure><p>可以修改host,port,以及elasticsearch的url</p><h5 id="5-2-加入开机自启动"><a href="#5-2-加入开机自启动" class="headerlink" title="5.2:加入开机自启动"></a>5.2:加入开机自启动</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sudo systemctl enable kibana</div><div class="line">sudo systemctl start kibana</div></pre></td></tr></table></figure><h5 id="5-3-通过system进行管理kibana"><a href="#5-3-通过system进行管理kibana" class="headerlink" title="5.3:通过system进行管理kibana"></a>5.3:通过system进行管理kibana</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">systemctl status kibana</div><div class="line"></div><div class="line">systemctl start kibana</div><div class="line"></div><div class="line">systemctl stop kibana</div><div class="line"></div><div class="line">systemctl restart kibana</div></pre></td></tr></table></figure><h4 id="6-安装Logstash"><a href="#6-安装Logstash" class="headerlink" title="6:安装Logstash"></a>6:安装Logstash</h4><p>Logstash 是一个开源的数据收集引擎具有实时管道能力。</p><p>Logstash 可以动态的统一数据从不同的来源和使数据规范化到你选择的目的地。</p><p>当Logstash 起初驾驭创新到日志收集,它的功能很好的扩展超出使用案例。任何事件的类型可以被丰富和改变使用一个input,filter和输出引擎,使用很多的本地的代码简化了采集的过程。</p><h5 id="6-1-通过apt安装"><a href="#6-1-通过apt安装" class="headerlink" title="6.1:通过apt安装"></a>6.1:通过apt安装</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">sudo apt-get install -y logstash</div></pre></td></tr></table></figure><h5 id="6-2-logstash的配置文件目录:"><a href="#6-2-logstash的配置文件目录:" class="headerlink" title="6.2:logstash的配置文件目录:"></a>6.2:logstash的配置文件目录:</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">/etc/logstash/</div><div class="line"></div><div class="line">├── conf.d</div><div class="line">│ └── kafka-logs-local.conf</div><div class="line">├── jvm.options</div><div class="line">├── log4j2.properties</div><div class="line">├── logstash.yml</div><div class="line">└── startup.options</div></pre></td></tr></table></figure><p>logstash.yml:</p><p>path.config:定义扫描input,filter,output的配置目录</p><p>path.logs: 定义log配置,在测试配置文件的时候有用。</p><p>input:kafka,output:elasticsearch的example:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div></pre></td><td class="code"><pre><div class="line">input {</div><div class="line"> kafka {</div><div class="line"> topics_pattern => ["service-logs-.*"]</div><div class="line"> bootstrap_servers => "10.1.220.27:9092"</div><div class="line"> group_id => "local-logstash"</div><div class="line"> decorate_events => true</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">filter {</div><div class="line"> json {</div><div class="line"> source => "message"</div><div class="line"> }</div><div class="line"> mutate {</div><div class="line"> add_field => {</div><div class="line"> "kafka_topic" => "%{[@metadata][kafka][topic]}"</div><div class="line"> "kafka_consumer_group" => "%{[@metadata][kafka][consumer_group]}"</div><div class="line"> "kafka_partition" => "%{[@metadata][kafka][partition]}"</div><div class="line"> "kafka_offset" => "%{[@metadata][kafka][offset]}"</div><div class="line"> "kafka_timestamp" => "%{[@metadata][kafka][timestamp]}"</div><div class="line"> }</div><div class="line"> }</div><div class="line">}</div><div class="line"></div><div class="line">output {</div><div class="line"> if [level] == "ERROR" {</div><div class="line"> http {</div><div class="line"> url => "http://localhost:8088/send/mail"</div><div class="line"> http_method => "post"</div><div class="line"> automatic_retries => 0</div><div class="line"> connect_timeout => 6</div><div class="line"> keepalive => false</div><div class="line"> }</div><div class="line"> }</div><div class="line"></div><div class="line"> elasticsearch {</div><div class="line"> hosts => ["127.0.0.1:9200"]</div><div class="line"> action => "index"</div><div class="line"> index => "logstash-%{[kafka_topic]}"</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure><h5 id="6-3-加入开机自启动"><a href="#6-3-加入开机自启动" class="headerlink" title="6.3:加入开机自启动"></a>6.3:加入开机自启动</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sudo systemctl enable logstash</div><div class="line">sudo systemctl start logstash</div></pre></td></tr></table></figure><h5 id="6-4-通过system进行管理logstash"><a href="#6-4-通过system进行管理logstash" class="headerlink" title="6.4:通过system进行管理logstash"></a>6.4:通过system进行管理logstash</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">systemctl status logstash</div><div class="line"></div><div class="line">systemctl start logstash</div><div class="line"></div><div class="line">systemctl stop logstash</div><div class="line"></div><div class="line">systemctl restart logstash</div></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="1-首先安装python-software-properties"><a href="#1-首先安装python-software-properties" class="headerlink" title="1.首先安装python-software-properties"></a>1.首先安装python-software-properties</h4><p>该程序将安装add-apt-repository的应用程序,更加方便的添加和使用PPA软件库。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">sudo apt-get update</div><div class="line">sudo apt-get install -y python-software-properties software-properties-common apt-transport-https</div></pre></td></tr></table></figure>
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Linux" scheme="https://renqiangme.github.io/tags/Linux/"/>
<category term="Ubuntu" scheme="https://renqiangme.github.io/tags/Ubuntu/"/>
<category term="Elastic Stack" scheme="https://renqiangme.github.io/tags/Elastic-Stack/"/>
</entry>
<entry>
<title>Ubuntu设置固定的ip</title>
<link href="https://renqiangme.github.io/2017/08/18/Ubuntu%E8%AE%BE%E7%BD%AE%E5%9B%BA%E5%AE%9A%E7%9A%84ip/"/>
<id>https://renqiangme.github.io/2017/08/18/Ubuntu设置固定的ip/</id>
<published>2017-08-18T05:28:18.000Z</published>
<updated>2019-03-18T04:47:07.761Z</updated>
<content type="html"><![CDATA[<p>修改配置文件:/etc/network/interfaces</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">vim /etc/network/interfaces</div><div class="line"></div><div class="line">#增加修改如下:</div><div class="line"></div><div class="line">#The primary network interface</div><div class="line">auto ens160</div><div class="line">iface ens160 inet static</div><div class="line">address 10.1.220.15</div><div class="line">netmask 255.255.0.0</div><div class="line">gateway 10.1.1.1</div><div class="line">dns-nameservers 8.8.8.8 8.8.4.4</div><div class="line"></div><div class="line">service networking restart</div></pre></td></tr></table></figure><a id="more"></a>]]></content>
<summary type="html">
<p>修改配置文件:/etc/network/interfaces</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">vim /etc/network/interfaces</div><div class="line"></div><div class="line">#增加修改如下:</div><div class="line"></div><div class="line">#The primary network interface</div><div class="line">auto ens160</div><div class="line">iface ens160 inet static</div><div class="line">address 10.1.220.15</div><div class="line">netmask 255.255.0.0</div><div class="line">gateway 10.1.1.1</div><div class="line">dns-nameservers 8.8.8.8 8.8.4.4</div><div class="line"></div><div class="line">service networking restart</div></pre></td></tr></table></figure>
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Linux" scheme="https://renqiangme.github.io/tags/Linux/"/>
<category term="Ubuntu" scheme="https://renqiangme.github.io/tags/Ubuntu/"/>
</entry>
<entry>
<title>部署管理Swoole服务</title>
<link href="https://renqiangme.github.io/2017/07/12/%E9%83%A8%E7%BD%B2%E7%AE%A1%E7%90%86Swoole%E6%9C%8D%E5%8A%A1/"/>
<id>https://renqiangme.github.io/2017/07/12/部署管理Swoole服务/</id>
<published>2017-07-12T03:20:38.000Z</published>
<updated>2019-03-25T13:46:38.846Z</updated>
<content type="html"><![CDATA[<h3 id="使用Systemd管理Swoole服务"><a href="#使用Systemd管理Swoole服务" class="headerlink" title="使用Systemd管理Swoole服务"></a>使用Systemd管理Swoole服务</h3><p>Systemd 是 Linux 系统工具,用来启动守护进程。</p><p>Systemd 并不是一个命令,而是一组命令,涉及到系统管理的方方面面。包括:systemctl,systemd-analyze,hostnamectl,localectl,timedatectl,loginctl</p><a id="more"></a><p>更多参考<a href="http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html/" target="_blank" rel="external">:Systemd介绍</a></p><p>所以Swoole的服务器程序可以编写一段service脚本,交由systemd进行管理。实现故障重启、开机自启动等功能。</p><p>使用systemd管理swoole服务参考文档:<a href="https://wiki.swoole.com/wiki/page/699.html/" target="_blank" rel="external">swoole官方文档</a></p><p>Demo:</p><p>在/etc/systemd/system/swoole_http.service新建一个service文件,内容如下:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">[Unit]</div><div class="line">Description=Swoole Http service</div><div class="line">After=network.target</div><div class="line">After=syslog.target</div><div class="line"></div><div class="line">[Service]</div><div class="line">Type=forking</div><div class="line">PIDFile=/home/www/http/bin/server.pid</div><div class="line">ExecStart=/home/www/http/bin/server</div><div class="line">ExecStop=/bin/kill -15 $MAINPID</div><div class="line">ExecReload=/bin/kill -USR1 $MAINPID</div><div class="line">Restart=always</div><div class="line"></div><div class="line">[Install]</div><div class="line">WantedBy=multi-user.target graphical.target</div></pre></td></tr></table></figure><p>需要注意的是$MAINPID必须要是manager的id,不然启动或者重启的时候会报错。而且还需要修改swoole配置参数,把swoole的守护进程化设置为daemonize => 1。</p><p>kill -USR1 pid 重启woker进程和task进程</p><p>kill -USR2 pid 重启task进程</p><p>kill -15 管理进程id 关掉所有的manager相关进程</p><p>关于swoole重启的文档:<a href="https://wiki.swoole.com/wiki/page/p-server/reload.html" target="_blank" rel="external">链接</a></p><h3 id="使用Supervisor管理swoole服务"><a href="#使用Supervisor管理swoole服务" class="headerlink" title="使用Supervisor管理swoole服务"></a>使用Supervisor管理swoole服务</h3><p>Supervisor是一个客户/服务器系统,它可以在类Unix系统中管理控制大量进程。Supervisor使用python开发,有多年历史,目前很多生产环境下的服务器都在使用Supervisor,部署python程序经常这个。</p><p>Supervisor的服务器端称为supervisord,主要负责在启动自身时启动管理的子进程,响应客户端的命令,重启崩溃或退出的子进程,记录子进程stdout和stderr输出,生成和处理子进程生命周期中的事件。可以在一个配置文件中配置相关参数,包括Supervisord自身的状态,其管理的各个子进程的相关属性。配置文件一般位于/etc/supervisord.conf。</p><p>Supervisor的客户端称为supervisorctl,它提供了一个类shell的接口(即命令行)来使用supervisord服务端提供的功能。通过supervisorctl,用户可以连接到supervisord服务器进程,获得服务器进程控制的子进程的状态,启动和停止子进程,获得正在运行的进程列表。客户端通过Unix域套接字或者TCP套接字与服务端进行通信,服务器端具有身份凭证认证机制,可以有效提升安全性。当客户端和服务器位于同一台机器上时,客户端与服务器共用同一个配置文件/etc/supervisord.conf,通过不同标签来区分两者的配置。</p><p>Supervisor也提供了一个web页面来查看和管理进程状态,这个功能非常酷.</p><h4 id="安装Supervisor"><a href="#安装Supervisor" class="headerlink" title="安装Supervisor"></a>安装Supervisor</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"># 我们可以通过pypi安装</div><div class="line">pip install supervisor</div><div class="line"># 或者从pypi上下载源码,然后安装</div><div class="line">python setup.py install</div><div class="line"># 安装完之后,使用下列命令来生成配置文件</div><div class="line">echo_supervisord_conf > /etc/supervisord.conf</div></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"># mkdir /etc/supervisord.d 用户存放被监控进程的配置文件</div></pre></td></tr></table></figure><p>修改/etc/supervisord.conf配置文件:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">在文件结尾[include]节点处把</div><div class="line">;files = relative/directory/*.ini改为files =/etc/supervisord.d/*.conf</div><div class="line"></div><div class="line">同时还需要去掉[include]前面的;</div></pre></td></tr></table></figure></p><p>保存并退出。</p><h4 id="把supervisor加入开机自启动服务"><a href="#把supervisor加入开机自启动服务" class="headerlink" title="把supervisor加入开机自启动服务"></a>把supervisor加入开机自启动服务</h4><p>到systemd系统下新建一个service配置文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">vim /lib/systemd/system/supervisor.service</div></pre></td></tr></table></figure></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">[Unit]</div><div class="line">Description=supervisor</div><div class="line">After=network.target</div><div class="line"></div><div class="line">[Service]</div><div class="line">Type=forking</div><div class="line">ExecStart=/usr/bin/supervisord -c /etc/supervisord.conf</div><div class="line">ExecStop=/usr/bin/supervisorctl $OPTIONS shutdown</div><div class="line">ExecReload=/usr/bin/supervisorctl $OPTIONS reload</div><div class="line">KillMode=process</div><div class="line">Restart=on-failure</div><div class="line">RestartSec=42s</div><div class="line"></div><div class="line">[Install]</div><div class="line">WantedBy=multi-user.target graphical.target</div></pre></td></tr></table></figure><p>上述文件编写后,执行如下命令即可:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">systemctl enable supervisor.service</div></pre></td></tr></table></figure></p><p>加入开机自启动服务<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">systemctl daemon-reload</div></pre></td></tr></table></figure></p><p>重新载入systemd,扫描新的或有变动的单元。</p><p>实际上supervisor已经加入了systemctl管理了,后续起停supervisor服务都可以通过systemctl来控制了。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">systemctl start supervisor.service 启动服务</div><div class="line"></div><div class="line">systemctl stop supervisor.service 停止服务</div><div class="line"></div><div class="line">systemctl restart supervisor.service 重新启动服务</div><div class="line"></div><div class="line">systemctl reload supervisor.service 重载配置文件</div><div class="line"></div><div class="line">systemctl status supervisor.service 查看服务状态</div></pre></td></tr></table></figure><h4 id="在-etc-supervisord-d-增加一个程序的demo配置参数:"><a href="#在-etc-supervisord-d-增加一个程序的demo配置参数:" class="headerlink" title="在/etc/supervisord.d 增加一个程序的demo配置参数:"></a>在/etc/supervisord.d 增加一个程序的demo配置参数:</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div></pre></td><td class="code"><pre><div class="line">[program:cat] ;程序名</div><div class="line">command=/bin/cat ;命令绝对路径,可以包含参数</div><div class="line">process_name=%(program_name)s ;进程名</div><div class="line">numprocs=1 ;supervisor启动多少个该程序,如果大于1,那么进程名必须包括%(process_num)s</div><div class="line">directory=/tmp ;该进程的启动时的工作目录</div><div class="line">umask=022 ;掩码</div><div class="line">priority=999 ;优先级</div><div class="line">autostart=true ;该程序是否在supervisor启动时启动</div><div class="line">autorestart=true ;如果为false,那么该程序的相关进程永远不会自动重启。如果为unexpected,该程序的相关进程仅会在退出码为exitcodes中的值时重启;如果为true时</div><div class="line">startsecs=10 ;最大启动时间</div><div class="line">startretries=3 ;最大启动重试次数。超过这个次数后,该进程会标记为FATAL状态</div><div class="line">exitcodes=0,2 ;退出码,关联autorestart=unexpected</div><div class="line"></div><div class="line">stopsignal=TERM ;关闭该程序相关进程所发送的信号量。可以为TERM, HUP, INT, QUIT, KILL, USR1, or USR2</div><div class="line">stopwaitsecs=10 ;supervisord父进程等待该程序的相关子进程返回SIGCLILD信号量的时间,超时后则发送SIGKILL</div><div class="line">user=chrism ;启动该程序进程的用户</div><div class="line">redirect_stderr=false ;如果为true,则将该程序的进程错误输出到supervisor主日志文件中</div><div class="line">stdout_logfile=/tmp ;标准输出</div><div class="line">stdout_logfile_maxbytes=1MB ;日志轮滚</div><div class="line">stdout_logfile_backups=10 ;日志轮滚</div><div class="line">stdout_capture_maxbytes=1MB </div><div class="line">stderr_logfile=/a/path </div><div class="line">stderr_logfile_maxbytes=1MB</div><div class="line">stderr_logfile_backups=10</div><div class="line">stderr_capture_maxbytes=1MB</div><div class="line">environment=A="1",B="2" ;!环境变量信息</div><div class="line">serverurl=AUTO ;传送给该子进程的环境变量SUPERVISOR_SERVER_URL ,AUTO则自动提供一个Supervisord的URL。用于该进程可以和内部HTTP Server进行通信,简化进程管理。</div></pre></td></tr></table></figure><p>从swoole的文档我们得知:<br>Swoole提供了柔性终止/重启的机制,管理员只需要向SwooleServer发送特定的信号,Server的worker进程可以安全的结束。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">SIGTERM: 向主进程/管理进程发送此信号服务器将安全终止</div><div class="line">在PHP代码中可以调用$serv->shutdown()完成此操作</div><div class="line"></div><div class="line">SIGUSR1: 向主进程/管理进程发送SIGUSR1信号,将平稳地restart所有worker进程</div><div class="line">在PHP代码中可以调用$serv->reload()完成此操作</div><div class="line">swoole的reload有保护机制,当一次reload正在进行时,收到新的重启信号会丢弃</div><div class="line">如果设置了user/group,Worker进程可能没有权限向master进程发送信息,这种情况下必须使用root账户,在shell中执行kill指令进行重启</div><div class="line">reload指令对addProcess添加的用户进程无效</div><div class="line"></div><div class="line">#重启所有worker进程</div><div class="line">kill -USR1 主进程PID</div><div class="line"></div><div class="line">#仅重启task进程</div><div class="line">kill -USR2 主进程PID</div></pre></td></tr></table></figure><p>supervisor的程序restart的原理是实际上是发信号,所以我们需要给swoole的程序stop信号配置为:stopsignal=TERM </p><p>同时还需要把swoole的守护进程化设置为daemonize => 0,不然会报spawned error</p><h4 id="supervisorctl控制program"><a href="#supervisorctl控制program" class="headerlink" title="supervisorctl控制program"></a>supervisorctl控制program</h4><p>现在supervisor的server端我们已经交给systemd去管理,现在我们可以通过supervisorctl去控制配置添加的program</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">supervisorctl -c supervisor.conf status 察看supervisor的状态</div><div class="line"></div><div class="line">supervisorctl -c supervisor.conf reload 重新载入 配置文件</div><div class="line"></div><div class="line">supervisorctl -c supervisor.conf start [all]|[appname] 启动指定/所有supervisor管理的程序进程</div><div class="line"></div><div class="line">supervisorctl -c supervisor.conf stop [all]|[appname] 关闭指定/所有 supervisor管理的程序进程</div></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h3 id="使用Systemd管理Swoole服务"><a href="#使用Systemd管理Swoole服务" class="headerlink" title="使用Systemd管理Swoole服务"></a>使用Systemd管理Swoole服务</h3><p>Systemd 是 Linux 系统工具,用来启动守护进程。</p>
<p>Systemd 并不是一个命令,而是一组命令,涉及到系统管理的方方面面。包括:systemctl,systemd-analyze,hostnamectl,localectl,timedatectl,loginctl</p>
</summary>
<category term="PHP" scheme="https://renqiangme.github.io/categories/PHP/"/>
<category term="PHP" scheme="https://renqiangme.github.io/tags/PHP/"/>
<category term="Systemd" scheme="https://renqiangme.github.io/tags/Systemd/"/>
<category term="Swoole" scheme="https://renqiangme.github.io/tags/Swoole/"/>
<category term="Supervisor" scheme="https://renqiangme.github.io/tags/Supervisor/"/>
</entry>
<entry>
<title>Python获取音频时长和分割音频</title>
<link href="https://renqiangme.github.io/2017/06/26/Python%E8%8E%B7%E5%8F%96%E9%9F%B3%E9%A2%91%E6%97%B6%E9%95%BF%E5%92%8C%E5%88%86%E5%89%B2%E9%9F%B3%E9%A2%91/"/>
<id>https://renqiangme.github.io/2017/06/26/Python获取音频时长和分割音频/</id>
<published>2017-06-26T12:12:07.000Z</published>
<updated>2019-03-18T04:46:23.249Z</updated>
<content type="html"><![CDATA[<p><code>ffmpeg</code>是视频和音频处理的利器,各种转格式,提取视频中的图片,合并或者分隔音频,录制屏幕,加字幕啊…都是可以的。</p><p>因为有需求需要获取音频的长度然后来分割。</p><p>虽然<code>ffmpeg -i xxx file</code>也可以获取到音频的长度,但是可能需要正则去匹配,然后发现他们家族的<code>ffprobe</code>就可以直接返回json格式的音频信息。<code>ffprobe</code>是一个多媒体流分析工具。</p><a id="more"></a><p>大概命令如下:</p><pre><code>ffprobe -v quiet -print_format json -show_format -show_streams 1.wav</code></pre><p>python中可以这样子调用:</p><pre><code>import subprocess as sptry: command = ['ffprobe', '-v', 'quiet', '-print_format', 'json', '-show_format','-show_streams', item["file_path"]] wav_info = sp.check_output(command, stderr=sp.STDOUT) print(wav_info)except sp.CalledProcessError as e: print('get audio info by ffprobe error %s' % e.output)</code></pre><p>分割音频就需要用到<code>ffmpeg</code>了,大概命令如下:</p><pre><code>ffmpeg -i 1.wav -ss 00:00:03 -t 00:00:12 -acodec copy tmp.wav源音频:source_mp3开始位置:-ss结束位置:-t原始编码:-acodec</code></pre><p>需要注意的是:input的音频格式必须和output的音频格式一致,不然要报格式错误!</p><p>python中可以这样子调用:</p><pre><code>try: cut_command = ['ffmpeg', '-y', '-i', origin_wav, '-ss', start_time, '-t',end_time, '-acodec', 'copy', cut_wav] wav_cut_result = sp.check_call(cut_command) if wav_cut_result == 0: #todo successexcept sp.CalledProcessError as e: print('cut audio info error %s' % e.output)</code></pre><p>音频格式转换:</p><pre><code>单声道&采样率16000ffmpeg -f s16le -ar 16000 -ac 1 -i xx.pcm xx.wav-f:强制格式s16le:无压缩-ar:采样率-ac:声道-i:输入文件</code></pre><p>更多命令相关参数:<code>ffmpeg --help</code></p>]]></content>
<summary type="html">
<p><code>ffmpeg</code>是视频和音频处理的利器,各种转格式,提取视频中的图片,合并或者分隔音频,录制屏幕,加字幕啊…都是可以的。</p>
<p>因为有需求需要获取音频的长度然后来分割。</p>
<p>虽然<code>ffmpeg -i xxx file</code>也可以获取到音频的长度,但是可能需要正则去匹配,然后发现他们家族的<code>ffprobe</code>就可以直接返回json格式的音频信息。<code>ffprobe</code>是一个多媒体流分析工具。</p>
</summary>
<category term="Python" scheme="https://renqiangme.github.io/categories/Python/"/>
<category term="Python" scheme="https://renqiangme.github.io/tags/Python/"/>
<category term="ffmpeg" scheme="https://renqiangme.github.io/tags/ffmpeg/"/>
</entry>
<entry>
<title>Redis通过模式匹配模糊删除key</title>
<link href="https://renqiangme.github.io/2017/03/25/Redis%E9%80%9A%E8%BF%87%E6%A8%A1%E5%BC%8F%E5%8C%B9%E9%85%8D%E6%A8%A1%E7%B3%8A%E5%88%A0%E9%99%A4key/"/>
<id>https://renqiangme.github.io/2017/03/25/Redis通过模式匹配模糊删除key/</id>
<published>2017-03-25T07:33:29.000Z</published>
<updated>2019-03-18T04:45:59.611Z</updated>
<content type="html"><![CDATA[<p>Redis命令del不支持模式匹配,但是keys支持,如果需要通过模式匹配来删除一批,可以执行:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">/usr/local/redis/bin/redis-cli -h xx -p xx -a xx KEYS “test_*” | xargs /usr/local/redis/bin/redis-cli -h xx-p xx -a xx DEL</div></pre></td></tr></table></figure><a id="more"></a><p>关于keys命令的模式匹配介绍,可以参考:</p><p><a href="https://redis.io/commands/keys" target="_blank" rel="external">https://redis.io/commands/keys</a></p>]]></content>
<summary type="html">
<p>Redis命令del不支持模式匹配,但是keys支持,如果需要通过模式匹配来删除一批,可以执行:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">/usr/local/redis/bin/redis-cli -h xx -p xx -a xx KEYS “test_*” | xargs /usr/local/redis/bin/redis-cli -h xx-p xx -a xx DEL</div></pre></td></tr></table></figure>
</summary>
<category term="Redis" scheme="https://renqiangme.github.io/categories/Redis/"/>
<category term="Redis" scheme="https://renqiangme.github.io/tags/Redis/"/>
</entry>
<entry>
<title>在Centos上面源码安装TensorFlow</title>
<link href="https://renqiangme.github.io/2017/03/18/%E5%9C%A8Centos%E4%B8%8A%E9%9D%A2%E6%BA%90%E7%A0%81%E5%AE%89%E8%A3%85TensorFlow/"/>
<id>https://renqiangme.github.io/2017/03/18/在Centos上面源码安装TensorFlow/</id>
<published>2017-03-18T03:28:19.000Z</published>
<updated>2019-03-18T04:45:42.956Z</updated>
<content type="html"><![CDATA[<p>最先一开始用pip安装,但是总是在运行的时有源码安装效果更好的提示,所以索性源码安装,整个编译过程还真的是蛮久的。</p><a id="more"></a><p>源码安装<strong>TensorFlow</strong>需要先安装<strong>Bazel</strong>这个google推出的自动化构建工具。</p><p>1:安装Bazel之前先安装JDK</p><p>2:下载源码zip包<br><a href="https://github.com/bazelbuild/bazel/releases/" title="https://github.com/bazelbuild/bazel/releases/" target="_blank" rel="external">https://github.com/bazelbuild/bazel/releases/</a></p><p>3:然后直接执行./compile.sh等待出现安装成功后<br>4:把bazel导入到环境变量。<br>:vim /etc/profile<br>加入export PATH=/home/yangrenqiang/bazel/output:$PATH<br>source /etc/profile</p><p>5:测试bazel是否安装成功<br>bazel help</p><p>6:在github上面下载tensorflow的源码<br>7:执行./configure<br>8:<br>bazel build –config=opt //tensorflow/tools/pip_package:build_pip_package<br>9:<br>bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg<br>10:<br>sudo pip install /tmp/tensorflow_pkg/tensorflow-1.0.1-py2-none-any.whl</p><p>具体参考:<br><a href="https://www.tensorflow.org/install/install_sources" title="https://www.tensorflow.org/install/install_sources" target="_blank" rel="external">https://www.tensorflow.org/install/install_sources</a></p><p>关于TensorFlow的中文文档:<a href="http://docs.pythontab.com/tensorflow/" title="http://docs.pythontab.com/tensorflow/" target="_blank" rel="external">http://docs.pythontab.com/tensorflow/</a></p>]]></content>
<summary type="html">
<p>最先一开始用pip安装,但是总是在运行的时有源码安装效果更好的提示,所以索性源码安装,整个编译过程还真的是蛮久的。</p>
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Linux" scheme="https://renqiangme.github.io/tags/Linux/"/>
<category term="TensorFlow" scheme="https://renqiangme.github.io/tags/TensorFlow/"/>
</entry>
<entry>
<title>Linux禁止某些用户和组SSH登录</title>
<link href="https://renqiangme.github.io/2017/02/08/Linux%E7%A6%81%E6%AD%A2%E6%9F%90%E4%BA%9B%E7%94%A8%E6%88%B7%E5%92%8C%E7%BB%84SSH%E7%99%BB%E5%BD%95/"/>
<id>https://renqiangme.github.io/2017/02/08/Linux禁止某些用户和组SSH登录/</id>
<published>2017-02-08T04:10:02.000Z</published>
<updated>2019-03-18T04:45:12.696Z</updated>
<content type="html"><![CDATA[<p>Linux系统可以通过sshd的配置项,禁止某些用户SSH登录,方法如下:</p><a id="more"></a><p>1、打开sshd的配置文件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">vim /etc/ssh/sshd_config</div></pre></td></tr></table></figure><p>2、修改该配置文件,增加或修改如下行</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">#禁止用户user1登陆,多个用户空格分隔</div><div class="line"></div><div class="line">DenyUsers user1</div></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">#禁止用户组group1的所有用户登录,多个空格分隔</div><div class="line"></div><div class="line">DenyGroups group1</div></pre></td></tr></table></figure><p>3、保存配置后,重启sshd</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">/etc/rc.d/init.d/sshd restart</div></pre></td></tr></table></figure><p>完成上面的配置后,就可以禁止用户或用户组的用户进行SSH登录</p><p>4、配置完毕后,在其它linux机器上使用如下命令进行测试</p><p>使用ssh测试</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">ssh [email protected]</div><div class="line">[email protected]'s password:</div><div class="line">Permission denied, please try again.</div></pre></td></tr></table></figure><p>授权被拒绝,已经实现禁用该用户使用SSH登录</p>]]></content>
<summary type="html">
<p>Linux系统可以通过sshd的配置项,禁止某些用户SSH登录,方法如下:</p>
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Linux" scheme="https://renqiangme.github.io/tags/Linux/"/>
<category term="SSH" scheme="https://renqiangme.github.io/tags/SSH/"/>
</entry>
<entry>
<title>Linux禁止root账户远程SSH登录</title>
<link href="https://renqiangme.github.io/2017/02/08/Linux%E7%A6%81%E6%AD%A2root%E8%B4%A6%E6%88%B7%E8%BF%9C%E7%A8%8BSSH%E7%99%BB%E5%BD%95/"/>
<id>https://renqiangme.github.io/2017/02/08/Linux禁止root账户远程SSH登录/</id>
<published>2017-02-08T03:25:42.000Z</published>
<updated>2019-03-18T04:44:55.451Z</updated>
<content type="html"><![CDATA[<p>为增强服务器的安全,我们通常会禁止root账户远程SSH登录。</p><p>首先增加一个普通权限的用户:</p><a id="more"></a><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">useradd demo</div><div class="line">passwd demo123</div></pre></td></tr></table></figure><p>修改配置文件/etc/ssh/sshd_config,禁止root远程SSH登录:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">vi /etc/ssh/sshd_config</div></pre></td></tr></table></figure><p>把PermitRootLogin改为no</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">PermitRootLogin yes</div><div class="line">PermitRootLogin no</div></pre></td></tr></table></figure><p>重启sshd服务</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">service sshd restart</div></pre></td></tr></table></figure><p>然后远程管理,用普通用户demo登录,然后用 su root 切换到root用户拿到最高权限,来保障服务器的安全。</p>]]></content>
<summary type="html">
<p>为增强服务器的安全,我们通常会禁止root账户远程SSH登录。</p>
<p>首先增加一个普通权限的用户:</p>
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Linux" scheme="https://renqiangme.github.io/tags/Linux/"/>
<category term="SSH" scheme="https://renqiangme.github.io/tags/SSH/"/>
</entry>
<entry>
<title>通过Nginx代理NodeJS支持Websocket</title>
<link href="https://renqiangme.github.io/2017/01/20/%E9%80%9A%E8%BF%87Nginx%E4%BB%A3%E7%90%86NodeJS%E6%94%AF%E6%8C%81Websocket/"/>
<id>https://renqiangme.github.io/2017/01/20/通过Nginx代理NodeJS支持Websocket/</id>
<published>2017-01-20T04:05:42.000Z</published>
<updated>2019-03-25T13:37:46.698Z</updated>
<content type="html"><![CDATA[<p>NGINX自从1.3版本就开始支持WebSocket了,并且可以为WebSocket应用程序做反向代理和负载均衡。</p><p>WebSocket 和HTTP协议不同,但是WebSocket中的握手和HTTP中的握手兼容,它使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket。这使得WebSocket程序可以更容易的使用现已存在的基础设施。例如,WebSocket可以使用标准的HTTP端口 80 和 443,因此,现存的防火墙规则也同样适用。<br><a id="more"></a><br>一个WebSockets的应用程序会在客户端和服务端保持一个长时间工作的连接。用来将连接从HTTP升级到WebSocket的HTTP升级机制使用HTTP的Upgrade和Connection协议头。反向代理服务器在支持WebSocket方面面临着一些挑战。一项挑战是WebSocket是一个hop-by-hop协议,所以,当代理服务器拦截到一个客户端发来的Upgrade请求时,它(指服务器)需要将它自己的Upgrade请求发送给后端服务器,也包括合适的请求头。此外,由于WebSocket连接是长时间保持的,所以代理服务器需要允许这些连接处于打开状态,而不是像对待HTTP使用的短连接那样将其关闭。</p><p>NGINX 通过在客户端和后端服务器之间建立起一条隧道来支持WebSocket。为了使NGINX可以将来自客户端的Upgrade请求发送给后端服务器,Upgrade和Connection的头信息必须被显式的设置。如下所示:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">proxy_set_header Upgrade $http_upgrade;</div><div class="line">proxy_set_header Connection "upgrade";</div></pre></td></tr></table></figure></p><p>完整配置:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line">upstream wsbackend {</div><div class="line"> server 127.0.0.1:3000;#nodejs启动的本地端口</div><div class="line"> keepalive 8;</div><div class="line">}</div><div class="line">server</div><div class="line"> {</div><div class="line"> listen 80;</div><div class="line"> server_name xxx.com;</div><div class="line"> index index.html index.htm index.php default.html default.htm default.php;</div><div class="line"> root /home/wwwroot/xxx.com;</div><div class="line"> location / {</div><div class="line"> proxy_pass http://wsbackend;</div><div class="line">#这两个HTTP头是因为采用了nginx作为代理后,后端可以通过 X-real-ip 或 X-Forwarded-For取得用户IP地址</div><div class="line"> proxy_set_header X-Real-IP $remote_addr;</div><div class="line"> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;</div><div class="line"> proxy_set_header Host $http_host;</div><div class="line"> proxy_set_header X-NginX-Proxy true;</div><div class="line"> proxy_http_version 1.1;</div><div class="line"> proxy_set_header Upgrade $http_upgrade;# 声明支持websocket</div><div class="line"> proxy_set_header Connection "upgrade";# 声明支持websocket</div><div class="line"> proxy_redirect off;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>]]></content>
<summary type="html">
<p>NGINX自从1.3版本就开始支持WebSocket了,并且可以为WebSocket应用程序做反向代理和负载均衡。</p>
<p>WebSocket 和HTTP协议不同,但是WebSocket中的握手和HTTP中的握手兼容,它使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket。这使得WebSocket程序可以更容易的使用现已存在的基础设施。例如,WebSocket可以使用标准的HTTP端口 80 和 443,因此,现存的防火墙规则也同样适用。<br>
</summary>
<category term="Nginx" scheme="https://renqiangme.github.io/categories/Nginx/"/>
<category term="Nginx" scheme="https://renqiangme.github.io/tags/Nginx/"/>
<category term="NodeJS" scheme="https://renqiangme.github.io/tags/NodeJS/"/>
<category term="Websocket" scheme="https://renqiangme.github.io/tags/Websocket/"/>
</entry>
<entry>
<title>网页加载优化-PHP压缩网页进Redis,OpenResty端直接输出</title>
<link href="https://renqiangme.github.io/2016/12/25/%E7%BD%91%E9%A1%B5%E5%8A%A0%E8%BD%BD%E4%BC%98%E5%8C%96-PHP%E5%8E%8B%E7%BC%A9%E7%BD%91%E9%A1%B5%E8%BF%9BRedis-OpenResty%E7%AB%AF%E7%9B%B4%E6%8E%A5%E8%BE%93%E5%87%BA/"/>
<id>https://renqiangme.github.io/2016/12/25/网页加载优化-PHP压缩网页进Redis-OpenResty端直接输出/</id>
<published>2016-12-25T14:07:30.000Z</published>
<updated>2019-03-18T04:44:09.518Z</updated>
<content type="html"><![CDATA[<p>其实商城项目的网页端,观察京东,淘宝他们有很多活动页面或者商品详情页,推广力度很多,流量也就比较多,通常一个页面很大很大,整个网页内容也很多,单纯考虑从webserver到走进php,java连接数据库等等读取数据拼装,再渲染视图输出到浏览器,整个过程下来,并发不大的情况还好,一大起来的就会性能大大的降低。</p><p>对于中小型项目,解决的方案肯定没有淘宝京东的方案多。<br><a id="more"></a><br>于是就要想解决优化的方案,像商品详情页有商品相关的静态数据,同时掺杂着一些评论,购买数量等等的动态数据,其实可以把整个网页动静分离,动态数据走接口,静态数据直接gzip压缩存进缓存,通过Openresty在nginx层面通过lua直接读取就输出,然后浏览器自动解压gzip。由于页面数据是压缩了的可以节省网络IO,大大提升页面的加载速度。但是像一些活动页面,动态数据可能没有那么多,改动商品相关的价格库存…等等改动那么频繁,其实可以直接扔进CDN,动态数据也走接口。</p><p>下面来看下PHP的几个GZIP压缩相关的函数,都是基于ZLIB库。</p><p>gzcompress gzdeflate gzencode函数的区别在于它们压缩的数据格式不同:</p><p>gzcompress使用的是ZLIB格式;</p><p>gzdeflate使用的是纯粹的DEFLATE格式;</p><p>gzencode使用的是GZIP格式;</p><p>但是有一点是相同的,它们压缩数据时都使用了DEFLATE压缩算法(理论上ZLIB和GZIP格式可以使用其他的压缩算法,但是目前实践中只使用DEFLATE算法),ZLIB和GZIP只不过是在DEFLATE的基础之上加了一些头部和尾部而已。</p><p>顺便提一下,HTTP协议中的Content-Encoding: deflate使用的是ZLIB格式而不是纯DEFLATE格式。</p><p>通过测试发现,gzencode和gzdeflate浏览器可以自动解压出来,前提是:http的请求头里面有accept-encoding:gzip, deflate,说明方案是可行的,但是对于一些浏览器可能不支持自动解压,所以需要判断下请求头,如果不支持,就需要lua解压之后再输出。</p><p>既然使用Openresty就在社区搜索了下。<br>lua的zlib库有两个:<br>–<a href="https://github.com/brimworks/lua-zlib" title="lua-zlib" target="_blank" rel="external">lua-zlib</a><br>–通过LuaJIT的FFI库来包装ZLIB模块</p><p>选择的是:lua-zlib</p><p>lua输出判断函数:<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line"><span class="keyword">local</span> <span class="function"><span class="keyword">function</span> <span class="title">echoPage</span><span class="params">(index_page)</span></span></div><div class="line"><span class="comment">--如果index_page=nil 就继续让nginx执行下一阶段,走进php让php自己处理</span></div><div class="line"><span class="keyword">if</span> <span class="keyword">not</span> index_page <span class="keyword">then</span></div><div class="line">ngx.exit(ngx.OK)</div><div class="line"><span class="keyword">end</span></div><div class="line"></div><div class="line"><span class="keyword">local</span> accept_encoding_table = ngx.req.get_headers()</div><div class="line"><span class="keyword">local</span> accept_encoding = accept_encoding_table[<span class="string">"accept-encoding"</span>]</div><div class="line"><span class="keyword">local</span> need_uncompress = <span class="number">0</span></div><div class="line"><span class="keyword">if</span> accept_encoding ~= <span class="keyword">nil</span> <span class="keyword">and</span> #accept_encoding><span class="number">0</span> <span class="keyword">then</span></div><div class="line"><span class="keyword">local</span> begin,stop = ngx.re.find(accept_encoding,<span class="string">'gzip'</span>)</div><div class="line"><span class="keyword">if</span> begin ~= <span class="keyword">nil</span> <span class="keyword">then</span></div><div class="line">need_uncompress = <span class="number">0</span></div><div class="line"><span class="keyword">else</span></div><div class="line">need_uncompress = <span class="number">1</span></div><div class="line"><span class="keyword">end</span></div><div class="line"><span class="keyword">else</span></div><div class="line">need_uncompress = <span class="number">1</span></div><div class="line"><span class="keyword">end</span></div><div class="line"><span class="keyword">if</span> need_uncompress == <span class="number">1</span> <span class="keyword">then</span></div><div class="line"><span class="keyword">local</span> zlib = <span class="built_in">require</span> <span class="string">"zlib"</span></div><div class="line"><span class="keyword">local</span> stream = zlib.inflate()</div><div class="line"><span class="keyword">local</span> inflated,stream_eof,bytes_in,bytes_out = stream(res)</div><div class="line">ngx.say(inflated)</div><div class="line"><span class="keyword">else</span></div><div class="line">ngx.header[<span class="string">"Content-Encoding"</span>] = <span class="string">"gzip"</span><span class="comment">--避免Nginx再去压缩,需要发送一个响应头,告诉Nginx是一个gzip压缩的</span></div><div class="line">ngx.send_headers()</div><div class="line">ngx.say(res)</div><div class="line"><span class="keyword">end</span></div><div class="line"><span class="keyword">end</span></div></pre></td></tr></table></figure></p><p>注释:<br><figure class="highlight lua"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">ngx.exit(ngx.OK)<span class="comment">--因为openresty有执行阶段这一个说法,是告诉openresty执行下一阶段</span></div><div class="line">ngx.exit(<span class="number">200</span>)<span class="comment">--意思是直接返回200,不再向下执行。也可以是其他的http状态码。</span></div></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<p>其实商城项目的网页端,观察京东,淘宝他们有很多活动页面或者商品详情页,推广力度很多,流量也就比较多,通常一个页面很大很大,整个网页内容也很多,单纯考虑从webserver到走进php,java连接数据库等等读取数据拼装,再渲染视图输出到浏览器,整个过程下来,并发不大的情况还好,一大起来的就会性能大大的降低。</p>
<p>对于中小型项目,解决的方案肯定没有淘宝京东的方案多。<br>
</summary>
<category term="OpenResty" scheme="https://renqiangme.github.io/categories/OpenResty/"/>
<category term="PHP" scheme="https://renqiangme.github.io/tags/PHP/"/>
<category term="OpenResty" scheme="https://renqiangme.github.io/tags/OpenResty/"/>
<category term="Redis" scheme="https://renqiangme.github.io/tags/Redis/"/>
</entry>
<entry>
<title>Linux学习之权限管理</title>
<link href="https://renqiangme.github.io/2016/12/24/Linux%E5%AD%A6%E4%B9%A0%E4%B9%8B%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86/"/>
<id>https://renqiangme.github.io/2016/12/24/Linux学习之权限管理/</id>
<published>2016-12-24T15:03:47.000Z</published>
<updated>2019-03-18T10:12:00.338Z</updated>
<content type="html"><![CDATA[<h3 id="ACL权限"><a href="#ACL权限" class="headerlink" title="ACL权限"></a>ACL权限</h3><h5 id="1:ACL权限简介和开启"><a href="#1:ACL权限简介和开启" class="headerlink" title="1:ACL权限简介和开启"></a>1:ACL权限简介和开启</h5><ul><li><p>A:不再考虑身份。用户或用户组直接拿过来给它改权限</p></li><li><p>B:查看分区ACL权限是否开启<br>dumpe2fs -h /dev/sda3 #dump2fs命令是查询指定分区详细文件系统信息的命令<br>选项:-h 仅显示超级块中信息,而不显示磁盘块组的详细信息</p><ul><li>步骤1:df -h #查看当前系统分区使用情况,容量,已用,可用,挂载点,找到用户所在分区。</li><li>步骤2:dumpe2fs -h /dev/sda3</li></ul></li><li>C:临时开启分区ACL权限<br>mount -o remount,acl / #重新挂载根分区,并载入acl权限</li><li>D:永久开启分区ACL权限<ul><li>步骤1:vi /etc/fstab #加入acl<br>UUID=c2cq6f57-b15c-43ea-bca0-f239083d8bd2 / ext4 defaults,acl 1 1 #defaults后面加了一个acl</li><li>步骤2:mount -o remount / #重新挂载文件系统或重启动系统,使修改生效 </li></ul></li></ul><a id="more"></a> <h5 id="2:查看与设定ACL权限"><a href="#2:查看与设定ACL权限" class="headerlink" title="2:查看与设定ACL权限"></a>2:查看与设定ACL权限</h5><ul><li><p>A:查看ACL命令 getfacl 文件名 #查看ACL权限</p></li><li><p>B:设定ACL权限 setfacl 选项 文件名</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">选项:</div><div class="line">-m 设定ACL权限 </div><div class="line">给用户设置ACL权限 setfacl -m u:qingwa:rx /project/</div><div class="line"> 给用户组设定ACL权限 setfacl -m g:xxgroup:rwx project/</div><div class="line"></div><div class="line">-x 删除指定的ACL权限 setfacl -x g:xxgroup /project/ #删除xxgroup在project下面的ACL权限</div><div class="line">-b 删除所有的ACL权限 setfacl -b /project/ #会删除在project下面所有用户用户组的ACL权限</div><div class="line">-d 设定默认的ACL权限</div><div class="line">-k 删除默认ACL权限</div><div class="line">-R 递归设定ACL权限</div></pre></td></tr></table></figure></li></ul><h5 id="3-最大有效权限与删除ACL权限"><a href="#3-最大有效权限与删除ACL权限" class="headerlink" title="3:最大有效权限与删除ACL权限"></a>3:最大有效权限与删除ACL权限</h5><p>最大有效权限mask<br>mask是用来指定最大有效权限的。如果我给用户赋予了ACL权限,是需要和mask的权限“相与”才能得到用户的真正权限。(相与—相当于逻辑的与 一个为假就都为假)</p><h5 id="4:默认ACL权限和递归ACL权限"><a href="#4:默认ACL权限和递归ACL权限" class="headerlink" title="4:默认ACL权限和递归ACL权限"></a>4:默认ACL权限和递归ACL权限</h5><p>递归是父目录在设定ACL权限时,所有的子文件和子目录也会拥有相同的ACL权限。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">setfacl -m u:用户名:权限 -R 文件名</div></pre></td></tr></table></figure></p><p>默认ACL权限<br>默认ACL权限的作用是如果给父目录设定了ACL权限,那么父目录中所有新建的子文件都会继承父目录的ACL权限。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">setfacl -m d:u用户名:权限 文件名</div></pre></td></tr></table></figure></p><h3 id="文件特殊权限"><a href="#文件特殊权限" class="headerlink" title="文件特殊权限"></a>文件特殊权限</h3><h5 id="1-SetUID"><a href="#1-SetUID" class="headerlink" title="1: SetUID"></a>1: SetUID</h5><p><strong>SetUID的功能</strong></p><ul><li>只有可以执行的二进制程序才能设定SUID权限</li><li>命令执行者要对该程序拥有x(执行)权限</li><li>命令执行者在执行该程序时获得该程序文件宿主的身份(在执行程序的过程中灵魂附体为文件的属主)</li><li>SetUID权限只在该程序执行过程中有效,也就是说身份改变只在程序执行过程中有效。</li></ul><p>设置SUID:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">4代表SUID</div><div class="line">chmod 4755 文件名</div><div class="line">chmod u+s 文件名</div></pre></td></tr></table></figure></p><p>取消SUID:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">chmod 755 文件名</div><div class="line">chmod u-s 文件名</div></pre></td></tr></table></figure></p><p>危险的SetUID:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">.关键目录应该严格控制写权限,比如“/”、“/usr”等。</div><div class="line">.用户的密码设置要严格遵守密码三原则。</div><div class="line">.对系统中默认应该是具有SetUID权限的文件作一列表,定时检查有没有这之外的文件被设置了SetUID权限。</div></pre></td></tr></table></figure></p><h5 id="2-SetGID"><a href="#2-SetGID" class="headerlink" title="2: SetGID"></a>2: SetGID</h5><p>SetGID针对文件的作用:</p><ul><li>只有可执行的二进制程序才能设置SGID权限</li><li>命令执行者要对该程序拥有x(执行)权限</li><li>命令执行在执行程序的时候,组身份升级为该程序文件的属组</li><li>SetGID权限同样只在该程序执行过程中有效,也就是说组身份改变只在程序执行过程中有效</li></ul><p>SetGID针对目录的作用:</p><ul><li>普通用户必须对此目录拥有r和x权限,才能进入此目录</li><li>普通用户在此目录中的有效组会变成此目录的属组</li><li>若普通用户对此目录拥有w权限时,新建的文件的默认属组是这个目录的属组</li></ul><p>设定SetGID:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">2代表SGID</div><div class="line">chmod 2755 文件名</div><div class="line">chmod g+s 文件名</div></pre></td></tr></table></figure></p><h5 id="3-Sticky-BIT"><a href="#3-Sticky-BIT" class="headerlink" title="3: Sticky BIT"></a>3: Sticky BIT</h5><p><strong>SBIT粘着位作用</strong></p><ul><li>粘着位目前只对目录有效</li><li>普通用户对该目录拥有w和x权限,即普通用户可以在此目录拥有写入权限</li><li>如果没有粘着位,因为普通用户拥有w权限,所以可以删除此目录下所有文件,包括其他用户建立的文件。一旦赋予了粘着位,除了root可以删除所有文件,普通用户就算拥有w权限,也只能删除自己建立的文件,但是不能删除其他用户建立的文件。</li></ul><p>设置与取消粘着位<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">1代表SBIT</div><div class="line">设置粘着位</div><div class="line">chmod 1755 目录名</div><div class="line">chmod o+t 目录名</div></pre></td></tr></table></figure></p><p>取消粘着位<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">chmod 777 目录名</div><div class="line">chmod o-t 目录名</div></pre></td></tr></table></figure></p><h3 id="文件系统属性chattr权限"><a href="#文件系统属性chattr权限" class="headerlink" title="文件系统属性chattr权限"></a>文件系统属性chattr权限</h3><p>chattr[+-=][选项]文件或目录名<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">+:增加权限</div><div class="line">-:删除权限</div><div class="line">=:等于某权限</div><div class="line"> </div><div class="line">选项:</div><div class="line"> i:如果对文件设置i属性,那么不允许对文件进行删除,改名,也不能添加和修改数据;如果对目录设置i属性,那么只能修改目录下文件的数据,但不允许建立和删除文件。</div><div class="line"> a:如果对文件设置a属性,那么只能在文件中增加数据,但是不能删除也不能修改数据;如果对目录设置a属性,那么只允许在目录中建立和修改文件,但是不允许删除。</div></pre></td></tr></table></figure></p><p>2、查看文件系统属性:lsattr 选项 文件名</p><p>选项:</p><ul><li>-a 显示所有文件和目录 </li><li>-d若目标是目录,仅列出目录本身的属性,而不是子文件的。</li></ul><h3 id="系统命令sudo权限"><a href="#系统命令sudo权限" class="headerlink" title="系统命令sudo权限"></a>系统命令sudo权限</h3><ul><li>1:<ul><li>root把本来只能超级用户执行的命令赋予普通用户执行</li><li>sudo的操作对象是系统命令</li></ul></li><li>2:sudo使用<br>visudo #需要超级管理员执行这个命令 实际修改的是<code>/etc/sudoers</code>文件 </li></ul>]]></content>
<summary type="html">
<h3 id="ACL权限"><a href="#ACL权限" class="headerlink" title="ACL权限"></a>ACL权限</h3><h5 id="1:ACL权限简介和开启"><a href="#1:ACL权限简介和开启" class="headerlink" title="1:ACL权限简介和开启"></a>1:ACL权限简介和开启</h5><ul>
<li><p>A:不再考虑身份。用户或用户组直接拿过来给它改权限</p>
</li>
<li><p>B:查看分区ACL权限是否开启<br>dumpe2fs -h /dev/sda3 #dump2fs命令是查询指定分区详细文件系统信息的命令<br>选项:-h 仅显示超级块中信息,而不显示磁盘块组的详细信息</p>
<ul>
<li>步骤1:df -h #查看当前系统分区使用情况,容量,已用,可用,挂载点,找到用户所在分区。</li>
<li>步骤2:dumpe2fs -h /dev/sda3</li>
</ul>
</li>
<li>C:临时开启分区ACL权限<br>mount -o remount,acl / #重新挂载根分区,并载入acl权限</li>
<li>D:永久开启分区ACL权限<ul>
<li>步骤1:vi /etc/fstab #加入acl<br>UUID=c2cq6f57-b15c-43ea-bca0-f239083d8bd2 / ext4 defaults,acl 1 1 #defaults后面加了一个acl</li>
<li>步骤2:mount -o remount / #重新挂载文件系统或重启动系统,使修改生效 </li>
</ul>
</li>
</ul>
</summary>
<category term="Linux" scheme="https://renqiangme.github.io/categories/Linux/"/>
<category term="Linux" scheme="https://renqiangme.github.io/tags/Linux/"/>
</entry>
</feed>