-
Notifications
You must be signed in to change notification settings - Fork 0
/
local-search.xml
639 lines (304 loc) · 204 KB
/
local-search.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
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>Vscode配置java环境</title>
<link href="/2024/09/16/Vscode%E9%85%8D%E7%BD%AEjava%E7%8E%AF%E5%A2%83/"/>
<url>/2024/09/16/Vscode%E9%85%8D%E7%BD%AEjava%E7%8E%AF%E5%A2%83/</url>
<content type="html"><![CDATA[<p>#java #VSCode<br>由于上课的需要,我开始考虑使用vscode作为java的ide。在此作为一个记录</p><p>我到VsCode的官网翻了翻,发现他提供了一个Coding Pack,里面包含了VS Code、JDK以及一些必要的插件,因此如果嫌麻烦直接用下面的链接安装就好了。</p><p><a href="https://aka.ms/vscode-java-installer-win">Windows - Coding Pack</a><br><a href="https://aka.ms/vscode-java-installer-mac">MacOS - Coding Pack</a></p><p>但是很显然我并没有用这个,<del>主要是因为刚开始我没看到</del></p><p>如果按照正常的安装流程,我们需要先有VsCode,这个自不必多言。然后就需要安装<a href="https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack">Extension Pack for Java</a>这个插件包,里面提供包含了一些可能需要的插件。但是我看了一眼发现这个插件包只有两个插件是必要的,也就是- <a href="https://marketplace.visualstudio.com/items?itemName=redhat.java">Language Support for Java™ by Red Hat</a>和 <a href="https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug">Debugger for Java</a></p><p>接下来我们就需要安装JDK~</p><h2 id="安装JDK"><a href="#安装JDK" class="headerlink" title="安装JDK"></a>安装JDK</h2><h3 id="什么是JDK?"><a href="#什么是JDK?" class="headerlink" title="什么是JDK?"></a>什么是JDK?</h3><p>JDK(Java Development Kit)是Java开发工具包,用于开发Java应用程序,它包含了编写、编译、调试Java代码的工具,最重要的工具是<code>javac</code>,用于将Java源代码编译成字节码。</p><p>而JRE是Java运行时环境,专门用于运行Java程序。JDK包含了JRE,所以它可以执行和开发Java程序。因此,JDK = JRE + 开发工具</p><p>因此我们需要用到的是JDK而不是JRE。因为我们需要编译并运行代码。</p><h3 id="安装哪个JDK?"><a href="#安装哪个JDK?" class="headerlink" title="安装哪个JDK?"></a>安装哪个JDK?</h3><p>Java的特点是百花齐放,不像c#或者go只有一家主导。因此我们不止有JDK的发行版需要选择,还有JDK的版本需要选择。有以下发行版可供选择:</p><ul><li><a href="https://aws.amazon.com/corretto">Amazon Corretto</a></li><li><a href="https://www.azul.com/downloads/?package=jdk">Azul Zulu</a></li><li><a href="https://adoptium.net/">Eclipse Adoptium’s Temurin</a></li><li><a href="https://developer.ibm.com/languages/java/semeru-runtimes">IBM Semeru Runtimes</a></li><li><a href="https://www.microsoft.com/openjdk">Microsoft Build of OpenJDK</a></li><li><a href="https://www.oracle.com/java/technologies/javase-downloads.html">Oracle Java SE</a></li><li><a href="https://developers.redhat.com/products/openjdk/download">Red Hat build of OpenJDK</a></li><li><a href="https://sapmachine.io/">SapMachine</a></li></ul><p>一般来说,我更推荐Eclipse Adoptium’s Temurin,因为它的前身是著名的AdoptOpenJDK,更新到jdk16后就停止更新了,因为AdoptOpenJDK移交给Eclipse基金会后改名为:Adoptium Eclipse Temurin,后续维护工作就交给Eclipse基金会了。当然如果你公司不怕花钱,你可以选择用甲骨文Oracle官方的JDK,最后的甲骨文免费版是jdk8u202,想用后面的版本就得花钱了,甲骨文的JDK肯定是最稳定、最效率、最专业的,如果不想花钱那就推荐用Adoptium Eclipse Temurin这个OpenJDK发行版。它背后是Eclipse基金会,项目稳定,多家大厂支持,不受制于某一特定厂家。</p><p>现在是版本。一般来说常用的是JDK8、JDK11、JDK17和最新的JDK21这几个版本,除此之外还有一堆。我更推荐JDK17,他是当前热门的 LTS 版本,但是相对来说,JDK8和JDK11是最常用的长期支持版本。JDK11的生态不太行,参杂在JDK8与JDK17之间。</p><p>知乎大佬直呼:</p><p>一直以来,Java8 都是 Java 社区心头的痛。因为它代表着以稳定性为主的企业管理层,与拥抱变化为主的底层码农层之间的、爱的魔力拉锯战。</p><p>不升!成为各大厂心照不宣的选择。</p><p>现在,这种平衡或将打破。因为 Java 届的霸主框架 SpringBoot,选择了最小支持的 Java lts 版本,就是最新的 Java17。</p><p>看来看去,还是选择了JDK17。</p><h2 id="你的第一份Java代码"><a href="#你的第一份Java代码" class="headerlink" title="你的第一份Java代码"></a>你的第一份Java代码</h2><p>创建一个新的java文件,然后输入</p><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Test</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> {<br> System.out.println(<span class="hljs-string">"Hello World!"</span>);<br> }<br>}<br></code></pre></td></tr></table></figure><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202409160250810.png" alt="image.png"></p><p>然后点击RUN即可。</p><blockquote><p>[!Note] 一点小提示<br>如果你在 VS Code 中打开一个 Java 文件但不打开其所在的文件夹,Java 语言服务器可能无法正常工作。</p></blockquote>]]></content>
<tags>
<tag>#VSCode</tag>
<tag>#java</tag>
</tags>
</entry>
<entry>
<title>使用ADB实现短信发送</title>
<link href="/2024/09/13/%E4%BD%BF%E7%94%A8ADB%E5%AE%9E%E7%8E%B0%E7%9F%AD%E4%BF%A1%E5%8F%91%E9%80%81/"/>
<url>/2024/09/13/%E4%BD%BF%E7%94%A8ADB%E5%AE%9E%E7%8E%B0%E7%9F%AD%E4%BF%A1%E5%8F%91%E9%80%81/</url>
<content type="html"><![CDATA[<p>#ADB #短信服务 #安卓<br>最近社团工作需要使用短信发送面试通知,本来我们是想直接使用诸如阿里云一类的<a href="https://www.aliyun.com/product/sms">短信服务</a>的,但由于短信模板审核一直无法通过,我不得不寻求其他替代方案。最终,我想到可以利用ADB(Android Debug Bridge)实现短信的自动发送。在这过程中遇到了一些挑战,特此记录下来,帮助后人少走弯路</p><h2 id="核心命令"><a href="#核心命令" class="headerlink" title="核心命令"></a>核心命令</h2><p>实现这个功能的核心在于两条ADB命令</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs bash">// 打开系统默认的短信应用并填充内容<br>adb shell am start -a android.intent.action.SENDTO -d sms:<phone> --es sms_body <span class="hljs-string">"<text>"</span><br><br>// 模拟点击发送按键<br>adb shell input tap <x> <y><br></code></pre></td></tr></table></figure><p>第一条命令的含义是打开系统默认的短信引用并填充内容,但是并不会自动发送,因此我们需要第二条命令模拟点击发送按键。为了获取点击位置,一个简单的方式就是通过我们手机的开发者选项,打开“显示触摸操作”和“显示指针位置”之类的设置,然后我们手动进行测试得出触摸屏幕的xy坐标即可。</p><p>这个方式在shell使用的时候是正常的,然而当我将这些命令移植到Python脚本中时,发现它并不总是如预期般顺利,也就是会失效而导致无法正确获取焦点,导致后面的输入都会出现问题。想来可能是因为设备没有足够的时间去处理每个命令,因此我们可以尝试使用滑动的命令或者使用<code>time.sleep(0)</code>的方法延长操作时间,让设备有足够的时间处理命令。例如:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">adb shell input swipe <from_x> <from_y> <to_x> <to_y><br></code></pre></td></tr></table></figure><p>接下来我们需要进入下一个问题的解决。对于面试短信而言,那当然包含面试人姓名、面试时间、面试地点等信息,那简单来说,其实我们正常做一个短信模板,然后把变量填充进去,然后直接通过上面的命令填充到短信应用发送就完了。但是显然这一切并没有这么简单。</p><h2 id="处理多行短信内容"><a href="#处理多行短信内容" class="headerlink" title="处理多行短信内容"></a>处理多行短信内容</h2><p>面试通知的短信模板通常会包含诸如面试者姓名、面试时间、地点等多个变量的信息。按理说,可以将这些变量填充进短信模板,然后使用上面的命令发送即可。然而,在实际操作中,使用<code>adb shell am start -a android.intent.action.SENDTO -d sms:<phone> --es sms_body "<text>"</code>命令发送多行文本时,只有第一行被填充,其他行被忽略。</p><p>既然这个不行,那我分成多行输入不就得了。但是这个时候又出现了一个问题,那就上面这个写法是覆写文本框而不是追加内容。因此这种方法并不可行。</p><h2 id="逐步填充文本框"><a href="#逐步填充文本框" class="headerlink" title="逐步填充文本框"></a>逐步填充文本框</h2><p>于是我只能尝试使用一个很呆的方法,那就是用上面这个命令打开短信应用但不填充内容,然后再通过点击文本框获取焦点,逐行填充内容。也就是:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-comment"># 打开默认短信应用</span><br>adb shell am start -a android.intent.action.SENDTO -d sms:<phone><br><br><span class="hljs-comment"># 点击文本框获取焦点</span><br>adb shell input tap <x> <y><br><br><span class="hljs-comment"># 填充内容</span><br>adb shell input text <text><br></code></pre></td></tr></table></figure><p>此时出现了一个新的问题:<code>adb shell input text</code>命令无法输入中文,导致报错:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">Exception occurred <span class="hljs-keyword">while</span> executing <span class="hljs-string">'text'</span>:<br>java.lang.NullPointerException: Attempt to get length of null array<br></code></pre></td></tr></table></figure><h2 id="ADBKeyBoard"><a href="#ADBKeyBoard" class="headerlink" title="ADBKeyBoard"></a>ADBKeyBoard</h2><p>上面的问题是因为<code>adb shell input text</code>命令不能输入中文,因为它并不是为此目的而设计的。但是幸运的是,有这个项目的存在:<a href="[senzhk/ADBKeyBoard: Android Virtual Keyboard Input via ADB (Useful for Test Automation">ADBKeyboard</a> (github.com)](<a href="https://github.com/senzhk/ADBKeyBoard)),这使得后续的工作得以顺利进行。">https://github.com/senzhk/ADBKeyBoard)),这使得后续的工作得以顺利进行。</a></p><p>因此我们只需要先<a href="https://github.com/senzhk/ADBKeyBoard/blob/master/ADBKeyboard.apk">下载</a>并安装ADBKeyBoard,然后再命令行中启用ADBKeyBoard并将其设置为默认输入法即可。可以使用以下命令:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">adb shell ime <span class="hljs-built_in">enable</span> com.android.adbkeyboard/.AdbIME<br>adb shell ime <span class="hljs-built_in">set</span> com.android.adbkeyboard/.AdbIME<br></code></pre></td></tr></table></figure><p>当我们完成任务的时候,可以使用以下命令来将系统输入法服务重置为默认选项,省去手动切换的麻烦。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">adb shell ime reset<br></code></pre></td></tr></table></figure><h2 id="脚本,启动!"><a href="#脚本,启动!" class="headerlink" title="脚本,启动!"></a>脚本,启动!</h2><p>知道了这些,后面就简单了。接下来就是编写实际的Python脚本,根据Excel表格中的数据逐条发送面试通知短信。</p><p>例如:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">import</span> os<br><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd<br><span class="hljs-keyword">import</span> time<br><br><span class="hljs-keyword">def</span> <span class="hljs-title function_">fill_template_from_excel</span>(<span class="hljs-params">template_path, excel_path</span>):<br> <span class="hljs-keyword">try</span>:<br> df = pd.read_excel(excel_path)<br> <span class="hljs-keyword">for</span> index, row <span class="hljs-keyword">in</span> df.iterrows():<br> phone = row[<span class="hljs-string">'Phone'</span>]<br> variables = {<br> <span class="hljs-string">"name"</span>: row[<span class="hljs-string">'Name'</span>],<br> <span class="hljs-string">"time"</span>: row[<span class="hljs-string">'Time'</span>]<br> }<br><br> output_lines = []<br> <span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(template_path, <span class="hljs-string">'r'</span>,<br> encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> file:<br> <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> file:<br> <span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> variables.items():<br> <span class="hljs-comment"># 如果变量存在于当前行,则进行替换</span><br> <span class="hljs-keyword">if</span> <span class="hljs-string">f"{{<span class="hljs-subst">{key}</span>}}"</span> <span class="hljs-keyword">in</span> line:<br> line = line.replace(<span class="hljs-string">f"{{<span class="hljs-subst">{key}</span>}}"</span>, value)<br> output_lines.append(line)<br><br> <span class="hljs-built_in">print</span>(<span class="hljs-string">f"生成的消息(第 <span class="hljs-subst">{index + <span class="hljs-number">1</span>}</span> 行):"</span>)<br> <span class="hljs-built_in">print</span>(<span class="hljs-string">f"手机号:<span class="hljs-subst">{phone}</span>"</span>)<br> <br> os.system(<span class="hljs-string">f"adb shell am start -a android.intent.action.SENDTO -d sms:<span class="hljs-subst">{phone}</span>"</span>)<br> time.sleep(<span class="hljs-number">0.5</span>) <span class="hljs-comment"># 这里不能太快,不然会出现焦点错误的问题</span><br> os.system(<span class="hljs-string">"adb shell input tap 389 2305"</span>)<br> <br> <span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> output_lines:<br> os.system(<span class="hljs-string">f"adb shell am broadcast -a ADB_INPUT_TEXT --es msg \"<span class="hljs-subst">{line}</span>\""</span>)<br> <span class="hljs-comment"># 系统默认回车</span><br> os.system(<span class="hljs-string">"adb shell input keyevent 66"</span>)<br> <br> <span class="hljs-comment"># 发送按键位置</span><br> os.system(<span class="hljs-string">"adb shell input swipe 985 2140 985 2140"</span>)<br> <span class="hljs-built_in">print</span>(<span class="hljs-string">"-"</span> * <span class="hljs-number">50</span>)<br><br> <span class="hljs-keyword">except</span> FileNotFoundError <span class="hljs-keyword">as</span> e:<br> <span class="hljs-built_in">print</span>(<span class="hljs-string">f"文件未找到: <span class="hljs-subst">{e}</span>"</span>)<br><br> <span class="hljs-keyword">except</span> KeyError <span class="hljs-keyword">as</span> e:<br> <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Excel 文件中缺少所需的列: <span class="hljs-subst">{e}</span>"</span>)<br><br> <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:<br> <span class="hljs-built_in">print</span>(<span class="hljs-string">f"读取文件或处理数据时发生错误: <span class="hljs-subst">{e}</span>"</span>)<br><br><span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:<br> template_path = <span class="hljs-string">"text.txt"</span><br> excel_path = <span class="hljs-string">"data.xlsx"</span><br> <br> fill_template_from_excel(template_path, excel_path)<br></code></pre></td></tr></table></figure><h2 id="Addition"><a href="#Addition" class="headerlink" title="Addition"></a>Addition</h2><p>实际使用的时候,有可能会出现这个问题:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">Broadcast completed: result=0<br>Broadcasting: Intent { act=ADB_INPUT_TEXT dat=8: flg=0x400000 (has extras) }<br></code></pre></td></tr></table></figure><p>然后文本框输入时空的。这是因为输入的文本中有不应存在的空格….就是系统会将文本中的空格识别为命令分隔符,因此没有输入也算是正常。此时我们是使用<br><code>%s</code>表示空格是没有用的,因此我们需要对空格进行转义…(也就我随便试试才知道这个逆天的操作的)</p><p>是的,你没有看错。我们需要对文本进行转义。例如:</p><figure class="highlight livescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs livescript"><span class="hljs-string">\</span> <span class="hljs-string">\</span> <span class="hljs-string">\</span> <span class="hljs-string">\</span> 面试时间:<span class="hljs-number">9</span>月<span class="hljs-number">21</span>日{time}<br></code></pre></td></tr></table></figure><p>说实话,这种写法,我也是头一回见到。</p><h2 id="Summary"><a href="#Summary" class="headerlink" title="Summary"></a>Summary</h2><p>通过上述方法,我们成功实现了利用ADB自动化发送面试通知短信的过程。虽然使用ADB的方式在稳定性上不如专业的短信服务,但在某些特定场景下,它依然可以作为一种临时解决方案。</p><p>其实正如冰冰学长提到,如果是他,他可能会选择使用KDE Connect这类工具来实现类似的功能。而KDE Connect是一种用于跨设备通信和共享的工具,可能提供更加灵活和便捷的方式来处理短信发送。不过由于时间关系,我还没来得及对这种方法进行实验和验证。希望后续有时间能探索更优的解决方案,尝试使用他所说的工具甚至是使用开发安卓应用等方式实现短信发送<del>(看起来不会那么呆,安卓应用的话几行就写完了)</del></p>]]></content>
<tags>
<tag>#ADB</tag>
<tag>#短信服务</tag>
<tag>#安卓</tag>
</tags>
</entry>
<entry>
<title>Git warning:LF will be replaced by CRLF the next time Git touches it</title>
<link href="/2024/09/11/Git%20warning%EF%BC%9ALF%20will%20be%20replaced%20by%20CRLF%20the%20next%20time%20Git%20touches%20it/"/>
<url>/2024/09/11/Git%20warning%EF%BC%9ALF%20will%20be%20replaced%20by%20CRLF%20the%20next%20time%20Git%20touches%20it/</url>
<content type="html"><![CDATA[<p>#github</p><p>这个警告表明文件的行尾符(Line Feed,简称 LF)将被替换为回车符和换行符(Carriage Return Line Feed,简称 CRLF)——也就是说,文件的行尾格式会发生变化。</p><p>这其实是由于不同操作系统对行尾符的处理方式不同:</p><ul><li><strong>Linux 和 macOS</strong> 使用 LF (<code>\n</code>) 作为行尾符。</li><li><strong>Windows</strong> 使用 CRLF (<code>\r\n</code>) 作为行尾符。</li></ul><p>Git 提供了一些配置来处理这种跨平台的行尾符差异:<br><code>core.autocrlf</code> 设置</p><ul><li>当它被设置为 <code>true</code> 时,Git 在将文件检出到工作目录时,会自动将 LF 转换为 CRLF;而在提交时,又会将 CRLF 转换回 LF。</li><li>当它被设置为 <code>input</code> 时,Git 只会在提交时将 CRLF 转换为 LF,而不对检出时的行尾符进行转换。- 设置为 <code>false</code> 时,Git 不会进行任何行尾符的转换。</li></ul><p>如果我们希望避免这个警告,可以根据项目的需求或系统的习惯调整 <code>core.autocrlf</code> 配置,使得 Git 不会自动修改行尾符。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">git config --global core.autocrlf <span class="hljs-literal">false</span><br></code></pre></td></tr></table></figure><p>我们也可以在项目的 <code>.gitattributes</code> 文件中指定行尾符的处理方式,使得 Git 会强制所有 HTML 文件使用 LF 行尾符。比如:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">*.html text eol=lf<br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>#github</tag>
</tags>
</entry>
<entry>
<title>WSL:”NAT 模式下的 WSL 不支持 localhost 代理“提示以及mirrored网络模式与TUN模式的冲突</title>
<link href="/2024/09/11/WSL%EF%BC%9A%E2%80%9DNAT%20%E6%A8%A1%E5%BC%8F%E4%B8%8B%E7%9A%84%20WSL%20%E4%B8%8D%E6%94%AF%E6%8C%81%20localhost%20%E4%BB%A3%E7%90%86%E2%80%9C%E6%8F%90%E7%A4%BA%E4%BB%A5%E5%8F%8Amirrored%E7%BD%91%E7%BB%9C%E6%A8%A1%E5%BC%8F%E4%B8%8ETUN%E6%A8%A1%E5%BC%8F%E7%9A%84%E5%86%B2%E7%AA%81/"/>
<url>/2024/09/11/WSL%EF%BC%9A%E2%80%9DNAT%20%E6%A8%A1%E5%BC%8F%E4%B8%8B%E7%9A%84%20WSL%20%E4%B8%8D%E6%94%AF%E6%8C%81%20localhost%20%E4%BB%A3%E7%90%86%E2%80%9C%E6%8F%90%E7%A4%BA%E4%BB%A5%E5%8F%8Amirrored%E7%BD%91%E7%BB%9C%E6%A8%A1%E5%BC%8F%E4%B8%8ETUN%E6%A8%A1%E5%BC%8F%E7%9A%84%E5%86%B2%E7%AA%81/</url>
<content type="html"><![CDATA[<p>#wsl #nat #网络<br>我们在启动wsl的时候经常看到这样的提示,这样我很是不爽</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">wsl: 检测到 localhost 代理配置,但未镜像到 WSL。NAT 模式下的 WSL 不支持 localhost 代理。<br></code></pre></td></tr></table></figure><p>这个问题其实是因为我使用了TUN模式进行代理,它会将系统的所有流量通过代理,包括 <code>localhost</code> 流量。<del>但是这个问题对我来说其实问题不大毕竟我用TUN</del></p><p>这个要说的话其实是WSL2更新了一种新的网络模式。首先我们就需要说一下这个wsl和wsl2的区别了。</p><p>WSL 1 与 Windows 系统共享同一个 IP 地址。因此,网络请求的处理比较简单,Linux 子系统内的应用程序可以直接通过 Windows 的 IP 地址进行访问。而WSL 2 使用了 Hyper-V 虚拟化技术,在运行时有一个独立的虚拟机。因此,WSL 2 的 Linux 子系统有自己的虚拟机 IP 地址,不再与 Windows 系统共享同一个 IP。</p><p>由于 WSL 2 使用独立的 IP,默认情况下服务无法通过 <code>localhost</code> 访问,需要获取 WSL 2 的 IP 地址才能访问。因此Windows 增加了一个机制,通过一些额外的配置,使得 WSL 2 内的服务可以通过 <code>localhost</code> 访问。这个也就是后面我们要说的网络的mirror模式。</p><p>如果我们需要使用这个镜像模式,只需要在用户文件夹下将<code>.wslconfig</code>文件中,添加网络模式相关配置就行了。即:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs yaml">[<span class="hljs-string">experimental</span>]<br><span class="hljs-string">networkingMode=NAT</span><br></code></pre></td></tr></table></figure><p>这样一来就和wsl有点像了,主机中的localhost和WSL2中的成为同一个,也就是将<code>localhost</code>镜像到WSL中了。</p><p>但是这个模式虽然方便,但是还是会给我们带来一些问题。例如我们使用tun模式进行代理的时候,WSL2内部会出现一个断网的现象。这是由于WSL2网络接口的mtu为1500,而tun模式虚拟出来的网卡接口mtu为9000,因此数据传输的过程中会出现一些问题。因此我们在WSL2中将这个tun模式的虚拟接口mtu改为1500即可。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> ip <span class="hljs-built_in">link</span> <span class="hljs-built_in">set</span> dev <Ethernet interface> mtu 1500<br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>#wsl</tag>
<tag>#nat</tag>
<tag>#网络</tag>
</tags>
</entry>
<entry>
<title>WSL2 图形界面</title>
<link href="/2024/09/10/WSL2%20%E5%9B%BE%E5%BD%A2%E7%95%8C%E9%9D%A2/"/>
<url>/2024/09/10/WSL2%20%E5%9B%BE%E5%BD%A2%E7%95%8C%E9%9D%A2/</url>
<content type="html"><![CDATA[<p>#wsl #x11<br>VcXsrv、X410 和 Xming 都是用于在 Windows 系统上运行 X11 应用程序的开源 X 服务器,主要作用是在 Windows 系统上为 X11 应用程序提供显示支持。但是考虑到近几年的Xming在维护方面较为落后,而且听说虽然X410需要付费但是可以一直试用,因此我们选择了X410作为我们的X服务器</p><p>首先我们需要了解一下,什么是X11,以及这些东西到底是做什么的。</p><h2 id="X11-协议"><a href="#X11-协议" class="headerlink" title="X11 协议"></a>X11 协议</h2><p><strong>X11</strong> 是一种网络透明的窗口系统协议,常用于 Unix/Linux 系统上。它允许图形用户界面的应用程序通过网络将其显示内容发送到 X 服务器。X 服务器负责显示窗口和处理用户输入(如鼠标点击、键盘输入等)。</p><p>在这种架构中,X 服务器负责屏幕输出和输入管理,<strong>X 客户端</strong>(应用程序)与 <strong>X 服务器</strong>通信来展示图形界面。而X 服务器是一个负责绘制图形和管理窗口的服务。在 Linux 系统上,X 服务器直接运行在本地,提供桌面显示。</p><p>当我们在 Windows 上运行 VcXsrv 或 Xming 时,它们就相当于一个虚拟的 X 服务器,模拟 Linux 系统的 X 服务器环境。Linux 应用程序通过 X11 协议将绘图请求发送给 VcXsrv/Xming,后者再把这些请求转化为 Windows 系统可以理解的图形指令,从而在 Windows 上显示。</p><p>在 WSL 中,X11 请求是通过 <code>localhost</code> 进行本地转发,因此性能非常高,并且通信延迟较低</p><h2 id="WSLg-WSL-GUI-支持"><a href="#WSLg-WSL-GUI-支持" class="headerlink" title="WSLg (WSL GUI 支持)"></a>WSLg (WSL GUI 支持)</h2><p>WSL其实是有自己的图形化界面的解决方法的。自 <strong>WSL 2</strong> 之后,微软推出了原生支持 GUI 应用的 <strong>WSLg (Windows Subsystem for Linux GUI)</strong> 功能。它无需手动安装 VcXsrv 或 Xming,直接通过 WSL 提供对 Linux GUI 应用程序的原生支持。WSLg 在后台自动管理 X 服务器,使 Linux 应用程序的图形界面可以无缝显示在 Windows 上。</p><p>但是这个方法我觉得页面相对比较简陋,示例如下:<br><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202409102007318.png" alt="image.png"></p><h2 id="使用X服务器"><a href="#使用X服务器" class="headerlink" title="使用X服务器"></a>使用X服务器</h2><p>我使用的是X410,因此下面的内容我将会用X410作为例子,并详细记录我探索的过程。</p><p>现在我们看到的页面就是这样了:</p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202409110051138.png" alt="image.png"></p><p>根据官方文档中的说法,我们只需要配置一个环境变量<code>DISPLAY</code>,让wsl中的应用知道将图形请求发送到哪里就行了。</p><p>为了简单,我们直接编辑 <code>.bashrc</code> 文件,设置 <code>DISPLAY</code> 环境变量就行了。对于wsl1而言,我们这样做就足够了。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"export DISPLAY=localhost:0.0"</span> >> ~/.bashrc<br><span class="hljs-built_in">source</span> ~/.bashrc<br></code></pre></td></tr></table></figure><p>这将确保在每次启动 WSL 时,<code>DISPLAY</code> 变量都被正确设置。</p><p>但是我使用的是wsl2,这两个最大的区别就是,wsl的localhost和宿主机是同一个,而wsl2是不同的,因此也衍生出后面的mirror-mode网络模式,<del>给我带来了一堆问题</del></p><p>根据官网的说法,我们需要这样做:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">export</span> DISPLAY=$(<span class="hljs-built_in">cat</span> /etc/resolv.conf | grep nameserver | awk <span class="hljs-string">'{print $2; exit;}'</span>):0.0<br></code></pre></td></tr></table></figure><p>整个命令的作用就是从<code>/etc/resolv.conf</code>这个文件中提取当前系统的 <code>nameserver</code> IP 地址,并将它与 <code>:0.0</code> 结合,设置为 <code>DISPLAY</code> 变量。这种方法也许是有效的,但是我的情况有点复杂,并没有成功。</p><p>但是依旧出现了问题:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">Error: Can<span class="hljs-string">'t open display: 10.255.255.254:0.0</span><br></code></pre></td></tr></table></figure><p>我们重新回去看刚才所执行的设置<code>DISPLAY</code>变量的命令,这句命令中获取的主机server的ip是从<code>resolv.conf</code>文件中提取出来的。我们看到,这个文件里面是长这个样子的:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-comment"># This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:</span><br><span class="hljs-comment"># [network]</span><br><span class="hljs-comment"># generateResolvConf = false</span><br><span class="hljs-string">nameserver</span> <span class="hljs-number">10.255</span><span class="hljs-number">.255</span><span class="hljs-number">.254</span><br></code></pre></td></tr></table></figure><p>但是我们使用<code>ip route</code>的时候看到的内容是这样的:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">default via 172.18.16.1 dev eth0 proto kernel<br>172.18.16.0/20 dev eth0 proto kernel scope <span class="hljs-built_in">link</span> src 172.18.31.70<br></code></pre></td></tr></table></figure><p>也就是说,此时<code>resolv.conf</code>显示的nameserver并不是指向主机的虚拟网络接口。因此无法显示是正常的。那么这个东西指向的是什么呢?</p><p>查了一下资料,<code>resolv.conf</code>这个文件用于指定域名解析(DNS)服务器的地址。目前来看,他指向的是<code>10.255.255.254</code>这个地址。我们返回去使用<code>ip a</code>命令查看的时候,我们看到的是这样的:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs bash">1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000<br> <span class="hljs-built_in">link</span>/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00<br> inet 127.0.0.1/8 scope host lo<br> valid_lft forever preferred_lft forever<br> inet 10.255.255.254/32 brd 10.255.255.254 scope global lo<br> valid_lft forever preferred_lft forever<br> inet6 ::1/128 scope host<br> valid_lft forever preferred_lft forever<br>2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000<br> <span class="hljs-built_in">link</span>/ether 00:15:5d:04:f9:94 brd ff:ff:ff:ff:ff:ff<br> inet 172.18.31.70/20 brd 172.18.31.255 scope global eth0<br> valid_lft forever preferred_lft forever<br> inet6 fe80::215:5dff:fe04:f994/64 scope <span class="hljs-built_in">link</span><br> valid_lft forever preferred_lft forever<br></code></pre></td></tr></table></figure><p>我有开始怀疑,这个地址指向的是wls虚拟的 DNS 隧道,然后这个DNS隧道再将信息传递给主机系统的 DNS 服务。我们尝试将wsl2的dns隧道功能关闭之后,这个文件中的内容变成了这样:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-comment"># This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:</span><br><span class="hljs-comment"># [network]</span><br><span class="hljs-comment"># generateResolvConf = false</span><br><span class="hljs-string">nameserver</span> <span class="hljs-number">172.18</span><span class="hljs-number">.16</span><span class="hljs-number">.1</span><br></code></pre></td></tr></table></figure><p>这进一步证实了我刚才的想法。而我们在主机中通过<code>ipconfig</code>命令查看:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs bash">以太网适配器 vEthernet (WSL (Hyper-V firewall)):<br><br> 连接特定的 DNS 后缀 . . . . . . . :<br> 本地链接 IPv6 地址. . . . . . . . : fe80::b828:9895:d8cb:57e7%71<br> IPv4 地址 . . . . . . . . . . . . : 172.18.16.1<br> 子网掩码 . . . . . . . . . . . . : 255.255.240.0<br> 默认网关. . . . . . . . . . . . . :<br></code></pre></td></tr></table></figure><p>我们看到,这个确实是WSL所虚拟出来的网络接口的地址。这种变化是因为我关闭了 WSL2 的 DNS 隧道管理。关闭隧道后,WSL2 不再自动生成 <code>10.255.255.254</code> 这样的虚拟 DNS,转而使用与 Windows 主机共享的虚拟网络适配器 (<code>172.18.16.1</code>),通过此适配器进行网络通信和 DNS 查询。</p><p>因此为了规避这个问题,我们使用以下命令就能将图形请求发送到正确的接口上:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">export</span> DISPLAY=$(ip route | grep default | awk <span class="hljs-string">'{print $3; exit;}'</span>):0.0<br></code></pre></td></tr></table></figure><p>但是当我们同时使用mirrored网络模式和DNS隧道,然后还使用tun模式进行代理的的时候,以上两种方法获取到的主机接口都是错误的(属实是buff叠满了)。此时只能我们手动去配置。因此我的建议是使用nat网络模式,这样会使得一切都变得简单起来。</p>]]></content>
<tags>
<tag>#wsl</tag>
<tag>#x11</tag>
</tags>
</entry>
<entry>
<title>使用Github Action自动部署Hexo博客</title>
<link href="/2024/09/08/%E4%BD%BF%E7%94%A8Github%20Action%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2Hexo%E5%8D%9A%E5%AE%A2/"/>
<url>/2024/09/08/%E4%BD%BF%E7%94%A8Github%20Action%E8%87%AA%E5%8A%A8%E9%83%A8%E7%BD%B2Hexo%E5%8D%9A%E5%AE%A2/</url>
<content type="html"><![CDATA[<p>#github #GitHubPages #hexo</p><p>因为懒所以懒</p><p>之前不是用Obsidian的git插件实现了自动同步,我转念一想,干脆搞个GitHub Aciton自动发布到博客好了,免得我自己再手动输一行命令去发布<del>多累啊</del></p><p>我使用的架构是这样的,由于先前我们Obsidian使用用来备份的仓库和我们的GitHub Page仓库不是同一个,而且我们也是直接把文章的源文件放到了main分支中,因此我决定将Hexo相关配置放到ObsidanNote仓库的Hexo分支,然后让GitHub Action去调用就行了。</p><p>首先我们需要搞一个Token</p><p>因为我们需要在 <strong>Hexo 项目仓库</strong> 执行 <strong>Github Actions</strong> 向 <strong>username.github.io 仓库</strong>推送代码,由于 Github 权限限制,我们需要在 GitHub 账户中创建一个具有足够权限的<strong>个人访问令牌(Personal Access Token,简称 PAT)</strong>。这个令牌需要有足够的权限来修改仓库。</p><p>点击右上角头像 -> 打开 <strong>Settings</strong> -> 左边栏滚到最后找到 <strong>Develop Setting</strong> 打开,如图</p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202409110537234.png" alt="image.png"></p><p>找到 <strong>Personal Access Token</strong> 点击 <strong>Tokens(classic)</strong> -> 选择 <strong>Generate new token (classic)</strong> ,如图</p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202409110538977.png" alt="image.png"></p><p>然后随便新建一个好了,只要有读写仓库的权限就行。</p><p>将生成的 <strong>PAT</strong> 添加到你的博客源代码仓库的 <strong>Secrets</strong>,也就是我们部署GitHub Action的仓库,名字填入 <strong>PERSONAL_TOKEN</strong> ,后面会用到这个变量名。</p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202409110540172.png" alt="image.png"></p><p>然后在我们存放Hexo配置的分支里面创建一个 .github/workflows 文件夹(如果尚未存在),然后新建一个yaml文件用于定义Github Action工作流。以下是我的yaml文件。</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">run-name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">Hexo</span> <span class="hljs-string">to</span> <span class="hljs-string">GitHub</span> <span class="hljs-string">Pages</span><br><span class="hljs-attr">on:</span><br> <span class="hljs-attr">push:</span><br> <span class="hljs-attr">branches:</span><br> <span class="hljs-bullet">-</span> <span class="hljs-string">main</span><br><br><span class="hljs-attr">jobs:</span><br> <span class="hljs-attr">deploy:</span><br> <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span><br> <span class="hljs-attr">steps:</span><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">hexo</span> <span class="hljs-string">branch</span> <span class="hljs-string">(Hexo</span> <span class="hljs-string">environment)</span><br> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span><br> <span class="hljs-attr">with:</span><br> <span class="hljs-attr">ref:</span> <span class="hljs-string">hexo</span><br> <span class="hljs-attr">path:</span> <span class="hljs-string">blog</span><br><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">articles</span> <span class="hljs-string">from</span> <span class="hljs-string">main</span> <span class="hljs-string">branch</span> <span class="hljs-string">(Blog</span> <span class="hljs-string">folder)</span><br> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span><br> <span class="hljs-attr">with:</span><br> <span class="hljs-attr">ref:</span> <span class="hljs-string">main</span><br> <span class="hljs-attr">path:</span> <span class="hljs-string">main-temp</span><br><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Check</span> <span class="hljs-string">if</span> <span class="hljs-string">Blog</span> <span class="hljs-string">folder</span> <span class="hljs-string">exists</span><br> <span class="hljs-attr">run:</span> <span class="hljs-string">ls</span> <span class="hljs-string">main-temp/Blog</span><br><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Move</span> <span class="hljs-string">articles</span> <span class="hljs-string">to</span> <span class="hljs-string">_posts</span><br> <span class="hljs-attr">run:</span> <span class="hljs-string">mv</span> <span class="hljs-string">main-temp/Blog/*</span> <span class="hljs-string">blog/source/_posts/</span><br><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Node.js</span><br> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v3</span><br> <span class="hljs-attr">with:</span><br> <span class="hljs-attr">node-version:</span> <span class="hljs-string">'16'</span><br><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Cache</span> <span class="hljs-string">dependencies</span><br> <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/cache@v3</span><br> <span class="hljs-attr">with:</span><br> <span class="hljs-attr">path:</span> <span class="hljs-string">blog/node_modules</span><br> <span class="hljs-attr">key:</span> <span class="hljs-string">${{</span> <span class="hljs-string">runner.os</span> <span class="hljs-string">}}-node-${{</span> <span class="hljs-string">hashFiles('**/package-lock.json')</span> <span class="hljs-string">}}</span><br> <span class="hljs-attr">restore-keys:</span> <span class="hljs-string">|</span><br><span class="hljs-string"> ${{ runner.os }}-node-</span><br><span class="hljs-string"></span><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">dependencies</span><br> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span><br> <span class="hljs-attr">working-directory:</span> <span class="hljs-string">./blog</span><br><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">Hexo</span> <span class="hljs-string">CLI</span><br> <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span> <span class="hljs-string">-g</span> <span class="hljs-string">hexo-cli</span><br> <span class="hljs-attr">working-directory:</span> <span class="hljs-string">./blog</span><br><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Generate</span> <span class="hljs-string">static</span> <span class="hljs-string">pages</span><br> <span class="hljs-attr">run:</span> <span class="hljs-string">hexo</span> <span class="hljs-string">generate</span><br> <span class="hljs-attr">working-directory:</span> <span class="hljs-string">./blog</span><br><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">List</span> <span class="hljs-string">generated</span> <span class="hljs-string">files</span><br> <span class="hljs-attr">run:</span> <span class="hljs-string">ls</span> <span class="hljs-string">-R</span> <span class="hljs-string">./blog/public</span><br><br> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">to</span> <span class="hljs-string">GitHub</span> <span class="hljs-string">Pages</span><br> <span class="hljs-attr">uses:</span> <span class="hljs-string">peaceiris/actions-gh-pages@v3</span><br> <span class="hljs-attr">with:</span><br> <span class="hljs-attr">personal_token:</span> <span class="hljs-string">${{</span> <span class="hljs-string">secrets.PERSONAL_TOKEN</span> <span class="hljs-string">}}</span><br> <span class="hljs-attr">publish_dir:</span> <span class="hljs-string">./blog/public</span><br> <span class="hljs-attr">external_repository:</span> <span class="hljs-string"><your</span> <span class="hljs-string">repo></span><br> <span class="hljs-attr">publish_branch:</span> <span class="hljs-string">main</span><br></code></pre></td></tr></table></figure><p>这里我的配置比较特殊,因为我对笔记文件进行了分类,然后只有Blog目录下的文件会进行发布,因此我们只需要看Blog目录是否发生改变。这个可以根据自己的需要进行修改。</p><p>然后我们将这些文件提交至GitHub上,触发特定条件就可以触发GitHub Action工作流实现自动部署</p>]]></content>
<tags>
<tag>#github</tag>
<tag>#hexo</tag>
<tag>#GitHubPages</tag>
</tags>
</entry>
<entry>
<title>C++前向声明</title>
<link href="/2024/09/06/C++%E5%89%8D%E5%90%91%E5%A3%B0%E6%98%8E/"/>
<url>/2024/09/06/C++%E5%89%8D%E5%90%91%E5%A3%B0%E6%98%8E/</url>
<content type="html"><![CDATA[<p>#前向声明 #Cpp</p><p><strong>前向声明(Forward Declaration)</strong> 是一种告诉编译器某个类型(如类、结构体或函数)存在的方式,而不提供该类型的完整定义。在前向声明中,我们只需要声明该类型的名称,但并不需要包含具体的定义细节。这对于减少编译依赖、提高编译速度有很大帮助。</p><h2 id="什么时候使用前向声明?"><a href="#什么时候使用前向声明?" class="headerlink" title="什么时候使用前向声明?"></a>什么时候使用前向声明?</h2><ol><li><strong>只声明指针或引用</strong>:如果你只需要在某个类或函数中使用指向某类型的指针或引用,而不需要访问其内部成员时,可以使用前向声明。</li><li><strong>减少编译依赖</strong>:前向声明能够减少不必要的头文件包含,使得代码模块之间的依赖关系更加简洁,从而减少编译时间和复杂度。</li></ol><p>举个例子,假设我们有一个 <code>Person</code> 结构体,他在这个<code>person.h</code>文件中有完整的定义</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> PERSON_H</span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> PERSON_H</span><br><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><string></span></span><br><br><span class="hljs-keyword">struct</span> <span class="hljs-title class_">Person</span> {<br> std::string name;<br> <span class="hljs-type">int</span> age;<br><br> <span class="hljs-built_in">Person</span>(<span class="hljs-type">const</span> std::string& n, <span class="hljs-type">int</span> a) : <span class="hljs-built_in">name</span>(n), <span class="hljs-built_in">age</span>(a) {}<br>};<br><br><span class="hljs-meta">#<span class="hljs-keyword">endif</span></span><br></code></pre></td></tr></table></figure><p>那比方说我们有一个类,需要使用到这个<code>Person</code>结构体。我们先不使用这个前向声明:</p><p><code>company.h</code>(不使用前向声明,直接包含 <code>person.h</code>):</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> COMPANY_H</span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> COMPANY_H</span><br><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"person.h"</span> <span class="hljs-comment">// 直接包含 Person 的定义</span></span><br><br><span class="hljs-keyword">struct</span> <span class="hljs-title class_">Company</span> {<br> std::string name;<br> Person* employee; <span class="hljs-comment">// 指向 Person 结构体的指针</span><br><br> <span class="hljs-built_in">Company</span>(<span class="hljs-type">const</span> std::string& n) : <span class="hljs-built_in">name</span>(n), <span class="hljs-built_in">employee</span>(<span class="hljs-literal">nullptr</span>) {}<br><br> <span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">hireEmployee</span><span class="hljs-params">(Person* employee)</span></span>;<br> <span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">printEmployeeInfo</span><span class="hljs-params">()</span> <span class="hljs-type">const</span></span>;<br>};<br><br><span class="hljs-meta">#<span class="hljs-keyword">endif</span></span><br></code></pre></td></tr></table></figure><p>而这个<code>company.cpp</code>就应该是这么写的:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"company.h"</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><iostream></span></span><br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Company::hireEmployee</span><span class="hljs-params">(Person* employee)</span> </span>{<br> <span class="hljs-keyword">this</span>->employee = employee;<br>}<br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Company::printEmployeeInfo</span><span class="hljs-params">()</span> <span class="hljs-type">const</span> </span>{<br> <span class="hljs-keyword">if</span> (employee) {<br> std::cout << <span class="hljs-string">"Employee: "</span> << employee->name << <span class="hljs-string">", Age: "</span> << employee->age << std::endl;<br> } <span class="hljs-keyword">else</span> {<br> std::cout << <span class="hljs-string">"No employee hired."</span> << std::endl;<br> }<br>}<br></code></pre></td></tr></table></figure><p>那如果我们使用了前向声明,那么这个<code>company.h</code>和<code>company.cpp</code>就应该是这么写的:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> COMPANY_H</span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> COMPANY_H</span><br><br><span class="hljs-comment">// 前向声明 Person 结构体</span><br><span class="hljs-keyword">struct</span> <span class="hljs-title class_">Person</span>;<br><br><span class="hljs-keyword">struct</span> <span class="hljs-title class_">Company</span> {<br> std::string name;<br> Person* employee; <span class="hljs-comment">// 指向 Person 结构体的指针</span><br><br> <span class="hljs-built_in">Company</span>(<span class="hljs-type">const</span> std::string& n) : <span class="hljs-built_in">name</span>(n), <span class="hljs-built_in">employee</span>(<span class="hljs-literal">nullptr</span>) {}<br><br> <span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">hireEmployee</span><span class="hljs-params">(Person* employee)</span></span>; <span class="hljs-comment">// 使用指向 Person 的指针</span><br> <span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">printEmployeeInfo</span><span class="hljs-params">()</span> <span class="hljs-type">const</span></span>;<br>};<br><br><span class="hljs-meta">#<span class="hljs-keyword">endif</span></span><br></code></pre></td></tr></table></figure><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"company.h"</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"person.h"</span> <span class="hljs-comment">// 包含 Person 的完整定义</span></span><br><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><iostream></span></span><br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Company::hireEmployee</span><span class="hljs-params">(Person* employee)</span> </span>{<br> <span class="hljs-keyword">this</span>->employee = employee;<br>}<br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Company::printEmployeeInfo</span><span class="hljs-params">()</span> <span class="hljs-type">const</span> </span>{<br> <span class="hljs-keyword">if</span> (employee) {<br> std::cout << <span class="hljs-string">"Employee: "</span> << employee->name << <span class="hljs-string">", Age: "</span> << employee->age << std::endl;<br> } <span class="hljs-keyword">else</span> {<br> std::cout << <span class="hljs-string">"No employee hired."</span> << std::endl;<br> }<br>}<br></code></pre></td></tr></table></figure><p>这样一来,虽然看上去没什么变化,但是他能够避免了直接包含 <code>person.h</code>,使得 <code>company.h</code> 更加简洁。不使用前向声明意味着 <code>company.h</code> 依赖于 <code>person.h</code>,如果 <code>person.h</code> 中有任何变化,所有包含 <code>company.h</code> 的文件都需要重新编译,这会增加编译时间和复杂度。同时前向声明也可以用来打破循环依赖,分解依赖关系。</p><p>C++项目的编写中其实有一个原则,就是最小化头文件依赖。即尽可能减少头文件中包含的其他头文件,以减少编译依赖,避免不必要的重编译。.h文件都应该尽量的让这个.c或者.cpp文件去包含而不是在头文件中直接包含。</p>]]></content>
<tags>
<tag>#前向声明</tag>
<tag>#Cpp</tag>
</tags>
</entry>
<entry>
<title>Nginx踩坑记录——location 路径匹配和 proxy_pass 转发行为的差异</title>
<link href="/2024/09/06/Nginx%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95%E2%80%94%E2%80%94location%20%E8%B7%AF%E5%BE%84%E5%8C%B9%E9%85%8D%E5%92%8C%20proxy_pass%20%E8%BD%AC%E5%8F%91%E8%A1%8C%E4%B8%BA%E7%9A%84%E5%B7%AE%E5%BC%82/"/>
<url>/2024/09/06/Nginx%E8%B8%A9%E5%9D%91%E8%AE%B0%E5%BD%95%E2%80%94%E2%80%94location%20%E8%B7%AF%E5%BE%84%E5%8C%B9%E9%85%8D%E5%92%8C%20proxy_pass%20%E8%BD%AC%E5%8F%91%E8%A1%8C%E4%B8%BA%E7%9A%84%E5%B7%AE%E5%BC%82/</url>
<content type="html"><![CDATA[<p>#Nginx</p><p>文章的开始我们先来看几种写法:</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">location</span> /b/ {<br><span class="hljs-attribute">proxy_pass</span> http://localhost:2017/;<br>}<br><span class="hljs-section">location</span> /b/ {<br><span class="hljs-attribute">proxy_pass</span> http://localhost:2017;<br>}<br><span class="hljs-section">location</span> /b {<br><span class="hljs-attribute">proxy_pass</span> http://localhost:2017;<br>}<br><span class="hljs-section">location</span> /b {<br><span class="hljs-attribute">proxy_pass</span> http://localhost:2017/;<br>}<br></code></pre></td></tr></table></figure><p>请你告诉我,这几种写法有什么区别</p><h2 id="location-b-和-location-b"><a href="#location-b-和-location-b" class="headerlink" title="location /b/ 和 location /b"></a><code>location /b/</code> 和 <code>location /b</code></h2><p>这两个东西看起来很像,但是其实区别有点大。</p><p>我们先来看<code>location /b/</code>。这个配置匹配的是以<code>/b/</code>开头的路径。例如,<code>/b/something</code> 或 <code>/b/subdir/file</code> 等等。重要的是,这种匹配要求路径紧跟在<code>/b/</code>后面,后面必须有<code>/</code>,而且<strong>不包括</strong><code>/b</code>。</p><p>而<code>location /b</code>这个配置匹配的是以<code>/b</code>开头的路径,既可以匹配<code>/b</code>本身,也可以匹配以<code>/b</code>开头的其他路径。例如,<code>/b</code>, <code>/b/something</code>, <code>/b/subdir/file</code> 都会被匹配。</p><h2 id="proxy-pass路径末尾有无"><a href="#proxy-pass路径末尾有无" class="headerlink" title="proxy_pass路径末尾有无/"></a>proxy_pass路径末尾有无/</h2><p>这两个是不一样的。</p><p>如果你在 <code>proxy_pass</code> 后面使用的是 <code>http://localhost:2017</code>,即没有带“/”,那么Nginx 会将客户端请求的 URI 直接转发到目标服务器,保持原始 URI 不变。例如:</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">location</span> /test/ {<br> <span class="hljs-attribute">proxy_pass</span> http://localhost:2017;<br>}<br></code></pre></td></tr></table></figure><p>在这种情况下,由于 <code>proxy_pass</code> 没有加斜杠,Nginx 不会去掉匹配的 <code>/test/</code> 前缀部分,而是直接将原始请求完整地转发给目标服务器。所以,假设客户端请求 <code>example.com/test/abc</code>,那么 Nginx 会将请求转发为 <code>http://localhost:2017/test/abc</code>。</p><p>如果你在 <code>proxy_pass</code> 后面加上了斜杠 <code>http://localhost:2017/</code>,在 <code>proxy_pass</code> 后面加上斜杠时,Nginx 会去掉客户端请求的 URI 中和<strong>匹配位置</strong>相关的部分,并替换为目标服务器的根路径。这里的<strong>前缀部分</strong>是指在 Nginx 配置中与 <code>location</code> 指令匹配的那部分 URL。例如:</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">location</span> /test/ {<br> <span class="hljs-attribute">proxy_pass</span> http://localhost:2017/;<br>}<br></code></pre></td></tr></table></figure><p>在这个例子中,客户端请求的 URI <code>/test/abc</code> 中,<code>/test/</code> 是匹配的前缀部分,而 Nginx 会将这一部分去掉,并把剩余的 <code>/abc</code> 转发给目标服务器。这时,Nginx 会将请求转发为 <code>http://localhost:2017/abc</code>,即<strong>去掉了匹配的前缀 <code>/test/</code>,并将剩余的部分加到目标服务器的根路径后</strong>。</p><h2 id="解答"><a href="#解答" class="headerlink" title="解答"></a>解答</h2><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">location</span> /b/ {<br><span class="hljs-attribute">proxy_pass</span> http://localhost:2017/;<br>}<br></code></pre></td></tr></table></figure><ul><li><strong>客户端请求</strong>: <code>http://example.com/b/abc</code></li><li><strong>Nginx 匹配的部分</strong>: <code>/b/</code></li><li><strong>剩余部分</strong>: <code>abc</code></li><li><strong>实际被转发的请求</strong>: <code>http://localhost:2017/abc</code></li></ul><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">location</span> /b/ {<br><span class="hljs-attribute">proxy_pass</span> http://localhost:2017;<br>}<br></code></pre></td></tr></table></figure><ul><li><strong>客户端请求</strong>: <code>http://example.com/b/abc</code></li><li><strong>Nginx 匹配的部分</strong>: <code>/b/</code></li><li><strong>剩余部分</strong>: <code>abc</code></li><li><strong>实际被转发的请求</strong>: <code>http://localhost:2017/b/abc</code></li></ul><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">location</span> /b {<br><span class="hljs-attribute">proxy_pass</span> http://localhost:2017;<br>}<br></code></pre></td></tr></table></figure><ul><li><strong>客户端请求</strong>: <code>http://example.com/b/abc</code></li><li><strong>Nginx 匹配的部分</strong>: <code>/b</code></li><li><strong>剩余部分</strong>: <code>/abc</code></li><li><strong>实际被转发的请求</strong>: <code>http://localhost:2017/b/abc</code></li></ul><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">location</span> /b {<br><span class="hljs-attribute">proxy_pass</span> http://localhost:2017/;<br>}<br></code></pre></td></tr></table></figure><ul><li><strong>客户端请求</strong>: <code>http://example.com/b/abc</code></li><li><strong>Nginx 匹配的部分</strong>: <code>/b</code></li><li><strong>剩余部分</strong>: <code>/abc</code></li><li><strong>实际被转发的请求</strong>: <code>http://localhost:2017/abc</code></li></ul>]]></content>
<tags>
<tag>#Nginx</tag>
</tags>
</entry>
<entry>
<title>C++编译中变量重复定义问题</title>
<link href="/2024/09/04/C++%E7%BC%96%E8%AF%91%E4%B8%AD%E5%8F%98%E9%87%8F%E9%87%8D%E5%A4%8D%E5%AE%9A%E4%B9%89%E9%97%AE%E9%A2%98/"/>
<url>/2024/09/04/C++%E7%BC%96%E8%AF%91%E4%B8%AD%E5%8F%98%E9%87%8F%E9%87%8D%E5%A4%8D%E5%AE%9A%E4%B9%89%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<p>#重复定义 #Cpp #extern关键字</p><p>C++编译过程中出现变量重复定义问题非常常见,通常表现为以下报错:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash">[build] CMakeFiles\NewPlayer.<span class="hljs-built_in">dir</span>/objects.a(imagehandler.cpp.obj):C:/Users/ZeroHzzzz/Desktop/QT_new/src/NewPlayer/imagehandler.h:197: multiple definition of `speedlineLeft<span class="hljs-string">'</span><br><span class="hljs-string">[build] CMakeFiles\NewPlayer.dir/objects.a(datahandler.cpp.obj):C:/Users/ZeroHzzzz/Desktop/QT_new/src/NewPlayer/imagehandler.h:197: first defined here</span><br></code></pre></td></tr></table></figure><p>出现这种报错通常分为以下几种情况:</p><h3 id="全局变量重复定义"><a href="#全局变量重复定义" class="headerlink" title="全局变量重复定义"></a>全局变量重复定义</h3><p>在多个源文件中定义了相同的全局变量,而没有使用<code>extern</code>关键字声明。这会导致链接器在合并目标文件时发现多个相同的符号定义。</p><h3 id="头文件中的直接定义变量"><a href="#头文件中的直接定义变量" class="headerlink" title="头文件中的直接定义变量"></a>头文件中的直接定义变量</h3><p>在C或C++中,<strong>不要直接在头文件(.h 文件)中定义全局变量</strong>,因为这样做会导致在多个文件中包含同一个头文件时出现多次定义的问题(即“重复定义”错误)</p><p>在头文件中直接定义了变量或函数,这些头文件被多个源文件包含。每次包含都会生成该变量或函数的一个定义,最终在链接时产生冲突。我们通常的做法是在头文件中声明一个变量但是不去定义他,然后再cpp文件中定义变量。</p><p>错误案例:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">// myheader.h</span><br><span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> MYHEADER_H</span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> MYHEADER_H</span><br><br><span class="hljs-type">int</span> myVar;<br><br><span class="hljs-meta">#<span class="hljs-keyword">endif</span> <span class="hljs-comment">// MYHEADER_H</span></span><br><br><span class="hljs-comment">// mysource.cpp</span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"myheader.h"</span></span><br><br><span class="hljs-keyword">extern</span> <span class="hljs-type">int</span> myVar = <span class="hljs-number">42</span>; <span class="hljs-comment">// 定义变量</span><br></code></pre></td></tr></table></figure><p>正确做法:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">// myheader.h</span><br><span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> MYHEADER_H</span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> MYHEADER_H</span><br><br><span class="hljs-keyword">extern</span> <span class="hljs-type">int</span> myVar; <span class="hljs-comment">// 仅声明,不定义</span><br><br><span class="hljs-meta">#<span class="hljs-keyword">endif</span> <span class="hljs-comment">// MYHEADER_H</span></span><br><br><span class="hljs-comment">// mysource.cpp</span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"myheader.h"</span></span><br><br><span class="hljs-type">int</span> myVar = <span class="hljs-number">42</span>; <span class="hljs-comment">// 定义变量</span><br><br><span class="hljs-comment">// othersource.cpp</span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string">"myheader.h"</span></span><br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">printVar</span><span class="hljs-params">()</span> </span>{<br> std::cout << <span class="hljs-string">"myVar: "</span> << myVar << std::endl; <span class="hljs-comment">// 使用变量</span><br>}<br><br></code></pre></td></tr></table></figure><h3 id="静态变量"><a href="#静态变量" class="headerlink" title="静态变量"></a>静态变量</h3><p>在头文件中定义了非静态的局部变量,如果这个头文件被多个源文件包含,也会导致重复定义问题。</p><h2 id="解决方法:"><a href="#解决方法:" class="headerlink" title="解决方法:"></a>解决方法:</h2><h3 id="使用extern声明全局变量"><a href="#使用extern声明全局变量" class="headerlink" title="使用extern声明全局变量"></a>使用<code>extern</code>声明全局变量</h3><p>如果需要在多个文件中使用相同的全局变量,可以在一个源文件中定义变量,在其他源文件中使用<code>extern</code>关键字来声明。例如:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">// 变量声明在header.h中</span><br><span class="hljs-keyword">extern</span> <span class="hljs-type">int</span> globalVar;<br><br><span class="hljs-comment">// 变量定义在main.cpp中</span><br><span class="hljs-type">int</span> globalVar = <span class="hljs-number">0</span>;<br></code></pre></td></tr></table></figure><h3 id="头文件中使用inline或static关键字"><a href="#头文件中使用inline或static关键字" class="headerlink" title="头文件中使用inline或static关键字"></a>头文件中使用<code>inline</code>或<code>static</code>关键字</h3><p>如果头文件中有函数定义,可以使用<code>inline</code>关键字来避免重复定义。例如:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">// header.h</span><br><span class="hljs-function"><span class="hljs-keyword">inline</span> <span class="hljs-type">void</span> <span class="hljs-title">func</span><span class="hljs-params">()</span> </span>{<br> <span class="hljs-comment">// 函数实现</span><br>}<br></code></pre></td></tr></table></figure><p>对于需要在头文件中定义的局部变量,可以使用<code>static</code>关键字:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">// header.h</span><br><span class="hljs-type">static</span> <span class="hljs-type">int</span> localVar = <span class="hljs-number">0</span>;<br></code></pre></td></tr></table></figure><h3 id="使用包含保护"><a href="#使用包含保护" class="headerlink" title="使用包含保护"></a>使用包含保护</h3><p>确保头文件有包含保护,防止同一个头文件被多次包含。可以通过<code>#ifndef</code>,<code>#define</code>,<code>#endif</code>来实现</p><p>[[C++编译中头文件重复包含问题]]</p><p>“包含保护”只是防止头文件被多次包含到<strong>同一个</strong>源文件中,它无法防止多个源文件中出现同样的变量定义</p><p>假设你在头文件中定义了一个全局变量:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">// myheader.h</span><br><span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> MYHEADER_H</span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> MYHEADER_H</span><br><br><span class="hljs-type">int</span> myVar = <span class="hljs-number">42</span>; <span class="hljs-comment">// 在头文件中定义变量</span><br><br><span class="hljs-meta">#<span class="hljs-keyword">endif</span> <span class="hljs-comment">// MYHEADER_H</span></span><br></code></pre></td></tr></table></figure><p>然后有两个源文件<code>a.cpp</code>和<code>b.cpp</code>都包含了这个头文件,当你编译时,<code>a.cpp</code>和<code>b.cpp</code>都会各自包含并定义<code>myVar</code>,这意味着编译器会看到两个不同的文件中都有一个全局变量<code>myVar</code>的定义,从而导致<strong>重复定义</strong>错误。正确的做法是<strong>在头文件中声明变量</strong>,而<strong>在某个源文件中定义变量</strong>。</p><h3 id="使用命名空间"><a href="#使用命名空间" class="headerlink" title="使用命名空间"></a>使用命名空间</h3><p>将全局变量放入命名空间内,可以减少不同文件中相同变量名的冲突:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">// header.h</span><br><span class="hljs-keyword">namespace</span> MyNamespace {<br> <span class="hljs-keyword">extern</span> <span class="hljs-type">int</span> globalVar;<br>}<br><br><span class="hljs-comment">// main.cpp</span><br><span class="hljs-type">int</span> MyNamespace::globalVar = <span class="hljs-number">0</span>;<br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>#Cpp</tag>
<tag>#重复定义</tag>
<tag>#extern关键字</tag>
</tags>
</entry>
<entry>
<title>C++编译中头文件重复包含问题</title>
<link href="/2024/09/01/C++%E7%BC%96%E8%AF%91%E4%B8%AD%E5%A4%B4%E6%96%87%E4%BB%B6%E9%87%8D%E5%A4%8D%E5%8C%85%E5%90%AB%E9%97%AE%E9%A2%98/"/>
<url>/2024/09/01/C++%E7%BC%96%E8%AF%91%E4%B8%AD%E5%A4%B4%E6%96%87%E4%BB%B6%E9%87%8D%E5%A4%8D%E5%8C%85%E5%90%AB%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<p>#Cpp #编译 #头文件保护</p><p>在C++开发过程中,重定义错误是一个常见的问题。如果存在一个头文件被多个文件引用,而头文件没有防重复包含保护的情况,就会引发重定义的问题,表现如下:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs bash">[build] C:/Users/ZeroHzzzz/Desktop/QT/Player/image.h:106:7: error: redefinition of <span class="hljs-string">'class ImageHandler'</span><br>[build] class ImageHandler { [build] ^~~~~~~~~~~~<br>[build] In file included from C:/Users/ZeroHzzzz/Desktop/QT/Player/datareader.h:3:0,<br>[build] from C:\Users\ZeroHzzzz\Desktop\QT\Player\mainwindow.h:4, [build] from C:\Users\ZeroHzzzz\Desktop\QT\Player\mainwindow.cpp:1:<br>[build] C:/Users/ZeroHzzzz/Desktop/QT/Player/image.h:106:7: note: previous definition of <span class="hljs-string">'class ImageHandler'</span><br>[build] class ImageHandler {<br>[build] ^~~~~~~~~~~~<br>[build] In file included from C:/Users/ZeroHzzzz/Desktop/QT/Player/datareader.h:14:0,<br>[build] from C:\Users\ZeroHzzzz\Desktop\QT\Player\datareader.cpp:1:<br></code></pre></td></tr></table></figure><h2 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h2><h3 id="使用预处理指令-ifndef、-define-和-endif"><a href="#使用预处理指令-ifndef、-define-和-endif" class="headerlink" title="使用预处理指令 #ifndef、#define 和 #endif"></a>使用预处理指令 <code>#ifndef</code>、<code>#define</code> 和 <code>#endif</code></h3><p>在<code>image.h</code>头文件的开头和结尾添加如下的预处理指令:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">// image.h 文件的开头</span><br><span class="hljs-meta">#<span class="hljs-keyword">ifndef</span> IMAGE_H <span class="hljs-comment">// 检查是否定义了IMAGE_H宏</span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> IMAGE_H <span class="hljs-comment">// 定义IMAGE_H宏</span></span><br><br><span class="hljs-comment">// 类定义和其他代码</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ImageHandler</span> {<br> <span class="hljs-comment">// 类的成员和方法</span><br>};<br><br><span class="hljs-meta">#<span class="hljs-keyword">endif</span> <span class="hljs-comment">// IMAGE_H // 结束条件编译</span></span><br></code></pre></td></tr></table></figure><p><code>#ifndef IMAGE_H</code>:检查是否已经定义了<code>IMAGE_H</code>宏,如果没有定义,则继续执行下面的代码。<br><code>#define IMAGE_H</code>:定义<code>IMAGE_H</code>宏,用于标记该头文件已经被包含。这确保了即使<code>image.h</code>被多次包含,<code>ImageHandler</code>类也只会被定义一次。<br><code>#endif</code>:结束条件编译</p><p><code>#ifndef</code>的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况</p><h3 id="使用-pragma-once"><a href="#使用-pragma-once" class="headerlink" title="使用 #pragma once"></a>使用 <code>#pragma once</code></h3><p>在<code>image.h</code>文件的开头添加:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-meta">#<span class="hljs-keyword">pragma</span> once</span><br><br><span class="hljs-comment">// 类定义和其他代码</span><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">ImageHandler</span> {<br> <span class="hljs-comment">// 类的成员和方法</span><br>};<br></code></pre></td></tr></table></figure><p><code>#pragma once</code>是一种编译器指令,指示编译器只包含一次该头文件。它的效果与使用<code>#ifndef</code>/<code>#define</code>保护符相同,但写法更简洁。这种方法更易于维护,但需要注意的是,<code>#pragma once</code>不是所有编译器都支持的标准,因此在一些特定的编译环境中可能需要退回到传统的防护符号方法。</p><p><code>#pragma once</code>由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指<strong>物理</strong>上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。</p><p>但是:</p><p><strong>你无法对一个头文件中的一段代码作pragma once声明,而只能针对文件。</strong></p><p>其好处是,你不必再担心宏名冲突了,当然也就不会出现宏名冲突引发的奇怪问题。大型项目的编译速度也因此提高了一些。</p><p>对应的缺点就是如果某个头文件有多份拷贝,这个方法不能保证他们不被重复包含。当然,相比宏名冲突引发的“找不到声明”的问题,这种重复包含很容易被发现并修正。</p><p>因此,对于可移植性方面而言,我更倾向于使用<code>#ifndef</code>的方法</p><h2 id="检查包含关系"><a href="#检查包含关系" class="headerlink" title="检查包含关系"></a>检查包含关系</h2><p>头文件的包含关系也需要注意。循环包含会导致难以定位的问题,影响程序的可维护性。</p><h3 id="使用编译器的预处理选项查看包含树"><a href="#使用编译器的预处理选项查看包含树" class="headerlink" title="使用编译器的预处理选项查看包含树"></a>使用编译器的预处理选项查看包含树</h3><p>许多编译器提供了查看包含文件树的选项,可以帮助你理解头文件的包含关系。</p><p>例如<code>gcc</code>或<code>g++</code>:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">g++ -H main.cpp -o main<br></code></pre></td></tr></table></figure><p>输出:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">. main.cpp<br>.. image.h<br>... other_header.h<br>.. another_header.h<br></code></pre></td></tr></table></figure><h3 id="使用-CMake-的include-what-you-use工具"><a href="#使用-CMake-的include-what-you-use工具" class="headerlink" title="使用 [[CMake]] 的include-what-you-use工具"></a>使用 [[CMake]] 的<code>include-what-you-use</code>工具</h3><p><code>include-what-you-use</code>(IWYU)是一个专门分析C/C++代码的工具,可以帮助检测和优化头文件的包含情况。IWYU可以生成详细的报告,指出哪些头文件是多余的,哪些头文件是缺失的。</p><p><strong>使用方法</strong>:</p><ol><li>安装<code>include-what-you-use</code>工具。</li><li>在CMake项目中,将<code>CMAKE_CXX_INCLUDE_WHAT_YOU_USE</code>设置为<code>iwyu</code>的路径。</li></ol><p>在CMakeLists.txt中添加:</p><figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs cmake"><span class="hljs-keyword">set</span>(CMAKE_CXX_INCLUDE_WHAT_YOU_USE <span class="hljs-string">"include-what-you-use"</span>)<br></code></pre></td></tr></table></figure><p>然后,运行CMake和构建系统,会自动生成包含分析的报告。</p>]]></content>
<tags>
<tag>#Cpp</tag>
<tag>#编译</tag>
<tag>#头文件保护</tag>
</tags>
</entry>
<entry>
<title>Windows环境中利用MinGW+CMake从源码编译OpenCV</title>
<link href="/2024/08/28/Windows%E7%8E%AF%E5%A2%83%E4%B8%AD%E5%88%A9%E7%94%A8MinGW+CMake%E4%BB%8E%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91OpenCV/"/>
<url>/2024/08/28/Windows%E7%8E%AF%E5%A2%83%E4%B8%AD%E5%88%A9%E7%94%A8MinGW+CMake%E4%BB%8E%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91OpenCV/</url>
<content type="html"><![CDATA[<p>#OpenCV #CMake配置 #MinGW</p><h2 id="安装前准备"><a href="#安装前准备" class="headerlink" title="安装前准备"></a>安装前准备</h2><ul><li>检查 <code>MinGW</code> 的安装版本是否为 <code>posix</code> 线程标准,目前 <code>OpenCV</code> 只支持 <code>posix</code> 标准,不支持 <code>win32</code> 标准</li><li>安装Windows版本的 <code>Cmake</code>,官网链接为<a href="https://cmake.org/download/" title="https://cmake.org/download/">https://cmake.org/download/</a></li><li>编译之前记得使用<code>gcc -v</code>查看自己的编译器版本,别到时候出现一些不必要的<code>error</code> <del>(我不说是谁)</del></li></ul><h2 id="下载OpenCV源码"><a href="#下载OpenCV源码" class="headerlink" title="下载OpenCV源码"></a>下载OpenCV源码</h2><p><a href="https://opencv.org/releases/">Releases - OpenCV</a></p><h2 id="生成makefile"><a href="#生成makefile" class="headerlink" title="生成makefile"></a>生成makefile</h2><p>选择解压后的opencv源码路径与编译二进制文件的路径,一般就选择源码路径下的build文件夹(Cmake会提醒创建,也可以自己提前创建),点击<code>Configure</code><br><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408290036458.png" alt="image.png"></p><p>选择MinGW Makefiles,如果对应的GNU编译器(包括gcc、g++、gfortran)已经在当前的环境变量PATH中,则可以选择默认的编译器,如下图所示;如果未添加进环境变量,可以选择<code>Specify native compilers</code>手动选择(不推荐,建议添加环境变量)</p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408290036926.png" alt="image.png|700"></p><p>等待Configure完成后,出现需要更新的红色的配置值,可以根据自己的需要进行适当调整。常用的调整项目有:</p><p><strong>CMAKE_INSTALL_PREFIX</strong>:修改默认安装路径,默认安装路径为<code>build/install</code><br><strong>BUILD_opencv_world</strong>:将所有编译后的库文件整合为一个<br><strong>OPENCV_GENERATE_PKGCONFIG</strong>:生成一个pkg-config的路径使得pkgconfig能够自动传递库路径给g++进行编译<br><strong>CMAKE_BUILD_TYPE</strong>:填入Release会编译发行版本的opencv包,从而去除debug信息和符号表,这可以提高性能;填入Debug则会编译debug版本的opencv(这是给需要深度开发opencv修改源码的人用的),而一般我们不需要深入opencv的源代码进行debug。<br><strong>OPENCV_EXTRA_MODULES_PATH</strong>:contrib包中的附加模组的路径<br><strong>WITH_QT</strong>:字面意思<br><strong>WITH_OPENGL</strong>:利用硬件加速来提高图像和视频处理的性能<br><strong>ENABLE_PRECOMPILED_HEADERS</strong>:启用预编译头,加快编译速度<br><strong>QT5_DIR</strong>:填入QT路径<br>再次configure。如果无报错之后选择generate生成makefile</p><h2 id="编译"><a href="#编译" class="headerlink" title="编译"></a>编译</h2><p>在build文件夹中打开cmd或者终端或者其他类shell工具,输入:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">mingw32-make<br></code></pre></td></tr></table></figure><p>可以传入<code>-jx</code>使用多线程编译以加快编译速度,其中x为线程数。</p><p>编译完成后,输入:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">mingw32-make install<br></code></pre></td></tr></table></figure><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408290045293.png" alt="image.png"></p><p>成功安装动态库到对应路径(若没有修改则是默认路径)。</p><h2 id="添加环境变量"><a href="#添加环境变量" class="headerlink" title="添加环境变量"></a>添加环境变量</h2><p>刚刚我们得到的文件是很多的,但是我们只需要留下build文件夹中的install目录即可,其他都是可以删掉的。</p><p>因此我最终的文件目录如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><code class="hljs tree">opencv-4.10.0/<br>├─etc<br>│ ├─haarcascades<br>│ ├─lbpcascades<br>│ └─licenses<br>├─include<br>│ └─opencv2<br>│ ├─calib3d<br>│ ├─core<br>│ │ ├─cuda<br>│ │ │ └─detail<br>│ │ ├─detail<br>│ │ ├─hal<br>│ │ ├─opencl<br>│ │ │ └─runtime<br>│ │ │ └─autogenerated<br>│ │ ├─parallel<br>│ │ │ └─backend<br>│ │ └─utils<br>│ ├─dnn<br>│ │ └─utils<br>│ ├─features2d<br>│ │ └─hal<br>│ ├─flann<br>│ ├─gapi<br>│ │ ├─cpu<br>│ │ ├─fluid<br>│ │ ├─gpu<br>│ │ ├─infer<br>│ │ ├─oak<br>│ │ ├─ocl<br>│ │ ├─own<br>│ │ ├─plaidml<br>│ │ ├─python<br>│ │ ├─render<br>│ │ ├─s11n<br>│ │ ├─streaming<br>│ │ │ ├─gstreamer<br>│ │ │ └─onevpl<br>│ │ └─util<br>│ ├─highgui<br>│ ├─imgcodecs<br>│ │ └─legacy<br>│ ├─imgproc<br>│ │ ├─detail<br>│ │ └─hal<br>│ ├─ml<br>│ ├─objdetect<br>│ ├─photo<br>│ │ └─legacy<br>│ ├─stitching<br>│ │ └─detail<br>│ ├─video<br>│ │ ├─detail<br>│ │ └─legacy<br>│ └─videoio<br>│ └─legacy<br>└─x64<br> └─mingw<br> ├─bin<br> └─lib<br> └─pkgconfig<br></code></pre></td></tr></table></figure><p>我们添加环境变量的时候只需要添加<code>x64/mingw/bin</code>就行了。</p>]]></content>
<tags>
<tag>#OpenCV</tag>
<tag>#CMake配置</tag>
<tag>#MinGW</tag>
</tags>
</entry>
<entry>
<title>使用qq邮箱群发邮件</title>
<link href="/2024/08/21/%E4%BD%BF%E7%94%A8qq%E9%82%AE%E7%AE%B1%E7%BE%A4%E5%8F%91%E9%82%AE%E4%BB%B6/"/>
<url>/2024/08/21/%E4%BD%BF%E7%94%A8qq%E9%82%AE%E7%AE%B1%E7%BE%A4%E5%8F%91%E9%82%AE%E4%BB%B6/</url>
<content type="html"><![CDATA[<p>#SMTP</p><p>我们通过qq邮箱的[[SMTP]]服务来实现邮件的发送</p><h2 id="From-和-To-Header-格式规范"><a href="#From-和-To-Header-格式规范" class="headerlink" title="From 和 To Header 格式规范"></a>From 和 To Header 格式规范</h2><p>我们在使用qq邮箱发送邮件的时候出现了以下错误:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">SMTPDataError: (550, b<span class="hljs-string">'The "From" header is missing or invalid. Please follow RFC5322, RFC2047, RFC822 standard protocol. https://service.mail.qq.com/detail/124/995.'</span>)<br></code></pre></td></tr></table></figure><p>这是因为其From合法性检查</p><h3 id="From合法性检查"><a href="#From合法性检查" class="headerlink" title="From合法性检查"></a>From合法性检查</h3><p><strong>一、根据RFC5322协议,邮件标头中需要包含’From’信息。</strong></p><p><strong>二、根据RFC2047, RFC822协议,邮件标头中的’From’形式为:</strong></p><ol><li><p>邮箱地址形式:prefix@domain, 如 ‘abc@qq.com’。</p></li><li><p>昵称+空格+<邮箱地址>形式:nickname <a href="mailto:prefix@domain">prefix@domain</a>,其中,nickname为ASCII字符集中字符组合或编码文本:</p></li></ol><p>(1)如果昵称全为ASCII字符,如’ABC’,邮箱地址为 ‘abc@qq.com’,则标头中的’From’为’ABC <a href="mailto:abc@qq.com">abc@qq.com</a>‘。注意’ABC’和’<a href="mailto:abc@qq.com">abc@qq.com</a>‘之间用空格隔开;</p><p>(2)如果昵称包含非ASCII字符,如中文,则请使用base64对昵称进行编码。nickname最终的形式为:”=?” charset “?” encoding “?” encoded-text “?=”。其中,charset为字符集;encoding为编码方式,’B’代表base64;encoded-text为编码后的文本。例如,昵称为’QQ邮箱昵称示例’,邮箱地址为 ‘abc@qq.com’,则对昵称进行base64编码,字符集使用UTF-8,则nickname为 ‘=?UTF-8?B?UVHpgq7nrrHmmLXnp7DnpLrkvos=?=’,最终邮件标头中的’From’为’”=?utf-8?B?UVHpgq7nrrHmmLXnp7DnpLrkvos=?=” <a href="mailto:abc@qq.com">abc@qq.com</a>‘。注意编码文本和邮件地址间用空格隔开。</p><h2 id="发送邮箱服务器端口"><a href="#发送邮箱服务器端口" class="headerlink" title="发送邮箱服务器端口"></a>发送邮箱服务器端口</h2><p>发送邮件服务器要用465端口,否则如下的报错:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">SMTPServerDisconnected: Connection unexpectedly closed<br></code></pre></td></tr></table></figure><h2 id="授权码"><a href="#授权码" class="headerlink" title="授权码"></a>授权码</h2><p>login的密码不是邮箱登录密码,而是授权码,需要在QQ邮箱设置-账号里获取。否则会出现以下报错:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1002)<br></code></pre></td></tr></table></figure><h2 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h2><p>最终我们的代码如下(无附件):</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">import</span> smtplib<br><span class="hljs-keyword">from</span> email.mime.text <span class="hljs-keyword">import</span> MIMEText<br><span class="hljs-keyword">from</span> email.header <span class="hljs-keyword">import</span> Header<br><span class="hljs-keyword">from</span> tqdm <span class="hljs-keyword">import</span> tqdm<br><br>sender = <span class="hljs-string">''</span><br>receivers = [<span class="hljs-string">''</span>]<br>auth_code = <span class="hljs-string">""</span><br>fails = []<br><br>Sendernickname = <span class="hljs-string">"=?UTF-8?B?5rWZ5rGf5bel5Lia5aSn5a2m57K+5byY572R57uc?="</span><br>text = <span class="hljs-string">"你好!"</span><br>message = MIMEText(text, <span class="hljs-string">'plain'</span>, <span class="hljs-string">'utf-8'</span>)<br>message[<span class="hljs-string">'From'</span>] = Header(<span class="hljs-string">f"<span class="hljs-subst">{Sendernickname}</span><<span class="hljs-subst">{sender}</span>>"</span>)<br>subject = <span class="hljs-string">'报名成功通知'</span><br>message[<span class="hljs-string">'Subject'</span>] = Header(subject, <span class="hljs-string">'utf-8'</span>)<br><br><span class="hljs-built_in">print</span>(<span class="hljs-string">'Begin to send message...'</span>)<br><span class="hljs-built_in">print</span>(<span class="hljs-string">f'共 <span class="hljs-subst">{<span class="hljs-built_in">len</span>(receivers)}</span> 名参赛者'</span>)<br><br><span class="hljs-keyword">for</span> receiver <span class="hljs-keyword">in</span> tqdm(receivers):<br> message[<span class="hljs-string">'To'</span>] = Header(<span class="hljs-string">f"Receiver<<span class="hljs-subst">{receiver}</span>>"</span>)<br> <span class="hljs-keyword">try</span>:<br> server = smtplib.SMTP_SSL(<span class="hljs-string">'smtp.qq.com'</span>, <span class="hljs-number">465</span>)<br> server.login(sender, auth_code)<br> server.sendmail(sender, receivers, message.as_string())<br> server.close()<br> <br> <span class="hljs-keyword">except</span> smtplib.SMTPException <span class="hljs-keyword">as</span> e:<br> fails.append(receiver)<br> <span class="hljs-built_in">print</span>(<span class="hljs-string">f"Error: 无法发送邮件,失败邮箱为:<span class="hljs-subst">{receiver}</span> ,失败原因为: <span class="hljs-subst">{e}</span>"</span>)<br><br><span class="hljs-built_in">print</span>(<span class="hljs-string">'End to send message...'</span>)<br><span class="hljs-built_in">print</span>(<span class="hljs-string">f'发送失败 <span class="hljs-subst">{<span class="hljs-built_in">len</span>(fails)}</span> 封, 为 <span class="hljs-subst">{fails}</span>'</span>)<br></code></pre></td></tr></table></figure><p>如果需要附件,可尝试以下代码:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">import</span> smtplib<br><span class="hljs-keyword">import</span> email.utils<br><span class="hljs-keyword">from</span> email.mime.application <span class="hljs-keyword">import</span> MIMEApplication<br><span class="hljs-keyword">from</span> email.mime.multipart <span class="hljs-keyword">import</span> MIMEMultipart<br><span class="hljs-keyword">from</span> email.mime.text <span class="hljs-keyword">import</span> MIMEText<br><span class="hljs-keyword">from</span> email.header <span class="hljs-keyword">import</span> Header<br><br><br><span class="hljs-keyword">def</span> <span class="hljs-title function_">send_email</span>(<span class="hljs-params">filename</span>):<br><br> sender = <span class="hljs-string">'xxxxx@qq.com'</span> <span class="hljs-comment"># 发送邮箱</span><br> receivers = [<span class="hljs-string">'xx@xx.com'</span>] <span class="hljs-comment"># 接收邮箱</span><br> auth_code = <span class="hljs-string">"auth code"</span> <span class="hljs-comment"># 授权码</span><br><br> message = MIMEMultipart()<br> message[<span class="hljs-string">'From'</span>] = email.utils.formataddr((<span class="hljs-string">'发送者'</span>, sender)) <span class="hljs-comment"># 发送者</span><br> message[<span class="hljs-string">'To'</span>] = email.utils.formataddr((<span class="hljs-string">'收件人'</span>, receivers[<span class="hljs-number">0</span>])) <span class="hljs-comment"># 接收者</span><br><br> message[<span class="hljs-string">'Subject'</span>] = Header(filename, <span class="hljs-string">'utf-8'</span>)<br><br> content = MIMEText(filename)<br> message.attach(content)<br><br> <span class="hljs-comment"># 附件</span><br> excel = MIMEApplication(<span class="hljs-built_in">open</span>(filename, <span class="hljs-string">'rb'</span>).read()) <span class="hljs-comment"># 打开Excel,读取Excel文件</span><br> excel[<span class="hljs-string">"Content-Type"</span>] = <span class="hljs-string">'application/octet-stream'</span> <span class="hljs-comment"># 设置内容类型</span><br> excel.add_header(<span class="hljs-string">'Content-Disposition'</span>, <span class="hljs-string">'attachment'</span>, filename=filename)<br> message.attach(excel)<br><br> <span class="hljs-keyword">try</span>:<br> server = smtplib.SMTP_SSL(<span class="hljs-string">'smtp.qq.com'</span>, <span class="hljs-number">465</span>)<br> server.login(sender, auth_code)<br> server.sendmail(sender, receivers, message.as_string())<br> server.set_debuglevel(<span class="hljs-literal">True</span>)<br> <span class="hljs-built_in">print</span>(<span class="hljs-string">"邮件发送成功"</span>)<br> server.close()<br> <span class="hljs-keyword">except</span> smtplib.SMTPException:<br> <span class="hljs-built_in">print</span>(<span class="hljs-string">"Error: 无法发送邮件"</span>)<br></code></pre></td></tr></table></figure><p>项目地址:<a href="https://github.com/ZeroHzzzz/Email-Autosender?tab=readme-ov-file">ZeroHzzzz/Email-Autosender (github.com)</a></p>]]></content>
<tags>
<tag>#SMTP</tag>
</tags>
</entry>
<entry>
<title>steam家庭共享游戏消失问题</title>
<link href="/2024/08/20/steam%E5%AE%B6%E5%BA%AD%E5%85%B1%E4%BA%AB%E6%B8%B8%E6%88%8F%E6%B6%88%E5%A4%B1%E9%97%AE%E9%A2%98/"/>
<url>/2024/08/20/steam%E5%AE%B6%E5%BA%AD%E5%85%B1%E4%BA%AB%E6%B8%B8%E6%88%8F%E6%B6%88%E5%A4%B1%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<p>#steam #黑神话悟空</p><p>最近买了黑神话悟空,但是我的两个儿子并没有在库中发现这个游戏,可是我们在商店页面发现这款游戏是支持家庭共享的,因此我们进行了求医问药。</p><p>最终的解决方法为:</p><p><strong>拥有游戏本体玩家,把游戏设置为私密在解开</strong></p><p>亲测有效。</p><p>剩下的几个方法没有尝试过,我们也没办法复现这个问题,因此不能确定其正确性,这这里一并贴出:</p><ul><li>自己在共有的游戏库更改游戏偏好选项(需要多人同时购买同一款游戏,才会出现偏好选项)</li><li>切换家庭库版本或更新steam。</li></ul><p>PS:游戏下好不能同时游玩,出现锁库现象的,可以试试让第一个登录的玩家,使用离线模式,后面人在使用在线模式(省事的话可以都采用离线模式)</p>]]></content>
<tags>
<tag>#steam</tag>
<tag>#黑神话悟空</tag>
</tags>
</entry>
<entry>
<title>Nginx代理转发请求方法改变问题</title>
<link href="/2024/08/19/Nginx%E4%BB%A3%E7%90%86%E8%BD%AC%E5%8F%91%E8%AF%B7%E6%B1%82%E6%96%B9%E6%B3%95%E6%94%B9%E5%8F%98%E9%97%AE%E9%A2%98/"/>
<url>/2024/08/19/Nginx%E4%BB%A3%E7%90%86%E8%BD%AC%E5%8F%91%E8%AF%B7%E6%B1%82%E6%96%B9%E6%B3%95%E6%94%B9%E5%8F%98%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<p>#Nginx重定向 #HTTP状态码</p><p>nginx的机制是所有转发默认是get,所以会导致post请求经过nginx转发后会被转化为get请求。</p><p>首先我们来了解一下几个[[HTTP#HTTP 状态码|http状态码]]的区别</p><h3 id="301-Moved-Permanently(永久重定向)"><a href="#301-Moved-Permanently(永久重定向)" class="headerlink" title="301 Moved Permanently(永久重定向)"></a>301 Moved Permanently(永久重定向)</h3><ul><li><strong>含义</strong>:表示请求的资源已被永久移动到新的 URL 上,客户端应使用新的 URL 进行访问。</li><li><strong>特点</strong>:浏览器或搜索引擎通常会缓存 301 重定向,后续访问时会自动使用新的 URL。</li><li><strong>请求方法</strong>:请求方法(如 GET 或 POST)可能会被更改为 GET。</li></ul><h3 id="302-Found(临时重定向)"><a href="#302-Found(临时重定向)" class="headerlink" title="302 Found(临时重定向)"></a>302 Found(临时重定向)</h3><ul><li><strong>含义</strong>:表示请求的资源临时被移动到新的 URL 上,但将来可能会返回到原来的 URL。</li><li><strong>特点</strong>:浏览器不会缓存 302 重定向,每次访问时都会重新请求原 URL。</li><li><strong>请求方法</strong>:请求方法可能会被更改为 GET,尤其是在表单提交时。</li></ul><h3 id="307-Temporary-Redirect(临时重定向)"><a href="#307-Temporary-Redirect(临时重定向)" class="headerlink" title="307 Temporary Redirect(临时重定向)"></a>307 Temporary Redirect(临时重定向)</h3><ul><li><strong>含义</strong>:与 302 类似,表示请求的资源临时被移动,但它严格要求客户端使用原始的请求方法进行重定向。</li><li><strong>特点</strong>:浏览器不会缓存 307 重定向,且保证在重定向时不会更改请求方法(例如,POST 仍然会使用 POST)。</li><li><strong>请求方法</strong>:请求方法不会改变,客户端会以原始请求方法进行重定向。</li></ul><h3 id="308-Permanent-Redirect(永久重定向)"><a href="#308-Permanent-Redirect(永久重定向)" class="headerlink" title="308 Permanent Redirect(永久重定向)"></a>308 Permanent Redirect(永久重定向)</h3><ul><li><strong>含义</strong>:与 301 类似,表示请求的资源已被永久移动到新的 URL。</li><li><strong>特点</strong>:浏览器或搜索引擎会缓存 308 重定向。</li><li><strong>请求方法</strong>:与 307 类似,308 要求请求方法不变,客户端会使用原始请求方法进行重定向。</li></ul><h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ul><li><strong>301</strong> 和 <strong>308</strong> 都表示永久重定向,但 301 可能会更改请求方法,而 308 则不会。</li><li><strong>302</strong> 和 <strong>307</strong> 都表示临时重定向,但 302 可能会更改请求方法,而 307 则不会。</li></ul><p>因此我们可以通过原样转发解决这个问题。也就是通过保留请求方法的重定向方式转发。</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">server</span> {<br><span class="hljs-attribute">listen</span> <span class="hljs-number">80</span>;<br><span class="hljs-attribute">server_name</span> test.<span class="hljs-number">123</span>.com;<br><span class="hljs-section">location</span> /test/api {<br><span class="hljs-attribute">return</span> <span class="hljs-number">307</span> http://192.168.1.133:8088/api;<br><span class="hljs-attribute">proxy_set_header</span> Host <span class="hljs-variable">$host</span>;<br>}<br>}<br></code></pre></td></tr></table></figure><p>而当我们要根据请求类型来过滤按照请求类型转发到指定的地址时可以用以下方式来实现</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">upstream</span> test123 {<br><span class="hljs-attribute">server</span> <span class="hljs-number">192.168.1.133:8888</span> max_fails=<span class="hljs-number">3</span> fail_timeout=<span class="hljs-number">30s</span>;<br><span class="hljs-section">server</span> {<br><span class="hljs-attribute">listen</span> <span class="hljs-number">80</span>;<br><span class="hljs-attribute">server_name</span> test.<span class="hljs-number">123</span>.com;<br><span class="hljs-section">location</span> /api/bbb {<br><span class="hljs-attribute">if</span> (<span class="hljs-variable">$request_method</span> = POST) {<br><span class="hljs-attribute">return</span> <span class="hljs-number">307</span> http://192.168.1.133:8088/aaa/bbb;<br>}<br><span class="hljs-attribute">proxy_pass</span> http://test123;<br><span class="hljs-attribute">proxy_set_header</span> Host <span class="hljs-variable">$host</span>;<br>}<br>}<br>}<br></code></pre></td></tr></table></figure><p>这样的话,当我们使用get请求<code>http://test.123.com/api/bbb</code>这个地址时请求不会被转发,而当我们使用post请求<code>http://test.123.com/api/bbb</code>这个地址时请求会被转发到<code>http://192.168.1.133:8088/aaa/bbb</code>这个地址</p>]]></content>
<tags>
<tag>#Nginx重定向</tag>
<tag>#HTTP状态码</tag>
</tags>
</entry>
<entry>
<title>OMP Error 15问题解决</title>
<link href="/2024/08/15/OMP%20Error%2015%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/"/>
<url>/2024/08/15/OMP%20Error%2015%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3/</url>
<content type="html"><![CDATA[<p>#OpenMP多线程</p><p>OMP 是 “OpenMP” 的缩写,全称为 “Open Multi-Processing”。它是一种用于多线程并行编程的 API,主要用于 C、C++ 和 Fortran 语言。OpenMP 提供了一组编译指令、函数和环境变量,使开发者能够更容易地在多核处理器上编写并行代码。通过在代码中插入 OpenMP 指令,开发者可以控制如何在多个线程之间分配工作负载,从而加速计算任务。OpenMP 常用于科学计算、工程模拟等需要高性能计算的领域。</p><p>目前遇到以下报错</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs log">OMP: Error \#15: Initializing libomp140.x86_64.dll, but found libiomp5md.dll already initialized.<br>OMP: Hint This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade performance or cause incorrect results. The best thing to do is to ensure that only a single OpenMP runtime is linked into the process, e.g. by avoiding static linking of the OpenMP runtime in any library. As an unsafe, unsupported, undocumented workaround you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but that may cause crashes or silently produce incorrect results. For more information, please see http://openmp.llvm.org/<br></code></pre></td></tr></table></figure><p>以及:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs log">OMP: Error \#15: Initializing libomp140.x86_64.dll, but found libomp140.x86_64.dll already initialized.<br>OMP: Hint This means that multiple copies of the OpenMP runtime have been linked into the program. That is dangerous, since it can degrade performance or cause incorrect results. The best thing to do is to ensure that only a single OpenMP runtime is linked into the process, e.g. by avoiding static linking of the OpenMP runtime in any library. As an unsafe, unsupported, undocumented workaround you can set the environment variable KMP_DUPLICATE_LIB_OK=TRUE to allow the program to continue to execute, but that may cause crashes or silently produce incorrect results. For more information, please see http://openmp.llvm.org/<br></code></pre></td></tr></table></figure><p>目前解决方法为:<br>在代码中加入:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">import</span> os<br>os.environ[<span class="hljs-string">"KMP_DUPLICATE_LIB_OK"</span>]=<span class="hljs-string">"TRUE"</span><br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>#OpenMP多线程</tag>
</tags>
</entry>
<entry>
<title>python-magic导入报错问题</title>
<link href="/2024/08/15/python-magic%E5%AF%BC%E5%85%A5%E6%8A%A5%E9%94%99%E9%97%AE%E9%A2%98/"/>
<url>/2024/08/15/python-magic%E5%AF%BC%E5%85%A5%E6%8A%A5%E9%94%99%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<p>#Langchain #libmagic<br>在使用Langchain中的DirectLoader加载PDF文件时,我们遇到了以下问题:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs bash">Import Error:<br>failed to find libmagic. Check your installation<br><br>File <span class="hljs-string">"C:\Users\ZeroHzzzz\Desktop\Jarvis\Docbot\create_index.py"</span>, line 12, <span class="hljs-keyword">in</span> <module> document = loader.load() ImportError: failed to find libmagic. Check your installation<br></code></pre></td></tr></table></figure><p>通过查询,我们发现这个问题源于程序在调用<code>magic</code>模块时出现了<code>ImportError</code>,其原因是缺少<code>libmagic</code>共享库。<code>magic</code>库主要用于识别文件类型,它通过读取文件的“魔术数字”(Magic Number)来推断文件的格式。魔术数字是文件开头的一些字节,可以标识文件类型,例如图片、压缩文件、可执行文件等。Langchain可能正是利用这个库来判断文件类型。</p><p>要解决这个问题,可以安装以下库:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">pip install pylibmagic<br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>#Langchain</tag>
<tag>#libmagic</tag>
</tags>
</entry>
<entry>
<title>Pytorch fbgemm.dll依赖问题</title>
<link href="/2024/08/15/Pytorch%20fbgemm.dll%E4%BE%9D%E8%B5%96%E9%97%AE%E9%A2%98/"/>
<url>/2024/08/15/Pytorch%20fbgemm.dll%E4%BE%9D%E8%B5%96%E9%97%AE%E9%A2%98/</url>
<content type="html"><![CDATA[<p>#PyTorch #DLL #fbegmm</p><p>今天在安装pytorch的时候出现了以下报错:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash">[WinError 126] 找不到指定的模块。 Error loading <span class="hljs-string">"c:\Users\ZeroHzzzz\miniconda3\envs\test\lib\site-packages\torch\lib\fbgemm.dll"</span> or one of its dependencies.<br><br>File <span class="hljs-string">"C:\Users\ZeroHzzzz\Desktop\Jarvis\Docbot\model.py"</span>, line 1, <span class="hljs-keyword">in</span> <module> from transformers import AutoModelForSequenceClassification, AutoTokenizer, AutoModel File <span class="hljs-string">"C:\Users\ZeroHzzzz\Desktop\Jarvis\Docbot\create_index.py"</span>, line 3, <span class="hljs-keyword">in</span> <module> from model import EmbeddingModel OSError: [WinError 126] 找不到指定的模块。 Error loading <span class="hljs-string">"c:\Users\ZeroHzzzz\miniconda3\envs\test\lib\site-packages\torch\lib\fbgemm.dll"</span> or one of its dependencies.<br></code></pre></td></tr></table></figure><p>但是我们到指定路径下检查后,发现这个<code>dll</code>实际上是存在的,那么根据报错信息,就是这个<code>dll</code>缺少了某个依赖。因此我们借助<a href="https://github.com/lucasg/Dependencies/releases/tag/v1.11.1">依赖分析工具</a>来解决这个问题。</p><p>启动后,打开<code>fbegmm.dll</code><br><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408260016559.png" alt="image.png"></p><p>我们发现,<code>libomp140</code>这个依赖是缺失的,那么我们就去下载这个<code>dll</code></p><p><a href="https://www.dllme.com/dll/files/libomp140_x86_64/037e19ea9ef9df624ddd817c6801014e/download">libomp140.x86_64.dll : Free .DLL download. (dllme.com)</a></p><p>将下载的<code>libomp140.dll</code>放入Pytorch的<code>lib</code>目录下。因为我们看到类似的<code>asmjit.dll</code>也在该目录下,因此将新的依赖文件放在同一目录下可以确保Pytorch能够找到并正确加载。</p><p>至此,问题得到了解决。</p>]]></content>
<tags>
<tag>#PyTorch</tag>
<tag>#DLL</tag>
<tag>#fbegmm</tag>
</tags>
</entry>
<entry>
<title>CV-PIL-Read-Photos</title>
<link href="/2024/08/05/CV-PIL-Read-Photos/"/>
<url>/2024/08/05/CV-PIL-Read-Photos/</url>
<content type="html"><![CDATA[<p>#OpenCV #pillow #python</p><p>Python 中,常用的图像处理库包括 OpenCV 和 PIL(Python Imaging Library)。但是两者读取图片有些区别,因而产生一些坑点。</p><p>首先我们来看一个代码,使用 OpenCV 和 PIL 读取图像,并将其转换为 PyTorch 的 Tensor 格式。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">import</span> cv2<br><span class="hljs-keyword">import</span> torch<br><span class="hljs-keyword">from</span> torchvision <span class="hljs-keyword">import</span> transforms<br><span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image<br><br><span class="hljs-comment"># 图像路径</span><br>path = <span class="hljs-string">'./archive/imagesTr/CHNCXR_0640_1.png'</span><br><br><span class="hljs-comment"># 定义数据转换</span><br>data_transforms = {<br> <span class="hljs-string">"train"</span>: transforms.Compose([<br> transforms.ToTensor()<br> ]),<br> <span class="hljs-string">"test"</span>: transforms.Compose([<br> transforms.ToTensor()<br> ])<br>}<br><br><span class="hljs-comment"># 使用 OpenCV 读取图像</span><br>img = cv2.imread(path, cv2.IMREAD_GRAYSCALE)<br><span class="hljs-built_in">print</span>(img.shape)<br>img = data_transforms[<span class="hljs-string">"test"</span>](img)<br><span class="hljs-built_in">print</span>(img.shape)<br><br><span class="hljs-comment"># 使用 PIL 读取图像</span><br>label = Image.<span class="hljs-built_in">open</span>(path).convert(<span class="hljs-string">"L"</span>)<br>label = data_transforms[<span class="hljs-string">"test"</span>](label)<br><span class="hljs-built_in">print</span>(label.shape)<br></code></pre></td></tr></table></figure><p>上面这个代码干了一下几件事:</p><p><strong>OpenCV 读取图像</strong><br>在上述代码中,<code>cv2.imread()</code> 用于读取图像。我们指定了 <code>cv2.IMREAD_GRAYSCALE</code> 参数,这意味着图像将被读取为灰度图像。读取的图像将以 NumPy 数组的形式返回,数组的形状可以通过 <code>img.shape</code> 获取。</p><p><strong>PIL 读取图像</strong><br>使用 <code>Image.open()</code> 函数可以通过 PIL 读取图像。为了与 OpenCV 的灰度读取保持一致,我们使用 <code>convert("L")</code> 将图像转换为灰度模式。PIL 读取的图像以 PIL Image 对象的形式返回。</p><p><strong>转换为 PyTorch Tensor</strong><br>无论是使用 OpenCV 还是 PIL 读取图像,我们最终都希望将图像转换为 PyTorch 的 Tensor 格式,以便输入到神经网络中。为此,我们使用了 torchvision 提供的 <code>transforms.ToTensor()</code> 转换。</p><h2 id="坑点"><a href="#坑点" class="headerlink" title="坑点"></a>坑点</h2><h3 id="OpenCV-和-PIL-读取图像的格式差异"><a href="#OpenCV-和-PIL-读取图像的格式差异" class="headerlink" title="OpenCV 和 PIL 读取图像的格式差异"></a>OpenCV 和 PIL 读取图像的格式差异</h3><p>一个显而易见的差异是 OpenCV 和 PIL 在读取图像时使用的默认格式不同。OpenCV 默认读取图像为 BGR 格式,而 PIL 默认使用 RGB 格式。这在处理彩色图像时尤为重要,因为如果不注意这一点,可能会导致颜色通道的错误匹配。虽然在本示例中,我们读取的是灰度图像,因此这一点并不会引发问题,但在彩色图像处理中需要格外小心。</p><h3 id="数据类型和范围的差异"><a href="#数据类型和范围的差异" class="headerlink" title="数据类型和范围的差异"></a>数据类型和范围的差异</h3><p>OpenCV 读取的图像是以 NumPy 数组的形式存在,数据类型通常为 <code>uint8</code>,值范围是 [0, 255]。而使用 <code>transforms.ToTensor()</code> 进行转换时,NumPy 数组会被转换为一个浮点数 Tensor,值的范围是 [0, 1]。</p><p>相比之下,PIL 读取图像后使用 <code>transforms.ToTensor()</code> 转换时,PIL Image 对象中的每个像素值同样会被归一化到 [0, 1] 范围内。</p><p>这种差异在处理和显示图像时可能会产生问题。例如,如果你在使用 OpenCV 读取图像并进行某些操作后,再用 PIL 显示图像,可能会看到意想不到的结果,因为数值范围的差异可能导致图像亮度和对比度异常。</p><h3 id="数据形状的差异"><a href="#数据形状的差异" class="headerlink" title="数据形状的差异"></a>数据形状的差异</h3><p>当使用 OpenCV 读取灰度图像时,返回的 NumPy 数组是一个二维数组,形状为 <code>(height, width)</code>。而使用 PIL 读取灰度图像并进行 Tensor 转换后,返回的是一个三维 Tensor,形状为 <code>(1, height, width)</code>,即多了一个颜色通道维度。这是因为 PyTorch 中的 Tensor 通常期望有一个明确的通道维度,无论图像是彩色还是灰度。</p><p>这意味着在使用 OpenCV 读取灰度图像并转换为 Tensor 时,我们可能需要手动添加一个通道维度,以使其与 PIL 的输出保持一致。可以使用以下代码进行转换:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs python">img = img[..., <span class="hljs-literal">None</span>] <span class="hljs-comment"># 增加一个维度</span><br>img = data_transforms[<span class="hljs-string">"test"</span>](img)<br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>#OpenCV</tag>
<tag>#pillow</tag>
<tag>#python</tag>
</tags>
</entry>
<entry>
<title>Hexo添加图片方式记录</title>
<link href="/2024/08/05/Hexo%E6%B7%BB%E5%8A%A0%E5%9B%BE%E7%89%87%E6%96%B9%E5%BC%8F%E8%AE%B0%E5%BD%95/"/>
<url>/2024/08/05/Hexo%E6%B7%BB%E5%8A%A0%E5%9B%BE%E7%89%87%E6%96%B9%E5%BC%8F%E8%AE%B0%E5%BD%95/</url>
<content type="html"><![CDATA[<p>#hexo</p><h2 id="Update-2024-05-02"><a href="#Update-2024-05-02" class="headerlink" title="Update 2024.05.02:"></a>Update 2024.05.02:</h2><p>最近期中考完也是化悲愤为力量把一些陈年老bug修了<br>之前提到的图片引用问题得到了解决:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">npm install hexo-renderer-marked --save<br></code></pre></td></tr></table></figure><p>此处的save参数是为了npm的局部安装,因为我们大概率在其他地方不用安装这玩意<br>安装了这东西之后,我们在_config..yml中将下面几个东西修改一下。如果没有就加上</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">post_asset_folder:</span> <span class="hljs-literal">true</span><br><span class="hljs-attr">marked:</span><br> <span class="hljs-attr">prependRoot:</span> <span class="hljs-literal">true</span><br> <span class="hljs-attr">postAsset:</span> <span class="hljs-literal">true</span><br></code></pre></td></tr></table></figure><p>然后就可以通过正常的markdown语法在资源文件夹中引用图片了</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs markdown">![<span class="hljs-string">Description</span>](<span class="hljs-link">path</span>) //注意这里的path是相对于资源文件夹的path<br></code></pre></td></tr></table></figure><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>在写文章的时候我们常常会使用图片来传达一些只可意会不可言传的含义….因此需要图片</p><h2 id="绝对路径"><a href="#绝对路径" class="headerlink" title="绝对路径"></a>绝对路径</h2><p>当Hexo项目中只用到少量图片时,可以将图片统一放在source/images文件夹中,通过markdown语法访问它们。<br>路径:source/images/image.jpg<br><code>![](/images/image.jpg)</code></p><p>这样图片既可以在首页内容中访问到,也可以在文章正文中访问到。</p><h2 id="相对路径"><a href="#相对路径" class="headerlink" title="相对路径"></a>相对路径</h2><p>图片除了可以放在统一的images文件夹中,还可以放在文章自己的目录中。文章的目录可以通过配置_config.yml来生成。</p><p>在根目录的_config.yml中:</p><p><code>post_asset_folder: true</code><br>但是据我惨痛的经历显示,下面这种写法是错误的:<br><code>![photo](passage_name/Photo.png)</code><br>因此我翻阅了hexo的<a href="https://hexo.io/zh-cn/docs/">文档</a>,里面是这么写的</p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281843451.png" alt="1.png"></p><p>但是不知道为啥这个艾斯比东西就是没有用….</p><p>因此我还是只能采用官方推荐的这种写法:<br><code>{% asset_img example.jpg failed_description %}</code></p><p>事后经过一翻谷歌搜索发现用md直接导入图片导致失败的原因可能是因为只是将图片放入文件夹,hexo生成静态界面时并没有处理该图片,所以运行后就找不到图片了….<br>给我整无语了。但是我发现他文件路径是这样的:<br><code>https://zerohzzzz.github.io/[passage_name]/1.png</code><br>而用<code>{% %}</code>方式导入图片,图片的路径是这样的:<br><code>https://zerohzzzz.github.io/2023/10/27/[passage_name]/1.png</code></p><p>但是这个问题似乎在插件的新版本中得到了解决,有兴趣可以看看<a href="https://github.com/boboidream/hexo-easy-images">hexo-easy-images</a>,但我认为有<code>{% %}</code>方式就已经足够了</p><h2 id="Addition"><a href="#Addition" class="headerlink" title="Addition"></a>Addition</h2><p><a href="http://codecook.site/2020/12/05/hexo+typora%E7%9A%84%E5%9B%BE%E7%89%87%E8%B7%AF%E5%BE%84%E9%97%AE%E9%A2%98/">hexo+typora的图片路径问题</a></p>]]></content>
<tags>
<tag>#hexo</tag>
</tags>
</entry>
<entry>
<title>Ubuntu LTS 22.04 libssl 1.1问题记录</title>
<link href="/2024/08/05/Ubuntu%20LTS%2022.04%20libssl%201.1%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95/"/>
<url>/2024/08/05/Ubuntu%20LTS%2022.04%20libssl%201.1%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95/</url>
<content type="html"><![CDATA[<p>#Ubuntu #libssl</p><h1 id="问题描述"><a href="#问题描述" class="headerlink" title="问题描述"></a>问题描述</h1><figure class="highlight nestedtext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs nestedtext"><span class="hljs-attribute">有一些软件包无法被安装。如果您用的是 unstable 发行版,这也许是</span><br><span class="hljs-attribute">因为系统无法达到您要求的状态造成的。该版本中可能会有一些您需要的软件</span><br><span class="hljs-attribute">包尚未被创建或是它们已被从新到(Incoming)目录移出。</span><br><span class="hljs-attribute">下列信息可能会对解决问题有所帮助:</span><br><span class="hljs-attribute"></span><br><span class="hljs-attribute">下列软件包有未满足的依赖关系:</span><br><span class="hljs-attribute"> erlang-crypto</span><span class="hljs-punctuation"> :</span> <span class="hljs-string">依赖: libssl1.1 (>= 1.1.1) 但无法安装它</span><br><span class="hljs-attribute">E</span><span class="hljs-punctuation">:</span> <span class="hljs-string">无法修正错误,因为您要求某些软件包保持现状,就是它们破坏了软件包间的依赖关系。</span><br><br>这几天尝试在ubuntu服务器上安装RabbitMQ的时候出现了以上问题,对此.....<br></code></pre></td></tr></table></figure><h1 id="问题解决"><a href="#问题解决" class="headerlink" title="问题解决"></a>问题解决</h1><p>经过查询资料可知,ubuntu LTS22.04 软件源中,并不包含libssl</p><p>因此,只能手动下载安装。<a href="http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/">http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/</a></p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">wget</span> http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.<span class="hljs-number">1</span>-udeb_1.<span class="hljs-number">1</span>.<span class="hljs-number">1</span>-<span class="hljs-number">1</span>ubuntu2.<span class="hljs-number">1</span>~<span class="hljs-number">18</span>.<span class="hljs-number">04</span>.<span class="hljs-number">23</span>_amd64.udeb<br><br><span class="hljs-attribute">sudo</span> dpkg -i libssl1.<span class="hljs-number">1</span>-udeb_1.<span class="hljs-number">1</span>.<span class="hljs-number">1</span>-<span class="hljs-number">1</span>ubuntu2.<span class="hljs-number">1</span>~<span class="hljs-number">18</span>.<span class="hljs-number">04</span>.<span class="hljs-number">23</span>_amd64.udeb<br></code></pre></td></tr></table></figure><p>问题就解决了</p>]]></content>
<tags>
<tag>#Ubuntu</tag>
<tag>#libssl</tag>
</tags>
</entry>
<entry>
<title>Ubuntu上使用Todesk</title>
<link href="/2024/08/05/Ubuntu%E4%B8%8A%E4%BD%BF%E7%94%A8Todesk/"/>
<url>/2024/08/05/Ubuntu%E4%B8%8A%E4%BD%BF%E7%94%A8Todesk/</url>
<content type="html"><![CDATA[<p>#Ubuntu #Todesk</p><h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><p>参照:<a href="https://www.todesk.com/linux.html">https://www.todesk.com/linux.html</a><br>官方文档上说:</p><figure class="highlight armasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs armasm"><span class="hljs-symbol">sudo</span> apt-<span class="hljs-meta">get</span> install ./todesk-<span class="hljs-built_in">v4</span>.<span class="hljs-number">3</span>.<span class="hljs-number">1</span>.<span class="hljs-number">0</span>-amd64.deb<br></code></pre></td></tr></table></figure><p>但是我试了没用(),由于我要用的是远程的ubuntu服务器,因此只能老老实实下载deb包然后通过scp传到服务器上。</p><h2 id="启动"><a href="#启动" class="headerlink" title="启动"></a>启动</h2><p>启动命令为:</p><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">todesk</span><br></code></pre></td></tr></table></figure><p>但是你都作为服务端了,你要gui界面你有看不到,因此只需要保持todeskd.service运行就行了。</p><p>但是我们显然看不到服务端的设备代码和临时密码,秉持着linux数据皆文件的原则,我们找到了他的配置文件,位于:/opt/todesk/config/config.ini</p><p>查看config.ini</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">cd</span> /opt/todesk/config<br><span class="hljs-built_in">cat</span> config.ini<br></code></pre></td></tr></table></figure><p>可以看到:</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-section">[configinfo]</span><br><span class="hljs-attr">passupdate</span> = <span class="hljs-number">3</span><br><span class="hljs-attr">screen_img</span> =<br><span class="hljs-attr">clientid</span> = ********(这里只是我人为的加密)<br><span class="hljs-attr">privatedata</span> = ea51f22264b6913deb2b29e925788531500fd14c303ac881eb8bf2104632d95c969ecc074f67273fd5eda82971dc56e5ca9cc57467ae6c4b83<br><span class="hljs-attr">updatepasstime</span> = <span class="hljs-number">20240220</span><br><br></code></pre></td></tr></table></figure><p>此时并没有tempauthpassex 字段。我们通过我们windows端的todesk的配置文件可以看到:</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-section">[ConfigInfo]</span><br><span class="hljs-attr">passUpdate</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">PrivateScreenLockScreen</span>=<span class="hljs-number">1</span><br><span class="hljs-attr">autoLockScreen</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">downloadtimes</span>=<span class="hljs-number">202309040</span><br><span class="hljs-attr">clientId</span>=********<br><span class="hljs-attr">PrivateData</span>=<span class="hljs-number">98</span>f13012367f8fa56c7b71bce229e7f6fd1d8275b1340122e53293861dc6256651992beeaac16e61a4b5fad7ba2d0d04f7fd75003e78d12651<br><span class="hljs-attr">PluginExpiresDays</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">Resolution</span>=<span class="hljs-number">2560</span>x1600<br><span class="hljs-attr">tempAuthPassEx</span>=f2c33773c4e07102cd9b30f1e762842b78a13df40e45bb730cd938953cc078a9d174a5b6ee1ad50b13ebb65a4de17f7e917a40969a966d0f<br><span class="hljs-attr">updatePassTime</span>=<span class="hljs-number">20230904</span><br><span class="hljs-attr">isOpenTempPass</span>=<span class="hljs-number">1</span><br><span class="hljs-attr">language</span>=<span class="hljs-number">936</span><br><span class="hljs-attr">isAdmissionControl</span>=<span class="hljs-number">1</span><br><span class="hljs-attr">WeakPasswordTip</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">Version</span>=<span class="hljs-number">4.7</span>.<span class="hljs-number">0.4</span><br><span class="hljs-attr">isUpdate</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">PresetDialogUpdateDate</span>=<span class="hljs-number">2024</span>-<span class="hljs-number">02</span>-<span class="hljs-number">20</span><br><span class="hljs-attr">PresetDialogShowCount</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">NewToken</span>=<br><span class="hljs-attr">Token</span>=cb3c958a5d8d8f79e7d3561495b25987<br><span class="hljs-attr">LoginType</span>=<span class="hljs-number">1</span><br><span class="hljs-attr">user</span>=<br><span class="hljs-attr">LoginPhone</span>=<span class="hljs-number">15918991630</span><br><span class="hljs-attr">LoginEmail</span>=<br><span class="hljs-attr">AreaCode</span>=<span class="hljs-number">86</span><br><span class="hljs-attr">UpdateFrequencyPromptBubble</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">UpdateTempPassDefault</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">LastPushTimeEx</span>=<span class="hljs-number">20240220</span><br><span class="hljs-attr">ShowToolbarGuide</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">IsFirstTimeConnect</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">MouseLeaveTip</span>=<span class="hljs-number">1</span><br><span class="hljs-attr">autoLogin</span>=<span class="hljs-number">2</span><br><span class="hljs-attr">AuthMode</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">minsizelock</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">loginlock</span>=<span class="hljs-number">0</span><br><span class="hljs-attr">passex</span>=<span class="hljs-number">8534</span>b3464a478963712d4a727bc9f34ddbe1b59cc1611fa58ec36c741823b03fa7a59cc821dab0cb617c26a737a6179c<br><span class="hljs-attr">RoundBallXPos</span>=<span class="hljs-number">167</span><br><span class="hljs-attr">RoundBallYPos</span>=<span class="hljs-number">28</span><br></code></pre></td></tr></table></figure><p>对比我们ui界面中的临时密码和设备码,可以确定,clientId就是设备代码,而tempAuthPassEx是通过加密后的临时密码</p><p>那么我们就可以通过我们现在已知的临时密码来获取他的加密,并且添加到服务端的配置文件中,这样一来,服务端的密码就已知了,就可以进行连接了。连接之前记得重启todeskd.service和查看其状态来确定其工作是否正常</p>]]></content>
<tags>
<tag>#Ubuntu</tag>
<tag>#Todesk</tag>
</tags>
</entry>
<entry>
<title>Ubuntu掉盘问题记录</title>
<link href="/2024/08/05/Ubuntu%E6%8E%89%E7%9B%98%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95/"/>
<url>/2024/08/05/Ubuntu%E6%8E%89%E7%9B%98%E9%97%AE%E9%A2%98%E8%AE%B0%E5%BD%95/</url>
<content type="html"><![CDATA[<p>#Ubuntu</p><p>最近属实是有点太压抑了,于是斥巨资买下了HOGWARTS,然后在下载的时候发现游戏盘掉了,表现为:</p><figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pgsql">unable <span class="hljs-keyword">to</span> <span class="hljs-keyword">access</span> "xxx", an operation <span class="hljs-keyword">is</span> pending<br></code></pre></td></tr></table></figure><p>找了一下,原因是上一次拔硬盘的时候没有安全退出</p><p>【解决方法】</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> fdisk -l<br></code></pre></td></tr></table></figure><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281844254.png" alt="image.png"></p><p>最后的设备/dev/sda1就是出问题的磁盘,于是我们需要修复挂载错误的相应分区</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> ntfsfix /dev/sda1<br></code></pre></td></tr></table></figure><p>然后再次插入硬盘就可以正常使用了,后续有空了可能会对挂载失败问题进行更深入的探究</p>]]></content>
<tags>
<tag>#Ubuntu</tag>
</tags>
</entry>
<entry>
<title>Ubuntu通过网络唤醒</title>
<link href="/2024/08/05/Ubuntu%E9%80%9A%E8%BF%87%E7%BD%91%E7%BB%9C%E5%94%A4%E9%86%92/"/>
<url>/2024/08/05/Ubuntu%E9%80%9A%E8%BF%87%E7%BD%91%E7%BB%9C%E5%94%A4%E9%86%92/</url>
<content type="html"><![CDATA[<p>#Ubuntu #WakeonLan</p><p>最近因为自己搭建了一个vps而欣喜若狂而导致日崩。由于某些…的需求,我需要能够再不用的时候将服务器关机。因此我开始折腾远程开机。</p><p>我的思路是通过电脑主板自带的Wake on Lan 功能,目前来说大部分主板都有(我的主板是x99 QD4)。最大的问题是在于配置为S5(shutdown)状态下时网卡需要在关机后处于激活状态,而这里需要系统在启动后将对应的网卡状态设置为对应状态。(因为Ubuntu20.04后网络唤醒重启之后网卡状态设置就会失效。。。不知道为啥)</p><p>过程很简单,即通过发送一组特殊格式的网络封包(Magic Packet)给具有某个MAC地址的电脑,让该电脑从睡眠模式甚至是关机模式苏醒,即从ACPI的Sx(S3,S4,S5)模式返回S0运行模式。</p><p>根据以上的思路,我们就开始着手准备了。</p><h2 id="服务端配置"><a href="#服务端配置" class="headerlink" title="服务端配置"></a>服务端配置</h2><p>我们可以通过ethtool工具来查看并修改网卡状态,因此首先安装ethtool工具:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> apt update<br><span class="hljs-built_in">sudo</span> apt install ethtool<br></code></pre></td></tr></table></figure><p>通过ifconfig查看网络信息:</p><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">ifconfig</span><br></code></pre></td></tr></table></figure><p>以我的为例:</p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">enp6s0</span>: flags=<span class="hljs-number">4163</span><UP,BROADCAST,RUNNING,MULTICAST> mtu <span class="hljs-number">1500</span><br> <span class="hljs-attribute">inet</span> <span class="hljs-number">192.168.0.200</span> netmask <span class="hljs-number">255.255.255.0</span> broadcast <span class="hljs-number">192.168.0.255</span><br> <span class="hljs-attribute">inet6</span> fe80::b7e2:<span class="hljs-number">6743</span>:aa3:<span class="hljs-number">5</span>e49 prefixlen <span class="hljs-number">64</span> scopeid <span class="hljs-number">0</span>x20<link><br> <span class="hljs-attribute">ether</span> <span class="hljs-number">0</span>a:e0:af:b3:<span class="hljs-number">23</span>:bf txqueuelen <span class="hljs-number">1000</span> (以太网)<br> <span class="hljs-attribute">RX</span> packets <span class="hljs-number">10466</span> bytes <span class="hljs-number">6877996</span> (<span class="hljs-number">6</span>.<span class="hljs-number">8</span> MB)<br> <span class="hljs-attribute">RX</span> errors <span class="hljs-number">0</span> dropped <span class="hljs-number">3</span> overruns <span class="hljs-number">0</span> frame <span class="hljs-number">0</span><br> <span class="hljs-attribute">TX</span> packets <span class="hljs-number">8851</span> bytes <span class="hljs-number">860614</span> (<span class="hljs-number">860</span>.<span class="hljs-number">6</span> KB)<br> <span class="hljs-attribute">TX</span> errors <span class="hljs-number">0</span> dropped <span class="hljs-number">0</span> overruns <span class="hljs-number">0</span> carrier <span class="hljs-number">0</span> collisions <span class="hljs-number">0</span><br></code></pre></td></tr></table></figure><p>这个就是我的有线网卡信息。可以看出,ether就是mac地址,网卡名为enp6s0。接下来通过ethtool查看网卡状态:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> ethtool enp6s0<br></code></pre></td></tr></table></figure><p>可以看到:</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-attribute">Supports</span> Wake-<span class="hljs-literal">on</span>: pumbg<br>Wake-<span class="hljs-literal">on</span>: d<br></code></pre></td></tr></table></figure><p>这里附上Wake-on各种状态的参数含义:</p><figure class="highlight vim"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs vim">OptionDescription<br><span class="hljs-keyword">p</span>Wake <span class="hljs-keyword">on</span> PHY activity<br><span class="hljs-keyword">u</span>Wake <span class="hljs-keyword">on</span> unicast <span class="hljs-keyword">messages</span><br><span class="hljs-keyword">m</span>Wake <span class="hljs-keyword">on</span> multicast <span class="hljs-keyword">messages</span><br><span class="hljs-keyword">b</span>Wake <span class="hljs-keyword">on</span> broadcast <span class="hljs-keyword">messages</span><br>gWake <span class="hljs-keyword">on</span> MagicPacket <span class="hljs-keyword">messages</span><br></code></pre></td></tr></table></figure><p>更新网卡状态。由于我们要使用的是MagicPacket信息,因此:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> ethtool --change enp6s0 wol g<br><span class="hljs-built_in">sudo</span> ethtool enp6s0<br></code></pre></td></tr></table></figure><p>此时看到:</p><figure class="highlight apache"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs apache"><span class="hljs-attribute">Wake</span>-<span class="hljs-literal">on</span>: g<br></code></pre></td></tr></table></figure><p>说明状态修改成功。</p><p>由于每次开机后都要重新设置网卡的状态才能在下一次关机后再次使用网络唤醒,所以我们可以通过systemd添加一个系统服务在每次开机后修改网卡状态。<br>首先确定ethtool路径:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">which</span> ethtool<br></code></pre></td></tr></table></figure><p>可见:</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs awk"><span class="hljs-regexp">/usr/</span>sbin/ethtool<br></code></pre></td></tr></table></figure><p>这个因机器而异,因此下面的内容需要根据实际情况修改:</p><p>创建一个 /etc/systemd/system/wol.service 文件,在这里写下启动执行一次的服务信息:</p><figure class="highlight ini"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs ini"><span class="hljs-section">[Unit]</span><br><span class="hljs-attr">Description</span>=Enable Wake <span class="hljs-literal">On</span> Lan<br><br><span class="hljs-section">[Service]</span><br><span class="hljs-attr">Type</span>=<span class="hljs-literal">on</span>eshot<br><span class="hljs-attr">ExecStart</span> = /usr/sbin/ethtool --change enp6s0 wol g<br><br><span class="hljs-section">[Install]</span><br><span class="hljs-attr">WantedBy</span>=basic.target<br></code></pre></td></tr></table></figure><p>之后只需要enable该服务就可以:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> systemctl daemon-reload<br><span class="hljs-built_in">sudo</span> systemctl <span class="hljs-built_in">enable</span> wol.service<br></code></pre></td></tr></table></figure><p>检查一下对应的状态:</p><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">systemctl status wol</span><br></code></pre></td></tr></table></figure><p>可以看到:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs routeros">○ wakeonlan.service - <span class="hljs-built_in">Enable</span> Wake On<span class="hljs-built_in"> Lan</span><br><span class="hljs-built_in"></span> Loaded: loaded (/etc/systemd/system/wol.service; enabled; vendor preset: enabled)<br> Active: inactive (dead) since Tue 2024-02-20 23:32:35 +08; 28min ago<br> Main PID: 948 (<span class="hljs-attribute">code</span>=exited, <span class="hljs-attribute">status</span>=0/SUCCESS)<br> CPU: 2ms<br><br>Feb 20 23:32:34<span class="hljs-built_in"> Server </span>systemd[1]: Starting <span class="hljs-built_in">Enable</span> Wake On Lan<span class="hljs-built_in">..</span>.<br>Feb 20 23:32:35<span class="hljs-built_in"> Server </span>systemd[1]: wol.service: Deactivated successfully.<br>Feb 20 23:32:35<span class="hljs-built_in"> Server </span>systemd[1]: Finished <span class="hljs-built_in">Enable</span> Wake On Lan.<br></code></pre></td></tr></table></figure><p>说明服务正常运行。</p><h2 id="远程启动"><a href="#远程启动" class="headerlink" title="远程启动"></a>远程启动</h2><h3 id="Ubuntu-amp-amp-Mac"><a href="#Ubuntu-amp-amp-Mac" class="headerlink" title="Ubuntu && Mac"></a>Ubuntu && Mac</h3><p>以Ubuntu和Mac为例,在命令行中执行wakeonlan xx:xx:xx:xx:xx:xx (输入Ubuntu机器对应的mac地址)就可以唤醒机器了</p><p>但是前提是安装了wakeonlan</p><h3 id="windows"><a href="#windows" class="headerlink" title="windows"></a>windows</h3><p>这里我偷懒了,不想自己写一个脚本出来,因此我就用一些现成的工具了。此处我选择的是<a href="https://www.depicus.com/wake-on-lan/wake-on-lan-gui">WakeOnLanGui</a></p><p>界面如下:</p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281844763.png" alt="image.png"></p><p>根据实际情况填写MAC地址、被控端域名\ip、子网掩码和端口号(任一)就行了</p>]]></content>
<tags>
<tag>#Ubuntu</tag>
<tag>#WakeonLan</tag>
</tags>
</entry>
<entry>
<title>Voicemeeter使用记录</title>
<link href="/2024/08/05/Voicemeeter%E4%BD%BF%E7%94%A8%E8%AE%B0%E5%BD%95/"/>
<url>/2024/08/05/Voicemeeter%E4%BD%BF%E7%94%A8%E8%AE%B0%E5%BD%95/</url>
<content type="html"><![CDATA[<p>#Voicemeeter</p><h1 id="一、基础知识"><a href="#一、基础知识" class="headerlink" title="一、基础知识"></a>一、基础知识</h1><h2 id="输入与输出"><a href="#输入与输出" class="headerlink" title="输入与输出"></a>输入与输出</h2><ul><li>硬件输入:就是现实的电脑上的麦克风、你头戴耳麦的麦克风等硬件录音设备。【硬件输入→(发出)→声音信号】(请注意这里的声音指的是电路中的声音信号,而不是你实际听到的声音。下同。)</li><li><p>硬件输出:就是现实的扬声器喇叭、你头戴耳麦的耳机等硬件发声设备。【声音信号→(被接收)→硬件输出】</p></li><li><p>虚拟输入:就是虚拟录音设备,专门监听系统中各种软件发出的声音信号。【声音信号→(被接收)→虚拟输入】</p></li></ul><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281845604.png" alt="virtual_input.jpg"></p><ul><li>虚拟输出:就是虚拟发声设备,有一个虚拟的扬声器,负责向别的设备发出声音信号。【虚拟输出→(发出)→声音信号】</li></ul><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281845439.png" alt="virtual_output.jpg"></p><ul><li>通道:用于接收和转发声音信号的中间人。</li></ul><h2 id="设置电脑的输入输出设备"><a href="#设置电脑的输入输出设备" class="headerlink" title="设置电脑的输入输出设备"></a>设置电脑的输入输出设备</h2><p>自行百度,这里不再赘述</p><h1 id="二、软件界面"><a href="#二、软件界面" class="headerlink" title="二、软件界面"></a>二、软件界面</h1><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281846233.png" alt="软件界面.jpg"></p><p>看下图硬件输入通道1下面框出来的按钮:A1、A2、A3、B1、B2 都是输出通道,你点亮了哪个,声音信号就会被接入到哪一个输出通道。</p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281846495.png" alt="硬件通道输入.jpg"></p><p>比如图中,点亮了A1和B1,那么硬件输入通道1的声音信号就会被发送到A1、B1两个输出通道中去。</p><h1 id="三、使用"><a href="#三、使用" class="headerlink" title="三、使用"></a>三、使用</h1><p>这里只讲解软件同时输出到多个蓝牙设备的使用方法:</p><ul><li>打开Voicemeeter</li><li>配置输出设备</li></ul><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281847030.png" alt="1.jpg"></p><ul><li>在虚拟输入栏中选择输出设备</li></ul><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281847879.png" alt="1.png"></p><ul><li>调节音量</li></ul><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281847699.png" alt="3.png"></p><ul><li>run!</li></ul><h1 id="Addition"><a href="#Addition" class="headerlink" title="Addition"></a>Addition</h1><p>如果想了解更多关于voicemeeter相关的知识,可到:<br><a href="http://vb-audio.cn/post/36.html">http://vb-audio.cn/post/36.html</a></p>]]></content>
<tags>
<tag>#Voicemeeter</tag>
</tags>
</entry>
<entry>
<title>Vscode中c编译器配置(mingw64)</title>
<link href="/2024/08/05/Vscode%E4%B8%ADc%E7%BC%96%E8%AF%91%E5%99%A8%E9%85%8D%E7%BD%AE%EF%BC%88mingw64%EF%BC%89/"/>
<url>/2024/08/05/Vscode%E4%B8%ADc%E7%BC%96%E8%AF%91%E5%99%A8%E9%85%8D%E7%BD%AE%EF%BC%88mingw64%EF%BC%89/</url>
<content type="html"><![CDATA[<p>#VSCode #Cpp</p><h2 id="To-Start"><a href="#To-Start" class="headerlink" title="To Start"></a>To Start</h2><ul><li>安装Vscode</li><li>请前往<a href="https://code.visualstudio.com/" title="Vscode 官网">https://code.visualstudio.com/</a>下载你所需要的Vscode版本</li></ul><p>下载完了之后,你就可以开始配置C++的运行环境了</p><h2 id="Install-the-extension"><a href="#Install-the-extension" class="headerlink" title="Install the extension"></a>Install the extension</h2><ul><li>打开Vscode</li><li>选择拓展选项卡或者使用快捷键<code>Ctrl+Shift+X</code></li><li>搜索C++</li><li>安装</li></ul><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281840906.png" alt="1.png"></p><h2 id="Set-up-for-your-C-environment"><a href="#Set-up-for-your-C-environment" class="headerlink" title="Set up for your C++ environment"></a>Set up for your C++ environment</h2><h3 id="下载Mingw64文件"><a href="#下载Mingw64文件" class="headerlink" title="下载Mingw64文件"></a>下载Mingw64文件</h3><ul><li>打开浏览器</li><li>前往<a href="https://github.com/niXman/mingw-builds-binaries/releases">Releases · niXman/mingw-builds-binaries (github.com)</a>下载MingW64文件</li><li>选择下列图片中标出的版本</li><li>解压,获得其中的Mingw64文件夹并放在你想放的位置</li></ul><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281840477.png" alt="2.png"></p><h3 id="配置环境变量"><a href="#配置环境变量" class="headerlink" title="配置环境变量"></a>配置环境变量</h3><ul><li>直接<code>win + S</code>快捷键搜索环境变量,进入该选项卡</li><li>点击环境变量</li><li>在用户变量和系统变量中找到Path,进入编辑</li><li>新建,并将刚才下载的Mingw64中的bin文件夹的路径填入</li><li>完成!</li></ul><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281840746.png" alt="3.png"></p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281840815.png" alt="4.png"></p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281841431.png" alt="5.png"></p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281841073.png" alt="6.png"></p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281841329.png" alt="7.png"></p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281841588.png" alt="8.png"></p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281841694.png" alt="9.png"></p><p>点击确定,完成!</p><h2 id="Check"><a href="#Check" class="headerlink" title="Check"></a>Check</h2><ul><li>直接<code>win + R</code>,输入cmd并运行,打开终端</li><li>输入<code>gcc -v</code>,如果出现下列画面就说明配置成功了</li><li>完成!</li></ul><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281842231.png" alt="10.png"></p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281842027.png" alt="11.png"></p><h2 id="Create-and-Run-a-C-file"><a href="#Create-and-Run-a-C-file" class="headerlink" title="Create and Run a C++ file"></a>Create and Run a C++ file</h2><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281842342.png" alt="12.png"></p><p>create a new file called <code>helloworld.cpp</code></p><p>复制,粘贴!</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><iostream></span></span><br><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br> std::cout << <span class="hljs-string">"Hello World"</span> << std::endl;<br>}<br></code></pre></td></tr></table></figure><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281843039.png" alt="13.png"></p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281843501.png" alt="14.png"></p><p>仅在第一次运行 helloworld.cpp 时提示您选择编译器。该编译器将成为tasks.json 文件中设置的“默认”编译器</p><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281843703.png" alt="15.png"></p><p>拿下!</p><p><strong>好好好,现在你就可以尽情的Coding了,可能还有一些其他的零碎配置</strong></p><p><strong>有空我再更新(</strong></p>]]></content>
<tags>
<tag>#Cpp</tag>
<tag>#VSCode</tag>
</tags>
</entry>
<entry>
<title>Vscode多文件编译配置</title>
<link href="/2024/08/05/Vscode%E5%A4%9A%E6%96%87%E4%BB%B6%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE/"/>
<url>/2024/08/05/Vscode%E5%A4%9A%E6%96%87%E4%BB%B6%E7%BC%96%E8%AF%91%E9%85%8D%E7%BD%AE/</url>
<content type="html"><![CDATA[<p>#VSCode #Cpp #编译</p><h2 id="正片开始"><a href="#正片开始" class="headerlink" title="正片开始"></a>正片开始</h2><p>默认VSCode 只能编译单个文件,若多个文件一起编译,经常会报 undefined reference 找不到引用的错误,比如下面的问题:</p><figure class="highlight moonscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs moonscript"><span class="hljs-string">"C:\Program Files\mingw64\bin\g++.exe"</span> -fdiagnostics-color=always -g <span class="hljs-name">C</span>:\Users\ZeroHzzzz\Desktop\dd\dd.cpp -o <span class="hljs-name">C</span>:\Users\ZeroHzzzz\Desktop\dd\dd.exe<br><span class="hljs-name">C</span>:\Users\ZEROHZ~<span class="hljs-number">1</span>\AppData\Local\Temp\ccYQ5ExK.<span class="hljs-name">o</span>: In function `main<span class="hljs-string">':</span><br><span class="hljs-string">C:/Users/ZeroHzzzz/Desktop/dd/dd.cpp:6: undefined reference to `maxn(int, int)'</span><br>collect2.<span class="hljs-name">exe</span>: <span class="hljs-name">error</span>: ld returned <span class="hljs-number">1</span> exit status<br></code></pre></td></tr></table></figure><p>解决方法如下:</p><ul><li>配置一下<code>.vscode</code>文件夹下的 <code>tasks.json</code> 就好了。</li><li>tasks.json的话,就把界面点到代码的界面,然后菜单栏<code>"Terminal"</code> - <code>"Configure Tasks..."</code> 生成默认的<code>tasks.json</code></li></ul><p>找到 tasks.json中的 args 选项,这个主要是用来配置待编译的文件信息的,<code>${file}</code>替换成 <code>${workspaceFolder}</code>, 结果如下:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-attr">"args"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><br> <span class="hljs-string">"-fdiagnostics-color=always"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"-g"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"${workspaceFolder}\\*.cpp"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"-o"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"${fileDirname}\\${fileBasenameNoExtension}.exe"</span><br><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span><br></code></pre></td></tr></table></figure><p>再次运行程序,就可以多文件正常编译了</p><h2 id="Addition"><a href="#Addition" class="headerlink" title="Addition"></a>Addition</h2><p>但是如果我们还有其它的二级目录,那就还需要修改<code>tasks.json</code>文件。</p><p>【举例】main函数所在<code>test.cpp</code>在一级目录下,其它<code>cpp</code>文件在 <code>others</code>目录下,这个时候就需要把<code>tasks.json</code>改成:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-attr">"args"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><br> <span class="hljs-string">"-fdiagnostics-color=always"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"-g"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"${workspaceFolder}\\*.cpp"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"${workspaceFolder}\\others\\*.cpp"</span><span class="hljs-punctuation">,</span> <span class="hljs-comment">//修改项</span><br> <span class="hljs-string">"-o"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"${fileDirname}\\${fileBasenameNoExtension}.exe"</span><br><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span><br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>#Cpp</tag>
<tag>#编译</tag>
<tag>#VSCode</tag>
</tags>
</entry>
<entry>
<title>Vscode自动格式化插件</title>
<link href="/2024/08/05/Vscode%E8%87%AA%E5%8A%A8%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%8F%92%E4%BB%B6/"/>
<url>/2024/08/05/Vscode%E8%87%AA%E5%8A%A8%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%8F%92%E4%BB%B6/</url>
<content type="html"><![CDATA[<p>#VSCode #Prettier</p><h2 id="Previous"><a href="#Previous" class="headerlink" title="Previous"></a>Previous</h2><p>事情的起因是我在某一天打开 vscode 后发现了 tab 变成了两个空格而导致我这个极度代码洁癖的人感觉很难受<br><del>由于懒</del>…由于习惯了编写 go 语言代码保存时候的自动格式化,这让最近因为 c++的<del>goushi</del>作业而焦头烂额的我开始思考能不能在其他语言编写的时候能不能也搞个</p><p>由于我平时使用的是 Vscode,因此我就直接使用了 prettier 插件。以下是我配置的一些记录:</p><h2 id="步骤"><a href="#步骤" class="headerlink" title="步骤"></a>步骤</h2><ul><li>安装 prettier 插件</li><li>配置<ul><li>可以通过 setting.json 进行配置, 这里就不多说了</li><li>也可以通过在 setting 中直接搜索 prettier 来实现</li></ul></li></ul><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-attr">"editor.formatOnSave"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span> <span class="hljs-comment">// 保存自动格式化</span><br><span class="hljs-attr">"prettier.useTabs"</span><span class="hljs-punctuation">:</span> <span class="hljs-literal"><span class="hljs-keyword">true</span></span><span class="hljs-punctuation">,</span><br><span class="hljs-attr">"prettier.tabWidth"</span><span class="hljs-punctuation">:</span> <span class="hljs-number">4</span><span class="hljs-punctuation">,</span> <span class="hljs-comment">// Tab 宽度</span><br><span class="hljs-attr">"C_Cpp.clang_format_style"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"{ BasedOnStyle: Chromium, IndentWidth: 4}"</span> <span class="hljs-comment">// c++/c 大括号不换行</span><br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>#VSCode</tag>
<tag>#Prettier</tag>
</tags>
</entry>
<entry>
<title>基于hexo搭建博客(GitHub)</title>
<link href="/2024/08/05/%E5%9F%BA%E4%BA%8Ehexo%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2%EF%BC%88GitHub%EF%BC%89/"/>
<url>/2024/08/05/%E5%9F%BA%E4%BA%8Ehexo%E6%90%AD%E5%BB%BA%E5%8D%9A%E5%AE%A2%EF%BC%88GitHub%EF%BC%89/</url>
<content type="html"><![CDATA[<p>#hexo</p><h2 id="准备工作"><a href="#准备工作" class="headerlink" title="准备工作"></a>准备工作</h2><ul><li>GitHub账号</li><li>安装git</li><li>安装node</li></ul><h2 id="创建仓库"><a href="#创建仓库" class="headerlink" title="创建仓库"></a>创建仓库</h2><ul><li>创建仓库,并将仓库命名为 username.github.io<br>注意这里的username()</li></ul><h2 id="安装hexo"><a href="#安装hexo" class="headerlink" title="安装hexo"></a>安装hexo</h2><ul><li>安装hexo<br><code>npm install -g hexo-cli</code></li><li>check<br><code>hexo -v</code></li><li>创建hexo项目并初始化</li></ul><figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs mipsasm">hexo init [hexo-<span class="hljs-keyword">blog(你新建的本地博客文件夹的名字,如果不输入默认为当前文件夹)]</span><br><span class="hljs-keyword"></span>cd hexo-<span class="hljs-keyword">blog</span><br><span class="hljs-keyword"></span>npm <span class="hljs-keyword">install</span><br></code></pre></td></tr></table></figure><h2 id="主题"><a href="#主题" class="headerlink" title="主题"></a>主题</h2><p>hexo默认主题为landscape,可以前往hexo官网寻找你心仪的主题<br><a href="https://hexo.io/themes/">Themes</a></p><figure class="highlight crmsh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs crmsh">git <span class="hljs-keyword">clone</span> <span class="hljs-title">[github</span>地址] [存放路径]<br><span class="hljs-comment"># 例如</span><br><span class="hljs-comment"># git clone https://github.com/iissnan/hexo-theme-next themes/next</span><br></code></pre></td></tr></table></figure><p>在根目录的 _config.yml 文件中找到theme字段并将它改成你主题的名字<br><code>theme: next</code></p><p>本地启动:</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs css">hexo <span class="hljs-selector-tag">g</span><br>hexo s<br></code></pre></td></tr></table></figure><p><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408281852233.png" alt="1.png"></p><h2 id="修改参数"><a href="#修改参数" class="headerlink" title="修改参数"></a>修改参数</h2><p>根据themes提供的文档修改参数</p><h2 id="Writing"><a href="#Writing" class="headerlink" title="Writing"></a>Writing</h2><p>新建文章<br><code>hexo new post 测试文章</code><br>然后就开始写吧</p><h2 id="本地预览"><a href="#本地预览" class="headerlink" title="本地预览"></a>本地预览</h2><ul><li>预览的同时可以修改文章内容或主题代码,保存后刷新页面即可</li><li>对 Hexo 根目录 _config.yml 的修改,需要重启本地服务器后才能预览效果<br><code>hexo s</code></li></ul><h2 id="Deloy"><a href="#Deloy" class="headerlink" title="Deloy"></a>Deloy</h2><ul><li>安装hexo-deployer-git<br><code>npm install hexo-deployer-git --save</code></li><li>修改根目录下的 _config.yml,配置 GitHub 相关信息,token获取方式自行百度</li></ul><figure class="highlight dts"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs dts"><span class="hljs-symbol">deploy:</span><br><span class="hljs-symbol"> type:</span> git<br><span class="hljs-symbol"> repo:</span> https:<span class="hljs-comment">//github.com/yaorongke/yaorongke.github.io.git</span><br><span class="hljs-symbol"> branch:</span> main<br><span class="hljs-symbol"> token:</span> ghp_3KakcaPHerunNRyMerofcFd9pblU282FSbsY <span class="hljs-meta"># 应该可写可不写</span><br></code></pre></td></tr></table></figure><ul><li>发布</li></ul><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs css">hexo <span class="hljs-selector-tag">g</span> -d<br></code></pre></td></tr></table></figure><h2 id="Addition"><a href="#Addition" class="headerlink" title="Addition"></a>Addition</h2><h3 id="使用Fluid主题的一些文章属性设置"><a href="#使用Fluid主题的一些文章属性设置" class="headerlink" title="使用Fluid主题的一些文章属性设置"></a>使用Fluid主题的一些文章属性设置</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs title">---<br>title: Hexo Fluid主题使用笔记<br><br>tags:<br> - Hexo<br> [Hexo, Fluid] # 推荐使用这种方法<br><br>categories:<br> - Hexo<br> - Fluid # 注意以上这两个标题不是并列关系,而是包含关系<br> - Hexo<br> - Fluid # 注意以上这两个标题是并列关系<br> - [Hexo, Fluid] # 并列关系<br><br>excerpt: 这是摘要 # 摘要还可以在正文通过 <!-- more --> 进行分割<br><br>hide: true # 隐藏文章,隐藏后依然可以通过文章链接访问<br><br>sticky: 100 # 数值越大排序越靠前<br><br>index_img: /img/example.jpg # 文章在首页的封面图,支持外链<br><br>banner_img: /img/post_banner.jpg # 文章详情页顶部大图,支持外链<br><br>toc: true # 生成文章目录,不填为true<br>---<br><br></code></pre></td></tr></table></figure><h3 id="一些有意思的东西"><a href="#一些有意思的东西" class="headerlink" title="一些有意思的东西"></a>一些有意思的东西</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs hexo">// 便签<br><br>{% note success %}<br>文字 或者 `markdown` 均可<br>{% endnote %}<br>或者使用 HTML 形式:<br><p class="note note-primary">标签</p><br><br><br>//行内标签<br><br>{% label primary @text %}<br>或者<br><span class="label label-primary">Label</span><br><br><br>//复选框<br><br>{% cb text, checked?, incline? %}<br><br>text:显示的文字<br>checked:默认是否已勾选,默认 false<br>incline: 是否内联(可以理解为后面的文字是否换行),默认 false<br><br><br>//按钮<br><br>{% btn url, text, title %}<br><br>或者:<br><br><a class="btn" href="url" title="title">text</a><br><br>url:跳转链接<br>text:显示的文字<br>title:鼠标悬停时显示的文字(可选)<br></code></pre></td></tr></table></figure><h2 id="EOF"><a href="#EOF" class="headerlink" title="EOF"></a>EOF</h2>]]></content>
<tags>
<tag>#hexo</tag>
</tags>
</entry>
<entry>
<title>给GitHub Pages配置CNAME</title>
<link href="/2024/07/29/%E7%BB%99GitHub%20Pages%E9%85%8D%E7%BD%AECNAME/"/>
<url>/2024/07/29/%E7%BB%99GitHub%20Pages%E9%85%8D%E7%BD%AECNAME/</url>
<content type="html"><![CDATA[<p>#CNAME #GitHubPages</p><h2 id="什么是-DNS-CNAME-记录"><a href="#什么是-DNS-CNAME-记录" class="headerlink" title="什么是 DNS CNAME 记录"></a>什么是 DNS CNAME 记录</h2><p>一个”冠名” (CNAME)记录从一个别名域指向一个”冠名” 域。当一个[[域名|域]]或子域是另一个域的别名时,CNAME记录被用来代替 [[A记录]] 。 所有CNAME记录都必须指向一个域名,而不是指向一个IP地址。 CNAME记录允许你把一个域名(别名)指向另一个域名(规范名)。这样,当用户访问别名时,实际上会被重定向到规范名。</p><p>例如,假设 blog.example.com 的 CNAME 记录的值为“example.com”(没有“blog”)。这意味着当 DNS 服务器点击 blog.example.com 的 DNS 记录时,它实际上会触发另一个对 example.com 的 DNS 查找,并通过其 A 记录返回 example.com 的 IP 地址。在这种情况下,我们会说 example.com 是 blog.example.com 的规范名称(或真实名称)。</p><p>这样也就带来了一个优势。通过CNAME记录,你可以简化域名的管理。如果你的主域名的IP地址更改了,只需更新主域名的A记录,而不需要逐个更新每个子域名的记录</p><p>人们常常误以为CNAME记录必须解析为它指向的域名所在的网站。也就是说,他们认为如果 <code>blog.example.com</code> 的CNAME记录指向 <code>example.com</code>,访问 <code>blog.example.com</code> 时看到的内容一定和 <code>example.com</code> 一样。但是,CNAME记录实际上只是将客户端(即用户的浏览器)指向与根域名相同的IP地址。换句话说,CNAME记录让 <code>blog.example.com</code> 和 <code>example.com</code> 指向同一个IP地址。当客户端连接到这个IP地址时,Web服务器会根据客户端请求的URL来决定返回什么内容。例如,当用户访问 <code>blog.example.com</code> 时,尽管这个域名通过CNAME记录指向 <code>example.com</code> 的IP地址,Web服务器会识别出请求的URL是 <code>blog.example.com</code>,然后返回博客页面而不是<code>example.com</code> 的主页。</p><p>也就是说,CNAME记录并不改变用户访问的URL,而是将用户导向同一个IP地址。之后,具体返回什么内容由Web服务器根据请求的URL来决定。CNAME记录实现的是域名之间的指向关系,而实际内容的返回取决于Web服务器对请求的处理。</p><div class="table-container"><table><thead><tr><th>blog.example.com</th><th>record type:</th><th>value:</th><th>TTL</th></tr></thead><tbody><tr><td>@</td><td>CNAME</td><td>is an alias of example.com</td><td>32600</td></tr></tbody></table></div><p>注意,MX 和 NS 记录不能指向 CNAME 记录,它们必须指向 A 记录(对于 IPv4)或 AAAA 记录。MX 记录是邮件交换记录,将电子邮件指向一个邮件服务器。NS 记录是“名称服务器”记录,表明哪个 DNS 服务器是该域的权威。</p><h2 id="给GitHub-Pages配置CNAME记录"><a href="#给GitHub-Pages配置CNAME记录" class="headerlink" title="给GitHub Pages配置CNAME记录"></a>给GitHub Pages配置CNAME记录</h2><p>我们这里主要讲述如何配置子域名。官方的文档<a href="https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site#configuring-a-subdomain">在这</a><br>其实不用很麻烦</p><p>首先需要建立一个名为CNAME的文件。文件中的内容也只需要一行,也就是自定义域名的空子域名,例如<code>blog.zerohzzzz.top</code>(请注意不是<code>https://blog.zerohzzzz.top</code>)。注意,在 <em>CNAME</em> 文件中只允许有<strong>一个域名</strong>。这个文件以后放在你博客中的sources文件夹中,以后<code>deloy</code>的时候会一起提交上去并出现在储存分支的根目录</p><p>进入你的<code>github.io</code>储存库,并进入设置(<code>setting</code>),在侧边栏中的<code>Code and automation</code>中选择<code>Pages</code></p><p>在<code>Custom domain</code>条目下,输入你的域名,然后选择保存,注意这个域名和你<em>CNAME</em>文件中的域名要保持一致。</p><p>最后去你的DNS提供商(你域名在哪买就去哪,或者可以选择托管到cloudfare,但是国内的话速度堪忧)新增一个CNAME记录,将你的二级域名指向你的GitHub Pages,如<code><user>.github.io</code>至此工作就全部完成了。</p>]]></content>
<tags>
<tag>#GitHubPages</tag>
<tag>#CNAME</tag>
</tags>
</entry>
<entry>
<title>Ubuntu-22-04-LTS安装Steam</title>
<link href="/2024/07/26/Ubuntu-22-04-LTS%E5%AE%89%E8%A3%85Steam/"/>
<url>/2024/07/26/Ubuntu-22-04-LTS%E5%AE%89%E8%A3%85Steam/</url>
<content type="html"><![CDATA[<p>#steam #Ubuntu</p><h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>很久很久以前,有个人有点受不了用windows这种系统了,由于Have no money()….经过了一段时间的观望,他开始转向Linux的怀抱。然而又因为某些智力因素于是他决定先从Ubuntu开始……</p><p>众所周知,安装系统后第一件事就是下载steam。原本来说,Linux系统的一大痛点就是不能玩游戏,但是随着 Steam Play 功能的推出,一切都开始有所转机</p><p>于是他尝试了很多种方法来实现自己的愿望。<br>我们将介绍每一种方法</p><h2 id="正片开始"><a href="#正片开始" class="headerlink" title="正片开始"></a>正片开始</h2><h3 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h3><p>系统环境:Ubuntu 22.04.4 LTS<br>桌面环境:Gnome 42.9<br>窗口系统:×11</p><p>硬件环境自不必多说,应该没有问题(毕竟是i9+4080</p><h3 id="Ubuntu-Software"><a href="#Ubuntu-Software" class="headerlink" title="Ubuntu Software"></a>Ubuntu Software</h3><p>这是一种抽象的方法因为Ubuntu Software是基于snap的<br>这里我为了不污染我的系统于是我就不试了<br>而且也确实没啥好讲的</p><h3 id="APT"><a href="#APT" class="headerlink" title="APT"></a>APT</h3><p>在我的观念中,能用apt装了没问题的软件就不用其他的装,因此这个方法是我的首选</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> apt intall steam<br></code></pre></td></tr></table></figure><p>也是顺利的装上了<br><img src="https://cloud.intro-iu.top:738/d/ThreeBody/ZeroHzzzzPic/202408210020685.png" alt="Steam"></p><p>但是这个方法不知道是不是我打开的方式有问题,每次我开双屏(<del>当然不得不提一下我的27寸大屏啦</del>)都会发现有一个屏幕显示异常,表现为一动不动但是另一个屏幕正常。看了网上的各种解决方法也还暂时不知道所以然。。。因此我果断</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">sudo apt purge steam<br></code></pre></td></tr></table></figure><p>然后开始尝试另一种方法</p><h3 id="Flatpak"><a href="#Flatpak" class="headerlink" title="Flatpak"></a>Flatpak</h3><p>这个方法是我最终使用方法,也是我比较喜欢的一种方式(虽然被学长说有点臃肿),毕竟他把runtime包在一起的缘故,应用程序可能随便都占1GB以上,除此之外还有沙盒权限问题</p><h4 id="安装flatpak"><a href="#安装flatpak" class="headerlink" title="安装flatpak"></a>安装flatpak</h4><p>这个方法首先要我们安装<a href="https://flatpak.org/setup/Ubuntu">flatpak</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> apt install flatpak<br></code></pre></td></tr></table></figure><p>当然也可以添加Flatpak PPA来安装(针对于旧版本Ubuntu)</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> add-apt-repository ppa:flatpak/stable<br><span class="hljs-built_in">sudo</span> apt update<br><span class="hljs-built_in">sudo</span> apt install flatpak<br></code></pre></td></tr></table></figure><p>(可选)安装flatpak插件,这样可以通过可视化界面安装flatpak软件</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> apt install gnome-software-plugin-flatpak<br></code></pre></td></tr></table></figure><p>添加Flathub 仓库</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo<br></code></pre></td></tr></table></figure><p>然后restart</p><h3 id="安装steam"><a href="#安装steam" class="headerlink" title="安装steam"></a>安装steam</h3><p>直接通过flatpak安装<a href="https://flathub.org/apps/com.valvesoftware.Steam">steam</a></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash">flatpak install flathub com.valvesoftware.Steam<br></code></pre></td></tr></table></figure><p>这样就顺利的装上了,记得启用Steam Play就行了,这样安装游戏的时候就能正常使用了(当然是大部分,据我所知大表哥就不行555~)</p><h3 id="Flatseal"><a href="#Flatseal" class="headerlink" title="Flatseal"></a>Flatseal</h3><p>这个玩意是用来管理Flatpak权限的,可装可不装,但是装上明显会更方便。因为记不住……</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs bash"><span class="hljs-built_in">sudo</span> apt install Flatseal<br></code></pre></td></tr></table></figure><h2 id="Additions"><a href="#Additions" class="headerlink" title="Additions"></a>Additions</h2><p>由于我系统盘空间不足的缘故,我想把游戏安装到外置硬盘。因此我尝试添加存储空间。<br>但我发现,添加存储空间的时候无法直接添加指定的驱动器,只能通过~/media/这个软链接来添加。置此备忘</p>]]></content>
<tags>
<tag>#Ubuntu</tag>
<tag>#steam</tag>
</tags>
</entry>
</search>