<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>https://rehtt.com/</id>
  <title type="text">Rehtt&apos;s Blog</title>
  <subtitle type="text">个人学习分享</subtitle>
  <updated>2026-05-10T04:13:00.000Z</updated>
  <author><name>Rehtt</name></author>
  <link rel="alternate" href="https://rehtt.com/"/>
  <link rel="self" href="https://rehtt.com/atom.xml"/>
  <generator uri="https://github.com/CuteLeaf/Firefly">Firefly v6.16.8</generator>
    <entry>
      <id>https://rehtt.com/posts/279/</id>
      <title type="text">【NFC】恢复被写入cpu卡SAK的CUID魔术卡</title>
      <published>2026-05-10T04:12:00.000Z</published>
      <updated>2026-05-10T04:13:00.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/279/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>不小心将cpu卡的uid及特征写入了Gen2 CUID魔术卡，导致魔术卡不能被设备正常识别 cpu卡的<code>SAK</code>通常为<code>0x20</code>或<code>0x60</code>，一般读卡器识别是cpu卡后要求卡要回复<code>ATS</code>，而CUID/M1 的魔术卡回复不了<code>ATS</code>，导致读卡握手失败 因为握手失败，所以常规的写卡手段都会卡在第一步报错读取不到卡 因此恢复方法是让写卡器忽略掉检测<code>ATS</code>这一步</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>使用变色龙cli处理：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>hw connent</span></div></div><div><div><div>2</div></div><div><span># 关键的一步，跳过ATS检测</span></div></div><div><div><div>3</div></div><div><span>hf 14a config --rats skip</span></div></div><div><div><div>4</div></div><div><span># 跳过后一般检测就正常了</span></div></div><div><div><div>5</div></div><div><span>hf 14a scan</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 向0区块写入正常M1 1K的数据</span></div></div><div><div><div>8</div></div><div><span>hf mf wrbl --blk 0 -a -k FFFFFFFFFFFF -d 11223344440804006263646566676869</span></div></div><div><div><div>9</div></div><div><span># 切换到正常模式</span></div></div><div><div><div>10</div></div><div><span>hf 14a config --std</span></div></div><div><div><div>11</div></div><div><span># 再次读取</span></div></div><div><div><div>12</div></div><div><span>hf 14a scan</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span># 如果A密钥失败，就写入B密钥</span></div></div><div><div><div>15</div></div><div><span>hf 14a config --rats skip</span></div></div><div><div><div>16</div></div><div><span>hf mf wrbl --blk 0 -b -k FFFFFFFFFFFF -d 11223344440804006263646566676869</span></div></div><div><div><div>17</div></div><div><span>hf 14a config --std</span></div></div><div><div><div>18</div></div><div><span>hf 14a scan</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>如果是Gen1A卡，可以试试Gen1A后门</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>hf 14a config --rats skip</span></div></div><div><div><div>2</div></div><div><span>hf 14a raw -b 7 -d 40 -k</span></div></div><div><div><div>3</div></div><div><span>hf 14a raw -d 43 -k</span></div></div><div><div><div>4</div></div><div><span>hf 14a raw -d A000 -c -k</span></div></div><div><div><div>5</div></div><div><span>hf 14a raw -d 11223344440804006263646566676869 -c</span></div></div><div><div><div>6</div></div><div><span>hf 14a config --std</span></div></div><div><div><div>7</div></div><div><span>hf 14a scan</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/278/</id>
      <title type="text">【脚本】在jetson nano上使用摄像头分段录像并开启端口推流</title>
      <published>2026-01-08T06:53:00.000Z</published>
      <updated>2026-01-09T09:01:56.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/278/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>可设置录像保留天数、分段时间、分辨率、码率</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/usr/bin/env python3</span></div></div><div><div><div>2</div></div><div><span>import</span><span> sys</span></div></div><div><div><div>3</div></div><div><span>import</span><span> os</span></div></div><div><div><div>4</div></div><div><span>import</span><span> time</span></div></div><div><div><div>5</div></div><div><span>import</span><span> datetime</span></div></div><div><div><div>6</div></div><div><span>import</span><span> threading</span></div></div><div><div><div>7</div></div><div><span>import</span><span> glob</span></div></div><div><div><div>8</div></div><div><span>import</span><span> gi</span></div></div><div><div><div>9</div></div><div><span>import</span><span> signal</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>gi.</span><span>require_version</span><span>(</span></span><span>"Gst"</span><span>, </span><span>"1.0"</span><span>)</span></div></div><div><div><div>12</div></div><div><span>from</span><span> gi.repository </span><span>import</span><span> Gst, GLib, GObject</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span># ================= 配置 =================</span></div></div><div><div><div>15</div></div><div><span><span>CONFIG</span><span> </span><span>=</span><span> {</span></span></div></div><div><div><div>16</div></div><div><span>    </span><span># 保存位置</span></div></div><div><div><div>17</div></div><div><span>    </span><span>"save_dir"</span><span>: </span><span>"/home/r/Videos/cctv"</span><span>,</span></div></div><div><div><div>18</div></div><div><span>    </span><span># 分段时长</span></div></div><div><div><div>19</div></div><div><span>    </span><span>"segment_duration_ns"</span><span>: </span><span>60</span><span><span> </span><span>*</span><span> </span></span><span>1_000_000_000</span><span>,  </span><span># 60s</span></div></div><div><div><div>20</div></div><div><span>    </span><span># 保留天数</span></div></div><div><div><div>21</div></div><div><span>    </span><span>"retention_days"</span><span>: </span><span>7</span><span>,</span></div></div><div><div><div>22</div></div><div><span>    </span><span># 剩余空间低于多少自动删除前面的录像</span></div></div><div><div><div>23</div></div><div><span>    </span><span>"free_space_threshold"</span><span>: </span><span>50</span><span><span> </span><span>*</span><span> </span></span><span>1024</span><span><span> </span><span>*</span><span> </span></span><span>1024</span><span>,  </span><span># 50MB</span></div></div><div><div><div>24</div></div><div><span>    </span><span># 端口</span></div></div><div><div><div>25</div></div><div><span>    </span><span>"stream_port"</span><span>: </span><span>5000</span><span>,</span></div></div><div><div><div>26</div></div><div><span>    </span><span># 摄像头地址</span></div></div><div><div><div>27</div></div><div><span>    </span><span>"usb_device"</span><span>: </span><span>"/dev/video0"</span><span>,</span></div></div><div><div><div>28</div></div><div><span>    </span><span># 分辨率</span></div></div><div><div><div>29</div></div><div><span>    </span><span>"width"</span><span>: </span><span>1280</span><span>,</span></div></div><div><div><div>30</div></div><div><span>    </span><span>"height"</span><span>: </span><span>720</span><span>,</span></div></div><div><div><div>31</div></div><div><span>    </span><span># 平均码率</span></div></div><div><div><div>32</div></div><div><span>    </span><span>"bitrate"</span><span>: </span><span>2000000</span><span>,</span></div></div><div><div><div>33</div></div><div><span>    </span><span># 峰值码率</span></div></div><div><div><div>34</div></div><div><span>    </span><span>"peak-bitrate"</span><span>: </span><span>4000000</span><span>,</span></div></div><div><div><div>35</div></div><div><span>}</span></div></div><div><div><div>36</div></div><div><span># =======================================</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div>
</div></div><div><div><div>39</div></div><div><span>class</span><span><span> </span><span>JetsonDVR</span></span><span>:</span></div></div><div><div><div>40</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>41</div></div><div><span>        </span><span># 初始化 GStreamer</span></div></div><div><div><div>42</div></div><div><span><span>        </span></span><span>Gst.</span><span>init</span><span>(</span><span>None</span><span>)</span></div></div><div><div><div>43</div></div><div>
</div></div><div><div><div>44</div></div><div><span>        </span><span>self</span><span><span>.mainloop </span><span>=</span><span> GLib.</span><span>MainLoop</span><span>()</span></span></div></div><div><div><div>45</div></div><div><span><span>        </span></span><span>os.</span><span>makedirs</span><span>(</span><span>CONFIG</span><span>[</span><span>"save_dir"</span><span>], </span><span>exist_ok</span><span>=</span><span>True</span><span>)</span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span>        </span><span># 清理线程</span></div></div><div><div><div>48</div></div><div><span>        </span><span>self</span><span><span>.cleanup_thread </span><span>=</span><span> threading.</span><span>Thread</span><span>(</span></span><span>target</span><span>=</span><span>self</span><span>.cleanup_loop, </span><span>daemon</span><span>=</span><span>True</span><span>)</span></div></div><div><div><div>49</div></div><div><span>        </span><span>self</span><span><span>.cleanup_thread.</span><span>start</span><span>()</span></span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span>        </span><span>self</span><span><span>.pipeline </span><span>=</span><span> </span></span><span>self</span><span><span>.</span><span>create_pipeline</span><span>()</span></span></div></div><div><div><div>52</div></div><div>
</div></div><div><div><div>53</div></div><div><span>        </span><span># 监听总线消息</span></div></div><div><div><div>54</div></div><div><span><span>        </span></span><span>bus </span><span>=</span><span> </span><span>self</span><span><span>.pipeline.</span><span>get_bus</span><span>()</span></span></div></div><div><div><div>55</div></div><div><span><span>        </span></span><span>bus.</span><span>add_signal_watch</span><span>()</span></div></div><div><div><div>56</div></div><div><span><span>        </span></span><span>bus.</span><span>connect</span><span>(</span><span>"message"</span><span>, </span><span>self</span><span>.on_message)</span></div></div><div><div><div>57</div></div><div>
</div></div><div><div><div>58</div></div><div><span>        </span><span># 优雅退出的信号处理</span></div></div><div><div><div>59</div></div><div><span><span>        </span></span><span>signal.</span><span>signal</span><span>(signal.</span><span>SIGINT</span><span>, </span><span>self</span><span>.handle_sigint)</span></div></div><div><div><div>60</div></div><div><span><span>        </span></span><span>signal.</span><span>signal</span><span>(signal.</span><span>SIGTERM</span><span>, </span><span>self</span><span>.handle_sigint)</span></div></div><div><div><div>61</div></div><div>
</div></div><div><div><div>62</div></div><div><span>    </span><span>def</span><span> </span><span>create_pipeline</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>63</div></div><div><span>        </span><span>print</span><span>(</span><span>f</span><span>"[*] 初始化管道... 设备: </span><span>{</span><span><span>CONFIG</span><span>[</span></span><span>'usb_device'</span><span>]</span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>64</div></div><div>
</div></div><div><div><div>65</div></div><div><span><span>        </span></span><span>source </span><span>=</span><span> (</span></div></div><div><div><div>66</div></div><div><span>            </span><span>f</span><span>"v4l2src device=</span><span>{</span><span><span>CONFIG</span><span>[</span></span><span>'usb_device'</span><span>]</span><span>}</span><span> ! "</span></div></div><div><div><div>67</div></div><div><span>            </span><span>f</span><span>"image/jpeg, width=</span><span>{</span><span><span>CONFIG</span><span>[</span></span><span>'width'</span><span>]</span><span>}</span><span>, height=</span><span>{</span><span><span>CONFIG</span><span>[</span></span><span>'height'</span><span>]</span><span>}</span><span>, framerate=30/1 ! "</span></div></div><div><div><div>68</div></div><div><span>            </span><span>"jpegdec ! "</span></div></div><div><div><div>69</div></div><div><span>            </span><span>"nvvidconv ! "</span></div></div><div><div><div>70</div></div><div><span>            </span><span>"video/x-raw(memory:NVMM), format=I420"</span></div></div><div><div><div>71</div></div><div><span><span>        </span></span><span>)</span></div></div><div><div><div>72</div></div><div>
</div></div><div><div><div>73</div></div><div><span>        </span><span>#        encoder = (</span></div></div><div><div><div>74</div></div><div><span>        </span><span>#            f" ! nvv4l2h264enc maxperf-enable=1 insert-sps-pps=1 bitrate={CONFIG['bitrate']} ! "</span></div></div><div><div><div>75</div></div><div><span>        </span><span>#            "h264parse ! tee name=t"</span></div></div><div><div><div>76</div></div><div><span>        </span><span>#        )</span></div></div><div><div><div>77</div></div><div>
</div></div><div><div><div>78</div></div><div><span>        </span><span># 使用 h265</span></div></div><div><div><div>79</div></div><div><span><span>        </span></span><span>encoder </span><span>=</span><span> (</span></div></div><div><div><div>80</div></div><div><span>            </span><span>" ! nvv4l2h265enc maxperf-enable=1 insert-sps-pps=1 "</span></div></div><div><div><div>81</div></div><div><span>            </span><span>f</span><span>"control-rate=1 bitrate=</span><span>{</span><span><span>CONFIG</span><span>[</span></span><span>'bitrate'</span><span>]</span><span>}</span><span> peak-bitrate=</span><span>{</span><span><span>CONFIG</span><span>[</span></span><span>'peak-bitrate'</span><span>]</span><span>}</span><span> ! "</span></div></div><div><div><div>82</div></div><div><span>            </span><span>"video/x-h265,stream-format=byte-stream ! "</span></div></div><div><div><div>83</div></div><div><span>            </span><span>"h265parse ! tee name=t"</span></div></div><div><div><div>84</div></div><div><span><span>        </span></span><span>)</span></div></div><div><div><div>85</div></div><div>
</div></div><div><div><div>86</div></div><div><span><span>        </span></span><span>record_branch </span><span>=</span><span> (</span></div></div><div><div><div>87</div></div><div><span>            </span><span>f</span><span>" t. ! queue ! "</span></div></div><div><div><div>88</div></div><div><span>            </span><span>f</span><span>"splitmuxsink name=sink "</span></div></div><div><div><div>89</div></div><div><span>            </span><span>f</span><span>"max-size-time=</span><span>{</span><span><span>CONFIG</span><span>[</span></span><span>'segment_duration_ns'</span><span>]</span><span>}</span><span> "</span></div></div><div><div><div>90</div></div><div><span>            </span><span>f</span><span>"muxer=mp4mux async-handling=true"</span></div></div><div><div><div>91</div></div><div><span><span>        </span></span><span>)</span></div></div><div><div><div>92</div></div><div>
</div></div><div><div><div>93</div></div><div><span>        </span><span># Streaming Branch (推流):</span></div></div><div><div><div>94</div></div><div><span><span>        </span></span><span>stream_branch </span><span>=</span><span> (</span></div></div><div><div><div>95</div></div><div><span>            </span><span>f</span><span>" t. ! queue leaky=1 ! "</span></div></div><div><div><div>96</div></div><div><span>            </span><span>f</span><span>"matroskamux streamable=true ! "</span></div></div><div><div><div>97</div></div><div><span>            </span><span>f</span><span>"tcpserversink host=0.0.0.0 port=</span><span>{</span><span><span>CONFIG</span><span>[</span></span><span>'stream_port'</span><span>]</span><span>}</span><span> "</span></div></div><div><div><div>98</div></div><div><span>            </span><span>f</span><span>"recover-policy=keyframe sync-method=latest-keyframe"</span></div></div><div><div><div>99</div></div><div><span><span>        </span></span><span>)</span></div></div><div><div><div>100</div></div><div>
</div></div><div><div><div>101</div></div><div><span><span>        </span></span><span>pipeline_str </span><span>=</span><span> source </span><span>+</span><span> encoder </span><span>+</span><span> record_branch </span><span>+</span><span> stream_branch</span></div></div><div><div><div>102</div></div><div>
</div></div><div><div><div>103</div></div><div><span>        </span><span>print</span><span>(</span><span>"-"</span><span><span> </span><span>*</span><span> </span></span><span>60</span><span>)</span></div></div><div><div><div>104</div></div><div><span>        </span><span>print</span><span>(</span><span>"GStreamer Pipeline String:"</span><span>)</span></div></div><div><div><div>105</div></div><div><span>        </span><span>print</span><span>(pipeline_str)</span></div></div><div><div><div>106</div></div><div><span>        </span><span>print</span><span>(</span><span>"-"</span><span><span> </span><span>*</span><span> </span></span><span>60</span><span>)</span></div></div><div><div><div>107</div></div><div>
</div></div><div><div><div>108</div></div><div><span>        </span><span>try</span><span>:</span></div></div><div><div><div>109</div></div><div><span><span>            </span></span><span>pipeline </span><span>=</span><span> Gst.</span><span>parse_launch</span><span>(pipeline_str)</span></div></div><div><div><div>110</div></div><div><span>        </span><span>except</span><span> </span><span>Exception</span><span> </span><span>as</span><span> e:</span></div></div><div><div><div>111</div></div><div><span>            </span><span>print</span><span>(</span><span>"[!] 管道构建失败:"</span><span>, e)</span></div></div><div><div><div>112</div></div><div><span><span>            </span></span><span>sys.</span><span>exit</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>113</div></div><div>
</div></div><div><div><div>114</div></div><div><span><span>        </span></span><span>sink </span><span>=</span><span> pipeline.</span><span>get_by_name</span><span>(</span><span>"sink"</span><span>)</span></div></div><div><div><div>115</div></div><div><span>        </span><span>if</span><span> sink:</span></div></div><div><div><div>116</div></div><div><span><span>            </span></span><span>sink.</span><span>connect</span><span>(</span><span>"format-location"</span><span>, </span><span>self</span><span>.on_format_location)</span></div></div><div><div><div>117</div></div><div><span>        </span><span>else</span><span>:</span></div></div><div><div><div>118</div></div><div><span>            </span><span>print</span><span>(</span><span>"[!] 警告: 找不到 splitmuxsink"</span><span>)</span></div></div><div><div><div>119</div></div><div>
</div></div><div><div><div>120</div></div><div><span>        </span><span>return</span><span> pipeline</span></div></div><div><div><div>121</div></div><div>
</div></div><div><div><div>122</div></div><div><span>    </span><span>def</span><span> </span><span>on_format_location</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>splitmux</span></span><span>,</span><span><span> </span><span>fragment_id</span></span><span>):</span></div></div><div><div><div>123</div></div><div><span><span>        </span></span><span>now </span><span>=</span><span> datetime.datetime.</span><span>now</span><span>()</span></div></div><div><div><div>124</div></div><div><span><span>        </span></span><span>filename </span><span>=</span><span> now.</span><span>strftime</span><span>(</span><span>"%Y%m</span><span>%d</span><span>-%H%M%S.mp4"</span><span>)</span></div></div><div><div><div>125</div></div><div><span>        </span><span>return</span><span><span> os.path.</span><span>join</span><span>(</span><span>CONFIG</span><span>[</span></span><span>"save_dir"</span><span>], filename)</span></div></div><div><div><div>126</div></div><div>
</div></div><div><div><div>127</div></div><div><span>    </span><span>def</span><span> </span><span>cleanup_loop</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>128</div></div><div><span><span>        </span></span><span>retention_sec </span><span>=</span><span> </span><span>CONFIG</span><span>[</span><span>"retention_days"</span><span><span>] </span><span>*</span><span> </span></span><span>24</span><span><span> </span><span>*</span><span> </span></span><span>3600</span></div></div><div><div><div>129</div></div><div><span>        </span><span>while</span><span> </span><span>True</span><span>:</span></div></div><div><div><div>130</div></div><div><span>            </span><span>try</span><span>:</span></div></div><div><div><div>131</div></div><div><span><span>                </span></span><span>now </span><span>=</span><span> time.</span><span>time</span><span>()</span></div></div><div><div><div>132</div></div><div><span>                </span><span>for</span><span> f </span><span>in</span><span><span> glob.</span><span>glob</span><span>(os.path.</span><span>join</span><span>(</span><span>CONFIG</span><span>[</span></span><span>"save_dir"</span><span>], </span><span>"*.mp4"</span><span>)):</span></div></div><div><div><div>133</div></div><div><span>                    </span><span>if</span><span><span> os.path.</span><span>isfile</span><span>(f):</span></span></div></div><div><div><div>134</div></div><div><span><span>                        </span></span><span>delete </span><span>=</span><span> </span><span>False</span></div></div><div><div><div>135</div></div><div><span>                        </span><span>if</span><span><span> now </span><span>-</span><span> os.path.</span><span>getmtime</span><span>(f) </span><span>&gt;</span><span> retention_sec:</span></span></div></div><div><div><div>136</div></div><div><span><span>                            </span></span><span>delete </span><span>=</span><span> </span><span>True</span></div></div><div><div><div>137</div></div><div><span>                        </span><span>elif</span><span><span> </span><span>CONFIG</span><span>[</span></span><span>"free_space_threshold"</span><span><span>] </span><span>&gt;</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>138</div></div><div><span><span>                            </span></span><span>s_info </span><span>=</span><span> os.</span><span>statvfs</span><span>(</span><span>CONFIG</span><span>[</span><span>"save_dir"</span><span>])</span></div></div><div><div><div>139</div></div><div><span><span>                            </span></span><span>free_space </span><span>=</span><span> s_info.f_bsize </span><span>*</span><span> s_info.f_bavail</span></div></div><div><div><div>140</div></div><div><span>                            </span><span>if</span><span><span> free_space </span><span>&lt;</span><span> </span><span>CONFIG</span><span>[</span></span><span>"free_space_threshold"</span><span>]:</span></div></div><div><div><div>141</div></div><div><span><span>                                </span></span><span>delete </span><span>=</span><span> </span><span>True</span></div></div><div><div><div>142</div></div><div><span>                        </span><span>if</span><span> delete:</span></div></div><div><div><div>143</div></div><div><span><span>                            </span></span><span>os.</span><span>remove</span><span>(f)</span></div></div><div><div><div>144</div></div><div><span>                            </span><span>print</span><span>(</span><span>f</span><span>"[-] 删除过期录像: </span><span>{</span><span><span>os.path.</span><span>basename</span><span>(f)</span></span><span>}</span><span>"</span><span>)</span></div></div><div><div><div>145</div></div><div><span>            </span><span>except</span><span> </span><span>Exception</span><span> </span><span>as</span><span> e:</span></div></div><div><div><div>146</div></div><div><span>                </span><span>print</span><span>(</span><span>"[!] 清理线程错误:"</span><span>, e)</span></div></div><div><div><div>147</div></div><div><span><span>            </span></span><span>time.</span><span>sleep</span><span>(</span><span>3600</span><span>)</span></div></div><div><div><div>148</div></div><div>
</div></div><div><div><div>149</div></div><div><span>    </span><span>def</span><span> </span><span>on_message</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>bus</span></span><span>,</span><span><span> </span><span>message</span></span><span>):</span></div></div><div><div><div>150</div></div><div><span><span>        </span></span><span>mtype </span><span>=</span><span> message.type</span></div></div><div><div><div>151</div></div><div><span>        </span><span>if</span><span><span> mtype </span><span>==</span><span> Gst.MessageType.</span><span>ERROR</span><span>:</span></span></div></div><div><div><div>152</div></div><div><span><span>            </span></span><span>err, debug </span><span>=</span><span> message.</span><span>parse_error</span><span>()</span></div></div><div><div><div>153</div></div><div><span>            </span><span>print</span><span>(</span><span>"[!] Pipeline Error:"</span><span>, err)</span></div></div><div><div><div>154</div></div><div><span>            </span><span>if</span><span> debug:</span></div></div><div><div><div>155</div></div><div><span>                </span><span>print</span><span>(</span><span>"[!] Debug Info:"</span><span>, debug)</span></div></div><div><div><div>156</div></div><div><span>            </span><span>self</span><span><span>.</span><span>quit</span><span>()</span></span></div></div><div><div><div>157</div></div><div><span>        </span><span>elif</span><span><span> mtype </span><span>==</span><span> Gst.MessageType.</span><span>EOS</span><span>:</span></span></div></div><div><div><div>158</div></div><div><span>            </span><span>print</span><span>(</span><span>"[*] End of Stream"</span><span>)</span></div></div><div><div><div>159</div></div><div><span>            </span><span>self</span><span><span>.</span><span>quit</span><span>()</span></span></div></div><div><div><div>160</div></div><div>
</div></div><div><div><div>161</div></div><div><span>    </span><span>def</span><span> </span><span>handle_sigint</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>sig</span></span><span>,</span><span><span> </span><span>frame</span></span><span>):</span></div></div><div><div><div>162</div></div><div><span>        </span><span>print</span><span>(</span><span>"</span><span>\n</span><span>[*] 接收到中断信号，正在停止..."</span><span>)</span></div></div><div><div><div>163</div></div><div><span>        </span><span>self</span><span><span>.</span><span>quit</span><span>()</span></span></div></div><div><div><div>164</div></div><div>
</div></div><div><div><div>165</div></div><div><span>    </span><span>def</span><span> </span><span>quit</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>166</div></div><div><span>        </span><span>if</span><span> </span><span>self</span><span><span>.mainloop.</span><span>is_running</span><span>():</span></span></div></div><div><div><div>167</div></div><div><span>            </span><span>self</span><span><span>.mainloop.</span><span>quit</span><span>()</span></span></div></div><div><div><div>168</div></div><div>
</div></div><div><div><div>169</div></div><div><span>    </span><span>def</span><span> </span><span>run</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>170</div></div><div><span>        </span><span>print</span><span>(</span><span>"[*] 启动 DVR 系统..."</span><span>)</span></div></div><div><div><div>171</div></div><div><span>        </span><span>self</span><span><span>.pipeline.</span><span>set_state</span><span>(Gst.State.</span><span>PLAYING</span><span>)</span></span></div></div><div><div><div>172</div></div><div><span>        </span><span>try</span><span>:</span></div></div><div><div><div>173</div></div><div><span>            </span><span>self</span><span><span>.mainloop.</span><span>run</span><span>()</span></span></div></div><div><div><div>174</div></div><div><span>        </span><span>except</span><span> </span><span>KeyboardInterrupt</span><span>:</span></div></div><div><div><div>175</div></div><div><span>            </span><span>pass</span></div></div><div><div><div>176</div></div><div><span>        </span><span>finally</span><span>:</span></div></div><div><div><div>177</div></div><div><span>            </span><span>self</span><span><span>.</span><span>stop_pipeline</span><span>()</span></span></div></div><div><div><div>178</div></div><div>
</div></div><div><div><div>179</div></div><div><span>    </span><span>def</span><span> </span><span>stop_pipeline</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>180</div></div><div><span>        </span><span>print</span><span>(</span><span>"[*] 发送 EOS 并停止管道..."</span><span>)</span></div></div><div><div><div>181</div></div><div><span>        </span><span># 发送 EOS 以正确结束录像文件（防止 MP4 损坏）</span></div></div><div><div><div>182</div></div><div><span>        </span><span>self</span><span><span>.pipeline.</span><span>send_event</span><span>(Gst.Event.</span><span>new_eos</span><span>())</span></span></div></div><div><div><div>183</div></div><div><span>        </span><span># 给一点时间让 EOS 传播</span></div></div><div><div><div>184</div></div><div><span><span>        </span></span><span>time.</span><span>sleep</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>185</div></div><div><span>        </span><span>self</span><span><span>.pipeline.</span><span>set_state</span><span>(Gst.State.</span><span>NULL</span><span>)</span></span></div></div><div><div><div>186</div></div><div><span>        </span><span>print</span><span>(</span><span>"[*] 已退出"</span><span>)</span></div></div><div><div><div>187</div></div><div>
</div></div><div><div><div>188</div></div><div>
</div></div><div><div><div>189</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>"__main__"</span><span>:</span></div></div><div><div><div>190</div></div><div><span><span>    </span></span><span>dvr </span><span>=</span><span> </span><span>JetsonDVR</span><span>()</span></div></div><div><div><div>191</div></div><div><span><span>    </span></span><span>dvr.</span><span>run</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/277/</id>
      <title type="text">【杂项】ssh隐匿登录</title>
      <published>2025-08-13T03:32:23.000Z</published>
      <updated>2025-08-13T03:32:23.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/277/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h3>0x01 清除 Bash 命令历史记录<a href="#0x01-清除-bash-命令历史记录"><span>#</span></a></h3><p>为防止命令行操作被记录，可在登录后立即禁用 Bash 的历史功能：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>unset</span><span> </span><span>HISTORY</span><span> </span><span>HISTFILE</span><span> </span><span>HISTSAVE</span><span> </span><span>HISTLOG</span><span> </span><span>HISTZONE</span><span> </span><span>HISTORY</span><span> </span><span>HISTLOG</span></div></div><div><div><div>2</div></div><div><span>export</span><span> </span><span>HISTFILE</span><span><span>=</span><span>/</span></span><span>dev</span><span>/</span><span>null</span></div></div><div><div><div>3</div></div><div><span>export</span><span> </span><span>HISTSIZE</span><span>=</span><span>0</span></div></div><div><div><div>4</div></div><div><span>export</span><span> </span><span>HISTFILESIZE</span><span>=</span><span>0</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h4>说明：<a href="#说明"><span>#</span></a></h4><ul>
<li><code>unset</code> 命令用于清除可能影响历史记录的环境变量。</li>
<li><code>HISTFILE=/dev/null</code> 将命令历史文件重定向至空设备，确保所有输入命令不会写入磁盘。</li>
<li><code>HISTSIZE=0</code> 和 <code>HISTFILESIZE=0</code> 分别禁用内存中的历史命令缓存和文件中的持久化存储。</li>
</ul><blockquote><p><strong>建议</strong>：该配置可临时生效。若需永久禁用，可将相关设置写入用户的 shell 配置文件（如 <code>.bashrc</code> 或 <code>.profile</code>），但应谨慎操作，避免影响正常运维。</p></blockquote><hr /></section></section>
<section><h3>0x02 隐藏登录 IP 地址<a href="#0x02-隐藏登录-ip-地址"><span>#</span></a></h3><p>系统命令 <code>last</code> 读取 <code>/var/log/lastlog</code> 文件显示用户登录记录。此文件为二进制格式，无法直接编辑。以下是两种处理方式：</p><section><h4>方法一：删除 lastlog 文件<a href="#方法一删除-lastlog-文件"><span>#</span></a></h4><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>rm</span><span> </span><span>/var/log/lastlog</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h5>注意事项：<a href="#注意事项"><span>#</span></a></h5><ul>
<li>删除该文件会清除所有用户的最近登录记录。</li>
<li>部分系统在重启或执行某些认证操作时会自动重建该文件。</li>
<li>此类操作可能触发日志完整性检测机制，引起管理员注意。</li>
<li><strong>不建议在生产环境中随意删除系统日志文件</strong>，尤其是未经审计许可的操作。</li>
</ul></section></section><section><h4>方法二：通过 SSH 端口转发隐藏真实 IP<a href="#方法二通过-ssh-端口转发隐藏真实-ip"><span>#</span></a></h4><p>使用本地端口转发建立代理连接：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-N</span><span> </span><span>-L</span><span> </span><span>2212:&lt;目标主机IP&gt;:22</span><span> </span><span>root@&lt;目标主机&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>随后通过本地端口连接目标系统：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-p</span><span> </span><span>2212</span><span> </span><span>root@127.0.0.1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h5>原理：<a href="#原理"><span>#</span></a></h5><ul>
<li>该命令将本地的 2212 端口映射到目标主机的 22 端口。</li>
<li>登录时，系统记录的来源 IP 是 <code>127.0.0.1</code>，即本地回环地址，而非你的真实公网 IP。</li>
<li><code>last</code> 或 <code>who</code> 命令显示的将是隧道末端的地址，从而实现一定程度的身份隐藏。</li>
</ul><blockquote><p><strong>补充说明</strong>：若目标系统启用了 PAM 审计模块或 <code>auditd</code> 等内核级审计工具，仍有可能记录原始连接信息。此方法仅适用于基础日志规避。</p></blockquote><hr /></section></section></section>
<section><h3>0x03 清理认证日志（auth.log）<a href="#0x03-清理认证日志authlog"><span>#</span></a></h3><p>认证相关的登录行为通常记录在 <code>/var/log/auth.log</code>（Debian/Ubuntu 系统）或 <code>/var/log/secure</code>（RHEL/CentOS 系统）中。可通过以下方式移除特定 IP 的记录。</p><section><h4>删除包含指定 IP 的日志行：<a href="#删除包含指定-ip-的日志行"><span>#</span></a></h4><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>sed</span><span> </span><span>-i</span><span> </span><span>'/192\.168\.1\.1/d'</span><span> </span><span>/var/log/auth.log</span></div></div></code></pre><div><div></div><div></div></div></figure></div><blockquote><p>注意：IP 地址中的点号需用反斜杠转义，否则会被当作正则表达式中的通配符处理。</p></blockquote></section><section><h4>替代方法：使用 grep 过滤并重写文件<a href="#替代方法使用-grep-过滤并重写文件"><span>#</span></a></h4><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>grep</span><span> </span><span>-v</span><span> </span><span>'192.168.1.100'</span><span> </span><span>/var/log/auth.log</span><span> &gt; </span><span>/tmp/auth.log</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>mv</span><span> </span><span>/tmp/auth.log</span><span> </span><span>/var/log/auth.log</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h4>对于使用 systemd 的系统：<a href="#对于使用-systemd-的系统"><span>#</span></a></h4><p>还需清理 <code>journald</code> 的内存日志：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>journalctl</span><span> </span><span>--vacuum-time=1d</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>该命令会删除超过一天的日志条目，释放存储空间。</p><blockquote><p><strong>提醒</strong>：</p><ul>
<li>修改认证日志属于高风险行为，容易被入侵检测系统（IDS）、安全信息与事件管理系统（SIEM）识别。</li>
<li>现代安全架构普遍采用集中式日志收集（如 ELK、Splunk、rsyslog 转发等），即使本地日志被清除，远程日志服务器仍可能保留副本。</li>
<li>任何日志篡改行为在未经授权的情况下均可能违反法律法规。</li>
</ul></blockquote><hr /></section></section>
<section><h3>0x04 清除 wtmp 与 btmp 登录记录<a href="#0x04-清除-wtmp-与-btmp-登录记录"><span>#</span></a></h3><p>Linux 系统中还有两个重要的二进制日志文件用于记录登录活动：</p><ul>
<li><code>/var/log/wtmp</code>：记录所有成功登录和登出的事件，<code>last</code> 命令读取此文件。</li>
<li><code>/var/log/btmp</code>：记录失败的登录尝试，<code>lastb</code> 命令可查看其内容。</li>
</ul><p>由于这两个文件为二进制格式，不能使用文本编辑器直接修改。</p><section><h4>清空日志文件：<a href="#清空日志文件"><span>#</span></a></h4><p>推荐使用 <code>truncate</code> 命令将文件大小置零：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>truncate</span><span> </span><span>-s</span><span> </span><span>0</span><span> </span><span>/var/log/wtmp</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>truncate</span><span> </span><span>-s</span><span> </span><span>0</span><span> </span><span>/var/log/btmp</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h4>替代方式（谨慎使用）：<a href="#替代方式谨慎使用"><span>#</span></a></h4><p>也可删除后创建新的空文件，并恢复正确权限：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>rm</span><span> </span><span>/var/log/wtmp</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>touch</span><span> </span><span>/var/log/wtmp</span></div></div><div><div><div>3</div></div><div><span>sudo</span><span> </span><span>chmod</span><span> </span><span>644</span><span> </span><span>/var/log/wtmp</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>对 <code>btmp</code> 文件操作类似。</p><blockquote><p><strong>提示</strong>：<code>truncate</code> 是更安全的选择，避免因删除文件导致某些服务无法写入日志。</p></blockquote><hr /></section></section>
<section><h3>0x05 隐藏进程痕迹<a href="#0x05-隐藏进程痕迹"><span>#</span></a></h3><p>运行扫描工具、反弹 shell 或提权程序时，进程名可能出现在 <code>ps</code>、<code>top</code> 等监控命令输出中，暴露操作行为。</p><section><h4>检测当前进程：<a href="#检测当前进程"><span>#</span></a></h4><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ps</span><span> </span><span>aux</span><span> | </span><span>grep</span><span> </span><span>python</span></div></div><div><div><div>2</div></div><div><span>top</span><span> </span><span>-b</span><span> </span><span>-n</span><span> </span><span>1</span><span> | </span><span>grep</span><span> </span><span>&lt;your-tool&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h4>隐藏进程名称：<a href="#隐藏进程名称"><span>#</span></a></h4><p>利用 <code>exec</code> 系统调用覆盖当前进程名：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>exec</span><span> </span><span>-a</span><span> </span><span>"sshd"</span><span> </span><span>/path/to/your-tool</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>执行后，该进程在 <code>ps</code> 输出中将显示为 <code>sshd</code>，具有一定迷惑性。</p><blockquote><p><strong>说明</strong>：这种方法仅修改进程的“显示名称”（argv[0]），不会改变实际的可执行文件路径或内存映像。高级监控工具（如 <code>auditd</code>、EDR 软件）仍可通过系统调用追踪其真实行为。</p></blockquote><hr /></section></section>
<section><h3>0x06 结语<a href="#0x06-结语"><span>#</span></a></h3><p>本文介绍的技术主要用于理解系统日志机制和攻击者可能采取的规避手段，帮助系统管理员加强日志保护与入侵检测能力。需要强调的是：</p><ul>
<li>所有日志清理操作都应仅在授权测试环境或合法合规前提下进行。</li>
<li>在真实生产系统中篡改或删除日志，不仅可能破坏系统稳定性，还可能触犯法律。</li>
<li>强烈建议部署集中式日志审计、文件完整性监控（FIM）和实时告警机制，以防范未授权访问和痕迹清除行为。</li>
</ul><p>了解攻击，是为了更好地防御。安全的本质，始终是攻防之间的持续博弈。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/276/</id>
      <title type="text">【Golang】xlsx.row to struct slice</title>
      <published>2025-05-13T01:10:00.000Z</published>
      <updated>2025-05-13T02:09:44.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/276/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>0x00<a href="#0x00"><span>#</span></a></h2><p>之前业务中解析xlsx表格总是用手动写数组下标的方式，这种方式一来繁琐二来容易出错，特别是表头多的时候排查起来也很麻烦。
所以就自己写一个将xlsx转为struct的模块，感觉用struct比数组更直观</p><section><h3>代码<a href="#代码"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> (</span></div></div><div><div><div>2</div></div><div><span>  </span><span>"errors"</span></div></div><div><div><div>3</div></div><div><span>  </span><span>"reflect"</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"strconv"</span></div></div><div><div><div>5</div></div><div><span>  </span><span>"strings"</span></div></div><div><div><div>6</div></div><div><span>  </span><span>"time"</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>  </span><span>"github.com/gogf/gf/v2/os/gtime"</span></div></div><div><div><div>9</div></div><div><span>  </span><span>"github.com/tealeg/xlsx"</span></div></div><div><div><div>10</div></div><div><span>)</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>type</span><span> </span><span>FieldTagOption</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>13</div></div><div><span>  </span><span>boolMap</span><span>    </span><span>map</span><span>[</span><span>string</span><span>]</span><span>bool</span><span> </span><span>// boolmap:是-true,否-false,真-true,假-false</span></div></div><div><div><div>14</div></div><div><span>  </span><span>timeformat</span><span> </span><span>string</span><span>          </span><span>// timeformat:2006-01-02 15:04:05</span></div></div><div><div><div>15</div></div><div><span>}</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>func</span><span> </span><span>ParseXlsxStruct</span><span><span>(</span><span>rows</span><span> []</span><span>*</span></span><span>xlsx</span><span>.</span><span>Row</span><span><span>, </span><span>data</span><span> </span></span><span>any</span><span>) </span><span>error</span><span> {</span></div></div><div><div><div>18</div></div><div><span>  </span><span>rdata</span><span><span> </span><span>:=</span><span> </span></span><span>reflect</span><span>.</span><span>ValueOf</span><span>(</span><span>data</span><span>)</span></div></div><div><div><div>19</div></div><div><span>  </span><span>if</span><span> </span><span>rdata</span><span>.</span><span>Kind</span><span><span>() </span><span>!=</span><span> </span></span><span>reflect</span><span>.</span><span>Ptr</span><span> {</span></div></div><div><div><div>20</div></div><div><span>    </span><span>return</span><span> </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"data must be &amp;[]*struct/&amp;[]struct"</span><span>)</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>  </span><span>rdata</span><span><span> </span><span>=</span><span> </span></span><span>rdata</span><span>.</span><span>Elem</span><span>()</span></div></div><div><div><div>23</div></div><div><span>  </span><span>if</span><span> </span><span>rdata</span><span>.</span><span>Type</span><span>().</span><span>Kind</span><span><span>() </span><span>!=</span><span> </span></span><span>reflect</span><span>.</span><span>Slice</span><span> {</span></div></div><div><div><div>24</div></div><div><span>    </span><span>return</span><span> </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"data must be &amp;[]*struct/&amp;[]struct"</span><span>)</span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span>  </span><span>dataElemType</span><span><span> </span><span>:=</span><span> </span></span><span>rdata</span><span>.</span><span>Type</span><span>().</span><span>Elem</span><span>()</span></div></div><div><div><div>27</div></div><div><span>  </span><span>var</span><span> </span><span>isPrt</span><span> </span><span>bool</span></div></div><div><div><div>28</div></div><div><span>  </span><span>if</span><span> </span><span>dataElemType</span><span>.</span><span>Kind</span><span><span>() </span><span>==</span><span> </span></span><span>reflect</span><span>.</span><span>Ptr</span><span> {</span></div></div><div><div><div>29</div></div><div><span>    </span><span>dataElemType</span><span><span> </span><span>=</span><span> </span></span><span>dataElemType</span><span>.</span><span>Elem</span><span>()</span></div></div><div><div><div>30</div></div><div><span>    </span><span>isPrt</span><span><span> </span><span>=</span><span> </span></span><span>true</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>32</div></div><div><span>  </span><span>if</span><span> </span><span>dataElemType</span><span>.</span><span>Kind</span><span><span>() </span><span>!=</span><span> </span></span><span>reflect</span><span>.</span><span>Struct</span><span> {</span></div></div><div><div><div>33</div></div><div><span>    </span><span>return</span><span> </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"data must be &amp;[]*struct/&amp;[]struct"</span><span>)</span></div></div><div><div><div>34</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>  </span><span>dataElemTypeOptions</span><span><span> </span><span>:=</span><span> </span></span><span>make</span><span>(</span><span>map</span><span>[</span><span>int</span><span><span>]</span><span>*</span></span><span>FieldTagOption</span><span>)</span></div></div><div><div><div>37</div></div><div><span>  </span><span>for</span><span> </span><span>i</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>; </span><span>i</span><span><span> </span><span>&lt;</span><span> </span></span><span>dataElemType</span><span>.</span><span>NumField</span><span>(); </span><span>i</span><span><span>++</span><span> {</span></span></div></div><div><div><div>38</div></div><div><span>    </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span><span>] </span><span>=</span><span> </span><span>&amp;</span></span><span>FieldTagOption</span><span>{}</span></div></div><div><div><div>39</div></div><div><span>    </span><span>for</span><span> </span><span>_</span><span>, </span><span>tag</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>strings</span><span>.</span><span>Split</span><span>(</span><span>dataElemType</span><span>.</span><span>Field</span><span>(</span><span>i</span><span>).</span><span>Tag</span><span>.</span><span>Get</span><span>(</span><span>"xlsx"</span><span>), </span><span>";"</span><span>) {</span></div></div><div><div><div>40</div></div><div><span>      </span><span>s</span><span><span> </span><span>:=</span><span> </span></span><span>strings</span><span>.</span><span>SplitN</span><span>(</span><span>tag</span><span>, </span><span>":"</span><span>, </span><span>2</span><span>)</span></div></div><div><div><div>41</div></div><div><span>      </span><span>switch</span><span> </span><span>s</span><span>[</span><span>0</span><span>] {</span></div></div><div><div><div>42</div></div><div><span>      </span><span>case</span><span> </span><span>"timeformat"</span><span>:</span></div></div><div><div><div>43</div></div><div><span>        </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>timeformat</span><span><span> </span><span>=</span><span> </span></span><span>s</span><span>[</span><span>1</span><span>]</span></div></div><div><div><div>44</div></div><div><span>      </span><span>case</span><span> </span><span>"boolmap"</span><span>:</span></div></div><div><div><div>45</div></div><div><span>        </span><span>for</span><span> </span><span>_</span><span>, </span><span>v</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>strings</span><span>.</span><span>Split</span><span>(</span><span>s</span><span>[</span><span>1</span><span>], </span><span>","</span><span>) {</span></div></div><div><div><div>46</div></div><div><span>          </span><span>if</span><span> </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>boolMap</span><span><span> </span><span>==</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>47</div></div><div><span>            </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>boolMap</span><span><span> </span><span>=</span><span> </span></span><span>make</span><span>(</span><span>map</span><span>[</span><span>string</span><span>]</span><span>bool</span><span>)</span></div></div><div><div><div>48</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>49</div></div><div><span>          </span><span>b</span><span><span> </span><span>:=</span><span> </span></span><span>strings</span><span>.</span><span>Split</span><span>(</span><span>v</span><span>, </span><span>"-"</span><span>)</span></div></div><div><div><div>50</div></div><div><span>          </span><span>if</span><span> </span><span>len</span><span>(</span><span>b</span><span><span>) </span><span>!=</span><span> </span></span><span>2</span><span> {</span></div></div><div><div><div>51</div></div><div><span>            </span><span>return</span><span> </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"boolmap tag value must be like true-false,true-true,false-false,false-false"</span><span>)</span></div></div><div><div><div>52</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>53</div></div><div><span>          </span><span>bb</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>strconv</span><span>.</span><span>ParseBool</span><span>(</span><span>b</span><span>[</span><span>1</span><span>])</span></div></div><div><div><div>54</div></div><div><span>          </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>55</div></div><div><span>            </span><span>return</span><span> </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"boolmap tag value must be like true-false,true-true,false-false,false-false"</span><span>)</span></div></div><div><div><div>56</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>57</div></div><div><span>          </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>boolMap</span><span>[</span><span>b</span><span>[</span><span>0</span><span><span>]] </span><span>=</span><span> </span></span><span>bb</span></div></div><div><div><div>58</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>59</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>60</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>61</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>62</div></div><div>
</div></div><div><div><div>63</div></div><div><span>  </span><span>tmp</span><span><span> </span><span>:=</span><span> </span></span><span>reflect</span><span>.</span><span>MakeSlice</span><span>(</span><span>reflect</span><span>.</span><span>SliceOf</span><span>(</span><span>rdata</span><span>.</span><span>Type</span><span>().</span><span>Elem</span><span>()), </span><span>0</span><span>, </span><span>len</span><span>(</span><span>rows</span><span>))</span></div></div><div><div><div>64</div></div><div><span>  </span><span>for</span><span> </span><span>_</span><span>, </span><span>r</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>rows</span><span> {</span></div></div><div><div><div>65</div></div><div><span>    </span><span>var</span><span> </span><span>elemPtr</span><span>, </span><span>elemVal</span><span> </span><span>reflect</span><span>.</span><span>Value</span></div></div><div><div><div>66</div></div><div><span>    </span><span>if</span><span> </span><span>isPrt</span><span> {</span></div></div><div><div><div>67</div></div><div><span>      </span><span>elemPtr</span><span><span> </span><span>=</span><span> </span></span><span>reflect</span><span>.</span><span>New</span><span>(</span><span>dataElemType</span><span>)</span></div></div><div><div><div>68</div></div><div><span>      </span><span>elemVal</span><span><span> </span><span>=</span><span> </span></span><span>elemPtr</span><span>.</span><span>Elem</span><span>()</span></div></div><div><div><div>69</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>70</div></div><div><span>      </span><span>elemVal</span><span><span> </span><span>=</span><span> </span></span><span>reflect</span><span>.</span><span>New</span><span>(</span><span>dataElemType</span><span>).</span><span>Elem</span><span>()</span></div></div><div><div><div>71</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>72</div></div><div><span>    </span><span>for</span><span> </span><span>i</span><span>, </span><span>v</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>r</span><span>.</span><span>Cells</span><span> {</span></div></div><div><div><div>73</div></div><div><span>      </span><span>if</span><span> </span><span>i</span><span><span> </span><span>&gt;=</span><span> </span></span><span>dataElemType</span><span>.</span><span>NumField</span><span>() {</span></div></div><div><div><div>74</div></div><div><span>        </span><span>break</span></div></div><div><div><div>75</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>76</div></div><div><span>      </span><span>f</span><span><span> </span><span>:=</span><span> </span></span><span>elemVal</span><span>.</span><span>Field</span><span>(</span><span>i</span><span>)</span></div></div><div><div><div>77</div></div><div><span>      </span><span>if</span><span><span> </span><span>!</span></span><span>f</span><span>.</span><span>CanSet</span><span>() {</span></div></div><div><div><div>78</div></div><div><span>        </span><span>continue</span></div></div><div><div><div>79</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>80</div></div><div>
</div></div><div><div><div>81</div></div><div><span>      </span><span>txt</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>v</span><span>.</span><span>FormattedValue</span><span>()</span></div></div><div><div><div>82</div></div><div><span>      </span><span>switch</span><span> </span><span>f</span><span>.</span><span>Kind</span><span>() {</span></div></div><div><div><div>83</div></div><div><span>      </span><span>case</span><span> </span><span>reflect</span><span>.</span><span>Int</span><span>, </span><span>reflect</span><span>.</span><span>Int8</span><span>, </span><span>reflect</span><span>.</span><span>Int16</span><span>, </span><span>reflect</span><span>.</span><span>Int32</span><span>, </span><span>reflect</span><span>.</span><span>Int64</span><span>:</span></div></div><div><div><div>84</div></div><div><span>        </span><span>if</span><span> </span><span>n</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>strconv</span><span>.</span><span>ParseInt</span><span>(</span><span>txt</span><span>, </span><span>10</span><span>, </span><span>64</span><span>); </span><span>err</span><span><span> </span><span>==</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>85</div></div><div><span>          </span><span>f</span><span>.</span><span>SetInt</span><span>(</span><span>n</span><span>)</span></div></div><div><div><div>86</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>87</div></div><div><span>      </span><span>case</span><span> </span><span>reflect</span><span>.</span><span>Uint</span><span>, </span><span>reflect</span><span>.</span><span>Uint8</span><span>, </span><span>reflect</span><span>.</span><span>Uint16</span><span>, </span><span>reflect</span><span>.</span><span>Uint32</span><span>, </span><span>reflect</span><span>.</span><span>Uint64</span><span>:</span></div></div><div><div><div>88</div></div><div><span>        </span><span>if</span><span> </span><span>n</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>strconv</span><span>.</span><span>ParseUint</span><span>(</span><span>txt</span><span>, </span><span>10</span><span>, </span><span>64</span><span>); </span><span>err</span><span><span> </span><span>==</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>89</div></div><div><span>          </span><span>f</span><span>.</span><span>SetUint</span><span>(</span><span>n</span><span>)</span></div></div><div><div><div>90</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>91</div></div><div><span>      </span><span>case</span><span> </span><span>reflect</span><span>.</span><span>Float32</span><span>, </span><span>reflect</span><span>.</span><span>Float64</span><span>:</span></div></div><div><div><div>92</div></div><div><span>        </span><span>if</span><span> </span><span>f64</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>strconv</span><span>.</span><span>ParseFloat</span><span>(</span><span>txt</span><span>, </span><span>64</span><span>); </span><span>err</span><span><span> </span><span>==</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>93</div></div><div><span>          </span><span>f</span><span>.</span><span>SetFloat</span><span>(</span><span>f64</span><span>)</span></div></div><div><div><div>94</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>95</div></div><div><span>      </span><span>case</span><span> </span><span>reflect</span><span>.</span><span>Bool</span><span>:</span></div></div><div><div><div>96</div></div><div><span>        </span><span>if</span><span> </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>boolMap</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>97</div></div><div><span>          </span><span>f</span><span>.</span><span>SetBool</span><span>(</span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>boolMap</span><span>[</span><span>txt</span><span>])</span></div></div><div><div><div>98</div></div><div><span><span>        </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>99</div></div><div><span>          </span><span>if</span><span> </span><span>b</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>strconv</span><span>.</span><span>ParseBool</span><span>(</span><span>txt</span><span>); </span><span>err</span><span><span> </span><span>==</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>100</div></div><div><span>            </span><span>f</span><span>.</span><span>SetBool</span><span>(</span><span>b</span><span>)</span></div></div><div><div><div>101</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>102</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>103</div></div><div><span>      </span><span>case</span><span> </span><span>reflect</span><span>.</span><span>String</span><span>:</span></div></div><div><div><div>104</div></div><div><span>        </span><span>f</span><span>.</span><span>SetString</span><span>(</span><span>txt</span><span>)</span></div></div><div><div><div>105</div></div><div><span>      </span><span>default</span><span>:</span></div></div><div><div><div>106</div></div><div><span>        </span><span>switch</span><span> </span><span>f</span><span>.</span><span>Interface</span><span>().(</span><span>type</span><span>) {</span></div></div><div><div><div>107</div></div><div><span>        </span><span>case</span><span><span> </span><span>*</span></span><span>gtime</span><span>.</span><span>Time</span><span>:</span></div></div><div><div><div>108</div></div><div><span>          </span><span>t</span><span><span> </span><span>:=</span><span> </span></span><span>gtime</span><span>.</span><span>NewFromStr</span><span>(</span><span>txt</span><span>)</span></div></div><div><div><div>109</div></div><div><span>          </span><span>if</span><span> </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>timeformat</span><span><span> </span><span>!=</span><span> </span></span><span>""</span><span> {</span></div></div><div><div><div>110</div></div><div><span>            </span><span>t</span><span><span> </span><span>=</span><span> </span></span><span>gtime</span><span>.</span><span>NewFromStrLayout</span><span>(</span><span>txt</span><span>, </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>timeformat</span><span>)</span></div></div><div><div><div>111</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>112</div></div><div><span>          </span><span>f</span><span>.</span><span>Set</span><span>(</span><span>reflect</span><span>.</span><span>ValueOf</span><span>(</span><span>t</span><span>))</span></div></div><div><div><div>113</div></div><div><span>        </span><span>case</span><span> </span><span>time</span><span>.</span><span>Time</span><span>:</span></div></div><div><div><div>114</div></div><div><span>          </span><span>t</span><span><span> </span><span>:=</span><span> </span></span><span>gtime</span><span>.</span><span>NewFromStr</span><span>(</span><span>txt</span><span>)</span></div></div><div><div><div>115</div></div><div><span>          </span><span>if</span><span> </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>timeformat</span><span><span> </span><span>!=</span><span> </span></span><span>""</span><span> {</span></div></div><div><div><div>116</div></div><div><span>            </span><span>t</span><span><span> </span><span>=</span><span> </span></span><span>gtime</span><span>.</span><span>NewFromStrLayout</span><span>(</span><span>txt</span><span>, </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>timeformat</span><span>)</span></div></div><div><div><div>117</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>118</div></div><div><span>          </span><span>f</span><span>.</span><span>Set</span><span>(</span><span>reflect</span><span>.</span><span>ValueOf</span><span>(</span><span>t</span><span>.</span><span>Time</span><span>))</span></div></div><div><div><div>119</div></div><div><span>        </span><span>case</span><span><span> </span><span>*</span></span><span>time</span><span>.</span><span>Time</span><span>:</span></div></div><div><div><div>120</div></div><div><span>          </span><span>t</span><span><span> </span><span>:=</span><span> </span></span><span>gtime</span><span>.</span><span>NewFromStr</span><span>(</span><span>txt</span><span>)</span></div></div><div><div><div>121</div></div><div><span>          </span><span>if</span><span> </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>timeformat</span><span><span> </span><span>!=</span><span> </span></span><span>""</span><span> {</span></div></div><div><div><div>122</div></div><div><span>            </span><span>t</span><span><span> </span><span>=</span><span> </span></span><span>gtime</span><span>.</span><span>NewFromStrLayout</span><span>(</span><span>txt</span><span>, </span><span>dataElemTypeOptions</span><span>[</span><span>i</span><span>].</span><span>timeformat</span><span>)</span></div></div><div><div><div>123</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>124</div></div><div><span>          </span><span>f</span><span>.</span><span>Set</span><span>(</span><span>reflect</span><span>.</span><span>ValueOf</span><span><span>(</span><span>&amp;</span></span><span>t</span><span>.</span><span>Time</span><span>))</span></div></div><div><div><div>125</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>126</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>127</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>128</div></div><div><span>    </span><span>if</span><span> </span><span>isPrt</span><span> {</span></div></div><div><div><div>129</div></div><div><span>      </span><span>tmp</span><span><span> </span><span>=</span><span> </span></span><span>reflect</span><span>.</span><span>Append</span><span>(</span><span>tmp</span><span>, </span><span>elemPtr</span><span>)</span></div></div><div><div><div>130</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>131</div></div><div><span>      </span><span>tmp</span><span><span> </span><span>=</span><span> </span></span><span>reflect</span><span>.</span><span>Append</span><span>(</span><span>tmp</span><span>, </span><span>elemVal</span><span>)</span></div></div><div><div><div>132</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>133</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>134</div></div><div><span>  </span><span>rdata</span><span>.</span><span>Set</span><span>(</span><span>tmp</span><span>)</span></div></div><div><div><div>135</div></div><div><span>  </span><span>return</span><span> </span><span>nil</span></div></div><div><div><div>136</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>测试用例<a href="#测试用例"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> (</span></div></div><div><div><div>2</div></div><div><span>  </span><span>"errors"</span></div></div><div><div><div>3</div></div><div><span>  </span><span>"reflect"</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"testing"</span></div></div><div><div><div>5</div></div><div><span>  </span><span>"time"</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>  </span><span>"github.com/gogf/gf/v2/os/gtime"</span></div></div><div><div><div>8</div></div><div><span>  </span><span>"github.com/tealeg/xlsx"</span></div></div><div><div><div>9</div></div><div><span>)</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>func</span><span> </span><span>newRow</span><span><span>(</span><span>sheet</span><span> </span><span>*</span></span><span>xlsx</span><span>.</span><span>Sheet</span><span><span>, </span><span>vals</span><span> ...</span></span><span>string</span><span><span>) </span><span>*</span></span><span>xlsx</span><span>.</span><span>Row</span><span> {</span></div></div><div><div><div>12</div></div><div><span>  </span><span>r</span><span><span> </span><span>:=</span><span> </span></span><span>sheet</span><span>.</span><span>AddRow</span><span>()</span></div></div><div><div><div>13</div></div><div><span>  </span><span>for</span><span> </span><span>_</span><span>, </span><span>v</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>vals</span><span> {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>cell</span><span><span> </span><span>:=</span><span> </span></span><span>r</span><span>.</span><span>AddCell</span><span>()</span></div></div><div><div><div>15</div></div><div><span>    </span><span>cell</span><span>.</span><span>SetString</span><span>(</span><span>v</span><span>)</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span>  </span><span>return</span><span> </span><span>r</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>type</span><span> </span><span>Person</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>21</div></div><div><span>  </span><span>Name</span><span>  </span><span>string</span></div></div><div><div><div>22</div></div><div><span>  </span><span>Age</span><span>   </span><span>int</span></div></div><div><div><div>23</div></div><div><span>  </span><span>GTime</span><span><span> </span><span>*</span></span><span>gtime</span><span>.</span><span>Time</span><span> </span><span>`xlsx:"timeformat:20060102"`</span></div></div><div><div><div>24</div></div><div><span>  </span><span>Time</span><span>  </span><span>time</span><span>.</span><span>Time</span></div></div><div><div><div>25</div></div><div><span>  </span><span>PTime</span><span><span> </span><span>*</span></span><span>time</span><span>.</span><span>Time</span></div></div><div><div><div>26</div></div><div><span>  </span><span>Bool</span><span>  </span><span>bool</span><span> </span><span>`xlsx:"boolmap:是-true,否-false"`</span></div></div><div><div><div>27</div></div><div><span>}</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>func</span><span> </span><span>TestParseXlsxStruct_Basic</span><span><span>(</span><span>t</span><span> </span><span>*</span></span><span>testing</span><span>.</span><span>T</span><span>) {</span></div></div><div><div><div>30</div></div><div><span>  </span><span>// 准备 2 行数据</span></div></div><div><div><div>31</div></div><div><span>  </span><span>file</span><span><span> </span><span>:=</span><span> </span></span><span>xlsx</span><span>.</span><span>NewFile</span><span>()</span></div></div><div><div><div>32</div></div><div><span>  </span><span>sh</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>file</span><span>.</span><span>AddSheet</span><span>(</span><span>"Sheet1"</span><span>)</span></div></div><div><div><div>33</div></div><div><span>  </span><span>_</span><span><span> </span><span>=</span><span> </span></span><span>newRow</span><span>(</span><span>sh</span><span>, </span><span>"Alice"</span><span>, </span><span>"30"</span><span>, </span><span>"20250405"</span><span>, </span><span>"2025-01-01"</span><span>, </span><span>"2022-01-01 12:14:15"</span><span>, </span><span>"是"</span><span>)</span></div></div><div><div><div>34</div></div><div><span>  </span><span>_</span><span><span> </span><span>=</span><span> </span></span><span>newRow</span><span>(</span><span>sh</span><span>, </span><span>"Bob"</span><span>, </span><span>"25"</span><span>, </span><span>"20250102"</span><span>)</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>  </span><span>var</span><span> </span><span>got</span><span> []</span><span>Person</span></div></div><div><div><div>37</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>ParseXlsxStruct</span><span>(</span><span>sh</span><span>.</span><span>Rows</span><span><span>, </span><span>&amp;</span></span><span>got</span><span>); </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>38</div></div><div><span>    </span><span>t</span><span>.</span><span>Fatalf</span><span>(</span><span>"unexpected error: </span><span>%v</span><span>"</span><span>, </span><span>err</span><span>)</span></div></div><div><div><div>39</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>  </span><span>p</span><span><span> </span><span>:=</span><span> </span></span><span>gtime</span><span>.</span><span>NewFromStr</span><span>(</span><span>"2022-01-01 12:14:15"</span><span>)</span></div></div><div><div><div>42</div></div><div><span>  </span><span>want</span><span><span> </span><span>:=</span><span> []</span></span><span>Person</span><span>{</span></div></div><div><div><div>43</div></div><div><span><span>    </span></span><span>{</span><span>Name</span><span>: </span><span>"Alice"</span><span>, </span><span>Age</span><span>: </span><span>30</span><span>, </span><span>GTime</span><span>: </span><span>gtime</span><span>.</span><span>NewFromStrLayout</span><span>(</span><span>"20250405"</span><span>, </span><span>"20060102"</span><span>), </span><span>Time</span><span>: </span><span>gtime</span><span>.</span><span>New</span><span>(</span><span>"2025-01-01"</span><span>).</span><span>Time</span><span>, </span><span>PTime</span><span><span>: </span><span>&amp;</span></span><span>p</span><span>.</span><span>Time</span><span>, </span><span>Bool</span><span>: </span><span>true</span><span>},</span></div></div><div><div><div>44</div></div><div><span><span>    </span></span><span>{</span><span>Name</span><span>: </span><span>"Bob"</span><span>, </span><span>Age</span><span>: </span><span>25</span><span>, </span><span>GTime</span><span>: </span><span>gtime</span><span>.</span><span>NewFromStrLayout</span><span>(</span><span>"20250102"</span><span>, </span><span>"20060102"</span><span>)},</span></div></div><div><div><div>45</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>46</div></div><div><span>  </span><span>if</span><span><span> </span><span>!</span></span><span>reflect</span><span>.</span><span>DeepEqual</span><span>(</span><span>got</span><span>, </span><span>want</span><span>) {</span></div></div><div><div><div>47</div></div><div><span>    </span><span>t</span><span>.</span><span>Fatalf</span><span>(</span><span>"mismatch</span><span>\n</span><span>want: </span><span>%+v</span><span>\n</span><span>got : </span><span>%+v</span><span>"</span><span>, </span><span>want</span><span>, </span><span>got</span><span>)</span></div></div><div><div><div>48</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>49</div></div><div><span>}</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span>func</span><span> </span><span>TestParseXlsxStruct_PtrSlice</span><span><span>(</span><span>t</span><span> </span><span>*</span></span><span>testing</span><span>.</span><span>T</span><span>) {</span></div></div><div><div><div>52</div></div><div><span>  </span><span>file</span><span><span> </span><span>:=</span><span> </span></span><span>xlsx</span><span>.</span><span>NewFile</span><span>()</span></div></div><div><div><div>53</div></div><div><span>  </span><span>sh</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>file</span><span>.</span><span>AddSheet</span><span>(</span><span>"Sheet1"</span><span>)</span></div></div><div><div><div>54</div></div><div><span>  </span><span>_</span><span><span> </span><span>=</span><span> </span></span><span>newRow</span><span>(</span><span>sh</span><span>, </span><span>"Cat"</span><span>, </span><span>"7"</span><span>)</span></div></div><div><div><div>55</div></div><div>
</div></div><div><div><div>56</div></div><div><span>  </span><span>var</span><span> </span><span>got</span><span><span> []</span><span>*</span></span><span>Person</span></div></div><div><div><div>57</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>ParseXlsxStruct</span><span>(</span><span>sh</span><span>.</span><span>Rows</span><span><span>, </span><span>&amp;</span></span><span>got</span><span>); </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>58</div></div><div><span>    </span><span>t</span><span>.</span><span>Fatalf</span><span>(</span><span>"unexpected error: </span><span>%v</span><span>"</span><span>, </span><span>err</span><span>)</span></div></div><div><div><div>59</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>60</div></div><div><span>  </span><span>if</span><span> </span><span>len</span><span>(</span><span>got</span><span><span>) </span><span>!=</span><span> </span></span><span>1</span><span><span> </span><span>||</span><span> </span></span><span>got</span><span>[</span><span>0</span><span>].</span><span>Name</span><span><span> </span><span>!=</span><span> </span></span><span>"Cat"</span><span><span> </span><span>||</span><span> </span></span><span>got</span><span>[</span><span>0</span><span>].</span><span>Age</span><span><span> </span><span>!=</span><span> </span></span><span>7</span><span> {</span></div></div><div><div><div>61</div></div><div><span>    </span><span>t</span><span>.</span><span>Fatalf</span><span>(</span><span>"unexpected result: </span><span>%+v</span><span>"</span><span>, </span><span>got</span><span>)</span></div></div><div><div><div>62</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>63</div></div><div><span>}</span></div></div><div><div><div>64</div></div><div>
</div></div><div><div><div>65</div></div><div><span>func</span><span> </span><span>TestParseXlsxStruct_NotPointer</span><span><span>(</span><span>t</span><span> </span><span>*</span></span><span>testing</span><span>.</span><span>T</span><span>) {</span></div></div><div><div><div>66</div></div><div><span>  </span><span>file</span><span><span> </span><span>:=</span><span> </span></span><span>xlsx</span><span>.</span><span>NewFile</span><span>()</span></div></div><div><div><div>67</div></div><div><span>  </span><span>sh</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>file</span><span>.</span><span>AddSheet</span><span>(</span><span>"Sheet1"</span><span>)</span></div></div><div><div><div>68</div></div><div><span>  </span><span>_</span><span><span> </span><span>=</span><span> </span></span><span>newRow</span><span>(</span><span>sh</span><span>, </span><span>"Dog"</span><span>, </span><span>"3"</span><span>)</span></div></div><div><div><div>69</div></div><div>
</div></div><div><div><div>70</div></div><div><span>  </span><span>var</span><span> </span><span>wrong</span><span> []</span><span>Person</span></div></div><div><div><div>71</div></div><div><span>  </span><span>// 直接传切片而不是 *切片，应报错</span></div></div><div><div><div>72</div></div><div><span>  </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>ParseXlsxStruct</span><span>(</span><span>sh</span><span>.</span><span>Rows</span><span>, </span><span>wrong</span><span>)</span></div></div><div><div><div>73</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>==</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>74</div></div><div><span>    </span><span>t</span><span>.</span><span>Fatal</span><span>(</span><span>"expected error, got nil"</span><span>)</span></div></div><div><div><div>75</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>76</div></div><div><span>}</span></div></div><div><div><div>77</div></div><div>
</div></div><div><div><div>78</div></div><div><span>func</span><span> </span><span>TestParseXlsxStruct_ElemNotStruct</span><span><span>(</span><span>t</span><span> </span><span>*</span></span><span>testing</span><span>.</span><span>T</span><span>) {</span></div></div><div><div><div>79</div></div><div><span>  </span><span>file</span><span><span> </span><span>:=</span><span> </span></span><span>xlsx</span><span>.</span><span>NewFile</span><span>()</span></div></div><div><div><div>80</div></div><div><span>  </span><span>sh</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>file</span><span>.</span><span>AddSheet</span><span>(</span><span>"Sheet1"</span><span>)</span></div></div><div><div><div>81</div></div><div><span>  </span><span>_</span><span><span> </span><span>=</span><span> </span></span><span>newRow</span><span>(</span><span>sh</span><span>, </span><span>"1"</span><span>, </span><span>"2"</span><span>)</span></div></div><div><div><div>82</div></div><div>
</div></div><div><div><div>83</div></div><div><span>  </span><span>var</span><span> </span><span>wrong</span><span> []</span><span>int</span></div></div><div><div><div>84</div></div><div><span>  </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>ParseXlsxStruct</span><span>(</span><span>sh</span><span>.</span><span>Rows</span><span><span>, </span><span>&amp;</span></span><span>wrong</span><span>)</span></div></div><div><div><div>85</div></div><div><span>  </span><span>if</span><span><span> </span><span>!</span></span><span>errors</span><span>.</span><span>Is</span><span>(</span><span>err</span><span>, </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"slice element must be struct or *struct"</span><span>)) {</span></div></div><div><div><div>86</div></div><div><span>    </span><span>// 只要报错即可；不必精确判定同一个 error 实例</span></div></div><div><div><div>87</div></div><div><span>    </span><span>if</span><span> </span><span>err</span><span><span> </span><span>==</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>88</div></div><div><span>      </span><span>t</span><span>.</span><span>Fatal</span><span>(</span><span>"expected error, got nil"</span><span>)</span></div></div><div><div><div>89</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>90</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>91</div></div><div><span>}</span></div></div><div><div><div>92</div></div><div>
</div></div><div><div><div>93</div></div><div><span>func</span><span> </span><span>TestParseXlsxStruct_ExtraColumnsIgnored</span><span><span>(</span><span>t</span><span> </span><span>*</span></span><span>testing</span><span>.</span><span>T</span><span>) {</span></div></div><div><div><div>94</div></div><div><span>  </span><span>file</span><span><span> </span><span>:=</span><span> </span></span><span>xlsx</span><span>.</span><span>NewFile</span><span>()</span></div></div><div><div><div>95</div></div><div><span>  </span><span>sh</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>file</span><span>.</span><span>AddSheet</span><span>(</span><span>"Sheet1"</span><span>)</span></div></div><div><div><div>96</div></div><div><span>  </span><span>// 第 3 列将被忽略</span></div></div><div><div><div>97</div></div><div><span>  </span><span>_</span><span><span> </span><span>=</span><span> </span></span><span>newRow</span><span>(</span><span>sh</span><span>, </span><span>"Eve"</span><span>, </span><span>"40"</span><span>, </span><span>"ignored"</span><span>)</span></div></div><div><div><div>98</div></div><div>
</div></div><div><div><div>99</div></div><div><span>  </span><span>var</span><span> </span><span>got</span><span> []</span><span>Person</span></div></div><div><div><div>100</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>ParseXlsxStruct</span><span>(</span><span>sh</span><span>.</span><span>Rows</span><span><span>, </span><span>&amp;</span></span><span>got</span><span>); </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>101</div></div><div><span>    </span><span>t</span><span>.</span><span>Fatalf</span><span>(</span><span>"unexpected error: </span><span>%v</span><span>"</span><span>, </span><span>err</span><span>)</span></div></div><div><div><div>102</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>103</div></div><div><span>  </span><span>if</span><span> </span><span>got</span><span>[</span><span>0</span><span>].</span><span>Name</span><span><span> </span><span>!=</span><span> </span></span><span>"Eve"</span><span><span> </span><span>||</span><span> </span></span><span>got</span><span>[</span><span>0</span><span>].</span><span>Age</span><span><span> </span><span>!=</span><span> </span></span><span>40</span><span> {</span></div></div><div><div><div>104</div></div><div><span>    </span><span>t</span><span>.</span><span>Fatalf</span><span>(</span><span>"unexpected result: </span><span>%+v</span><span>"</span><span>, </span><span>got</span><span>[</span><span>0</span><span>])</span></div></div><div><div><div>105</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>106</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/275/</id>
      <title type="text">【杂项】tmpfs</title>
      <published>2024-09-25T14:26:01.000Z</published>
      <updated>2024-09-25T14:26:01.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/275/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>blog-tmpfs<a href="#blog-tmpfs"><span>#</span></a></h1></section>
<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p><code>tmpfs</code>是一种临时文件系统，物理位置位于内存或交换分区中。读写文件的速度远远快于硬盘的速度（未使用交换分区时），但因为物理位置位于内存或交换分区，当机器重启时就会丢失数据。因为高速且重启自动删除数据，因此适合用来存储临时文件，例如一些编程语言的临时编译文件，在一些<code>linux</code>发行版中会将<code>/tmp</code>挂载为<code>tmpfs</code>（使用<code>df /tmp</code>命令可以查看）。<code>tmpfs</code>可以灵活调整大小，且实际占用大小也是根据存储的数据大小动态分配的。假如创建了4G大小的<code>tmpfs</code>分区，并往里面写入1G大小的文件，这时实际占用内存大小为1G而不是4G</p><p><code>tmpfs</code>衍生于<code>ramfs</code>，<code>ramfs</code>是完全位使用物理内存的文件系统，但是<code>ramfs</code>没有处理内存不足的情况会影响整个系统。而<code>tmpfs</code>会在物理内存不足时使用交换分区中的空间，但又因为交换分区一般都是挂载在硬盘上，因此当使用交换分区时性能与硬盘普通文件系统没有差别。</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><section><h2>Linux挂载tmpfs<a href="#linux挂载tmpfs"><span>#</span></a></h2><p>使用命令</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 将tmpfs挂载在/mnt/tmpfs上，并限定大小为4G</span></div></div><div><div><div>2</div></div><div><span># 如果不指定size将会自动调整为实际内存大小的一半</span></div></div><div><div><div>3</div></div><div><span>sudo</span><span> </span><span>mount</span><span> </span><span>-o</span><span> </span><span>size=4G</span><span> </span><span>tmpfs</span><span> </span><span>/mnt/tmpfs</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 将大小调整为1G</span></div></div><div><div><div>6</div></div><div><span>sudo</span><span> </span><span>mount</span><span> </span><span>-o</span><span> </span><span>remount,size=1G</span><span> </span><span>tmpfs</span><span> </span><span>/mnt/tmpfs</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>MacOS挂载<a href="#macos挂载"><span>#</span></a></h2><p>在网上搜索MacOS上使用tmpfs时，显示的结果都是使用<code>ramdisk</code>文件系统，而<code>ramdisk</code>就没有<code>tmpfs</code>那么灵活，并且占用内存是创建时固定分配的。
在一筹莫展时，在终端里输入<code>mount</code>并按了两次tab键，在提示框中显示有<code>mount_tmpfs</code>选项，这说明在MacOS中也可以使用<code>tmpfs</code>文件系统</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 将/Volumes/tmpfs_dir挂载为tmpfs</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>mount_tmpfs</span><span> </span><span>-s</span><span> </span><span>4G</span><span> </span><span>/Volumes/tmpfs_dir</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/274/</id>
      <title type="text">【杂项】常用正则匹配备忘（持续更新）</title>
      <published>2024-05-31T08:20:43.000Z</published>
      <updated>2024-05-31T08:20:43.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/274/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>找出没有包含“数值”的句子<a href="#找出没有包含数值的句子"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>^(?!数值).</span><span>*</span><span>&amp;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>解释：</p><ul>
<li><code>^</code> 表示行的开始。</li>
<li><code>(?=.*数值)</code> 是正向前瞻，表示任意位置包含“数值”</li>
<li><code>(?!.*数值)</code> 是负向前瞻，表示任意位置不包含“数值”</li>
<li><code>.*</code> 匹配任意字符（除换行符外）</li>
<li><code>$</code> 表示行的结束
<code>(?!abc)</code>与<code>[^abc]</code>的区别：
<code>[^abc]</code>匹配任何不是 <code>a</code>、<code>b</code> 或 <code>c</code> 的单个字符
<code>(?!abc)</code>匹配不是<code>abc</code>这个”词语”</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/262/</id>
      <title type="text">【杂项】搜集各种好用的库(不定时更新)</title>
      <published>2024-03-27T01:08:00.000Z</published>
      <updated>2024-03-27T01:08:23.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/262/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>Golang<a href="#golang"><span>#</span></a></h2><ul>
<li><a href="https://github.com/kardianos/service" target="_blank">kardianos/service</a> - 将golang程序作为服务运行 [📕]</li>
<li><a href="https://github.com/go-survey/survey" target="_blank">go-survey/survey</a> - 用于构建交互式和可访问的提示，并完全支持windows和posix终端。[📕]</li>
<li><a href="https://github.com/go-toast/toast" target="_blank">go-toast/toast</a> - windows通知 [📕]</li>
<li><a href="https://github.com/getlantern/systray" target="_blank">getlantern/systray</a> - 托盘 [📕]</li>
<li><a href="https://github.com/lxn/win" target="_blank">lxn/win</a> - windows api封装 [📕]</li>
<li><a href="https://github.com/lxn/walk" target="_blank">lxn/walk</a> - windows gui [📕]</li>
<li><a href="https://github.com/jroimartin/gocui" target="_blank">jroimartin/gocui</a> - 漂亮的cli gui库 [📕]</li>
<li><a href="https://github.com/jesseduffield/lazygit" target="_blank">jesseduffield/lazygit</a> - 使用了<code>gocui</code>的git gui客户端 [📕]</li>
<li><a href="https://github.com/SagerNet/sing-box" target="_blank">SagerNet/sing-box</a> - 通用代理平台</li>
<li><a href="https://github.com/jmorganca/ollama" target="_blank">jmorganca/ollama</a> - 在本地启动并运行 Llama 2 和其他大型语言模型</li>
<li><a href="https://github.com/flyteorg/flyte" target="_blank">flyteorg/flyte</a> - 可扩展且灵活的工作流协调平台，可无缝统一数据、ML 和分析堆栈</li>
<li><a href="https://github.com/AdguardTeam/AdGuardHome" target="_blank">AdguardTeam/AdGuardHome</a> - 全网广告和跟踪器拦截 DNS 服务器</li>
<li><a href="https://github.com/argoproj/argo-cd" target="_blank">argoproj/argo-cd</a> - Kubernetes 的声明式持续部署</li>
<li><a href="https://github.com/avelino/awesome-go" target="_blank">avelino/awesome-go</a> - 超赞 Go 框架、库和软件的精选列表 [集合]</li>
<li><a href="https://github.com/sundowndev/phoneinfoga" target="_blank">sundowndev/phoneinfoga</a> - 电话号码信息收集框架</li>
<li><a href="https://github.com/msteinert/pam" target="_blank">msteinert/pam</a> - PAM api</li>
<li><a href="https://github.com/go-delve/delve" target="_blank">go-delve/delve</a> - 类似<code>pprof</code>的调试工具，可以调试运行中的程序</li>
<li><a href="https://github.com/alist-org/alist" target="_blank">alist-org/alist</a> -  一个支持多存储的文件列表/WebDAV程序，使用 Gin 和 Solidjs</li>
<li><a href="https://github.com/shenghui0779/api-tpl-go" target="_blank">shenghui0779/api-tpl-go</a> - 🔥 轻量好用的 Go API 项目框架 🚀🚀🚀 [📕]</li>
<li><a href="https://github.com/ginuerzh/gost" target="_blank">ginuerzh/gost</a> - GO语言实现的安全隧道</li>
<li><a href="https://github.com/usememos/memos" target="_blank">usememos/memos</a> - 开源轻量级在线笔记</li>
<li><a href="https://github.com/zzl/go-win32api" target="_blank">zzl/go-win32api</a> - win32 api 封装 [📕]</li>
<li><a href="https://github.com/casdoor/casdoor" target="_blank">casdoor/casdoor</a> - 基于 OAuth 2.0 / OIDC 的 UI 优先集中认证 / 单点登录 (SSO) 平台</li>
</ul></section>
<section><h2>前端<a href="#前端"><span>#</span></a></h2><ul>
<li><a href="https://github.com/baidu/amis" target="_blank">baidu/amis</a> - 前端低代码框架，通过 JSON 配置就能生成各种页面</li>
<li><a href="https://github.com/youzan/vant" target="_blank">youzan/vant</a> - 一个轻量级的、可定制的Vue UI库，用于移动web应用程序</li>
</ul></section>
<section><h2>Windows Shell<a href="#windows-shell"><span>#</span></a></h2><ul>
<li><a href="https://github.com/lukesampson/psutils" target="_blank">https://github.com/lukesampson/psutils</a> - powershell 实用脚本（常用：sudo.ps1）</li>
</ul></section>
<section><h2>Android<a href="#android"><span>#</span></a></h2><ul>
<li><a href="https://github.com/rev1si0n/lamda" target="_blank">LAMDA </a> - 安卓抓包/逆向/HOOK &amp; 云手机/远程桌面/自动化辅助框架</li>
<li><a href="https://github.com/Rehtt/DisplayToggle" target="_blank">DisplayToggle</a> - 关闭屏幕而不是熄屏</li>
</ul></section>
<section><h2>Python<a href="#python"><span>#</span></a></h2><ul>
<li><a href="https://github.com/Ciphey/Ciphey" target="_blank">Ciphey</a> - 使用自然语言处理和人工智能以及一些全自动解密/解码/破解工具</li>
<li><a href="https://github.com/immich-app/immich" target="_blank">immich</a> - 自建照片视频库</li>
</ul></section>
<section><h2>杂项<a href="#杂项"><span>#</span></a></h2><ul>
<li><a href="https://github.com/typst/typst" target="_blank">typst</a> - 类Markdown语法，可以输出类似word的效果</li>
<li><a href="https://github.com/dbcli/mycli" target="_blank">dbcli/mycli</a> - 基于Python的MySQL/MariaDB/Percona的命令行client，自动补全非常好用</li>
<li><a href="https://reqable.com/zh-CN/" target="_blank">reqable</a> - 抓包工具，界面直观</li>
<li><a href="https://github.com/0dayCTF/reverse-shell-generator" target="_blank">0dayCTF/reverse-shell-generator</a> - 反弹shell</li>
<li><a href="https://github.com/dockur/windows" target="_blank">dockur/windows</a> - 在docker里跑windows</li>
</ul></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/273/</id>
      <title type="text">Gorm1.25.7 同时使用joins与preload获取列表 报错 reflect: call of reflect.Value.Field on slice Value</title>
      <published>2024-03-04T03:13:00.000Z</published>
      <updated>2024-03-04T03:27:41.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/273/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<blockquote><p>参考issues:
<a href="https://github.com/go-gorm/gorm/issues/6834" target="_blank">6834</a></p></blockquote>
<section><h1>触发错误<a href="#触发错误"><span>#</span></a></h1><p>当join与preload是同一个表时会触发错误，例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span> </span><span>a</span><span> []</span><span>A</span></div></div><div><div><div>2</div></div><div><span>db</span><span>.</span><span>where</span><span>(</span><span>"type = 2"</span><span>).</span><span>Joins</span><span>(</span><span>"A"</span><span>).</span><span>Preload</span><span>(</span><span>"A.B"</span><span>).</span><span>Find</span><span><span>(</span><span>&amp;</span></span><span>a</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>触发错误：<strong>reflect: call of reflect.Value.Field on slice Value</strong></p></section>
<section><h1>触发原因<a href="#触发原因"><span>#</span></a></h1><p>源码 <a href="https://github.com/go-gorm/gorm/blob/v1.25.7/callbacks/preload.go#L124" target="_blank">preload.go&lt;124&gt;</a></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>reflectValue</span><span><span> </span><span>:=</span><span> </span></span><span>rel</span><span>.</span><span>Field</span><span>.</span><span>ReflectValueOf</span><span>(</span><span>db</span><span>.</span><span>Statement</span><span>.</span><span>Context</span><span>, </span><span>db</span><span>.</span><span>Statement</span><span>.</span><span>ReflectValue</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用<code>rel.Field.ReflectValueOf</code>获取<code>db.Statement.ReflectValue</code>对象<code>field</code>，但是前面<code>Find(&amp;a)</code>是一个<code>slice</code>类型，因此会导致映射错误</p></section>
<section><h1>解决办法（2024-03-04）<a href="#解决办法2024-03-04"><span>#</span></a></h1><p>在go.mod 将 gorm 回滚至 <code>1.25.6</code></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/272/</id>
      <title type="text">【linux】目录</title>
      <published>2024-02-19T02:09:40.000Z</published>
      <updated>2024-02-19T02:09:40.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/272/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>发现自己以及周围的人关于<code>linux</code>的目录结构和作用还不怎么清楚，因此查了一些资料并记录下来</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p><strong>首先更正一点， <code>/usr</code> 目录很多人认为是<code>user</code>的意思，而<code>usr</code>是<code>Unix System Resource</code>的缩写，是系统级目录</strong></p><p><code>/usr/bin</code> 为系统预装的一些可执行程序，所有用户都可用，随系统升级会改变
<code>/usr/sbin</code> 存放超级用户才能使用的应用程序
<code>/usr/local</code>为用户级目录，用户可以将自己编译的程序放在该目录的<code>bin</code>下</p><p><code>/bin</code> 存放所有用户皆可用的系统程序，系统启动或者系统修复时可用
<code>/sbin</code> 存放超级用户才能使用的系统程序</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/271/</id>
      <title type="text">好用的工具</title>
      <published>2024-01-04T01:49:00.000Z</published>
      <updated>2024-01-04T01:52:26.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/271/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>Linux<a href="#linux"><span>#</span></a></h1><section><h2>CLI工具<a href="#cli工具"><span>#</span></a></h2><section><h3>speedometer 显示网卡接口出入流量速度<a href="#speedometer-显示网卡接口出入流量速度"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>speedometer</span></div></div><div><div><div>2</div></div><div><span>speedometer</span><span> </span><span>-r</span><span> </span><span>eth0</span><span> </span><span>-t</span><span> </span><span>eth0</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>btop/bashtop/bpytop 比htop更全面更炫酷的资源显示<a href="#btopbashtopbpytop-比htop更全面更炫酷的资源显示"><span>#</span></a></h3><p>其中bashtop是第一个版本，使用bash实现
bpytop 是第二个迭代版本，使用python实现
btop++ 是第三个迭代版本，使用c++实现，但是功能相对bpytop少</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>btop</span></div></div><div><div><div>2</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>bashtop</span></div></div><div><div><div>3</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>bpytop</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>s-tui CPU温度显示<a href="#s-tui-cpu温度显示"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>s-tui</span></div></div><div><div><div>2</div></div><div><span>或</span></div></div><div><div><div>3</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>s-tui</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>macchanger 更改mac地址<a href="#macchanger-更改mac地址"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>macchanger</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>macchanger</span><span> </span><span>-s</span><span> </span><span>eth0</span><span> </span><span># 显示当前mac</span></div></div><div><div><div>4</div></div><div><span>macchanger</span><span> </span><span>-r</span><span> </span><span>eth0</span><span> </span><span># 随机生成mac</span></div></div><div><div><div>5</div></div><div><span>macchanger</span><span> </span><span>-m</span><span> </span><span>XX:XX:XX:XX:XX:XX</span><span> </span><span>eth0</span><span> </span><span># 指定mac</span></div></div><div><div><div>6</div></div><div><span>macchanger</span><span> </span><span>-e</span><span> </span><span>eth0</span><span> </span><span># 生成同品牌mac地址</span></div></div><div><div><div>7</div></div><div><span>macchanger</span><span> </span><span>-a</span><span> </span><span>eth0</span><span> </span><span># 生成不同厂家同一类型mac地址</span></div></div><div><div><div>8</div></div><div><span>macchanger</span><span> </span><span>-A</span><span> </span><span>eth0</span><span> </span><span># 生成不同厂家不同类型mac地址</span></div></div><div><div><div>9</div></div><div><span>macchanger</span><span> </span><span>-l</span><span> </span><span># 品牌列表</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/270/</id>
      <title type="text">【备忘】nvimdots安装及配置（持续更新）</title>
      <published>2023-11-23T00:41:21.000Z</published>
      <updated>2023-11-23T00:41:21.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/270/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p><code>nvim</code>即<code>neovim</code>，对<code>vim</code>架构进行了大调整，并可以使用<code>lua</code>进行编写插件和配置，<code>nvim</code>集成了<code>LSP</code>
尽管<code>nvim</code> 已经集成了很多功能，但对于新手和不愿意折腾的人来说还是太麻烦了，于是就有了<a href="https://github.com/ayamir/nvimdots" target="_blank"><code>nvimdots</code></a>，<code>nvimdots</code>是一个集成<code>nvim</code>常用功能和插件的开源项目，就好比<code>oh-my-zsh</code>与<code>zsh</code>的关系一样</p></section>
<section><h1>0x01 准备<a href="#0x01-准备"><span>#</span></a></h1><p>尽管 <code>nvimdots</code> 有安装脚本，但是还是有一些依赖需要手动安装
<a href="https://github.com/ayamir/nvimdots/wiki/Prerequisites" target="_blank">nvimdots wiki</a> 里有相关的教程，按照教程基本没问题</p><p>不过<code>nvim</code>还是需要手动安装，截至目前<code>nvim</code>建议安装<code>0.9</code>版本
<a href="https://github.com/neovim/neovim/wiki/Installing-Neovim" target="_blank">nvim wiki</a>有相关教程</p></section>
<section><h1>0x02 安装<a href="#0x02-安装"><span>#</span></a></h1><p>因为安装时大部分插件是从<code>github</code>上下载的，因此国内用户需要自备梯子，并在安装时将梯子设为全局代理，否则大概率会安装失败</p><p>linux安装</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>if</span><span> </span><span>command</span><span> </span><span>-v</span><span> </span><span>curl</span><span> &gt;</span><span>/dev/null</span><span> 2&gt;&amp;1; </span><span>then</span></div></div><div><div><div>2</div></div><div><span>    </span><span>bash</span><span> </span><span>-c</span><span> </span><span>"$(</span><span>curl</span><span> </span><span>-fsSL</span><span> https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh)"</span></div></div><div><div><div>3</div></div><div><span>else</span></div></div><div><div><div>4</div></div><div><span>    </span><span>bash</span><span> </span><span>-c</span><span> </span><span>"$(</span><span>wget</span><span> </span><span>-O-</span><span> https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh)"</span></div></div><div><div><div>5</div></div><div><span>fi</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>windows安装</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>Set-ExecutionPolicy</span><span><span> Bypass </span><span>-</span><span>Scope </span></span><span>Process</span><span><span> </span><span>-</span><span>Force; </span></span><span>Invoke-Expression</span><span> ((</span><span>New-Object</span><span> System.Net.WebClient).DownloadString(</span><span>'https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.ps1'</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x03 配置<a href="#0x03-配置"><span>#</span></a></h1><p>进入<code>nvim</code>使用<code>:Mason</code>管理<code>LSP</code>，过打开文件后使用<code>:LspInstall</code>可以安装或查看对应的<code>LSP</code></p><p><code>clangd</code>的默认<code>filetype</code>中包含<code>proto</code>文件类型，但是在非<code>C/C++</code>项目中使用<code>proto</code>文件会一直提示报错，虽然没什么影响但是很碍眼，而<code>clangd</code>又是默认安装的还卸载不掉，卸载后又会自动安装。因此使用的办法是修改<code>clangd</code>的配置文件，使其不对<code>proto</code>文件做出反应。
默认的<code>clangd</code>中的<code>filetype</code>是<code>"c", "cpp", "objc", "objcpp", "cuda", "proto"</code></p><blockquote><p><a href="https://github.com/neovim/nvim-lspconfig/blob/master/lua/lspconfig/server_configurations/clangd.lua" target="_blank">clangd.lua</a>
因此我们需要删除<code>proto</code></p></blockquote><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>nvim</span><span> </span><span>~/.config/nvim/lua/modules/configs/completion/servers/clangd.lua</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在<code>require("lspconfig").clangd.setup({...})</code>的里面加入</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>filetypes</span><span> = { </span><span>"c"</span><span>, </span><span>"cpp"</span><span>, </span><span>"objc"</span><span>, </span><span>"objcpp"</span><span>, </span><span>"cuda" </span><span>},</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/269/</id>
      <title type="text">【Linux】使用Go开发PAM模块</title>
      <published>2023-10-20T15:17:12.000Z</published>
      <updated>2023-10-20T15:17:12.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/269/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x0 前言<a href="#0x0-前言"><span>#</span></a></h1><p>PAM (Pluggable Authentication Modules) 系统的一部分，它是一个用于 Linux 系统认证的模块化框架。</p><p>如果给 ssh 登录添加 <code>TOTP</code> 验证一般会用到 <code>google-authenticator</code> 模块，这个模块就是实现和使用 PAM API 实现的。</p><p>PAM 不光可以在 ssh 登录时使用在其他大多数需要验证的时候也可以使用，甚至可以在自己程序中调用，总之 PAM 是一个非常好用的系统认证框架。</p><p>本篇文章将使用 Go 实现相关功能，而 PAM 的接口是用 C 语言实现的。因此将会使用 Go 的 <code>CGO</code> 进行编译，并且会尽量减少 C 语言的部分。</p></section>
<section><h1>0x1 准备<a href="#0x1-准备"><span>#</span></a></h1><p>因为 PAM 是 Linux 系统的认证框架，所以在 Linux 上开发最方便</p><p>首先安装依赖库：
Debian/Ubuntu</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>libpam0g-dev</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>Centos</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>yum</span><span> </span><span>install</span><span> </span><span>pam-devel</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>安装后 include 文件在 <code>/usr/include/security/</code> 目录下</p></section>
<section><h1>0x2 开发 PAM 认证模块<a href="#0x2-开发-pam-认证模块"><span>#</span></a></h1><p>首先在 Go 中引入 C 的库， Go 是在 <code>import "C"</code> 上方使用注释的方式引入 C 的内容</p><p>注意 <code>import "C"</code> 上方不能有空行</p><p><code>#cgo LDFLAGS: -lpam</code> 是 <code>CGO</code> 的命令，<code>LDFLAGS: -lpam</code> 是表示链接 PAM 静态库</p><p><code>typedef const char cchar_t;</code> 是将 <code>cchar_t</code> 自定义为 <code>const char</code> 关键字，因为后面讲 C 转写成 GO 的时候 <code>const xx</code> 无法转写，因此需要提前定义一个关键字</p><p><code>#include "pam_prompt_wrapper.h"</code> 是引入一个本地自定义的库，后面会后详解</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/*</span></div></div><div><div><div>2</div></div><div><span>#cgo LDFLAGS: -lpam</span></div></div><div><div><div>3</div></div><div><span>#include &lt;stdio.h&gt;</span></div></div><div><div><div>4</div></div><div><span>#include &lt;stdlib.h&gt;</span></div></div><div><div><div>5</div></div><div><span>#include &lt;security/pam_appl.h&gt;</span></div></div><div><div><div>6</div></div><div><span>#include &lt;security/pam_modules.h&gt;</span></div></div><div><div><div>7</div></div><div><span>#include &lt;security/pam_ext.h&gt;</span></div></div><div><div><div>8</div></div><div><span>#include "pam_prompt_wrapper.h"</span></div></div><div><div><div>9</div></div><div><span>typedef const char cchar_t;</span></div></div><div><div><div>10</div></div><div><span>*/</span></div></div><div><div><div>11</div></div><div><span>import</span><span> </span><span>"C"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h2>函数说明<a href="#函数说明"><span>#</span></a></h2><p><code>pam_sm_authenticate</code>是认证逻辑的接口函数，也是认证的核心，函数定义在<code>pam_modules.h</code>里</p><p><em>接口函数是需要开发人员自己实现的函数，在函数内可以实现各种自定义的功能</em></p><p>函数签名为</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>pam_sm_authenticate</span><span>(</span><span>pam_handle_t</span><span> </span><span>*</span><span><span>pamh</span><span>,</span><span> </span></span><span>int</span><span><span> </span><span>flags</span><span>,</span></span></div></div><div><div><div>2</div></div><div><span>                        </span><span>int</span><span><span> </span><span>argc</span><span>,</span><span> </span></span><span>const</span><span> </span><span>char</span><span> </span><span>**</span><span><span>argv</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用 Go 实现，因为这个函数是要被外部调用的，因此需要在上方添加 <code>//export</code> 的注释，<code>CGO</code> 转写成 C 的时候会转成 <code>extern</code> 关键字</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//export pam_sm_authenticate</span></div></div><div><div><div>2</div></div><div><span>func</span><span> </span><span>pam_sm_authenticate</span><span><span>(</span><span>pamh</span><span> </span><span>*</span></span><span>C</span><span>.</span><span>pam_handle_t</span><span><span>, </span><span>flags</span><span> </span></span><span>C</span><span>.</span><span>int</span><span><span>, </span><span>argc</span><span> </span></span><span>C</span><span>.</span><span>int</span><span><span>, </span><span>argv</span><span> </span><span>**</span></span><span>C</span><span>.</span><span>cchar_t</span><span>) </span><span>C</span><span>.</span><span>int</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>return</span><span> </span><span>C</span><span>.</span><span>PAM_SUCCESS</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>pam_sm_acct_mgmt</code>是用户识别管理接口函数，用户判断用户否有权限，ssh登录中需要，函数定义也在<code>pam_modules.h</code>里，函数签名为</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>pam_sm_acct_mgmt</span><span>(</span><span>pam_handle_t</span><span> </span><span>*</span><span><span>pamh</span><span>,</span><span> </span></span><span>int</span><span><span> </span><span>flags</span><span>,</span><span> </span></span><span>int</span><span><span> </span><span>argc</span><span>,</span></span></div></div><div><div><div>2</div></div><div><span>                                </span><span>const</span><span> </span><span>char</span><span> </span><span>**</span><span><span>argv</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用 Go 实现</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//export pam_sm_acct_mgmt</span></div></div><div><div><div>2</div></div><div><span>func</span><span> </span><span>pam_sm_acct_mgmt</span><span><span>(</span><span>pamh</span><span> </span><span>*</span></span><span>C</span><span>.</span><span>pam_handle_t</span><span><span>, </span><span>flags</span><span> </span></span><span>C</span><span>.</span><span>int</span><span><span>, </span><span>argc</span><span> </span></span><span>C</span><span>.</span><span>int</span><span><span>, </span><span>argv</span><span> </span><span>**</span></span><span>C</span><span>.</span><span>cchar_t</span><span>) </span><span>C</span><span>.</span><span>int</span><span> {</span></div></div><div><div><div>3</div></div><div><span>  </span><span>return</span><span> </span><span>C</span><span>.</span><span>PAM_SUCCESS</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>pam_prompt</code>是认证过程中用于交互的函数，改函数直接调用，函数定义在 <code>pam_ext.h</code> 中，函数签名为</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>extern</span><span> </span><span>int</span><span> </span><span>PAM_FORMAT</span><span><span>((</span><span>printf</span><span>,</span><span> </span></span><span>4</span><span><span>,</span><span> </span></span><span>5</span><span>)) </span><span>PAM_NONNULL</span><span>((</span><span>1</span><span>,</span><span>4</span><span>))</span></div></div><div><div><div>2</div></div><div><span>pam_prompt</span><span><span> </span><span>(</span></span><span>pam_handle_t</span><span> </span><span>*</span><span><span>pamh</span><span>,</span><span> </span></span><span>int</span><span><span> </span><span>style</span><span>,</span><span> </span></span><span>char</span><span> </span><span>**</span><span><span>response</span><span>,</span></span></div></div><div><div><div>3</div></div><div><span>      </span><span>const</span><span> </span><span>char</span><span> </span><span>*</span><span><span>fmt</span><span>,</span><span> ...</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><strong>注意</strong> 该函数中带有 <code>...</code> 表示可以接受可变参数，而 <code>CGO</code> 中则不支持调用可变参数函数。因此需要使用 C 将该函数简单包装成一个固定参数的函数</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>int</span><span> </span><span>pam_prompt_wrapper</span><span><span> </span><span>(</span></span><span>pam_handle_t</span><span> </span><span>*</span><span><span>pamh</span><span>,</span><span> </span></span><span>int</span><span><span> </span><span>style</span><span>,</span><span> </span></span><span>char</span><span> </span><span>**</span><span><span>response</span><span>,</span></span><span>const</span><span> </span><span>char</span><span> </span><span>*</span><span><span>str</span><span>) {</span></span></div></div><div><div><div>2</div></div><div><span>  </span><span>return</span><span> </span><span>pam_prompt</span><span>(pamh, style, response, </span><span>"</span><span>%s</span><span>"</span><span>, str)</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>并且该函数要额外使用 C 文件存储，并在 Go 中引入</p></section><section><h2>代码文件<a href="#代码文件"><span>#</span></a></h2><p>pam_prompt_wrapper.h</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;security/pam_appl.h&gt;</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>int</span><span> </span><span>pam_prompt_wrapper</span><span>(</span><span>pam_handle_t</span><span> </span><span>*</span><span><span>pamh</span><span>,</span><span> </span></span><span>int</span><span><span> </span><span>style</span><span>,</span><span> </span></span><span>char</span><span> </span><span>**</span><span><span>response</span><span>,</span><span> </span></span><span>const</span><span> </span><span>char</span><span> </span><span>*</span><span><span>str</span><span>);</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>pam_prompt_wrapper.c</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#include</span><span> </span><span>&lt;security/pam_appl.h&gt;</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;security/pam_ext.h&gt;</span></div></div><div><div><div>3</div></div><div><span>#include</span><span> </span><span>&lt;security/pam_modules.h&gt;</span></div></div><div><div><div>4</div></div><div><span>#include</span><span> </span><span>&lt;stdarg.h&gt;</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>int</span><span> </span><span>pam_prompt_wrapper</span><span>(</span><span>pam_handle_t</span><span> </span><span>*</span><span><span>pamh</span><span>,</span><span> </span></span><span>int</span><span><span> </span><span>style</span><span>,</span><span> </span></span><span>char</span><span> </span><span>**</span><span><span>response</span><span>,</span><span> </span></span><span>const</span><span> </span><span>char</span><span> </span><span>*</span><span><span>str</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span> </span><span>pam_prompt</span><span>(pamh, style, response, </span><span>"</span><span>%s</span><span>"</span><span>, fmt);</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>main.go</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>main</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>/*</span></div></div><div><div><div>4</div></div><div><span>#cgo LDFLAGS: -lpam</span></div></div><div><div><div>5</div></div><div><span>#include &lt;stdio.h&gt;</span></div></div><div><div><div>6</div></div><div><span>#include &lt;stdlib.h&gt;</span></div></div><div><div><div>7</div></div><div><span>#include &lt;security/pam_appl.h&gt;</span></div></div><div><div><div>8</div></div><div><span>#include &lt;security/pam_modules.h&gt;</span></div></div><div><div><div>9</div></div><div><span>#include &lt;security/pam_ext.h&gt;</span></div></div><div><div><div>10</div></div><div><span>#include "pam_prompt_wrapper.h"</span></div></div><div><div><div>11</div></div><div><span>typedef const char cchar_t;</span></div></div><div><div><div>12</div></div><div><span>*/</span></div></div><div><div><div>13</div></div><div><span>import</span><span> </span><span>"C"</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>import</span><span> (</span></div></div><div><div><div>16</div></div><div><span>    </span><span>"fmt"</span></div></div><div><div><div>17</div></div><div><span>    </span><span>"os"</span></div></div><div><div><div>18</div></div><div><span>    </span><span>"unsafe"</span></div></div><div><div><div>19</div></div><div><span>)</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>//export pam_sm_authenticate</span></div></div><div><div><div>22</div></div><div><span>func</span><span> </span><span>pam_sm_authenticate</span><span><span>(</span><span>pamh</span><span> </span><span>*</span></span><span>C</span><span>.</span><span>pam_handle_t</span><span><span>, </span><span>flags</span><span> </span></span><span>C</span><span>.</span><span>int</span><span><span>, </span><span>argc</span><span> </span></span><span>C</span><span>.</span><span>int</span><span><span>, </span><span>argv</span><span> </span><span>**</span></span><span>C</span><span>.</span><span>cchar_t</span><span>) </span><span>C</span><span>.</span><span>int</span><span> {</span></div></div><div><div><div>23</div></div><div><span>    </span><span>// 实现认证功能</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>    </span><span>// 例如：</span></div></div><div><div><div>26</div></div><div><span>    </span><span>// 认证时会显示 input &gt;</span></div></div><div><div><div>27</div></div><div><span>    </span><span>// 输入 123 后认证成功，否则失败</span></div></div><div><div><div>28</div></div><div><span>    </span><span>a</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>qa</span><span>(</span><span>pamh</span><span>, </span><span>false</span><span>, </span><span>"input &gt;"</span><span>)</span></div></div><div><div><div>29</div></div><div><span>    </span><span>if</span><span> </span><span>a</span><span><span> </span><span>==</span><span> </span></span><span>"123"</span><span> {</span></div></div><div><div><div>30</div></div><div><span>        </span><span>return</span><span> </span><span>C</span><span>.</span><span>PAM_SUCCESS</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>    </span><span>return</span><span> </span><span>C</span><span>.</span><span>PAM_AUTH_ERR</span></div></div><div><div><div>34</div></div><div><span>}</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>//export pam_sm_acct_mgmt</span></div></div><div><div><div>37</div></div><div><span>func</span><span> </span><span>pam_sm_acct_mgmt</span><span><span>(</span><span>pamh</span><span> </span><span>*</span></span><span>C</span><span>.</span><span>pam_handle_t</span><span><span>, </span><span>flags</span><span> </span></span><span>C</span><span>.</span><span>int</span><span><span>, </span><span>argc</span><span> </span></span><span>C</span><span>.</span><span>int</span><span><span>, </span><span>argv</span><span> </span><span>**</span></span><span>C</span><span>.</span><span>cchar_t</span><span>) </span><span>C</span><span>.</span><span>int</span><span> {</span></div></div><div><div><div>38</div></div><div><span>    </span><span>// 这里直接返回成功，也可以根据自己需求添加更多功能</span></div></div><div><div><div>39</div></div><div><span>    </span><span>return</span><span> </span><span>C</span><span>.</span><span>PAM_SUCCESS</span></div></div><div><div><div>40</div></div><div><span>}</span></div></div><div><div><div>41</div></div><div>
</div></div><div><div><div>42</div></div><div><span>// 简单封装了交互函数</span></div></div><div><div><div>43</div></div><div><span>func</span><span> </span><span>qa</span><span><span>(</span><span>pamh</span><span> </span><span>*</span></span><span>C</span><span>.</span><span>pam_handle_t</span><span><span>, </span><span>echo</span><span> </span></span><span>bool</span><span><span>, </span><span>query</span><span> </span></span><span>string</span><span>) (</span><span>string</span><span>, </span><span>C</span><span>.</span><span>int</span><span>) {</span></div></div><div><div><div>44</div></div><div><span>    </span><span>var</span><span> </span><span>f</span><span> </span><span>C</span><span>.</span><span>int</span></div></div><div><div><div>45</div></div><div><span>    </span><span>f</span><span><span> </span><span>=</span><span> </span></span><span>C</span><span>.</span><span>PAM_PROMPT_ECHO_OFF</span></div></div><div><div><div>46</div></div><div><span>    </span><span>if</span><span> </span><span>echo</span><span> {</span></div></div><div><div><div>47</div></div><div><span>        </span><span>f</span><span><span> </span><span>=</span><span> </span></span><span>C</span><span>.</span><span>PAM_PROMPT_ECHO_ON</span></div></div><div><div><div>48</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>49</div></div><div><span>    </span><span>input</span><span><span> </span><span>:=</span><span> </span></span><span>C</span><span>.</span><span>CString</span><span>(</span><span>""</span><span>)</span></div></div><div><div><div>50</div></div><div><span>    </span><span>defer</span><span> </span><span>C</span><span>.</span><span>free</span><span>(</span><span>unsafe</span><span>.</span><span>Pointer</span><span>(</span><span>input</span><span>))</span></div></div><div><div><div>51</div></div><div><span>    </span><span>prompt</span><span><span> </span><span>:=</span><span> </span></span><span>C</span><span>.</span><span>CString</span><span>(</span><span>query</span><span>)</span></div></div><div><div><div>52</div></div><div><span>    </span><span>defer</span><span> </span><span>C</span><span>.</span><span>free</span><span>(</span><span>unsafe</span><span>.</span><span>Pointer</span><span>(</span><span>prompt</span><span>))</span></div></div><div><div><div>53</div></div><div><span>    </span><span>code</span><span><span> </span><span>:=</span><span> </span></span><span>C</span><span>.</span><span>pam_prompt_wrapper</span><span>(</span><span>pamh</span><span>, </span><span>f</span><span><span>, </span><span>&amp;</span></span><span>input</span><span>, </span><span>prompt</span><span>)</span></div></div><div><div><div>54</div></div><div><span>    </span><span>return</span><span> </span><span>C</span><span>.</span><span>GoString</span><span>(</span><span>input</span><span>), </span><span>code</span></div></div><div><div><div>55</div></div><div><span>}</span></div></div><div><div><div>56</div></div><div>
</div></div><div><div><div>57</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>58</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>编译<a href="#编译"><span>#</span></a></h2><p>需要将 Go 编译成 C 的共享库</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>go</span><span> </span><span>build</span><span> </span><span>-buildmode=c-shared</span><span> </span><span>-o</span><span> </span><span>pam_example.so</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>0x3 使用<a href="#0x3-使用"><span>#</span></a></h1><p>需要将模块放置到指定目录</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>cp</span><span> </span><span>pam_example.so</span><span> </span><span>/lib/x86_64-linux-gnu/security</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>然后启动，这里展示在 ssh 登录验证中使用我们的模块</p><p>首先编辑 <code>/etc/ssh/sshd_config</code> ，修改 <code>ChallengeResponseAuthentication</code> 或 <code>KbdInteractiveAuthentication </code>选项的值将其设为 <code>yes</code></p><p>重启 <code>sshd</code> 服务 <code>sudo service sshd restart</code></p><p>编辑 <code>/etc/pam.d/sshd</code> ，在文件添加 <code>auth required pam_example.so</code></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/268/</id>
      <title type="text">【Linux】使用cryptsetup进行luks加密</title>
      <published>2023-09-19T09:38:00.000Z</published>
      <updated>2023-09-19T09:39:19.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/268/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><blockquote><p>LUKS （Linux Unified Key Setup）是 Linux 硬盘加密的标准。 通过提供标准的磁盘格式，它不仅可以促进发行版之间的兼容性，还可以提供对多个用户密码的安全管理。 与现有解决方案相比，LUKS 将所有必要的设置信息存储在分区信息首部中，使用户能够无缝传输或迁移其数据。</p></blockquote></section>
<section><h1>0x01 准备<a href="#0x01-准备"><span>#</span></a></h1><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>cryptsetup</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02 使用<a href="#0x02-使用"><span>#</span></a></h1><section><h2>加密磁盘分区<a href="#加密磁盘分区"><span>#</span></a></h2><p>假设现在有磁盘分区 <code>/dev/sdb2</code></p><ol>
<li>格式化磁盘分区为luks</li>
</ol><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>cryptsetup</span><span> </span><span>luksFormat</span><span> </span><span>/dev/sdb2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输入大写<code>YES</code>
输入两次密码</p><p>这个时候会对磁盘分区进行全盘覆写，所以速度会比较慢</p><p>使用密钥文件（可选）：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>dd</span><span> </span><span>if=/dev/random</span><span> </span><span>of=keyfile</span><span> </span><span>bs=1K</span><span> </span><span>count=</span><span>16</span><span>  </span><span># 创建一个16k密钥文件，count可以大一点</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>cryptsetup</span><span> </span><span>luksAddKey</span><span> </span><span>/dev/sdb2</span><span> </span><span>keyfile</span><span> </span><span># 使用密钥文件加密</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>映射加密分区</li>
</ol><p>映射加密分区到<code>jmsdb2</code>，实际上是将加密分区映射到linux逻辑分区<code>/dev/mapper/jmsdb2</code>中</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>cryptsetup</span><span> </span><span>luksOpen</span><span> </span><span>/dev/sdb2</span><span> </span><span>jmsdb2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>格式化加密分区</li>
</ol><p>之前在<code>1</code>中的格式化是将加密的物理分区格式化为luks，这个时候还需要对加密的逻辑分区格式化为常见的文件系统才可以使用</p><p>我这里示例选用<code>ext4</code></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>mkfs.ext4</span><span> </span><span>/dev/mapper/jmsdb2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>结构：</span></div></div><div><div><div>2</div></div><div><span>┌────────┐</span></div></div><div><div><div>3</div></div><div><span>│  luks  │</span></div></div><div><div><div>4</div></div><div><span>│┌──────┐│</span></div></div><div><div><div>5</div></div><div><span>││ ext4 ││</span></div></div><div><div><div>6</div></div><div><span>│└──────┘│</span></div></div><div><div><div>7</div></div><div><span>└────────┘</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>挂载分区</li>
</ol><p>为了正常使用需要将逻辑分区挂载出来作为一个普通目录进行读写
我这挂在到<code>/mnt/jmsdb2</code></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># sudo mkdir /mnt/jmsdb2 # 如果有创建/mnt/jmsdb2可以跳过这一步</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>mount</span><span> </span><span>/dev/mapper/jmsdb2</span><span> </span><span>/mnt/jmsdb2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>至此可以正常在 <code>/mnt/jmsdb2</code> 写数据了</p><ol>
<li>卸载分区</li>
</ol><p>如果不想使用了可以对分区进行卸载</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>umont</span><span> </span><span>/mnt/jmsdb2</span><span>  </span><span># 卸载逻辑分区</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>cryptsetup</span><span> </span><span>luksClose</span><span> </span><span>jmsdb2</span><span>  </span><span>#关闭加密分区</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>创建加密文件<a href="#创建加密文件"><span>#</span></a></h2><p>如果不想对整个分区加密，那可以在普通磁盘里创建一个加密文件，这样的好处是可以随意移动加密文件</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>dd</span><span> </span><span>if=/dev/zero</span><span> </span><span>of=/home/rehtt/cryptfile</span><span> </span><span>bs=1M</span><span> </span><span>count=</span><span>1024</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里在<code>/home/rehtt/</code>下创建了一个名为<code>cryptfile</code>的文件，块大小(<code>bs</code>)为1M，共有(<code>count</code>)1024个块，也就是1024M</p><p>将上面的<code>加密磁盘分区</code>中的<code>/dev/sdb2</code>替换为<code>/home/rehtt/cryptfile</code>再跟着步骤即可</p></section><section><h2>开机自动挂载<a href="#开机自动挂载"><span>#</span></a></h2><p>首先要使用密钥加密（上述第1步）</p><p>编辑<code>/etc/crypttab</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># &lt;target name&gt; &lt;source device&gt;    &lt;key file&gt;      &lt;options&gt;</span></div></div><div><div><div>2</div></div><div><span>jmsdb2 /dev/sdb2 /home/rehtt/keyfile luks</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编辑<code>/etc/fstab</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/dev/mapper/jmsdb2 /mnt/jmsdb2 ext4  0 0</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/267/</id>
      <title type="text">【脚本】修改wireguard端口</title>
      <published>2023-09-12T09:03:27.000Z</published>
      <updated>2023-09-12T09:03:27.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/267/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/bash</span></div></div><div><div><div>2</div></div><div><span>PORT</span><span>=</span><span>0</span></div></div><div><div><div>3</div></div><div><span>#判断当前端口是否被占用，没被占用返回0，反之1</span></div></div><div><div><div>4</div></div><div><span>function</span><span> </span><span>Listening</span><span> {</span></div></div><div><div><div>5</div></div><div><span>   </span><span>TCPListeningnum</span><span>=</span><span>`</span><span>netstat</span><span> </span><span>-an</span><span> </span><span>|</span><span> </span><span>grep</span><span> ":</span><span>$1</span><span> " </span><span>|</span><span> </span><span>awk</span><span> '$1 == "tcp" &amp;&amp; $NF == "LISTEN" {print $0}' </span><span>|</span><span> </span><span>wc</span><span> </span><span>-l</span><span>`</span></div></div><div><div><div>6</div></div><div><span>   </span><span>UDPListeningnum</span><span>=</span><span>`</span><span>netstat</span><span> </span><span>-an</span><span> </span><span>|</span><span> </span><span>grep</span><span> ":</span><span>$1</span><span> " </span><span>|</span><span> </span><span>awk</span><span> '$1 == "udp" &amp;&amp; $NF == "0.0.0.0:*" {print $0}' </span><span>|</span><span> </span><span>wc</span><span> </span><span>-l</span><span>`</span></div></div><div><div><div>7</div></div><div><span><span>   </span></span><span>(( </span><span>Listeningnum</span><span><span> </span><span>=</span><span> </span></span><span>TCPListeningnum</span><span><span> </span><span>+</span><span> </span></span><span>UDPListeningnum</span><span> ))</span></div></div><div><div><div>8</div></div><div><span>   </span><span>if</span><span> [ </span><span>$Listeningnum</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span> ]; </span><span>then</span></div></div><div><div><div>9</div></div><div><span>       </span><span>echo</span><span> </span><span>"0"</span></div></div><div><div><div>10</div></div><div><span>   </span><span>else</span></div></div><div><div><div>11</div></div><div><span>       </span><span>echo</span><span> </span><span>"1"</span></div></div><div><div><div>12</div></div><div><span>   </span><span>fi</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>#指定区间随机数</span></div></div><div><div><div>16</div></div><div><span>function</span><span> </span><span>random_range</span><span> {</span></div></div><div><div><div>17</div></div><div><span>   </span><span>shuf</span><span> </span><span>-i</span><span><span> </span><span>$1</span></span><span>-</span><span><span>$2</span><span> </span></span><span>-n1</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>#得到随机端口</span></div></div><div><div><div>21</div></div><div><span>function</span><span> </span><span>get_random_port</span><span> {</span></div></div><div><div><div>22</div></div><div><span>   </span><span>templ</span><span>=</span><span>0</span></div></div><div><div><div>23</div></div><div><span>   </span><span>while</span><span> [ </span><span>$PORT</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span> ]; </span><span>do</span></div></div><div><div><div>24</div></div><div><span>       </span><span>temp1</span><span>=</span><span>`</span><span>random_range</span><span> </span><span>$1</span><span> </span><span>$2</span><span>`</span></div></div><div><div><div>25</div></div><div><span>       </span><span>if</span><span> [ </span><span>`</span><span>Listening</span><span> </span><span>$temp1</span><span>`</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span> ] ; </span><span>then</span></div></div><div><div><div>26</div></div><div><span>              </span><span>PORT</span><span>=</span><span>$temp1</span></div></div><div><div><div>27</div></div><div><span>       </span><span>fi</span></div></div><div><div><div>28</div></div><div><span>   </span><span>done</span></div></div><div><div><div>29</div></div><div><span>}</span></div></div><div><div><div>30</div></div><div><span>get_random_port</span><span> </span><span>9000</span><span> </span><span>10000</span><span>  </span><span># 9000 ~ 10000 端口</span></div></div><div><div><div>31</div></div><div><span>wg</span><span> </span><span>set</span><span> </span><span>wg0</span><span> </span><span>listen-port</span><span> </span><span>$PORT</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/266/</id>
      <title type="text">【脚本】wireguard配合socat转发端口</title>
      <published>2023-09-12T09:01:11.000Z</published>
      <updated>2023-09-12T09:01:11.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/266/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x0<a href="#0x0"><span>#</span></a></h1><p>之前是使用<code>iptables</code>进行端口转发，但是<code>iptables</code>规则较为麻烦，所以就使用<code>socat</code>进行转发</p></section>
<section><h1>0x1<a href="#0x1"><span>#</span></a></h1><p>首先，在<code>PostUp</code>选项中启动socat时，将socat的进程ID（PID）保存到一个文件中。然后，在<code>PostDown</code>选项中读取该文件，并使用保
存的PID来关闭socat进程。</p><p>示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>[Interface]</span></div></div><div><div><div>2</div></div><div><span>PrivateKey</span><span><span> </span><span>=</span><span> &lt;PrivateKey&gt;</span></span></div></div><div><div><div>3</div></div><div><span>Address</span><span><span> </span><span>=</span><span> &lt;IPAddress&gt;</span></span></div></div><div><div><div>4</div></div><div><span>...</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>PostUp</span><span><span> </span><span>=</span><span> /usr/bin/python3 /root/socat.py --range </span></span><span>'10.13.13.0/24'</span><span> add 8080 192.168.137.1:8000</span></div></div><div><div><div>7</div></div><div><span># -d -d可以输出详细的调试信息</span></div></div><div><div><div>8</div></div><div><span>#PostUp = socat -d -d TCP-LISTEN:8080,range=10.13.13.0/24,fork,reuseaddr TCP:192.168.137.1:8000 &amp; echo $! &gt; /home/rehtt/8080_socat.pid</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span># 在停止 WireGuard 接口之后执行操作</span></div></div><div><div><div>11</div></div><div><span>PostDown</span><span><span> </span><span>=</span><span> /usr/bin/python3 /root/socat.py --range </span></span><span>'10.13.13.0/24'</span><span> del 8080 192.168.137.1:8000</span></div></div><div><div><div>12</div></div><div><span>#PostDown = kill $(cat /home/rehtt/8080_socat.pid) &amp;&amp; rm -f /home/rehtt/8080_socat.pid</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在示例中，使用<code>/home/rehtt/8080_socat.pid</code>文件来存储socat进程的PID，并在<code>PostUp</code>选项中使用<code>echo $!</code>将其写入文件。然后，在<code>PostDown</code>选项中，我们使用<code>kill $(cat /home/rehtt/8080_socat.pid)</code>命令来杀死socat进程，并使用<code>rm -f /home/rehtt/8080_socat.pid</code>命令删除PID文件</p><p>使用封装好的脚本处理</p><p><a href="https://github.com/Rehtt/socat_tools" target="_blank">脚本链接</a></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/265/</id>
      <title type="text">【脚本】使用Python对socat简单的控制</title>
      <published>2023-09-12T08:11:00.000Z</published>
      <updated>2023-09-12T09:41:19.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/265/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>Use<a href="#use"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>python3</span><span> </span><span>socat.py</span><span> </span><span>add</span><span> </span><span>8080</span><span> </span><span>192.168.137.1:8000</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>python3</span><span> </span><span>socat.py</span><span> </span><span>del</span><span> </span><span>8080</span><span> </span><span>192.168.137.1:8000</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>python3</span><span> </span><span>socat.py</span><span> </span><span>list</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>python3</span><span> </span><span>socat.py</span><span> </span><span>-h</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>Code<a href="#code"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> argparse</span></div></div><div><div><div>2</div></div><div><span>import</span><span> os</span></div></div><div><div><div>3</div></div><div><span>import</span><span> re</span></div></div><div><div><div>4</div></div><div><span>import</span><span> subprocess</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>def</span><span> </span><span>get_dict</span><span>(</span><span>d</span><span>,</span><span><span> </span><span>key</span></span><span>):</span></div></div><div><div><div>8</div></div><div><span>    </span><span>if</span><span> </span><span>type</span><span>(d) </span><span>is</span><span> </span><span>not</span><span> </span><span>dict</span><span>:</span></div></div><div><div><div>9</div></div><div><span>        </span><span>raise</span><span> </span><span>Exception</span><span>(</span><span>'not dict'</span><span>)</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>dd </span><span>=</span><span> d.</span><span>get</span><span>(key)</span></div></div><div><div><div>11</div></div><div><span>    </span><span>if</span><span> dd </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>12</div></div><div><span>        </span><span>return</span><span> </span><span>''</span></div></div><div><div><div>13</div></div><div><span>    </span><span>return</span><span> dd</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>def</span><span> </span><span>socat_port</span><span>():</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>output </span><span>=</span><span> subprocess.</span><span>check_output</span><span>(</span><span>"ps aux | grep socat"</span><span>, </span><span>shell</span><span>=</span><span>True</span><span>, </span><span>universal_newlines</span><span>=</span><span>True</span><span>)</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>out </span><span>=</span><span> []</span></div></div><div><div><div>20</div></div><div><span>    </span><span>for</span><span> line </span><span>in</span><span><span> output.</span><span>splitlines</span><span>():</span></span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>match </span><span>=</span><span> re.</span><span>compile</span><span>(</span><span>r</span><span><span>'socat </span><span>(</span><span>\w</span></span><span>+</span><span><span>)</span><span>-LISTEN:</span><span>(</span><span>\d</span></span><span>+</span><span><span>)</span><span>'</span></span><span><span>).</span><span>search</span><span>(line)</span></span></div></div><div><div><div>22</div></div><div><span>        </span><span>if</span><span> </span><span>not</span><span> match:</span></div></div><div><div><div>23</div></div><div><span>            </span><span>continue</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>data </span><span>=</span><span> {</span></div></div><div><div><div>25</div></div><div><span>            </span><span>'listen_protocol'</span><span><span>: match.</span><span>group</span><span>(</span></span><span>1</span><span><span>).</span><span>upper</span><span>(),</span></span></div></div><div><div><div>26</div></div><div><span>            </span><span>'listen_port'</span><span><span>: match.</span><span>group</span><span>(</span></span><span>2</span><span>)</span></div></div><div><div><div>27</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>match </span><span>=</span><span> re.</span><span>compile</span><span>(</span><span>r</span><span><span>'</span><span>(</span><span>\w</span></span><span>+</span><span><span>)</span><span>:</span><span>(</span></span><span><span>[</span><span>^</span></span><span>:</span><span>]+</span><span><span>)</span><span>:</span><span>(</span><span>\d</span></span><span>+</span><span><span>)</span><span>$'</span></span><span><span>).</span><span>search</span><span>(line)</span></span></div></div><div><div><div>30</div></div><div><span>        </span><span>if</span><span> </span><span>not</span><span> match:</span></div></div><div><div><div>31</div></div><div><span>            </span><span>continue</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>data[</span><span>'remote_protocol'</span><span><span>] </span><span>=</span><span> match.</span><span>group</span><span>(</span></span><span>1</span><span><span>).</span><span>upper</span><span>()</span></span></div></div><div><div><div>33</div></div><div><span><span>        </span></span><span>data[</span><span>'remote_host'</span><span><span>] </span><span>=</span><span> match.</span><span>group</span><span>(</span></span><span>2</span><span>)</span></div></div><div><div><div>34</div></div><div><span><span>        </span></span><span>data[</span><span>'remote_port'</span><span><span>] </span><span>=</span><span> match.</span><span>group</span><span>(</span></span><span>3</span><span>)</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span><span>        </span></span><span>match </span><span>=</span><span> re.</span><span>compile</span><span>(</span><span>r</span><span><span>'</span><span>(</span><span>\d</span></span><span>+</span><span><span>)</span><span>'</span></span><span><span>).</span><span>search</span><span>(line)</span></span></div></div><div><div><div>37</div></div><div><span>        </span><span>if</span><span> </span><span>not</span><span> match:</span></div></div><div><div><div>38</div></div><div><span>            </span><span>continue</span></div></div><div><div><div>39</div></div><div><span><span>        </span></span><span>data[</span><span>'listen_pid'</span><span><span>] </span><span>=</span><span> match.</span><span>group</span><span>(</span></span><span>1</span><span>)</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span><span>        </span></span><span>match </span><span>=</span><span> re.</span><span>compile</span><span>(</span><span>r</span><span><span>',range=</span><span>(</span></span><span><span>[</span><span>^</span></span><span>,</span><span>]+</span><span><span>)</span><span>,'</span></span><span><span>).</span><span>search</span><span>(line)</span></span></div></div><div><div><div>42</div></div><div><span>        </span><span>if</span><span> match:</span></div></div><div><div><div>43</div></div><div><span><span>            </span></span><span>data[</span><span>'listen_range'</span><span><span>] </span><span>=</span><span> match.</span><span>group</span><span>(</span></span><span>1</span><span>)</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>match </span><span>=</span><span> re.</span><span>compile</span><span>(</span><span>r</span><span><span>',bind=</span><span>(</span></span><span><span>[</span><span>^</span></span><span>,</span><span>]+</span><span><span>)</span><span>,'</span></span><span><span>).</span><span>search</span><span>(line)</span></span></div></div><div><div><div>45</div></div><div><span>        </span><span>if</span><span> match:</span></div></div><div><div><div>46</div></div><div><span><span>            </span></span><span>data[</span><span>'listen_bind'</span><span><span>] </span><span>=</span><span> match.</span><span>group</span><span>(</span></span><span>1</span><span>)</span></div></div><div><div><div>47</div></div><div><span><span>        </span></span><span>out.</span><span>append</span><span>(data)</span></div></div><div><div><div>48</div></div><div>
</div></div><div><div><div>49</div></div><div><span>    </span><span>return</span><span> out</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div>
</div></div><div><div><div>52</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>'__main__'</span><span>:</span></div></div><div><div><div>53</div></div><div><span><span>    </span></span><span>parser </span><span>=</span><span> argparse.</span><span>ArgumentParser</span><span>()</span></div></div><div><div><div>54</div></div><div><span><span>    </span></span><span>parser.</span><span>add_argument</span><span>(</span><span>'-r'</span><span>, </span><span>'--range'</span><span>, </span><span>help</span><span>=</span><span>'监听网段范围，例如：192.168.1.0/24'</span><span>)</span></div></div><div><div><div>55</div></div><div><span><span>    </span></span><span>parser.</span><span>add_argument</span><span>(</span><span>'-b'</span><span>, </span><span>'--bind'</span><span>, </span><span>help</span><span>=</span><span>'绑定监听地址，例如：192.168.1.1'</span><span>)</span></div></div><div><div><div>56</div></div><div><span><span>    </span></span><span>parser.</span><span>add_argument</span><span>(</span><span>'-p'</span><span>, </span><span>'--protocol'</span><span>, </span><span>default</span><span>=</span><span>'all'</span><span>, </span><span>help</span><span>=</span><span>'[all | tcp | udp]'</span><span>)</span></div></div><div><div><div>57</div></div><div><span><span>    </span></span><span>parser.</span><span>add_argument</span><span>(</span><span>'positional'</span><span>, </span><span>nargs</span><span>=</span><span>'*'</span><span>,</span></div></div><div><div><div>58</div></div><div><span>                        </span><span>help</span><span>=</span><span>'&lt;add | del | list&gt; &lt;本地端口&gt; &lt;远程地址&gt;，例如：add 8000 192.168.1.2:8080'</span><span>)</span></div></div><div><div><div>59</div></div><div>
</div></div><div><div><div>60</div></div><div><span><span>    </span></span><span>args </span><span>=</span><span> parser.</span><span>parse_args</span><span>()</span></div></div><div><div><div>61</div></div><div>
</div></div><div><div><div>62</div></div><div><span>    </span><span>try</span><span>:</span></div></div><div><div><div>63</div></div><div><span><span>        </span></span><span>operation </span><span>=</span><span> args.positional[</span><span>0</span><span>]</span></div></div><div><div><div>64</div></div><div><span>        </span><span>if</span><span><span> operation </span><span>!=</span><span> </span></span><span>'list'</span><span>:</span></div></div><div><div><div>65</div></div><div><span>            </span><span>if</span><span> </span><span>len</span><span><span>(args.positional) </span><span>!=</span><span> </span></span><span>3</span><span>:</span></div></div><div><div><div>66</div></div><div><span>                </span><span>raise</span><span> </span><span>Exception</span><span>()</span></div></div><div><div><div>67</div></div><div>
</div></div><div><div><div>68</div></div><div><span><span>            </span></span><span>port </span><span>=</span><span> </span><span>int</span><span>(args.positional[</span><span>1</span><span>])</span></div></div><div><div><div>69</div></div><div><span><span>            </span></span><span>raddr </span><span>=</span><span> args.positional[</span><span>2</span><span>]</span></div></div><div><div><div>70</div></div><div>
</div></div><div><div><div>71</div></div><div><span>            </span><span>if</span><span> </span><span>not</span><span> </span><span>0</span><span><span> </span><span>&lt;</span><span> port </span><span>&lt;</span><span> </span></span><span>1</span><span><span> </span><span>&lt;&lt;</span><span> </span></span><span>16</span><span>:</span></div></div><div><div><div>72</div></div><div><span>                </span><span>print</span><span>(</span><span>'端口不正确'</span><span>)</span></div></div><div><div><div>73</div></div><div><span>                </span><span>exit</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>74</div></div><div><span>    </span><span>except</span><span>:</span></div></div><div><div><div>75</div></div><div><span><span>        </span></span><span>parser.</span><span>print_usage</span><span>()</span></div></div><div><div><div>76</div></div><div><span>        </span><span>exit</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>77</div></div><div>
</div></div><div><div><div>78</div></div><div><span>    </span><span>if</span><span><span> operation </span><span>==</span><span> </span></span><span>'add'</span><span>:</span></div></div><div><div><div>79</div></div><div><span><span>        </span></span><span>command </span><span>=</span><span> </span><span>'socat </span><span>{protocol}</span><span>-LISTEN:</span><span>{port}</span><span>,</span><span>{option}</span><span>fork,reuseaddr </span><span>{protocol}</span><span>:</span><span>{raddr}</span><span> &amp;'</span></div></div><div><div><div>80</div></div><div><span><span>        </span></span><span>option </span><span>=</span><span> </span><span>''</span></div></div><div><div><div>81</div></div><div><span>        </span><span>if</span><span> args.range </span><span>is</span><span> </span><span>not</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>82</div></div><div><span><span>            </span></span><span>option </span><span>+=</span><span> </span><span>'range=</span><span>%s</span><span>,'</span><span><span> </span><span>%</span><span> args.range</span></span></div></div><div><div><div>83</div></div><div><span>        </span><span>if</span><span> args.bind </span><span>is</span><span> </span><span>not</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>84</div></div><div><span><span>            </span></span><span>option </span><span>+=</span><span> </span><span>'bind=</span><span>%s</span><span>,'</span><span><span> </span><span>%</span><span> args.bind</span></span></div></div><div><div><div>85</div></div><div>
</div></div><div><div><div>86</div></div><div><span><span>        </span></span><span>commands </span><span>=</span><span> []</span></div></div><div><div><div>87</div></div><div><span>        </span><span>if</span><span><span> args.protocol </span><span>==</span><span> </span></span><span>'all'</span><span>:</span></div></div><div><div><div>88</div></div><div><span><span>            </span></span><span>commands.</span><span>append</span><span>({</span><span>'protocol'</span><span>: </span><span>'TCP'</span><span>,</span></div></div><div><div><div>89</div></div><div><span>                             </span><span>'command'</span><span><span>: command.</span><span>format</span><span>(</span></span><span>protocol</span><span>=</span><span>'TCP'</span><span>, </span><span>port</span><span><span>=</span><span>port, </span></span><span>option</span><span><span>=</span><span>option, </span></span><span>raddr</span><span><span>=</span><span>raddr)})</span></span></div></div><div><div><div>90</div></div><div><span><span>            </span></span><span>commands.</span><span>append</span><span>({</span><span>'protocol'</span><span>: </span><span>'UDP'</span><span>,</span></div></div><div><div><div>91</div></div><div><span>                             </span><span>'command'</span><span><span>: command.</span><span>format</span><span>(</span></span><span>protocol</span><span>=</span><span>'UDP'</span><span>, </span><span>port</span><span><span>=</span><span>port, </span></span><span>option</span><span><span>=</span><span>option, </span></span><span>raddr</span><span><span>=</span><span>raddr)})</span></span></div></div><div><div><div>92</div></div><div><span>        </span><span>elif</span><span><span> args.protocol </span><span>==</span><span> </span></span><span>'tcp'</span><span>:</span></div></div><div><div><div>93</div></div><div><span><span>            </span></span><span>commands.</span><span>append</span><span>({</span><span>'protocol'</span><span>: </span><span>'TCP'</span><span>,</span></div></div><div><div><div>94</div></div><div><span>                             </span><span>'command'</span><span><span>: command.</span><span>format</span><span>(</span></span><span>protocol</span><span>=</span><span>'TCP'</span><span>, </span><span>port</span><span><span>=</span><span>port, </span></span><span>option</span><span><span>=</span><span>option, </span></span><span>raddr</span><span><span>=</span><span>raddr)})</span></span></div></div><div><div><div>95</div></div><div><span>        </span><span>elif</span><span><span> args.protocol </span><span>==</span><span> </span></span><span>'udp'</span><span>:</span></div></div><div><div><div>96</div></div><div><span><span>            </span></span><span>commands.</span><span>append</span><span>({</span><span>'protocol'</span><span>: </span><span>'UDP'</span><span>,</span></div></div><div><div><div>97</div></div><div><span>                             </span><span>'command'</span><span><span>: command.</span><span>format</span><span>(</span></span><span>protocol</span><span>=</span><span>'UDP'</span><span>, </span><span>port</span><span><span>=</span><span>port, </span></span><span>option</span><span><span>=</span><span>option, </span></span><span>raddr</span><span><span>=</span><span>raddr)})</span></span></div></div><div><div><div>98</div></div><div><span>        </span><span>list</span><span><span> </span><span>=</span><span> </span><span>socat_port</span><span>()</span></span></div></div><div><div><div>99</div></div><div><span>        </span><span>for</span><span> c </span><span>in</span><span> commands:</span></div></div><div><div><div>100</div></div><div><span><span>            </span></span><span>bk </span><span>=</span><span> </span><span>False</span></div></div><div><div><div>101</div></div><div><span>            </span><span>for</span><span> data </span><span>in</span><span> </span><span>list</span><span>:</span></div></div><div><div><div>102</div></div><div><span>                </span><span>if</span><span><span> data.</span><span>get</span><span>(</span></span><span>'listen_port'</span><span><span>) </span><span>==</span><span> </span></span><span>str</span><span><span>(c.</span><span>get</span><span>(</span></span><span>'port'</span><span>)) </span><span>and</span><span><span> data.</span><span>get</span><span>(</span></span><span>'listen_protocol'</span><span><span>) </span><span>==</span><span> c.</span><span>get</span><span>(</span></span></div></div><div><div><div>103</div></div><div><span>                        </span><span>'protocol'</span><span><span>).</span><span>upper</span><span>():</span></span></div></div><div><div><div>104</div></div><div><span><span>                    </span></span><span>bk </span><span>=</span><span> </span><span>True</span></div></div><div><div><div>105</div></div><div><span>                    </span><span>break</span></div></div><div><div><div>106</div></div><div><span>            </span><span>if</span><span> bk:</span></div></div><div><div><div>107</div></div><div><span>                </span><span>print</span><span>(</span><span>'</span><span>{protocol}</span><span> </span><span>{port}</span><span> 已被占用'</span><span><span>.</span><span>format</span><span>(</span></span><span>protocol</span><span><span>=</span><span>c.</span><span>get</span><span>(</span></span><span>'protocol'</span><span>), </span><span>port</span><span><span>=</span><span>c.</span><span>get</span><span>(</span></span><span>'port'</span><span>)))</span></div></div><div><div><div>108</div></div><div><span>                </span><span>continue</span></div></div><div><div><div>109</div></div><div><span><span>            </span></span><span>os.</span><span>system</span><span>(c.</span><span>get</span><span>(</span><span>'command'</span><span>))</span></div></div><div><div><div>110</div></div><div><span>    </span><span>elif</span><span><span> operation </span><span>==</span><span> </span></span><span>'del'</span><span>:</span></div></div><div><div><div>111</div></div><div><span>        </span><span>list</span><span><span> </span><span>=</span><span> </span><span>socat_port</span><span>()</span></span></div></div><div><div><div>112</div></div><div><span><span>        </span></span><span>command </span><span>=</span><span> </span><span>'kill </span><span>%s</span><span>'</span></div></div><div><div><div>113</div></div><div><span><span>        </span></span><span>commands </span><span>=</span><span> []</span></div></div><div><div><div>114</div></div><div><span>        </span><span>for</span><span> data </span><span>in</span><span> </span><span>list</span><span>:</span></div></div><div><div><div>115</div></div><div><span>            </span><span>if</span><span><span> args.protocol </span><span>!=</span><span> </span></span><span>'all'</span><span> </span><span>and</span><span><span> data.</span><span>get</span><span>(</span></span><span>'listen_protocol'</span><span><span>) </span><span>!=</span><span> args.protocol:</span></span></div></div><div><div><div>116</div></div><div><span>                </span><span>continue</span></div></div><div><div><div>117</div></div><div><span>            </span><span>if</span><span> </span><span>str</span><span><span>(port) </span><span>!=</span><span> data.</span><span>get</span><span>(</span></span><span>'listen_port'</span><span>):</span></div></div><div><div><div>118</div></div><div><span>                </span><span>continue</span></div></div><div><div><div>119</div></div><div><span><span>            </span></span><span>commands.</span><span>append</span><span>(command </span><span>%</span><span> data.</span><span>get</span><span>(</span><span>'listen_pid'</span><span>))</span></div></div><div><div><div>120</div></div><div>
</div></div><div><div><div>121</div></div><div><span>        </span><span>for</span><span> c </span><span>in</span><span> commands:</span></div></div><div><div><div>122</div></div><div><span><span>            </span></span><span>os.</span><span>system</span><span>(c)</span></div></div><div><div><div>123</div></div><div><span>    </span><span>elif</span><span><span> operation </span><span>==</span><span> </span></span><span>'list'</span><span>:</span></div></div><div><div><div>124</div></div><div><span><span>        </span></span><span>layout </span><span>=</span><span> </span><span>'</span><span>{listen_protocol}</span><span>\t</span><span>{listen_port}</span><span>\t</span><span>{listen_bind}</span><span>\t</span><span>{listen_range}</span><span>\t</span><span>{remote}</span><span>'</span></div></div><div><div><div>125</div></div><div><span>        </span><span># print(layout.format(listen_protocol=''))</span></div></div><div><div><div>126</div></div><div><span>        </span><span>for</span><span> data </span><span>in</span><span><span> </span><span>socat_port</span><span>():</span></span></div></div><div><div><div>127</div></div><div><span>            </span><span>print</span><span><span>(layout.</span><span>format</span><span>(</span></span></div></div><div><div><div>128</div></div><div><span>                </span><span>listen_protocol</span><span><span>=</span><span>get_dict</span><span>(data, </span></span><span>'listen_protocol'</span><span>),</span></div></div><div><div><div>129</div></div><div><span>                </span><span>listen_port</span><span><span>=</span><span>get_dict</span><span>(data, </span></span><span>'listen_port'</span><span>),</span></div></div><div><div><div>130</div></div><div><span>                </span><span>listen_bind</span><span><span>=</span><span>get_dict</span><span>(data, </span></span><span>'listen_bind'</span><span>),</span></div></div><div><div><div>131</div></div><div><span>                </span><span>listen_range</span><span><span>=</span><span>get_dict</span><span>(data, </span></span><span>'listen_range'</span><span>),</span></div></div><div><div><div>132</div></div><div><span>                </span><span>remote</span><span>=</span><span>'</span><span>%s</span><span>:</span><span>%s</span><span>:</span><span>%s</span><span>'</span><span><span> </span><span>%</span><span> (</span></span></div></div><div><div><div>133</div></div><div><span><span>                    </span></span><span>get_dict</span><span>(data, </span><span>'remote_protocol'</span><span><span>), </span><span>get_dict</span><span>(data, </span></span><span>'remote_host'</span><span><span>), </span><span>get_dict</span><span>(data, </span></span><span>'remote_port'</span><span>)),</span></div></div><div><div><div>134</div></div><div><span><span>            </span></span><span>))</span></div></div><div><div><div>135</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>136</div></div><div><span>        </span><span>print</span><span>(</span><span>'参数不正确'</span><span>)</span></div></div><div><div><div>137</div></div><div><span><span>        </span></span><span>parser.</span><span>print_usage</span><span>()</span></div></div><div><div><div>138</div></div><div><span>        </span><span>exit</span><span>(</span><span>1</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/264/</id>
      <title type="text">【脚本】ADB调用摄像头拍照并处理图片</title>
      <published>2023-06-29T01:20:00.000Z</published>
      <updated>2023-06-30T08:59:43.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/264/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>需安装：jpegoptim</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/bash</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 预处理目录</span></div></div><div><div><div>4</div></div><div><span>pre_dir</span><span>=</span><span>/mnt/sda/cam/pre</span></div></div><div><div><div>5</div></div><div><span># 最终保存目录</span></div></div><div><div><div>6</div></div><div><span>dir</span><span>=</span><span>/mnt/sda/cam</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>mkdir</span><span> </span><span>$pre_dir</span><span> </span><span>2</span><span>&amp;&gt;1 &gt; /dev/null</span></div></div><div><div><div>9</div></div><div><span>mkdir</span><span> </span><span>$dir</span><span> </span><span>2</span><span>&amp;&gt;1 &gt; /dev/null</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span># 【可选】上报电池信息，用于自动化充电</span></div></div><div><div><div>12</div></div><div><span># adb shell dumpsys battery | grep -E 'level|AC' |</span></div></div><div><div><div>13</div></div><div><span>#     sed ':a;N;s/\n/,/g;ta' - |</span></div></div><div><div><div>14</div></div><div><span>#     sed 's/AC powered/AC/g' - |</span></div></div><div><div><div>15</div></div><div><span>#     sed 's/ //g' - |</span></div></div><div><div><div>16</div></div><div><span>#     sed 's/,/,"/g' - |</span></div></div><div><div><div>17</div></div><div><span>#     sed 's/:/":/g' - |</span></div></div><div><div><div>18</div></div><div><span>#     sed 's/^|&amp;/"/g' - |</span></div></div><div><div><div>19</div></div><div><span>#     sed 's/^/{"/g' - |</span></div></div><div><div><div>20</div></div><div><span>#     sed 's/$/}/g' - |</span></div></div><div><div><div>21</div></div><div><span>#     xargs -I value -o mosquitto_pub -t 'phone/battery/level' -h 192.168.31.110 -p 9883 -m 'value'</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>adb</span><span> </span><span>shell</span><span> </span><span>input</span><span> </span><span>keyevent</span><span> </span><span>26</span></div></div><div><div><div>25</div></div><div><span>sleep</span><span> </span><span>0.5</span></div></div><div><div><div>26</div></div><div><span>adb</span><span> </span><span>shell</span><span> </span><span>am</span><span> </span><span>start</span><span> </span><span>-a</span><span> </span><span>android.media.action.STILL_IMAGE_CAMERA</span></div></div><div><div><div>27</div></div><div><span>sleep</span><span> </span><span>0.5</span></div></div><div><div><div>28</div></div><div><span>adb</span><span> </span><span>shell</span><span> </span><span>input</span><span> </span><span>tap</span><span> </span><span>539</span><span> </span><span>900</span></div></div><div><div><div>29</div></div><div><span>sleep</span><span> </span><span>1</span></div></div><div><div><div>30</div></div><div><span>adb</span><span> </span><span>shell</span><span> </span><span>input</span><span> </span><span>keyevent</span><span> </span><span>27</span></div></div><div><div><div>31</div></div><div><span>sleep</span><span> </span><span>1</span></div></div><div><div><div>32</div></div><div><span>adb</span><span> </span><span>shell</span><span> </span><span>input</span><span> </span><span>keyevent</span><span> </span><span>4</span></div></div><div><div><div>33</div></div><div><span>adb</span><span> </span><span>shell</span><span> </span><span>input</span><span> </span><span>keyevent</span><span> </span><span>26</span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span>adb</span><span> </span><span>shell</span><span> </span><span>find</span><span> </span><span>/sdcard/DCIM/Camera</span><span> </span><span>-name</span><span> </span><span>"*.jpg"</span><span> | </span><span>xargs</span><span> </span><span>-o</span><span> </span><span>-I</span><span> </span><span>path</span><span> </span><span>adb</span><span> </span><span>pull</span><span> </span><span>path</span><span> </span><span>$pre_dir</span></div></div><div><div><div>36</div></div><div><span>adb</span><span> </span><span>shell</span><span> </span><span>rm</span><span> </span><span>/sdcard/DCIM/Camera/</span><span>*</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span># 【可选】压缩图片，修改size可控制图片大小</span></div></div><div><div><div>39</div></div><div><span>find</span><span> </span><span>$pre_dir</span><span> </span><span>-name</span><span> </span><span>"*.jpg"</span><span> | </span><span>xargs</span><span> </span><span>jpegoptim</span><span> </span><span>--size=500k</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>mv</span><span> </span><span>$pre_dir</span><span>/</span><span>*</span><span> </span><span>$dir</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<br />
<p>python3版本：</p>
<p>添加了对屏幕是否亮屏的检测</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/python3</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>import</span><span> os</span></div></div><div><div><div>4</div></div><div><span>import</span><span> re</span></div></div><div><div><div>5</div></div><div><span>import</span><span> json</span></div></div><div><div><div>6</div></div><div><span>import</span><span> time</span></div></div><div><div><div>7</div></div><div><span><span>adb_id </span><span>=</span><span> </span></span><span>'192.168.31.129:5555'</span></div></div><div><div><div>8</div></div><div><span><span>pre_dir </span><span>=</span><span> </span></span><span>'/mnt/sda/cam/pre/'</span></div></div><div><div><div>9</div></div><div><span>dir</span><span><span> </span><span>=</span><span> </span></span><span>'/mnt/sda/cam/'</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>try</span><span>:</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>os.</span><span>mkdir</span><span>(</span><span>dir</span><span>)</span></div></div><div><div><div>13</div></div><div><span>except</span><span>:</span></div></div><div><div><div>14</div></div><div><span>    </span><span>pass</span></div></div><div><div><div>15</div></div><div><span>try</span><span>:</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>os.</span><span>mkdir</span><span>(pre_dir)</span></div></div><div><div><div>17</div></div><div><span>except</span><span>:</span></div></div><div><div><div>18</div></div><div><span>    </span><span>pass</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>def</span><span> </span><span>cmd</span><span>(</span><span>command</span><span>,</span><span><span> </span><span>display</span></span><span>=</span><span>True</span><span>):</span></div></div><div><div><div>22</div></div><div><span>    </span><span>if</span><span> display:</span></div></div><div><div><div>23</div></div><div><span>        </span><span>print</span><span>(command)</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>out </span><span>=</span><span> os.</span><span>popen</span><span>(command).</span><span>read</span><span>()</span></div></div><div><div><div>25</div></div><div><span>    </span><span>if</span><span> display:</span></div></div><div><div><div>26</div></div><div><span>        </span><span>print</span><span>(out)</span></div></div><div><div><div>27</div></div><div><span>    </span><span>return</span><span> out</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>def</span><span> </span><span>adb</span><span>(</span><span>shell</span><span>,</span><span><span> </span><span>display</span></span><span>=</span><span>True</span><span>):</span></div></div><div><div><div>31</div></div><div><span>    </span><span>if</span><span> </span><span>not</span><span><span> shell.</span><span>startswith</span><span>(</span></span><span>'adb'</span><span>):</span></div></div><div><div><div>32</div></div><div><span><span>        </span></span><span>shell </span><span>=</span><span> </span><span>'adb </span><span>%s</span><span>'</span><span><span> </span><span>%</span><span> (shell)</span></span></div></div><div><div><div>33</div></div><div><span>    </span><span>return</span><span><span> </span><span>cmd</span><span>(shell.</span><span>replace</span><span>(</span></span><span>'adb'</span><span>, </span><span>'adb -s </span><span>%s</span><span>'</span><span><span> </span><span>%</span><span> (adb_id)), display)</span></span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>def</span><span> </span><span>is_screenState</span><span>():</span></div></div><div><div><div>37</div></div><div><span>    </span><span>return</span><span> </span><span>True</span><span> </span><span>if</span><span> </span><span>'state=ON'</span><span> </span><span>in</span><span><span> </span><span>adb</span><span>(</span></span><span>'shell dumpsys power | grep "Display Power: state="'</span><span>) </span><span>else</span><span> </span><span>False</span></div></div><div><div><div>38</div></div><div>
</div></div><div><div><div>39</div></div><div>
</div></div><div><div><div>40</div></div><div><span>def</span><span> </span><span>open_screen</span><span>():</span></div></div><div><div><div>41</div></div><div><span>    </span><span>if</span><span> </span><span>not</span><span><span> </span><span>is_screenState</span><span>():</span></span></div></div><div><div><div>42</div></div><div><span><span>        </span></span><span>adb</span><span>(</span><span>'shell input keyevent 26'</span><span>)</span></div></div><div><div><div>43</div></div><div>
</div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>def</span><span> </span><span>close_screen</span><span>():</span></div></div><div><div><div>46</div></div><div><span>    </span><span>if</span><span><span> </span><span>is_screenState</span><span>():</span></span></div></div><div><div><div>47</div></div><div><span><span>        </span></span><span>adb</span><span>(</span><span>'shell input keyevent 26'</span><span>)</span></div></div><div><div><div>48</div></div><div>
</div></div><div><div><div>49</div></div><div><span># 发送电量数据</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div>
</div></div><div><div><div>52</div></div><div><span>def</span><span> </span><span>send_power_status</span><span>():</span></div></div><div><div><div>53</div></div><div><span><span>    </span></span><span>info </span><span>=</span><span> </span><span>adb</span><span>(</span><span>'shell dumpsys battery'</span><span>, </span><span>False</span><span>)</span></div></div><div><div><div>54</div></div><div><span><span>    </span></span><span>ac </span><span>=</span><span> </span><span>True</span><span> </span><span>if</span><span><span> re.</span><span>compile</span><span>(</span></span></div></div><div><div><div>55</div></div><div><span>        </span><span>r</span><span><span>'AC powered: </span><span>(</span></span><span><span>[</span><span>^</span></span><span>\n</span><span>]+</span><span><span>)</span><span>'</span></span><span><span>).</span><span>findall</span><span>(info)[</span></span><span>0</span><span><span>] </span><span>==</span><span> </span></span><span>'true'</span><span> </span><span>else</span><span> </span><span>False</span></div></div><div><div><div>56</div></div><div><span><span>    </span></span><span>level </span><span>=</span><span> </span><span>int</span><span><span>(re.</span><span>compile</span><span>(</span></span><span>r</span><span><span>'level: </span><span>(</span></span><span>[</span><span>0-9</span><span>]+</span><span><span>)</span><span>'</span></span><span><span>).</span><span>findall</span><span>(info)[</span></span><span>0</span><span>])</span></div></div><div><div><div>57</div></div><div><span><span>    </span></span><span>j </span><span>=</span><span> json.</span><span>dumps</span><span>({</span><span>"level"</span><span>: level, </span><span>"AC"</span><span>: ac})</span></div></div><div><div><div>58</div></div><div><span><span>    </span></span><span>os.</span><span>popen</span><span>(</span></div></div><div><div><div>59</div></div><div><span>        </span><span>'mosquitto_pub -t </span><span>\'</span><span>phone/oppo/battery</span><span>\'</span><span> -h 192.168.31.110 -p 9883 -m </span><span>\'</span><span>%s</span><span>\'</span><span>'</span><span><span> </span><span>%</span><span> (j))</span></span></div></div><div><div><div>60</div></div><div>
</div></div><div><div><div>61</div></div><div>
</div></div><div><div><div>62</div></div><div><span><span>send_power_status</span><span>()</span></span></div></div><div><div><div>63</div></div><div><span><span>open_screen</span><span>()</span></span></div></div><div><div><div>64</div></div><div><span><span>adb</span><span>(</span></span><span>'shell am start -a android.media.action.STILL_IMAGE_CAMERA'</span><span>)</span></div></div><div><div><div>65</div></div><div><span><span>time.</span><span>sleep</span><span>(</span></span><span>0.5</span><span>)</span></div></div><div><div><div>66</div></div><div><span><span>adb</span><span>(</span></span><span>'shell input tap 539 900'</span><span>)</span></div></div><div><div><div>67</div></div><div><span><span>time.</span><span>sleep</span><span>(</span></span><span>1</span><span>)</span></div></div><div><div><div>68</div></div><div><span><span>adb</span><span>(</span></span><span>'shell input keyevent 27'</span><span>)</span></div></div><div><div><div>69</div></div><div><span><span>time.</span><span>sleep</span><span>(</span></span><span>1</span><span>)</span></div></div><div><div><div>70</div></div><div><span><span>adb</span><span>(</span></span><span>'shell input keyevent 4'</span><span>)</span></div></div><div><div><div>71</div></div><div><span><span>close_screen</span><span>()</span></span></div></div><div><div><div>72</div></div><div>
</div></div><div><div><div>73</div></div><div><span>for</span><span> path </span><span>in</span><span><span> </span><span>adb</span><span>(</span></span><span>'adb shell find /sdcard/DCIM/Camera -name "*.jpg"'</span><span><span>).</span><span>split</span><span>(</span></span><span>'</span><span>\n</span><span>'</span><span>):</span></div></div><div><div><div>74</div></div><div><span>    </span><span>if</span><span><span> path </span><span>==</span><span> </span></span><span>''</span><span>:</span></div></div><div><div><div>75</div></div><div><span>        </span><span>continue</span></div></div><div><div><div>76</div></div><div><span><span>    </span></span><span>adb</span><span>(</span><span>'adb pull </span><span>%s</span><span> </span><span>%s</span><span>'</span><span><span> </span><span>%</span><span> (path, pre_dir))</span></span></div></div><div><div><div>77</div></div><div><span><span>adb</span><span>(</span></span><span>'adb shell rm /sdcard/DCIM/Camera/*'</span><span>)</span></div></div><div><div><div>78</div></div><div><span>for</span><span> path </span><span>in</span><span><span> </span><span>cmd</span><span>(</span></span><span>'find </span><span>%s</span><span> -name "*.jpg"'</span><span><span> </span><span>%</span><span> (pre_dir)).</span><span>split</span><span>(</span></span><span>'</span><span>\n</span><span>'</span><span>):</span></div></div><div><div><div>79</div></div><div><span>    </span><span>if</span><span><span> path </span><span>==</span><span> </span></span><span>''</span><span>:</span></div></div><div><div><div>80</div></div><div><span>        </span><span>continue</span></div></div><div><div><div>81</div></div><div><span><span>    </span></span><span>cmd</span><span>(</span><span>'jpegoptim --size=250k </span><span>%s</span><span>'</span><span><span> </span><span>%</span><span> (path))</span></span></div></div><div><div><div>82</div></div><div><span><span>cmd</span><span>(</span></span><span>'mv </span><span>%s</span><span>/* </span><span>%s</span><span>'</span><span><span> </span><span>%</span><span> (pre_dir, </span></span><span>dir</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/263/</id>
      <title type="text">【Golang】反射</title>
      <published>2023-06-14T09:32:34.000Z</published>
      <updated>2023-06-14T09:32:34.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/263/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>程序正常编译时变量会被转换为内存地址，而变量名、类型信息等不会被编译进可执行部分。而使用<code>反射</code>（golang中使用<code>reflect</code>包）则会将这些信息编译进可执行文件（所以有时为了程序安全而不会使用反射）。</p></section>
<section><h1>0x01 实例<a href="#0x01-实例"><span>#</span></a></h1><p>贴上一个经常用的xlsx文件转[]*struct代码</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> (</span></div></div><div><div><div>2</div></div><div><span>  </span><span>"errors"</span></div></div><div><div><div>3</div></div><div><span>  </span><span>"github.com/tealeg/xlsx"</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"io"</span></div></div><div><div><div>5</div></div><div><span>  </span><span>"net/http"</span></div></div><div><div><div>6</div></div><div><span>  </span><span>"reflect"</span></div></div><div><div><div>7</div></div><div><span>)</span></div></div><div><div><div>8</div></div><div><span>// ParseXlsxToStruct</span></div></div><div><div><div>9</div></div><div><span>//</span></div></div><div><div><div>10</div></div><div><span>//   @Description: 解析xlsx到struct中</span></div></div><div><div><div>11</div></div><div><span>//   @param data  xlsx数据</span></div></div><div><div><div>12</div></div><div><span>//   @param out  目标struct</span></div></div><div><div><div>13</div></div><div><span>//   @param sheet 默认第一个sheet</span></div></div><div><div><div>14</div></div><div><span>//   @return error</span></div></div><div><div><div>15</div></div><div><span>//    ParseXlsxToStruct(data,&amp;out)</span></div></div><div><div><div>16</div></div><div><span>func</span><span> </span><span>ParseXlsxToStruct</span><span><span>(</span><span>data</span><span> []</span></span><span>byte</span><span><span>, </span><span>out</span><span> </span></span><span>any</span><span><span>, </span><span>sheet</span><span> ...</span></span><span>string</span><span>) </span><span>error</span><span> {</span></div></div><div><div><div>17</div></div><div><span>  </span><span>value</span><span><span> </span><span>:=</span><span> </span></span><span>reflect</span><span>.</span><span>ValueOf</span><span>(</span><span>out</span><span>)</span></div></div><div><div><div>18</div></div><div><span>  </span><span>if</span><span> </span><span>value</span><span>.</span><span>Type</span><span>().</span><span>Kind</span><span><span>() </span><span>!=</span><span> </span></span><span>reflect</span><span>.</span><span>Ptr</span><span> {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>return</span><span> </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"必须以指针的方式传入"</span><span>)</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span>  </span><span>value</span><span><span> </span><span>=</span><span> </span></span><span>value</span><span>.</span><span>Elem</span><span>()</span></div></div><div><div><div>22</div></div><div><span>  </span><span>if</span><span> </span><span>value</span><span>.</span><span>Type</span><span>().</span><span>Kind</span><span><span>() </span><span>!=</span><span> </span></span><span>reflect</span><span>.</span><span>Slice</span><span> {</span></div></div><div><div><div>23</div></div><div><span>    </span><span>return</span><span> </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"内部必须为struct切片"</span><span>)</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span>  </span><span>if</span><span> </span><span>value</span><span>.</span><span>Len</span><span><span>() </span><span>!=</span><span> </span></span><span>0</span><span> {</span></div></div><div><div><div>26</div></div><div><span>    </span><span>return</span><span> </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"必须是空切片"</span><span>)</span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>  </span><span>xfile</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>xlsx</span><span>.</span><span>OpenBinary</span><span>(</span><span>data</span><span>)</span></div></div><div><div><div>30</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>31</div></div><div><span>    </span><span>return</span><span> </span><span>err</span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>33</div></div><div><span>  </span><span>if</span><span> </span><span>len</span><span>(</span><span>xfile</span><span>.</span><span>Sheets</span><span><span>) </span><span>==</span><span> </span></span><span>0</span><span> {</span></div></div><div><div><div>34</div></div><div><span>    </span><span>return</span><span> </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"xlsx中没有sheet"</span><span>)</span></div></div><div><div><div>35</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>36</div></div><div><span>  </span><span>var</span><span> </span><span>sheets</span><span><span> []</span><span>*</span></span><span>xlsx</span><span>.</span><span>Sheet</span></div></div><div><div><div>37</div></div><div><span>  </span><span>if</span><span> </span><span>len</span><span>(</span><span>sheet</span><span><span>) </span><span>&gt;</span><span> </span></span><span>0</span><span> {</span></div></div><div><div><div>38</div></div><div><span>    </span><span>sheets</span><span><span> </span><span>=</span><span> </span></span><span>make</span><span><span>([]</span><span>*</span></span><span>xlsx</span><span>.</span><span>Sheet</span><span>, </span><span>0</span><span>, </span><span>len</span><span>(</span><span>sheet</span><span>))</span></div></div><div><div><div>39</div></div><div><span>    </span><span>for</span><span> </span><span>_</span><span>, </span><span>v</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>sheet</span><span> {</span></div></div><div><div><div>40</div></div><div><span>      </span><span>if</span><span> </span><span>s</span><span>, </span><span>ok</span><span><span> </span><span>:=</span><span> </span></span><span>xfile</span><span>.</span><span>Sheet</span><span>[</span><span>v</span><span>]; </span><span>ok</span><span> {</span></div></div><div><div><div>41</div></div><div><span>        </span><span>sheets</span><span><span> </span><span>=</span><span> </span></span><span>append</span><span>(</span><span>sheets</span><span>, </span><span>s</span><span>)</span></div></div><div><div><div>42</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>43</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>44</div></div><div><span><span>  </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>45</div></div><div><span>    </span><span>sheets</span><span><span> </span><span>=</span><span> </span></span><span>append</span><span>(</span><span>sheets</span><span>, </span><span>xfile</span><span>.</span><span>Sheets</span><span>[</span><span>0</span><span>])</span></div></div><div><div><div>46</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>  </span><span>title</span><span><span> </span><span>:=</span><span> </span></span><span>GetUniqueSheetsTitle</span><span>(</span><span>sheets</span><span>)</span></div></div><div><div><div>49</div></div><div><span>  </span><span>var</span><span> </span><span>tmp</span><span><span> </span><span>=</span><span> </span></span><span>make</span><span>(</span><span>map</span><span>[</span><span>string</span><span>][]</span><span>string</span><span>, </span><span>len</span><span>(</span><span>title</span><span>))</span></div></div><div><div><div>50</div></div><div><span>  </span><span>for</span><span> </span><span>_</span><span>, </span><span>s</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>sheets</span><span> {</span></div></div><div><div><div>51</div></div><div><span>    </span><span>if</span><span> </span><span>len</span><span>(</span><span>s</span><span>.</span><span>Rows</span><span><span>) </span><span>==</span><span> </span></span><span>0</span><span> {</span></div></div><div><div><div>52</div></div><div><span>      </span><span>continue</span></div></div><div><div><div>53</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>54</div></div><div><span>    </span><span>title</span><span><span> </span><span>:=</span><span> </span></span><span>GetSheetTitle</span><span>(</span><span>s</span><span>)</span></div></div><div><div><div>55</div></div><div><span>    </span><span>for</span><span> </span><span>i</span><span>, </span><span>row</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>s</span><span>.</span><span>Rows</span><span> {</span></div></div><div><div><div>56</div></div><div><span>      </span><span>if</span><span> </span><span>i</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span> {</span></div></div><div><div><div>57</div></div><div><span>        </span><span>continue</span></div></div><div><div><div>58</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>59</div></div><div><span>      </span><span>var</span><span> </span><span>dataMap</span><span><span> </span><span>=</span><span> </span></span><span>make</span><span>(</span><span>map</span><span>[</span><span>string</span><span>]</span><span>string</span><span>)</span></div></div><div><div><div>60</div></div><div><span>      </span><span>for</span><span> </span><span>j</span><span>, </span><span>cell</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>row</span><span>.</span><span>Cells</span><span> {</span></div></div><div><div><div>61</div></div><div><span>        </span><span>if</span><span> </span><span>title</span><span>[</span><span>j</span><span><span>] </span><span>==</span><span> </span></span><span>""</span><span> {</span></div></div><div><div><div>62</div></div><div><span>          </span><span>continue</span></div></div><div><div><div>63</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>64</div></div><div><span>        </span><span>dataMap</span><span>[</span><span>title</span><span>[</span><span>j</span><span><span>]] </span><span>=</span><span> </span></span><span>cell</span><span>.</span><span>String</span><span>()</span></div></div><div><div><div>65</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>66</div></div><div><span>      </span><span>for</span><span> </span><span>_</span><span>, </span><span>t</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>title</span><span> {</span></div></div><div><div><div>67</div></div><div><span>        </span><span>if</span><span> </span><span>t</span><span><span> </span><span>==</span><span> </span></span><span>""</span><span> {</span></div></div><div><div><div>68</div></div><div><span>          </span><span>continue</span></div></div><div><div><div>69</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>70</div></div><div><span>        </span><span>tmp</span><span>[</span><span>t</span><span><span>] </span><span>=</span><span> </span></span><span>append</span><span>(</span><span>tmp</span><span>[</span><span>t</span><span>], </span><span>dataMap</span><span>[</span><span>t</span><span>])</span></div></div><div><div><div>71</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>72</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>73</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>74</div></div><div><span>  </span><span>MapToStructByTag</span><span>(</span><span>tmp</span><span>, </span><span>out</span><span>, </span><span>"xlsx"</span><span>)</span></div></div><div><div><div>75</div></div><div><span>  </span><span>return</span><span> </span><span>nil</span></div></div><div><div><div>76</div></div><div><span>}</span></div></div><div><div><div>77</div></div><div>
</div></div><div><div><div>78</div></div><div><span>func</span><span> </span><span>MapToStructByTag</span><span><span>(</span><span>data</span><span> </span></span><span>map</span><span>[</span><span>string</span><span>][]</span><span>string</span><span><span>, </span><span>in</span><span> </span></span><span>interface</span><span><span>{}, </span><span>tagKey</span><span> </span></span><span>string</span><span>) {</span></div></div><div><div><div>79</div></div><div><span>  </span><span>// 获取传入结构体切片的反射类型和值</span></div></div><div><div><div>80</div></div><div><span>  </span><span>inValue</span><span><span> </span><span>:=</span><span> </span></span><span>reflect</span><span>.</span><span>ValueOf</span><span>(</span><span>in</span><span>).</span><span>Elem</span><span>()</span></div></div><div><div><div>81</div></div><div><span>  </span><span>inType</span><span><span> </span><span>:=</span><span> </span></span><span>inValue</span><span>.</span><span>Type</span><span>().</span><span>Elem</span><span>()</span></div></div><div><div><div>82</div></div><div>
</div></div><div><div><div>83</div></div><div><span>  </span><span>var</span><span> </span><span>l</span><span> </span><span>int</span></div></div><div><div><div>84</div></div><div><span>  </span><span>for</span><span> </span><span>_</span><span>, </span><span>v</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>data</span><span> {</span></div></div><div><div><div>85</div></div><div><span>    </span><span>if</span><span> </span><span>l</span><span><span> </span><span>&lt;</span><span> </span></span><span>len</span><span>(</span><span>v</span><span>) {</span></div></div><div><div><div>86</div></div><div><span>      </span><span>l</span><span><span> </span><span>=</span><span> </span></span><span>len</span><span>(</span><span>v</span><span>)</span></div></div><div><div><div>87</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>88</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>89</div></div><div><span>  </span><span>//fmt.Println(inType)</span></div></div><div><div><div>90</div></div><div><span>  </span><span>news</span><span><span> </span><span>:=</span><span> </span></span><span>reflect</span><span>.</span><span>MakeSlice</span><span>(</span><span>inValue</span><span>.</span><span>Type</span><span>(), </span><span>l</span><span>, </span><span>l</span><span>)</span></div></div><div><div><div>91</div></div><div><span>  </span><span>defer</span><span> </span><span>func</span><span>() {</span></div></div><div><div><div>92</div></div><div><span>    </span><span>inValue</span><span>.</span><span>Set</span><span>(</span><span>news</span><span>)</span></div></div><div><div><div>93</div></div><div><span><span>  </span></span><span>}()</span></div></div><div><div><div>94</div></div><div>
</div></div><div><div><div>95</div></div><div><span>  </span><span>for</span><span> </span><span>i</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>; </span><span>i</span><span><span> </span><span>&lt;</span><span> </span></span><span>news</span><span>.</span><span>Len</span><span>(); </span><span>i</span><span><span>++</span><span> {</span></span></div></div><div><div><div>96</div></div><div><span>    </span><span>structValue</span><span><span> </span><span>:=</span><span> </span></span><span>news</span><span>.</span><span>Index</span><span>(</span><span>i</span><span>)</span></div></div><div><div><div>97</div></div><div><span>    </span><span>structType</span><span><span> </span><span>:=</span><span> </span></span><span>inType</span></div></div><div><div><div>98</div></div><div><span>    </span><span>// 获取结构体指针所指向的类型</span></div></div><div><div><div>99</div></div><div><span>    </span><span>var</span><span> </span><span>prt</span><span> </span><span>bool</span></div></div><div><div><div>100</div></div><div><span>    </span><span>var</span><span> </span><span>structValuePtr</span><span> </span><span>reflect</span><span>.</span><span>Value</span></div></div><div><div><div>101</div></div><div><span>    </span><span>if</span><span> </span><span>structValue</span><span>.</span><span>Kind</span><span><span>() </span><span>==</span><span> </span></span><span>reflect</span><span>.</span><span>Ptr</span><span> {</span></div></div><div><div><div>102</div></div><div><span>      </span><span>structType</span><span><span> </span><span>=</span><span> </span></span><span>structType</span><span>.</span><span>Elem</span><span>()</span></div></div><div><div><div>103</div></div><div><span>      </span><span>structValuePtr</span><span><span> </span><span>=</span><span> </span></span><span>reflect</span><span>.</span><span>New</span><span>(</span><span>structType</span><span>)</span></div></div><div><div><div>104</div></div><div><span>      </span><span>structValue</span><span><span> </span><span>=</span><span> </span></span><span>structValuePtr</span><span>.</span><span>Elem</span><span>()</span></div></div><div><div><div>105</div></div><div><span>      </span><span>prt</span><span><span> </span><span>=</span><span> </span></span><span>true</span></div></div><div><div><div>106</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>107</div></div><div>
</div></div><div><div><div>108</div></div><div><span>    </span><span>// 遍历结构体字段</span></div></div><div><div><div>109</div></div><div><span>    </span><span>for</span><span> </span><span>j</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>; </span><span>j</span><span><span> </span><span>&lt;</span><span> </span></span><span>structType</span><span>.</span><span>NumField</span><span>(); </span><span>j</span><span><span>++</span><span> {</span></span></div></div><div><div><div>110</div></div><div><span>      </span><span>fieldValue</span><span><span> </span><span>:=</span><span> </span></span><span>structValue</span><span>.</span><span>Field</span><span>(</span><span>j</span><span>)</span></div></div><div><div><div>111</div></div><div><span>      </span><span>fieldType</span><span><span> </span><span>:=</span><span> </span></span><span>structType</span><span>.</span><span>Field</span><span>(</span><span>j</span><span>)</span></div></div><div><div><div>112</div></div><div><span>      </span><span>// 检查字段的 tag 是否与 key 匹配</span></div></div><div><div><div>113</div></div><div><span>      </span><span>tag</span><span><span> </span><span>:=</span><span> </span></span><span>fieldType</span><span>.</span><span>Tag</span><span>.</span><span>Get</span><span>(</span><span>tagKey</span><span>)</span></div></div><div><div><div>114</div></div><div><span>      </span><span>if</span><span> </span><span>values</span><span>, </span><span>ok</span><span><span> </span><span>:=</span><span> </span></span><span>data</span><span>[</span><span>tag</span><span>]; </span><span>ok</span><span> {</span></div></div><div><div><div>115</div></div><div><span>        </span><span>if</span><span> </span><span>i</span><span><span> </span><span>&gt;=</span><span> </span></span><span>len</span><span>(</span><span>values</span><span>) {</span></div></div><div><div><div>116</div></div><div><span>          </span><span>continue</span></div></div><div><div><div>117</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>118</div></div><div><span>        </span><span>// 检查字段是否可以被设置</span></div></div><div><div><div>119</div></div><div><span>        </span><span>if</span><span> </span><span>fieldValue</span><span>.</span><span>CanSet</span><span>() {</span></div></div><div><div><div>120</div></div><div><span>          </span><span>// 根据字段类型进行适当的转换并设置值</span></div></div><div><div><div>121</div></div><div><span>          </span><span>switch</span><span> </span><span>fieldType</span><span>.</span><span>Type</span><span>.</span><span>Kind</span><span>() {</span></div></div><div><div><div>122</div></div><div><span>          </span><span>case</span><span> </span><span>reflect</span><span>.</span><span>String</span><span>:</span></div></div><div><div><div>123</div></div><div><span>            </span><span>structValue</span><span>.</span><span>Field</span><span>(</span><span>j</span><span>).</span><span>SetString</span><span>(</span><span>values</span><span>[</span><span>i</span><span>])</span></div></div><div><div><div>124</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>125</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>126</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>127</div></div><div>
</div></div><div><div><div>128</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>129</div></div><div><span>    </span><span>if</span><span> </span><span>prt</span><span> {</span></div></div><div><div><div>130</div></div><div><span>      </span><span>news</span><span>.</span><span>Index</span><span>(</span><span>i</span><span>).</span><span>Set</span><span>(</span><span>structValuePtr</span><span>)</span></div></div><div><div><div>131</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>132</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>133</div></div><div><span>}</span></div></div><div><div><div>134</div></div><div>
</div></div><div><div><div>135</div></div><div><span>func</span><span> </span><span>ParseXlsxToStructByUrl</span><span><span>(</span><span>url</span><span> </span></span><span>string</span><span><span>, </span><span>out</span><span> </span></span><span>any</span><span><span>, </span><span>sheet</span><span> ...</span></span><span>string</span><span>) </span><span>error</span><span> {</span></div></div><div><div><div>136</div></div><div><span>  </span><span>resp</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>http</span><span>.</span><span>Get</span><span>(</span><span>url</span><span>)</span></div></div><div><div><div>137</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>138</div></div><div><span>    </span><span>return</span><span> </span><span>err</span></div></div><div><div><div>139</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>140</div></div><div><span>  </span><span>defer</span><span> </span><span>resp</span><span>.</span><span>Body</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>141</div></div><div><span>  </span><span>data</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>io</span><span>.</span><span>ReadAll</span><span>(</span><span>resp</span><span>.</span><span>Body</span><span>)</span></div></div><div><div><div>142</div></div><div><span>  </span><span>return</span><span> </span><span>ParseXlsxToStruct</span><span>(</span><span>data</span><span>, </span><span>out</span><span>, </span><span>sheet</span><span>...)</span></div></div><div><div><div>143</div></div><div><span>}</span></div></div><div><div><div>144</div></div><div>
</div></div><div><div><div>145</div></div><div><span>func</span><span> </span><span>ParseStructToXlsx</span><span><span>(</span><span>a</span><span> </span></span><span>any</span><span><span>, </span><span>fn</span><span> </span></span><span>func</span><span><span>(</span><span>tag</span><span> </span></span><span>string</span><span><span>, </span><span>val</span><span> </span></span><span>any</span><span><span>, </span><span>cell</span><span> </span><span>*</span></span><span>xlsx</span><span>.</span><span>Cell</span><span>) </span><span>error</span><span><span>) (</span><span>*</span></span><span>xlsx</span><span>.</span><span>File</span><span>, </span><span>error</span><span>) {</span></div></div><div><div><div>146</div></div><div><span>  </span><span>val</span><span><span> </span><span>:=</span><span> </span></span><span>reflect</span><span>.</span><span>ValueOf</span><span>(</span><span>a</span><span>)</span></div></div><div><div><div>147</div></div><div><span>  </span><span>if</span><span> </span><span>val</span><span>.</span><span>Type</span><span>().</span><span>Kind</span><span><span>() </span><span>!=</span><span> </span></span><span>reflect</span><span>.</span><span>Slice</span><span> {</span></div></div><div><div><div>148</div></div><div><span>    </span><span>return</span><span> </span><span>nil</span><span>, </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"必须传入[]*struct"</span><span>)</span></div></div><div><div><div>149</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>150</div></div><div><span>  </span><span>xFile</span><span><span> </span><span>:=</span><span> </span></span><span>xlsx</span><span>.</span><span>NewFile</span><span>()</span></div></div><div><div><div>151</div></div><div><span>  </span><span>sheet</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>xFile</span><span>.</span><span>AddSheet</span><span>(</span><span>"A1"</span><span>)</span></div></div><div><div><div>152</div></div><div><span>  </span><span>title</span><span><span> </span><span>:=</span><span> </span></span><span>sheet</span><span>.</span><span>AddRow</span><span>()</span></div></div><div><div><div>153</div></div><div><span>  </span><span>for</span><span> </span><span>i</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>; </span><span>i</span><span><span> </span><span>&lt;</span><span> </span></span><span>val</span><span>.</span><span>Len</span><span>(); </span><span>i</span><span><span>++</span><span> {</span></span></div></div><div><div><div>154</div></div><div><span>    </span><span>elemVal</span><span><span> </span><span>:=</span><span> </span></span><span>val</span><span>.</span><span>Index</span><span>(</span><span>i</span><span>)</span></div></div><div><div><div>155</div></div><div><span>    </span><span>for</span><span> </span><span>elemVal</span><span>.</span><span>Kind</span><span><span>() </span><span>==</span><span> </span></span><span>reflect</span><span>.</span><span>Ptr</span><span> {</span></div></div><div><div><div>156</div></div><div><span>      </span><span>elemVal</span><span><span> </span><span>=</span><span> </span></span><span>elemVal</span><span>.</span><span>Elem</span><span>()</span></div></div><div><div><div>157</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>158</div></div><div><span>    </span><span>if</span><span> </span><span>elemVal</span><span>.</span><span>Kind</span><span><span>() </span><span>!=</span><span> </span></span><span>reflect</span><span>.</span><span>Struct</span><span> {</span></div></div><div><div><div>159</div></div><div><span>      </span><span>return</span><span> </span><span>nil</span><span>, </span><span>errors</span><span>.</span><span>New</span><span>(</span><span>"必须传入[]*struct"</span><span>)</span></div></div><div><div><div>160</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>161</div></div><div><span>    </span><span>row</span><span><span> </span><span>:=</span><span> </span></span><span>sheet</span><span>.</span><span>AddRow</span><span>()</span></div></div><div><div><div>162</div></div><div><span>    </span><span>for</span><span> </span><span>j</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>; </span><span>j</span><span><span> </span><span>&lt;</span><span> </span></span><span>elemVal</span><span>.</span><span>NumField</span><span>(); </span><span>j</span><span><span>++</span><span> {</span></span></div></div><div><div><div>163</div></div><div><span>      </span><span>cell</span><span><span> </span><span>:=</span><span> </span></span><span>row</span><span>.</span><span>AddCell</span><span>()</span></div></div><div><div><div>164</div></div><div><span>      </span><span>tag</span><span>, </span><span>ok</span><span><span> </span><span>:=</span><span> </span></span><span>elemVal</span><span>.</span><span>Type</span><span>().</span><span>Field</span><span>(</span><span>j</span><span>).</span><span>Tag</span><span>.</span><span>Lookup</span><span>(</span><span>"xlsx"</span><span>)</span></div></div><div><div><div>165</div></div><div><span>      </span><span>if</span><span><span> </span><span>!</span></span><span>ok</span><span> {</span></div></div><div><div><div>166</div></div><div><span>        </span><span>continue</span></div></div><div><div><div>167</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>168</div></div><div><span>      </span><span>if</span><span> </span><span>i</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span> {</span></div></div><div><div><div>169</div></div><div><span>        </span><span>title</span><span>.</span><span>AddCell</span><span>().</span><span>SetString</span><span>(</span><span>tag</span><span>)</span></div></div><div><div><div>170</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>171</div></div><div><span>      </span><span>v</span><span><span> </span><span>:=</span><span> </span></span><span>elemVal</span><span>.</span><span>Field</span><span>(</span><span>j</span><span>).</span><span>Interface</span><span>()</span></div></div><div><div><div>172</div></div><div><span>      </span><span>if</span><span> </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>fn</span><span>(</span><span>tag</span><span>, </span><span>v</span><span>, </span><span>cell</span><span>); </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>173</div></div><div><span>        </span><span>return</span><span> </span><span>nil</span><span>, </span><span>err</span></div></div><div><div><div>174</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>175</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>176</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>177</div></div><div><span>  </span><span>return</span><span> </span><span>xFile</span><span>, </span><span>nil</span></div></div><div><div><div>178</div></div><div><span>}</span></div></div><div><div><div>179</div></div><div>
</div></div><div><div><div>180</div></div><div><span>func</span><span> </span><span>GetUniqueSheetsTitle</span><span><span>(</span><span>ss</span><span> []</span><span>*</span></span><span>xlsx</span><span>.</span><span>Sheet</span><span>) []</span><span>string</span><span> {</span></div></div><div><div><div>181</div></div><div><span>  </span><span>var</span><span> </span><span>tmp</span><span><span> </span><span>=</span><span> </span></span><span>make</span><span>(</span><span>map</span><span>[</span><span>string</span><span>]</span><span>struct</span><span>{})</span></div></div><div><div><div>182</div></div><div><span>  </span><span>var</span><span> </span><span>out</span><span> []</span><span>string</span></div></div><div><div><div>183</div></div><div><span>  </span><span>for</span><span> </span><span>_</span><span>, </span><span>s</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>ss</span><span> {</span></div></div><div><div><div>184</div></div><div><span>    </span><span>title</span><span><span> </span><span>:=</span><span> </span></span><span>GetSheetTitle</span><span>(</span><span>s</span><span>)</span></div></div><div><div><div>185</div></div><div><span>    </span><span>for</span><span> </span><span>_</span><span>, </span><span>t</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>title</span><span> {</span></div></div><div><div><div>186</div></div><div><span>      </span><span>if</span><span> </span><span>_</span><span>, </span><span>ok</span><span><span> </span><span>:=</span><span> </span></span><span>tmp</span><span>[</span><span>t</span><span><span>]; </span><span>!</span></span><span>ok</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>t</span><span><span> </span><span>!=</span><span> </span></span><span>""</span><span> {</span></div></div><div><div><div>187</div></div><div><span>        </span><span>out</span><span><span> </span><span>=</span><span> </span></span><span>append</span><span>(</span><span>out</span><span>, </span><span>t</span><span>)</span></div></div><div><div><div>188</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>189</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>190</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>191</div></div><div><span>  </span><span>return</span><span> </span><span>out</span></div></div><div><div><div>192</div></div><div><span>}</span></div></div><div><div><div>193</div></div><div>
</div></div><div><div><div>194</div></div><div><span>func</span><span> </span><span>GetSheetTitle</span><span><span>(</span><span>s</span><span> </span><span>*</span></span><span>xlsx</span><span>.</span><span>Sheet</span><span>) []</span><span>string</span><span> {</span></div></div><div><div><div>195</div></div><div><span>  </span><span>if</span><span> </span><span>len</span><span>(</span><span>s</span><span>.</span><span>Rows</span><span><span>) </span><span>==</span><span> </span></span><span>0</span><span> {</span></div></div><div><div><div>196</div></div><div><span>    </span><span>return</span><span> </span><span>nil</span></div></div><div><div><div>197</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>198</div></div><div><span>  </span><span>if</span><span> </span><span>row</span><span><span> </span><span>:=</span><span> </span></span><span>s</span><span>.</span><span>Rows</span><span>[</span><span>0</span><span>]; </span><span>row</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>199</div></div><div><span>    </span><span>var</span><span> </span><span>title</span><span><span> </span><span>=</span><span> </span></span><span>make</span><span>([]</span><span>string</span><span>, </span><span>len</span><span>(</span><span>row</span><span>.</span><span>Cells</span><span>))</span></div></div><div><div><div>200</div></div><div><span>    </span><span>for</span><span> </span><span>i</span><span>, </span><span>cell</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>row</span><span>.</span><span>Cells</span><span> {</span></div></div><div><div><div>201</div></div><div><span>      </span><span>title</span><span>[</span><span>i</span><span><span>] </span><span>=</span><span> </span></span><span>cell</span><span>.</span><span>String</span><span>()</span></div></div><div><div><div>202</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>203</div></div><div><span>    </span><span>return</span><span> </span><span>title</span></div></div><div><div><div>204</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>205</div></div><div><span>  </span><span>return</span><span> </span><span>nil</span></div></div><div><div><div>206</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/261/</id>
      <title type="text">【Linux】使用iptables进行端口映射</title>
      <published>2023-04-21T10:16:00.000Z</published>
      <updated>2023-04-21T10:21:13.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/261/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>使用<a href="#使用"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./iptable.sh</span><span> </span><span>-I</span><span> </span><span>本地ip</span><span> </span><span>本地端口</span><span> </span><span>远程ip</span><span> </span><span>远程端口</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>插入到头部</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./iptable.sh</span><span> </span><span>-I</span><span> </span><span>127.0.0.1</span><span> </span><span>1234</span><span> </span><span>127.0.0.2</span><span> </span><span>2345</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>尾部追加</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./iptable.sh</span><span> </span><span>-A</span><span> </span><span>127.0.0.1</span><span> </span><span>1234</span><span> </span><span>127.0.0.2</span><span> </span><span>2345</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>删除</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./iptable.sh</span><span> </span><span>-D</span><span> </span><span>127.0.0.1</span><span> </span><span>1234</span><span> </span><span>127.0.0.2</span><span> </span><span>2345</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>脚本<a href="#脚本"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/bash</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>case</span><span><span> </span><span>$1</span><span> </span></span><span>in</span></div></div><div><div><div>4</div></div><div><span>  </span><span>-I</span><span>)</span></div></div><div><div><div>5</div></div><div><span>    </span><span>echo</span><span> </span><span>"执行插入操作-I"</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>7</div></div><div><span>  </span><span>-A</span><span>)</span></div></div><div><div><div>8</div></div><div><span>    </span><span>echo</span><span> </span><span>"执行追加操作-A"</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>10</div></div><div><span>  </span><span>-D</span><span>)</span></div></div><div><div><div>11</div></div><div><span>    </span><span>echo</span><span> </span><span>"执行删除操作-D"</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>13</div></div><div><span>  </span><span>-h</span><span>)</span></div></div><div><div><div>14</div></div><div><span>    </span><span>echo</span><span> </span><span>"</span><span>$0</span><span> &lt;-I -A -D&gt; 本地ip 本地端口 远程ip 远程端口"</span></div></div><div><div><div>15</div></div><div><span>    </span><span>exit</span><span> </span><span>0</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>*)</span></div></div><div><div><div>18</div></div><div><span>    </span><span>echo</span><span> </span><span>"无效的参数，请输入-I -A -D之一"</span></div></div><div><div><div>19</div></div><div><span>    </span><span>echo</span><span> </span><span>"</span><span>$0</span><span> &lt;-I -A -D&gt; 本地ip 本地端口 远程ip 远程端口"</span></div></div><div><div><div>20</div></div><div><span>    </span><span>exit</span><span> </span><span>1</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>22</div></div><div><span>esac</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>iptables</span><span> </span><span>-t</span><span> </span><span>nat</span><span><span> </span><span>$1</span><span> </span></span><span>PREROUTING</span><span> </span><span>-p</span><span> </span><span>tcp</span><span> </span><span>-d</span><span><span> </span><span>$2</span><span> </span></span><span>--dport</span><span><span> </span><span>$3</span><span> </span></span><span>-j</span><span> </span><span>DNAT</span><span> </span><span>--to</span><span><span> </span><span>$4</span></span><span>:</span><span>$5</span></div></div><div><div><div>25</div></div><div><span>iptables</span><span> </span><span>-t</span><span> </span><span>nat</span><span><span> </span><span>$1</span><span> </span></span><span>POSTROUTING</span><span> </span><span>-p</span><span> </span><span>tcp</span><span> </span><span>-d</span><span><span> </span><span>$4</span><span> </span></span><span>--dport</span><span><span> </span><span>$5</span><span> </span></span><span>-j</span><span> </span><span>SNAT</span><span> </span><span>--to</span><span><span> </span><span>$2</span></span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span># 本地链路</span></div></div><div><div><div>28</div></div><div><span>iptables</span><span> </span><span>-t</span><span> </span><span>nat</span><span><span> </span><span>$1</span><span> </span></span><span>OUTPUT</span><span> </span><span>-p</span><span> </span><span>tcp</span><span> </span><span>-d</span><span><span> </span><span>$2</span><span> </span></span><span>--dport</span><span><span> </span><span>$3</span><span> </span></span><span>-j</span><span> </span><span>DNAT</span><span> </span><span>--to</span><span><span> </span><span>$4</span></span><span>:</span><span>$5</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/260/</id>
      <title type="text">【LXC】lxc debian安装桌面</title>
      <published>2023-02-24T13:47:18.000Z</published>
      <updated>2023-02-24T13:47:18.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/260/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<blockquote><p>转自 <a href="https://www.right.com.cn/forum/thread-8227639-1-1.html" target="_blank">https://www.right.com.cn/forum/thread-8227639-1-1.html</a></p></blockquote>
<blockquote><p>原教程写得很简练，就直接转过来了，改天再提取一下</p></blockquote>
<p>1、创建一个debian 11系统，模板在PVE管理页面下载就有（ubuntu也可以，试过安装debian更精减），4G内存，2 CPU起步，指定你想要的ip（例如：192.168.1.10/24）</p>
<p>2、登录并修改为清华软件源</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>nano</span><span> </span><span>/etc/apt/sources.list</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>apt</span><span> </span><span>update</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>3、添加一个新用户</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>adduser</span><span> </span><span>username</span></div></div><div><div><div>2</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>sudo</span></div></div><div><div><div>3</div></div><div><span>usermod</span><span> </span><span>-aG</span><span> </span><span>sudo</span><span> </span><span>username</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>4、配置中文环境：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>dpkg-reconfigure</span><span> </span><span>locales</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>选择zh_CN.UTF-8 UTF-8</p>
<p>5、安装XFCE桌面环境和思源字体：在安装过程中，会看到一个屏幕询问想要哪个桌面管理器：选择 lightdm</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>xfce4</span><span> </span><span>xfce4-goodies</span><span> </span><span>xorg</span><span> </span><span>dbus-x11</span><span> </span><span>x11-xserver-utils</span><span> </span><span>fonts-noto-cjk</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>7、安装xrdp</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>xrdp</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>8、验证 xrdp 安装是否正确并且正在运行</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>systemctl</span><span> </span><span>status</span><span> </span><span>xrdp</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>9、 RDP 安装后需要添加这个代码，以便让桌面管理器知道使用什么来显示</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>update-alternatives</span><span> </span><span>--set</span><span> </span><span>x-session-manager</span><span> </span><span>/usr/bin/xfce4-session</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>这时可以使用远程桌面连接192.168.1.10了，中文输入法可以安装fcitx（fcitx-table-wbpy这个是五笔拼音混合输入）</p>
<section><h2>0x2<a href="#0x2"><span>#</span></a></h2><p>更新一下xrdp远程桌面连接声音重定向
<a href="https://bbs.deepin.org/post/192129" target="_blank">https://bbs.deepin.org/post/192129</a>
<a href="https://github.com/neutrinolabs/xrdp" target="_blank">https://github.com/neutrinolabs/xrdp</a>
<a href="https://github.com/neutrinolabs/pulseaudio-module-xrdp" target="_blank">https://github.com/neutrinolabs/pulseaudio-module-xrdp</a>
1、安装编译需要的环境</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>build-essential</span><span> </span><span>dpkg-dev</span><span> </span><span>libpulse-dev</span><span> </span><span>git</span><span> </span><span>autoconf</span><span> </span><span>libtool</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>2、安装pulseaudio和编译依赖 (需要启用deb-src源）
非root用户进入 /home/username</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>build-dep</span><span> </span><span>pulseaudio</span></div></div><div><div><div>3</div></div><div><span>apt</span><span> </span><span>source</span><span> </span><span>pulseaudio</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>3、编译
cd 下载的pulseaudio源码目录</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./bootstrap</span></div></div><div><div><div>2</div></div><div><span>./configure</span></div></div><div><div><div>3</div></div><div><span>make</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>4、下载 pulseaudio-module-xrdp源码并编译</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>git</span><span> </span><span>clone</span><span> </span><span>https://github.com/neutrinolabs/pulseaudio-module-xrdp.git</span></div></div><div><div><div>2</div></div><div><span>cd</span><span> </span><span>pulseaudio-module-xrdp</span></div></div><div><div><div>3</div></div><div><span>./bootstrap</span><span> &amp;&amp; </span><span>./configure</span><span> </span><span>PULSE_DIR=/home/username/pulseaudio-14.2</span><span>(</span><span>上一步下载的源码目录）</span></div></div><div><div><div>4</div></div><div><span>make</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>5、安装模块</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>cd</span><span> </span><span>src</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>make</span><span> </span><span>install</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>6、查看是否成功</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ls</span><span> $(</span><span>pkg-config</span><span> </span><span>--variable=modlibexecdir</span><span> </span><span>libpulse</span><span>) | </span><span>grep</span><span> </span><span>xrdp</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>现出module-xrdp-sink.so 和 module-xrdp-source.so 就是成功了</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/259/</id>
      <title type="text">【疑难杂症】特权lxc下运行非特权docker报错</title>
      <published>2023-02-24T00:53:31.000Z</published>
      <updated>2023-02-24T00:53:31.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/259/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x0 问题<a href="#0x0-问题"><span>#</span></a></h1><p>报错类似：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>AppArmor enabled on system but the docker-default profile could not be loaded: running `/usr/sbin/apparmor_parser apparmor_parser</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x1 解决<a href="#0x1-解决"><span>#</span></a></h1><p>在lxc的配置文件添加：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>lxc.apparmor.profile</span><span><span> </span><span>=</span><span> unconfined</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>添加后重启lxc</p><p>docker运行参数添加：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>--security-opt apparmor=unconfined</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果是以docker-compose，添加：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>services</span><span>:</span></div></div><div><div><div>2</div></div><div><span>  </span><span>your_service</span><span>:</span></div></div><div><div><div>3</div></div><div><span>    </span><span>security_opt</span><span>:</span></div></div><div><div><div>4</div></div><div><span><span>      </span></span><span>- </span><span>apparmor=unconfined</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/258/</id>
      <title type="text">【N5105】PVE+Docker+Jellyfin 核显直通 </title>
      <published>2023-02-19T02:41:00.000Z</published>
      <updated>2023-02-24T00:54:04.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/258/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>当前我使用的PVE版本是<code>7.3-3</code>当前的内核是<code>5.15.74</code>，网上教程试了一圈发现都不行。最后发现问题是内核的原因。</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>首先升级宿主机内核</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>apt</span><span> </span><span>update</span></div></div><div><div><div>2</div></div><div><span>apt</span><span> </span><span>upgrade</span><span> </span><span>-y</span></div></div><div><div><div>3</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>pve-kernel-5.19</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>查看固件</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>cd</span><span> </span><span>/lib/firmware/i915</span><span> &amp;&amp; </span><span>ls</span><span> </span><span>ehl_guc</span><span>*</span><span>.bin</span><span> &amp;&amp;  </span><span>ls</span><span> </span><span>ehl_huc</span><span>*</span><span>.bin</span><span> &amp;&amp;  </span><span>ls</span><span> </span><span>icl_dmc</span><span>*</span><span>.bin</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>修改配置并重启</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>echo</span><span> </span><span>"options i915 enable_guc=3"</span><span> &gt;&gt; </span><span>/etc/modprobe.d/i915.conf</span></div></div><div><div><div>2</div></div><div><span>reboot</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>启动后检查</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>journalctl</span><span> </span><span>-b</span><span> </span><span>-o</span><span> </span><span>short-monotonic</span><span> </span><span>-k</span><span> | </span><span>egrep</span><span> </span><span>-i</span><span> </span><span>"i915|dmr|dmc|guc|huc"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输出的内容中有<code>GuV</code> <code>HuC</code>就代表驱动成功</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>[    4.841415] home kernel: Setting dangerous option enable_guc - tainting kernel</span></div></div><div><div><div>2</div></div><div><span>[    4.866046] home kernel: i915 0000:00:02.0: vgaarb: deactivate vga console</span></div></div><div><div><div>3</div></div><div><span>[    4.869642] home kernel: i915 0000:00:02.0: vgaarb: changed VGA decodes: olddecodes=io+mem,decodes=io+mem:owns=io+mem</span></div></div><div><div><div>4</div></div><div><span>[    4.871436] home kernel: i915 0000:00:02.0: [drm] Finished loading DMC firmware i915/icl_dmc_ver1_09.bin (v1.9)</span></div></div><div><div><div>5</div></div><div><span>[    4.876510] home kernel: mei_hdcp 0000:00:16.0-b638ab7e-94e2-4ea2-a552-d1c54b627f04: bound 0000:00:02.0 (ops i915_hdcp_component_ops [i915])</span></div></div><div><div><div>6</div></div><div><span>[    5.545198] home kernel: i915 0000:00:02.0: [drm] failed to retrieve link info, disabling eDP</span></div></div><div><div><div>7</div></div><div><span>[    5.552915] home kernel: i915 0000:00:02.0: [drm] GuC firmware i915/ehl_guc_70.1.1.bin version 70.1</span></div></div><div><div><div>8</div></div><div><span>[    5.552922] home kernel: i915 0000:00:02.0: [drm] HuC firmware i915/ehl_huc_9.0.0.bin version 9.0</span></div></div><div><div><div>9</div></div><div><span>[    5.569445] home kernel: i915 0000:00:02.0: [drm] HuC authenticated</span></div></div><div><div><div>10</div></div><div><span>[    5.569889] home kernel: i915 0000:00:02.0: [drm] GuC submission enabled</span></div></div><div><div><div>11</div></div><div><span>[    5.569891] home kernel: i915 0000:00:02.0: [drm] GuC SLPC disabled</span></div></div><div><div><div>12</div></div><div><span>[    5.572145] home kernel: [drm] Initialized i915 1.6.0 20201103 for 0000:00:02.0 on minor 0</span></div></div><div><div><div>13</div></div><div><span>[    5.575832] home kernel: sof-audio-pci-intel-icl 0000:00:1f.3: bound 0000:00:02.0 (ops i915_audio_component_bind_ops [i915])</span></div></div><div><div><div>14</div></div><div><span>[    5.576361] home kernel: i915 0000:00:02.0: [drm] Cannot find any crtc or sizes</span></div></div><div><div><div>15</div></div><div><span>[    5.576501] home kernel: i915 0000:00:02.0: [drm] Cannot find any crtc or sizes</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>docker映射设备<code>/dev/dri:/dev/dri</code></p><p>jellyfin 硬解选择QSV</p><p>如果中间还加了一层<code>LXC</code>就在配置上添加</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>lxc.cgroup2.devices.allow: c 226:0 rwm</span></div></div><div><div><div>2</div></div><div><span>lxc.cgroup2.devices.allow: c 226:128 rwm</span></div></div><div><div><div>3</div></div><div><span>lxc.cgroup2.devices.allow: c 29:0 rwm</span></div></div><div><div><div>4</div></div><div><span>lxc.mount.entry: /dev/dri dev/dri none bind,optional,</span><span>create</span><span><span>=</span><span>dir</span></span></div></div><div><div><div>5</div></div><div><span>lxc.apparmor.profile: unconfined</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/257/</id>
      <title type="text">【脚本】docker日志清理</title>
      <published>2023-01-05T00:07:00.000Z</published>
      <updated>2023-01-05T00:09:09.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/257/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x0<a href="#0x0"><span>#</span></a></h1><p>docker的容器日志一般存储在<code>/var/lib/docker/containers/</code>下，容器的id的目录下有一个<code>-json.log</code>结尾的文件就是日志文件。</p><p>因为linux的文件系统原因，正在运行的容器中的日志直接删除是不会中断进程与文件的连接的，说人话就是“删不掉”（可以删除，但磁盘空间不会释放），所以直接删除就必须停止docker容器。</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>所以如果想不停docker容器的情况下清理日志，那就清空日志文件（这里用词是“清空”）。</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>echo</span><span> </span><span>""</span><span> | </span><span>sudo</span><span> </span><span>tee</span><span> </span><span>/var/lib/docker/containers/容器id/容器id-json.log</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>这里我使用<code>find</code>命令批量清理：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>find</span><span> </span><span>/var/lib/docker/containers/</span><span> </span><span>-name</span><span> </span><span>*</span><span>-json.log</span><span> </span><span>-size</span><span> </span><span>+10M</span><span> </span><span>-ok</span><span> </span><span>dd</span><span> </span><span>if=/dev/null</span><span> </span><span>of={}</span><span> </span><span>\;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>参数：</p><p><code>-name</code> 文件名匹配</p><p><code>-size +10M</code> 匹配大小超过10M的文件</p><p><code>-ok</code> 后面接匹配到文件后执行命令，会提示输入<code>y/n</code>的保险来确认是否执行命令，如果想不提示<code>y/n</code>就自动处理就将<code>-ok</code>替换为<code>-exec</code>，命令最后面接<code>\;</code>结束命令</p><p>这里将文件置空我使用的是<code>dd if=/dev/null of={}</code>，其中的<code>{}</code>表示文件路径，是<code>find</code>的占位符会自动替换为匹配到的文件路径。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/256/</id>
      <title type="text">【Linux】文件备份脚本</title>
      <published>2022-10-26T10:14:00.000Z</published>
      <updated>2022-10-26T10:42:20.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/256/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/bash</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>backup_num</span><span>=</span><span>3</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>function</span><span> </span><span>help</span><span>() {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>echo</span><span> </span><span>"-in 源文件路径"</span></div></div><div><div><div>7</div></div><div><span>  </span><span>echo</span><span> </span><span>"-out 备份路径"</span></div></div><div><div><div>8</div></div><div><span>  </span><span>echo</span><span> </span><span>"-backup_num 备份数量"</span></div></div><div><div><div>9</div></div><div><span>  </span><span>echo</span><span> </span><span>"-inKey 使用公钥加密，详情：https://github.com/Rehtt/archive"</span></div></div><div><div><div>10</div></div><div><span>  </span><span>echo</span><span> </span><span>"-genKey 生成密钥对，详情：https://github.com/Rehtt/archive"</span></div></div><div><div><div>11</div></div><div><span>  </span><span>exit</span><span> </span><span>0</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>while</span><span> [ </span><span>$#</span><span><span> </span><span>-gt</span><span> </span></span><span>0</span><span> ]; </span><span>do</span></div></div><div><div><div>15</div></div><div><span>  </span><span>case</span><span><span> </span><span>$1</span><span> </span></span><span>in</span></div></div><div><div><div>16</div></div><div><span>  </span><span>-in</span><span>)</span></div></div><div><div><div>17</div></div><div><span>    </span><span>in_path</span><span>=</span><span>"</span><span>$2</span><span>"</span></div></div><div><div><div>18</div></div><div><span>    </span><span>shift</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>20</div></div><div><span>  </span><span>-out</span><span>)</span></div></div><div><div><div>21</div></div><div><span>    </span><span>out</span><span>=</span><span>"</span><span>$2</span><span>"</span></div></div><div><div><div>22</div></div><div><span>    </span><span>shift</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>24</div></div><div><span>  </span><span>-backup_num</span><span>)</span></div></div><div><div><div>25</div></div><div><span>    </span><span>backup_num</span><span><span>=</span><span>$2</span></span></div></div><div><div><div>26</div></div><div><span>    </span><span>shift</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>28</div></div><div><span>  </span><span>-inKey</span><span>)</span></div></div><div><div><div>29</div></div><div><span>    </span><span>inKey</span><span>=</span><span>"</span><span>$2</span><span>"</span></div></div><div><div><div>30</div></div><div><span>    </span><span>shift</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>32</div></div><div><span>  </span><span>-genKey</span><span>)</span></div></div><div><div><div>33</div></div><div><span>    </span><span>archive</span><span> </span><span>-generateRsaKey</span></div></div><div><div><div>34</div></div><div><span>    </span><span>exit</span><span> </span><span>0</span></div></div><div><div><div>35</div></div><div><span>    </span><span>shift</span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>37</div></div><div><span>  </span><span>-help</span><span>)</span></div></div><div><div><div>38</div></div><div><span>    </span><span>help</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>40</div></div><div><span>  </span><span>-h</span><span>)</span></div></div><div><div><div>41</div></div><div><span>    </span><span>help</span></div></div><div><div><div>42</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>43</div></div><div><span>  </span><span>esac</span></div></div><div><div><div>44</div></div><div><span>  </span><span>shift</span></div></div><div><div><div>45</div></div><div><span>done</span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span>if</span><span> [ x</span><span>"</span><span>$in_path</span><span>"</span><span><span> </span><span>=</span><span> x ]; </span></span><span>then</span></div></div><div><div><div>48</div></div><div><span>  </span><span>help</span></div></div><div><div><div>49</div></div><div><span>fi</span></div></div><div><div><div>50</div></div><div><span>if</span><span> [ x</span><span>"</span><span>$out</span><span>"</span><span><span> </span><span>=</span><span> x ]; </span></span><span>then</span></div></div><div><div><div>51</div></div><div><span>  </span><span>help</span></div></div><div><div><div>52</div></div><div><span>fi</span></div></div><div><div><div>53</div></div><div>
</div></div><div><div><div>54</div></div><div><span>filename</span><span><span>=</span><span>$(</span></span><span>basename</span><span> </span><span>"</span><span>$in_path</span><span>"</span><span>)</span></div></div><div><div><div>55</div></div><div><span>tmp_file</span><span>=</span><span>"/tmp/</span><span>$filename</span><span>-$(</span><span>date</span><span> +%Y-%m-%d).tar.xz"</span></div></div><div><div><div>56</div></div><div><span>out</span><span>=</span><span>"</span><span>$out</span><span>/</span><span>$filename</span><span>"</span></div></div><div><div><div>57</div></div><div>
</div></div><div><div><div>58</div></div><div><span>function</span><span> </span><span>get_last_file</span><span>() {</span></div></div><div><div><div>59</div></div><div><span>  </span><span>local</span><span> </span><span>time</span><span>=</span><span>1</span></div></div><div><div><div>60</div></div><div><span>  </span><span>del_file</span><span>=</span><span>""</span></div></div><div><div><div>61</div></div><div><span>  </span><span>file_num</span><span>=</span><span>0</span></div></div><div><div><div>62</div></div><div><span>  </span><span>while</span><span> [ </span><span>$#</span><span><span> </span><span>-gt</span><span> </span></span><span>0</span><span> ]; </span><span>do</span></div></div><div><div><div>63</div></div><div><span>    </span><span>local</span><span> </span><span>name</span><span><span>=</span><span>$1</span></span></div></div><div><div><div>64</div></div><div><span>    </span><span>local</span><span> </span><span>name</span><span>=</span><span><span>${</span><span>name</span></span><span>##*/</span><span>}</span></div></div><div><div><div>65</div></div><div><span>    </span><span>local</span><span> </span><span>t</span><span><span>=</span><span>$(</span></span><span>echo</span><span> </span><span>$name</span><span> | </span><span>grep</span><span> </span><span>-o</span><span> </span><span>'[[:digit:]]\{4,\}-[[:digit:]]\{1,2\}-[[:digit:]]\{1,2\}'</span><span>)</span></div></div><div><div><div>66</div></div><div><span>    </span><span>if</span><span> [ x</span><span>"</span><span>$t</span><span>"</span><span><span> </span><span>=</span><span> x ]; </span></span><span>then</span></div></div><div><div><div>67</div></div><div><span>      </span><span>shift</span></div></div><div><div><div>68</div></div><div><span>      </span><span>continue</span></div></div><div><div><div>69</div></div><div><span>    </span><span>fi</span></div></div><div><div><div>70</div></div><div><span>    </span><span>local</span><span> </span><span>date_str</span><span><span>=</span><span>$(</span></span><span>date</span><span> </span><span>+%s</span><span> </span><span>-d</span><span> </span><span>"</span><span>$t</span><span>"</span><span>)</span></div></div><div><div><div>71</div></div><div><span>    </span><span>file_num</span><span><span>=</span><span>$((</span></span><span>$file_num</span><span> + 1))</span></div></div><div><div><div>72</div></div><div><span>    </span><span>#    echo $name</span></div></div><div><div><div>73</div></div><div><span>    </span><span>local</span><span> </span><span>now</span><span><span>=</span><span>$(</span></span><span>date</span><span> </span><span>+%s</span><span>)</span></div></div><div><div><div>74</div></div><div><span>    </span><span>if</span><span> [[ $((</span><span>$now</span><span> - </span><span>$date_str</span><span><span>)) </span><span>-gt</span><span> </span></span><span>$time</span><span> ]]; </span><span>then</span></div></div><div><div><div>75</div></div><div><span>      </span><span>local</span><span> </span><span>time</span><span><span>=</span><span>$((</span></span><span>$now</span><span> - </span><span>$date_str</span><span>))</span></div></div><div><div><div>76</div></div><div><span>      </span><span>del_file</span><span>=</span><span>$name</span></div></div><div><div><div>77</div></div><div><span>    </span><span>fi</span></div></div><div><div><div>78</div></div><div><span>    </span><span>shift</span></div></div><div><div><div>79</div></div><div><span>  </span><span>done</span></div></div><div><div><div>80</div></div><div><span>}</span></div></div><div><div><div>81</div></div><div>
</div></div><div><div><div>82</div></div><div><span>#判断是否加密</span></div></div><div><div><div>83</div></div><div><span>if</span><span> [ x</span><span>"</span><span>$inKey</span><span>"</span><span><span> </span><span>=</span><span> x ]; </span></span><span>then</span></div></div><div><div><div>84</div></div><div><span>  </span><span>tar</span><span> </span><span>-Jcvf</span><span> </span><span>"</span><span>$tmp_file</span><span>"</span><span> </span><span>"</span><span>$in_path</span><span>"</span></div></div><div><div><div>85</div></div><div><span>else</span></div></div><div><div><div>86</div></div><div><span>  </span><span>tmp_file</span><span>=</span><span>$tmp_file</span><span>.d</span></div></div><div><div><div>87</div></div><div><span>  </span><span>if</span><span> [ x</span><span>"$(</span><span>which</span><span> archive)"</span><span><span> </span><span>=</span><span> x ]; </span></span><span>then</span></div></div><div><div><div>88</div></div><div><span>    </span><span>echo</span><span> </span><span>"缺少archive"</span></div></div><div><div><div>89</div></div><div><span>    </span><span>help</span></div></div><div><div><div>90</div></div><div><span>  </span><span>fi</span></div></div><div><div><div>91</div></div><div><span>  </span><span>archive</span><span> </span><span>-a</span><span> </span><span>-e</span><span> </span><span>-inKey</span><span> </span><span>"</span><span>$inKey</span><span>"</span><span> </span><span>-in</span><span> </span><span>"</span><span>$in_path</span><span>"</span><span> </span><span>-out</span><span> </span><span>"</span><span>$tmp_file</span><span>"</span></div></div><div><div><div>92</div></div><div><span>fi</span></div></div><div><div><div>93</div></div><div>
</div></div><div><div><div>94</div></div><div><span># 判断是本地保存还是用rclone保存</span></div></div><div><div><div>95</div></div><div><span>if</span><span> [[ $(</span><span>echo</span><span> </span><span>"</span><span>$out</span><span>"</span><span> | </span><span>grep</span><span> </span><span>":"</span><span><span>) </span><span>!=</span><span> </span></span><span>""</span><span> ]]; </span><span>then</span></div></div><div><div><div>96</div></div><div><span>  </span><span>if</span><span> [ x</span><span>"$(</span><span>which</span><span> rclone)"</span><span><span> </span><span>=</span><span> x ]; </span></span><span>then</span></div></div><div><div><div>97</div></div><div><span>    </span><span>echo</span><span> </span><span>"缺少rclone"</span></div></div><div><div><div>98</div></div><div><span>    </span><span>help</span></div></div><div><div><div>99</div></div><div><span>  </span><span>fi</span></div></div><div><div><div>100</div></div><div><span>  </span><span>rclone</span><span> </span><span>mkdir</span><span> </span><span>"</span><span>$out</span><span>"</span></div></div><div><div><div>101</div></div><div><span>  </span><span>list</span><span><span>=</span><span>$(</span></span><span>rclone</span><span> </span><span>ls</span><span> </span><span>"</span><span>$out</span><span>"</span><span>)</span></div></div><div><div><div>102</div></div><div><span>  </span><span>get_last_file</span><span> </span><span>$list</span></div></div><div><div><div>103</div></div><div><span>  </span><span>while</span><span> [ </span><span>$file_num</span><span><span> </span><span>-ge</span><span> </span></span><span>$backup_num</span><span> ]; </span><span>do</span></div></div><div><div><div>104</div></div><div><span>    </span><span>rclone</span><span> </span><span>delete</span><span> </span><span>"</span><span>$out</span><span>/</span><span>$del_file</span><span>"</span></div></div><div><div><div>105</div></div><div><span>    </span><span>list</span><span><span>=</span><span>$(</span></span><span>rclone</span><span> </span><span>ls</span><span> </span><span>"</span><span>$out</span><span>"</span><span>)</span></div></div><div><div><div>106</div></div><div><span>    </span><span>get_last_file</span><span> </span><span>$list</span></div></div><div><div><div>107</div></div><div><span>  </span><span>done</span></div></div><div><div><div>108</div></div><div><span>  </span><span>rclone</span><span> </span><span>copy</span><span> </span><span>"</span><span>$tmp_file</span><span>"</span><span> </span><span>"</span><span>$out</span><span>"</span></div></div><div><div><div>109</div></div><div><span>else</span></div></div><div><div><div>110</div></div><div><span>  </span><span>mkdir</span><span> </span><span>-p</span><span> </span><span>"</span><span>$out</span><span>"</span></div></div><div><div><div>111</div></div><div><span>  </span><span>list</span><span><span>=</span><span>$(</span></span><span>ls</span><span> </span><span>"</span><span>$out</span><span>"</span><span>)</span></div></div><div><div><div>112</div></div><div><span>  </span><span>get_last_file</span><span> </span><span>$list</span></div></div><div><div><div>113</div></div><div><span>  </span><span>while</span><span> [ </span><span>$file_num</span><span><span> </span><span>-ge</span><span> </span></span><span>$backup_num</span><span> ]; </span><span>do</span></div></div><div><div><div>114</div></div><div><span>    </span><span>rm</span><span> </span><span>-f</span><span> </span><span>"</span><span>$out</span><span>/</span><span>$del_file</span><span>"</span></div></div><div><div><div>115</div></div><div><span>    </span><span>list</span><span><span>=</span><span>$(</span></span><span>ls</span><span> </span><span>"</span><span>$out</span><span>"</span><span>)</span></div></div><div><div><div>116</div></div><div><span>    </span><span>get_last_file</span><span> </span><span>$list</span></div></div><div><div><div>117</div></div><div><span>  </span><span>done</span></div></div><div><div><div>118</div></div><div><span>  </span><span>cp</span><span> </span><span>"</span><span>$tmp_file</span><span>"</span><span> </span><span>"</span><span>$out</span><span>"</span></div></div><div><div><div>119</div></div><div><span>fi</span></div></div><div><div><div>120</div></div><div><span>rm</span><span> </span><span>-f</span><span> </span><span>"</span><span>$tmp_file</span><span>"</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/255/</id>
      <title type="text">【Golang】调用syscall调用windows dll弹窗</title>
      <published>2022-09-22T02:47:18.000Z</published>
      <updated>2022-09-22T02:47:18.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/255/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>main</span></div></div><div><div><div>2</div></div><div><span>import</span><span> (</span></div></div><div><div><div>3</div></div><div><span>    </span><span>"fmt"</span></div></div><div><div><div>4</div></div><div><span>    </span><span>"syscall"</span></div></div><div><div><div>5</div></div><div><span>    </span><span>"time"</span></div></div><div><div><div>6</div></div><div><span>    </span><span>"unsafe"</span></div></div><div><div><div>7</div></div><div><span>)</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>const</span><span> (</span></div></div><div><div><div>10</div></div><div><span>    </span><span>MB_OK</span><span><span>                </span><span>=</span><span> </span></span><span><span>0x</span><span>00000000</span></span></div></div><div><div><div>11</div></div><div><span>    </span><span>MB_OKCANCEL</span><span><span>          </span><span>=</span><span> </span></span><span><span>0x</span><span>00000001</span></span></div></div><div><div><div>12</div></div><div><span>    </span><span>MB_ABORTRETRYIGNORE</span><span><span>  </span><span>=</span><span> </span></span><span><span>0x</span><span>00000002</span></span></div></div><div><div><div>13</div></div><div><span>    </span><span>MB_YESNOCANCEL</span><span><span>       </span><span>=</span><span> </span></span><span><span>0x</span><span>00000003</span></span></div></div><div><div><div>14</div></div><div><span>    </span><span>MB_YESNO</span><span><span>             </span><span>=</span><span> </span></span><span><span>0x</span><span>00000004</span></span></div></div><div><div><div>15</div></div><div><span>    </span><span>MB_RETRYCANCEL</span><span><span>       </span><span>=</span><span> </span></span><span><span>0x</span><span>00000005</span></span></div></div><div><div><div>16</div></div><div><span>    </span><span>MB_CANCELTRYCONTINUE</span><span><span> </span><span>=</span><span> </span></span><span><span>0x</span><span>00000006</span></span></div></div><div><div><div>17</div></div><div><span>    </span><span>MB_ICONHAND</span><span><span>          </span><span>=</span><span> </span></span><span><span>0x</span><span>00000010</span></span></div></div><div><div><div>18</div></div><div><span>    </span><span>MB_ICONQUESTION</span><span><span>      </span><span>=</span><span> </span></span><span><span>0x</span><span>00000020</span></span></div></div><div><div><div>19</div></div><div><span>    </span><span>MB_ICONEXCLAMATION</span><span><span>   </span><span>=</span><span> </span></span><span><span>0x</span><span>00000030</span></span></div></div><div><div><div>20</div></div><div><span>    </span><span>MB_ICONASTERISK</span><span><span>      </span><span>=</span><span> </span></span><span><span>0x</span><span>00000040</span></span></div></div><div><div><div>21</div></div><div><span>    </span><span>MB_USERICON</span><span><span>          </span><span>=</span><span> </span></span><span><span>0x</span><span>00000080</span></span></div></div><div><div><div>22</div></div><div><span>    </span><span>MB_ICONWARNING</span><span><span>       </span><span>=</span><span> </span></span><span>MB_ICONEXCLAMATION</span></div></div><div><div><div>23</div></div><div><span>    </span><span>MB_ICONERROR</span><span><span>         </span><span>=</span><span> </span></span><span>MB_ICONHAND</span></div></div><div><div><div>24</div></div><div><span>    </span><span>MB_ICONINFORMATION</span><span><span>   </span><span>=</span><span> </span></span><span>MB_ICONASTERISK</span></div></div><div><div><div>25</div></div><div><span>    </span><span>MB_ICONSTOP</span><span><span>          </span><span>=</span><span> </span></span><span>MB_ICONHAND</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>    </span><span>MB_DEFBUTTON1</span><span><span> </span><span>=</span><span> </span></span><span><span>0x</span><span>00000000</span></span></div></div><div><div><div>28</div></div><div><span>    </span><span>MB_DEFBUTTON2</span><span><span> </span><span>=</span><span> </span></span><span><span>0x</span><span>00000100</span></span></div></div><div><div><div>29</div></div><div><span>    </span><span>MB_DEFBUTTON3</span><span><span> </span><span>=</span><span> </span></span><span><span>0x</span><span>00000200</span></span></div></div><div><div><div>30</div></div><div><span>    </span><span>MB_DEFBUTTON4</span><span><span> </span><span>=</span><span> </span></span><span><span>0x</span><span>00000300</span></span></div></div><div><div><div>31</div></div><div><span>)</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>func</span><span> </span><span>abort</span><span><span>(</span><span>funcname</span><span> </span></span><span>string</span><span><span>, </span><span>err</span><span> </span></span><span>syscall</span><span>.</span><span>Errno</span><span>) {</span></div></div><div><div><div>34</div></div><div><span>    </span><span>panic</span><span>(</span><span>funcname</span><span><span> </span><span>+</span><span> </span></span><span>" failed: "</span><span><span> </span><span>+</span><span> </span></span><span>err</span><span>.</span><span>Error</span><span>())</span></div></div><div><div><div>35</div></div><div><span>}</span></div></div><div><div><div>36</div></div><div>
</div></div><div><div><div>37</div></div><div><span>var</span><span> (</span></div></div><div><div><div>38</div></div><div><span>    </span><span>user32</span><span>, </span><span>_</span><span><span>     </span><span>=</span><span> </span></span><span>syscall</span><span>.</span><span>LoadLibrary</span><span>(</span><span>"user32.dll"</span><span>)</span></div></div><div><div><div>39</div></div><div><span>    </span><span>messageBox</span><span>, </span><span>_</span><span><span> </span><span>=</span><span> </span></span><span>syscall</span><span>.</span><span>GetProcAddress</span><span>(</span><span>user32</span><span>, </span><span>"MessageBoxW"</span><span>)</span></div></div><div><div><div>40</div></div><div><span>)</span></div></div><div><div><div>41</div></div><div>
</div></div><div><div><div>42</div></div><div><span>func</span><span> </span><span>IntPtr</span><span><span>(</span><span>n</span><span> </span></span><span>int</span><span>) </span><span>uintptr</span><span> {</span></div></div><div><div><div>43</div></div><div><span>    </span><span>return</span><span> </span><span>uintptr</span><span>(</span><span>n</span><span>)</span></div></div><div><div><div>44</div></div><div><span>}</span></div></div><div><div><div>45</div></div><div>
</div></div><div><div><div>46</div></div><div><span>func</span><span> </span><span>StrPtr</span><span><span>(</span><span>s</span><span> </span></span><span>string</span><span>) </span><span>uintptr</span><span> {</span></div></div><div><div><div>47</div></div><div><span>    </span><span>return</span><span> </span><span>uintptr</span><span>(</span><span>unsafe</span><span>.</span><span>Pointer</span><span>(</span><span>syscall</span><span>.</span><span>StringToUTF16Ptr</span><span>(</span><span>s</span><span>)))</span></div></div><div><div><div>48</div></div><div><span>}</span></div></div><div><div><div>49</div></div><div>
</div></div><div><div><div>50</div></div><div><span>func</span><span> </span><span>MessageBox</span><span><span>(</span><span>caption</span><span>, </span><span>text</span><span> </span></span><span>string</span><span><span>, </span><span>style</span><span> </span></span><span>uintptr</span><span><span>) (</span><span>result</span><span> </span></span><span>int</span><span>) {</span></div></div><div><div><div>51</div></div><div><span>    </span><span>ret</span><span>, </span><span>_</span><span>, </span><span>callErr</span><span><span> </span><span>:=</span><span> </span></span><span>syscall</span><span>.</span><span>Syscall9</span><span>(</span><span>messageBox</span><span>,</span></div></div><div><div><div>52</div></div><div><span>        </span><span>4</span><span>,</span></div></div><div><div><div>53</div></div><div><span>        </span><span>0</span><span>,</span></div></div><div><div><div>54</div></div><div><span>        </span><span>StrPtr</span><span>(</span><span>text</span><span>),</span></div></div><div><div><div>55</div></div><div><span>        </span><span>StrPtr</span><span>(</span><span>caption</span><span>),</span></div></div><div><div><div>56</div></div><div><span>        </span><span>style</span><span>,</span></div></div><div><div><div>57</div></div><div><span>        </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>0</span><span>)</span></div></div><div><div><div>58</div></div><div><span>    </span><span>if</span><span> </span><span>callErr</span><span><span> </span><span>!=</span><span> </span></span><span>0</span><span> {</span></div></div><div><div><div>59</div></div><div><span>        </span><span>abort</span><span>(</span><span>"Call MessageBox"</span><span>, </span><span>callErr</span><span>)</span></div></div><div><div><div>60</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>61</div></div><div><span>    </span><span>result</span><span><span> </span><span>=</span><span> </span></span><span>int</span><span>(</span><span>ret</span><span>)</span></div></div><div><div><div>62</div></div><div><span>    </span><span>return</span></div></div><div><div><div>63</div></div><div><span>}</span></div></div><div><div><div>64</div></div><div>
</div></div><div><div><div>65</div></div><div><span>func</span><span> </span><span>ShowMessage2</span><span><span>(</span><span>title</span><span>, </span><span>text</span><span> </span></span><span>string</span><span>) {</span></div></div><div><div><div>66</div></div><div><span>    </span><span>user32</span><span><span> </span><span>:=</span><span> </span></span><span>syscall</span><span>.</span><span>NewLazyDLL</span><span>(</span><span>"user32.dll"</span><span>)</span></div></div><div><div><div>67</div></div><div><span>    </span><span>MessageBoxW</span><span><span> </span><span>:=</span><span> </span></span><span>user32</span><span>.</span><span>NewProc</span><span>(</span><span>"MessageBoxW"</span><span>)</span></div></div><div><div><div>68</div></div><div><span>    </span><span>MessageBoxW</span><span>.</span><span>Call</span><span>(</span><span>IntPtr</span><span>(</span><span>0</span><span>), </span><span>StrPtr</span><span>(</span><span>text</span><span>), </span><span>StrPtr</span><span>(</span><span>title</span><span>), </span><span>IntPtr</span><span>(</span><span>0</span><span>))</span></div></div><div><div><div>69</div></div><div><span>}</span></div></div><div><div><div>70</div></div><div>
</div></div><div><div><div>71</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>72</div></div><div><span>    </span><span>defer</span><span> </span><span>syscall</span><span>.</span><span>FreeLibrary</span><span>(</span><span>user32</span><span>)</span></div></div><div><div><div>73</div></div><div>
</div></div><div><div><div>74</div></div><div><span>    </span><span>num</span><span><span> </span><span>:=</span><span> </span></span><span>MessageBox</span><span>(</span><span>"Title1"</span><span>, </span><span>"test1"</span><span>, </span><span>MB_YESNOCANCEL</span><span>)</span></div></div><div><div><div>75</div></div><div><span>    </span><span>fmt</span><span>.</span><span>Printf</span><span>(</span><span>"Get Retrun Value Before MessageBox </span><span>%d</span><span>\n</span><span>"</span><span>, </span><span>num</span><span>)</span></div></div><div><div><div>76</div></div><div><span>    </span><span>ShowMessage2</span><span>(</span><span>"Title2"</span><span>, </span><span>"test2"</span><span>)</span></div></div><div><div><div>77</div></div><div><span>    </span><span>time</span><span>.</span><span>Sleep</span><span>(</span><span>3</span><span><span> </span><span>*</span><span> </span></span><span>time</span><span>.</span><span>Second</span><span>)</span></div></div><div><div><div>78</div></div><div><span>}</span></div></div><div><div><div>79</div></div><div>
</div></div><div><div><div>80</div></div><div><span>func</span><span> </span><span>init</span><span>() {</span></div></div><div><div><div>81</div></div><div><span>    </span><span>fmt</span><span>.</span><span>Print</span><span>(</span><span>"start...</span><span>\n</span><span>"</span><span>)</span></div></div><div><div><div>82</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/254/</id>
      <title type="text">【Golang】Go的构建模式</title>
      <published>2022-05-05T12:38:09.000Z</published>
      <updated>2022-05-05T12:38:09.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/254/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<blockquote><p>未完成</p></blockquote>
<p>构建模式是在<code>go build</code>打包二进制的时候指定的打包模式，通过<code>go help buildmode</code>查看支持的打包模式</p>
<div><div><div><figure><figcaption><span></span><span>Terminal window</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>go</span><span> </span><span>version</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>go</span><span> </span><span>version</span><span> </span><span>go1.18.1</span><span> </span><span>linux/amd64</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>$</span><span> </span><span>go</span><span> </span><span>help</span><span> </span><span>buildmode</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>The</span><span> </span><span>'go build'</span><span> </span><span>and</span><span> </span><span>'go install'</span><span> </span><span>commands</span><span> </span><span>take</span><span> </span><span>a</span><span> </span><span>-buildmode</span><span> </span><span>argument</span><span> </span><span>which</span></div></div><div><div><div>8</div></div><div><span>indicates</span><span> </span><span>which</span><span> </span><span>kind</span><span> </span><span>of</span><span> </span><span>object</span><span> </span><span>file</span><span> </span><span>is</span><span> </span><span>to</span><span> </span><span>be</span><span> </span><span>built.</span><span> </span><span>Currently</span><span> </span><span>supported</span><span> </span><span>values</span></div></div><div><div><div>9</div></div><div><span>are:</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>        </span><span>-buildmode</span><span>=</span><span>archive</span></div></div><div><div><div>12</div></div><div><span>                </span><span>Build</span><span> </span><span>the</span><span> </span><span>listed</span><span> </span><span>non-main</span><span> </span><span>packages</span><span> </span><span>into</span><span> </span><span>.a</span><span> </span><span>files.</span><span> </span><span>Packages</span><span> </span><span>named</span></div></div><div><div><div>13</div></div><div><span>                </span><span>main</span><span> </span><span>are</span><span> </span><span>ignored.</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>        </span><span>-buildmode</span><span>=</span><span>c-archive</span></div></div><div><div><div>16</div></div><div><span>                </span><span>Build</span><span> </span><span>the</span><span> </span><span>listed</span><span> </span><span>main</span><span> </span><span>package,</span><span> </span><span>plus</span><span> </span><span>all</span><span> </span><span>packages</span><span> </span><span>it</span><span> </span><span>imports,</span></div></div><div><div><div>17</div></div><div><span>                </span><span>into</span><span> </span><span>a</span><span> </span><span>C</span><span> </span><span>archive</span><span> </span><span>file.</span><span> </span><span>The</span><span> </span><span>only</span><span> </span><span>callable</span><span> </span><span>symbols</span><span> </span><span>will</span><span> </span><span>be</span><span> </span><span>those</span></div></div><div><div><div>18</div></div><div><span>                </span><span>functions</span><span> </span><span>exported</span><span> </span><span>using</span><span> </span><span>a</span><span> </span><span>cgo</span><span> </span><span>//export</span><span> </span><span>comment.</span><span> </span><span>Requires</span></div></div><div><div><div>19</div></div><div><span>                </span><span>exactly</span><span> </span><span>one</span><span> </span><span>main</span><span> </span><span>package</span><span> </span><span>to</span><span> </span><span>be</span><span> </span><span>listed.</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>        </span><span>-buildmode</span><span>=</span><span>c-shared</span></div></div><div><div><div>22</div></div><div><span>                </span><span>Build</span><span> </span><span>the</span><span> </span><span>listed</span><span> </span><span>main</span><span> </span><span>package,</span><span> </span><span>plus</span><span> </span><span>all</span><span> </span><span>packages</span><span> </span><span>it</span><span> </span><span>imports,</span></div></div><div><div><div>23</div></div><div><span>                </span><span>into</span><span> </span><span>a</span><span> </span><span>C</span><span> </span><span>shared</span><span> </span><span>library.</span><span> </span><span>The</span><span> </span><span>only</span><span> </span><span>callable</span><span> </span><span>symbols</span><span> </span><span>will</span></div></div><div><div><div>24</div></div><div><span>                </span><span>be</span><span> </span><span>those</span><span> </span><span>functions</span><span> </span><span>exported</span><span> </span><span>using</span><span> </span><span>a</span><span> </span><span>cgo</span><span> </span><span>//export</span><span> </span><span>comment.</span></div></div><div><div><div>25</div></div><div><span>                </span><span>Requires</span><span> </span><span>exactly</span><span> </span><span>one</span><span> </span><span>main</span><span> </span><span>package</span><span> </span><span>to</span><span> </span><span>be</span><span> </span><span>listed.</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>        </span><span>-buildmode</span><span>=</span><span>default</span></div></div><div><div><div>28</div></div><div><span>                </span><span>Listed</span><span> </span><span>main</span><span> </span><span>packages</span><span> </span><span>are</span><span> </span><span>built</span><span> </span><span>into</span><span> </span><span>executables</span><span> </span><span>and</span><span> </span><span>listed</span></div></div><div><div><div>29</div></div><div><span>                </span><span>non-main</span><span> </span><span>packages</span><span> </span><span>are</span><span> </span><span>built</span><span> </span><span>into</span><span> </span><span>.a</span><span> </span><span>files</span><span> (the </span><span>default</span></div></div><div><div><div>30</div></div><div><span>                </span><span>behavior</span><span>).</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>        </span><span>-buildmode</span><span>=</span><span>shared</span></div></div><div><div><div>33</div></div><div><span>                </span><span>Combine</span><span> </span><span>all</span><span> </span><span>the</span><span> </span><span>listed</span><span> </span><span>non-main</span><span> </span><span>packages</span><span> </span><span>into</span><span> </span><span>a</span><span> </span><span>single</span><span> </span><span>shared</span></div></div><div><div><div>34</div></div><div><span>                </span><span>library</span><span> </span><span>that</span><span> </span><span>will</span><span> </span><span>be</span><span> </span><span>used</span><span> </span><span>when</span><span> </span><span>building</span><span> </span><span>with</span><span> </span><span>the</span><span> </span><span>-linkshared</span></div></div><div><div><div>35</div></div><div><span>                </span><span>option.</span><span> </span><span>Packages</span><span> </span><span>named</span><span> </span><span>main</span><span> </span><span>are</span><span> </span><span>ignored.</span></div></div><div><div><div>36</div></div><div>
</div></div><div><div><div>37</div></div><div><span>        </span><span>-buildmode</span><span>=</span><span>exe</span></div></div><div><div><div>38</div></div><div><span>                </span><span>Build</span><span> </span><span>the</span><span> </span><span>listed</span><span> </span><span>main</span><span> </span><span>packages</span><span> </span><span>and</span><span> </span><span>everything</span><span> </span><span>they</span><span> </span><span>import</span><span> </span><span>into</span></div></div><div><div><div>39</div></div><div><span>                </span><span>executables.</span><span> </span><span>Packages</span><span> </span><span>not</span><span> </span><span>named</span><span> </span><span>main</span><span> </span><span>are</span><span> </span><span>ignored.</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>        </span><span>-buildmode</span><span>=</span><span>pie</span></div></div><div><div><div>42</div></div><div><span>                </span><span>Build</span><span> </span><span>the</span><span> </span><span>listed</span><span> </span><span>main</span><span> </span><span>packages</span><span> </span><span>and</span><span> </span><span>everything</span><span> </span><span>they</span><span> </span><span>import</span><span> </span><span>into</span></div></div><div><div><div>43</div></div><div><span>                </span><span>position</span><span> </span><span>independent</span><span> </span><span>executables</span><span> (PIE). Packages not named</span></div></div><div><div><div>44</div></div><div><span>                </span><span>main</span><span> </span><span>are</span><span> </span><span>ignored.</span></div></div><div><div><div>45</div></div><div>
</div></div><div><div><div>46</div></div><div><span>        </span><span>-buildmode</span><span>=</span><span>plugin</span></div></div><div><div><div>47</div></div><div><span>                </span><span>Build</span><span> </span><span>the</span><span> </span><span>listed</span><span> </span><span>main</span><span> </span><span>packages,</span><span> </span><span>plus</span><span> </span><span>all</span><span> </span><span>packages</span><span> </span><span>that</span><span> </span><span>they</span></div></div><div><div><div>48</div></div><div><span>                </span><span>import,</span><span> </span><span>into</span><span> </span><span>a</span><span> </span><span>Go</span><span> </span><span>plugin.</span><span> </span><span>Packages</span><span> </span><span>not</span><span> </span><span>named</span><span> </span><span>main</span><span> </span><span>are</span><span> </span><span>ignored.</span></div></div><div><div><div>49</div></div><div>
</div></div><div><div><div>50</div></div><div><span>On</span><span> </span><span>AIX,</span><span> </span><span>when</span><span> </span><span>linking</span><span> </span><span>a</span><span> </span><span>C</span><span> </span><span>program</span><span> </span><span>that</span><span> </span><span>uses</span><span> </span><span>a</span><span> </span><span>Go</span><span> </span><span>archive</span><span> </span><span>built</span><span> </span><span>with</span></div></div><div><div><div>51</div></div><div><span>-buildmode</span><span>=</span><span>c-archive,</span><span> </span><span>you</span><span> </span><span>must</span><span> </span><span>pass</span><span> </span><span>-Wl,-bnoobjreorder</span><span> </span><span>to</span><span> </span><span>the</span><span> </span><span>C</span><span> </span><span>compiler.</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<br />
<section><h1>archive 模式<a href="#archive-模式"><span>#</span></a></h1><br /></section>
<section><h1>shared 模式<a href="#shared-模式"><span>#</span></a></h1><br /></section>
<section><h1>c-archive 模式<a href="#c-archive-模式"><span>#</span></a></h1><br /></section>
<section><h1>c-shared 模式<a href="#c-shared-模式"><span>#</span></a></h1><br /></section>
<section><h1>exe 模式<a href="#exe-模式"><span>#</span></a></h1><br /></section>
<section><h1>pie 模式<a href="#pie-模式"><span>#</span></a></h1><p>是一种使用PIE技术的安全编译模式，能提供一定防反编译的防护能力（但也不能只寄望与一种技术，世界上没有绝对的技术）</p><section><h2>PIE技术<a href="#pie技术"><span>#</span></a></h2><p>PIE全称是position-independent executable，中文解释为地址无关可执行文件。</p><p>一般程序的代码段(<code>.text</code>)、数据段(<code>.data</code>)和全局变量段(<code>.bss</code>)加载时是一个固定的地址，而PIE技术就是使其每次加载程序时都会变换地址，所以提高了反编译的难度。</p><br /></section></section>
<section><h1>plugin 模式<a href="#plugin-模式"><span>#</span></a></h1><p>该模式会将非<code>main</code>包的go程序打包成可以热加载的插件。</p><p>==不过，目前使用这种模板打包插件还是有缺陷的，首先它不支持<code>windows</code>下打包和使用，其次插件不支持热卸载==</p><section><h2>使用<a href="#使用"><span>#</span></a></h2><p>插件要求是 编译插件的包名必须是<code>main</code></p><p><code>hello.go</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>main</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>import</span><span> </span><span>"fmt"</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>func</span><span> </span><span>Hello</span><span><span>(</span><span>say</span><span> </span></span><span>any</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>"在hello里："</span><span>,</span><span>say</span><span>)</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>go</span><span> </span><span>build</span><span> </span><span>-buildmode=plugin</span><span> </span><span>-o</span><span> </span><span>hello.so</span><span> </span><span>hello.go</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Hello</span><span> </span><span>func</span><span><span>(</span><span>say</span><span> </span></span><span>any</span><span>)</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>p</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>plugin</span><span>.</span><span>Open</span><span>(</span><span>"./plugin.so"</span><span>)</span></div></div><div><div><div>5</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>log</span><span>.</span><span>Fatalln</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>  </span><span>h</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>p</span><span>.</span><span>Lookup</span><span>(</span><span>"Hello"</span><span>)</span></div></div><div><div><div>9</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>10</div></div><div><span>    </span><span>log</span><span>.</span><span>Fatalln</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>  </span><span>h</span><span>.(</span><span>Hello</span><span>)(</span><span>"hello"</span><span>)</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><br /><br /><ul>
<li><code>archive</code> 模式，最终会编译出名为<code>.a</code>的静态文件，编译时会忽略<code>main</code>包（也就是会忽略<code>main</code>入口）。这种模式类似与c/c++程序的打包过程，将代码编译为二进制，但此时程序还不能直接运行。</li>
<li><code>c-archive</code> 模式，生成c/c++的静态库，编译后会生成<code>.a</code>和<code>.h</code>的c头文件，随后可将go程序一同编译进c程序。</li>
<li><code>c-shared</code> 模式，与<code>c-archive</code>基本一致，区别是<code>c-shared</code>最终生成的是c/c++动态库。</li>
<li><code>default</code> 模式，就是默认的模式，直接使用<code>go build</code>的时候就是使用此模式。</li>
<li><code>shared</code> 模式，与<code>archive</code>基本一致，区别是<code>shared</code>生成的是go的动态库。</li>
<li><code>exe</code> 模式，与<code>default</code>基本一致，区别是最终会生成<code>exe</code>文件。</li>
<li><code>pie</code> 模式，会使编译后的文件更安全，使其无法轻易地反编译，主要是使用PIE技术。一般程序的代码段(<code>.text</code>)、数据段(<code>.data</code>)和全局变量段(<code>.bss</code>)是一个固定的地址，而PIE技术就是使其每次加载程序时都会变换地址，所以提高了反编译的难度。</li>
<li><code>plugin</code> 模式，会生成go插件，可以在其他程序中热加载。</li>
</ul></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/253/</id>
      <title type="text">【Golang】1.18泛型初步理解</title>
      <published>2022-04-18T14:23:00.000Z</published>
      <updated>2022-04-29T08:41:41.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/253/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>这次golang正式更新了泛型（之前的1.17 和1.18 Beta 1 中的只是测试版，其中有一些用法和正式版有较大的差别），是一次重大的更新，原以为在GO2.0的时候更新。</p></section>
<section><h1>0x01 类型形参（Type Parameters）<a href="#0x01-类型形参type-parameters"><span>#</span></a></h1><p>在之前想要实现一些通用的功能还是比较麻烦的，而且代码冗余。</p><p>比如实现gorm添加json类型字段：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Table</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>AField</span><span>    </span><span>A</span></div></div><div><div><div>3</div></div><div><span>  </span><span>BField</span><span>    </span><span>B</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>type</span><span> </span><span>A</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>AText</span><span> </span><span>string</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div><span>func</span><span> (</span><span>A</span><span>) </span><span>GormDataType</span><span>() </span><span>string</span><span> {</span></div></div><div><div><div>10</div></div><div><span>    </span><span>return</span><span> </span><span>"json"</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div><span>func</span><span><span> (</span><span>a </span><span>*</span></span><span>A</span><span>) </span><span>Scan</span><span><span>(</span><span>value</span><span> </span></span><span>interface</span><span>{}) </span><span>error</span><span> {</span></div></div><div><div><div>13</div></div><div><span>    </span><span>return</span><span> </span><span>json</span><span>.</span><span>Unmarshal</span><span>(</span><span>value</span><span>.([]</span><span>byte</span><span>), </span><span>a</span><span>)</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div><div><div><div>15</div></div><div><span>func</span><span><span> (</span><span>a </span></span><span>A</span><span>) </span><span>Value</span><span><span>() (</span><span>value</span><span> </span></span><span>driver</span><span>.</span><span>Value</span><span><span>, </span><span>err</span><span> </span></span><span>error</span><span>) {</span></div></div><div><div><div>16</div></div><div><span>    </span><span>src</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>json</span><span>.</span><span>Marshal</span><span>(</span><span>a</span><span>)</span></div></div><div><div><div>17</div></div><div><span>    </span><span>return</span><span> </span><span>string</span><span>(</span><span>src</span><span>), </span><span>err</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>type</span><span> </span><span>B</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>21</div></div><div><span>    </span><span>BText</span><span> </span><span>string</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div><div><div><div>23</div></div><div><span>func</span><span> (</span><span>B</span><span>) </span><span>GormDataType</span><span>() </span><span>string</span><span> {</span></div></div><div><div><div>24</div></div><div><span>    </span><span>return</span><span> </span><span>"json"</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div><div><div><div>26</div></div><div><span>func</span><span><span> (</span><span>b </span><span>*</span></span><span>B</span><span>) </span><span>Scan</span><span><span>(</span><span>value</span><span> </span></span><span>interface</span><span>{}) </span><span>error</span><span> {</span></div></div><div><div><div>27</div></div><div><span>    </span><span>return</span><span> </span><span>json</span><span>.</span><span>Unmarshal</span><span>(</span><span>value</span><span>.([]</span><span>byte</span><span>), </span><span>b</span><span>)</span></div></div><div><div><div>28</div></div><div><span>}</span></div></div><div><div><div>29</div></div><div><span>func</span><span><span> (</span><span>b </span></span><span>B</span><span>) </span><span>Value</span><span><span>() (</span><span>value</span><span> </span></span><span>driver</span><span>.</span><span>Value</span><span><span>, </span><span>err</span><span> </span></span><span>error</span><span>) {</span></div></div><div><div><div>30</div></div><div><span>    </span><span>src</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>json</span><span>.</span><span>Marshal</span><span>(</span><span>b</span><span>)</span></div></div><div><div><div>31</div></div><div><span>    </span><span>return</span><span> </span><span>string</span><span>(</span><span>src</span><span>), </span><span>err</span></div></div><div><div><div>32</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>可以看到<code>A</code>和<code>B</code>中的<code>GormDataType</code> <code>Scan</code> <code>Value</code>方法几乎都是重复的，假如再添加<code>C</code> <code>D</code>那么就要添加6个重复发方法。</p><br /><p>而golang 1.8开始正式支持泛型，那么利用泛型可以降低这样的代码冗余</p><p>使用泛型再次实现上述内容：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Table</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>AField</span><span>    </span><span>JSON</span><span>[</span><span>A</span><span>]</span></div></div><div><div><div>3</div></div><div><span>  </span><span>BField</span><span>    </span><span>JSON</span><span>[</span><span>B</span><span>]</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>type</span><span> </span><span>A</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>AText</span><span> </span><span>string</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>type</span><span> </span><span>B</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>11</div></div><div><span>  </span><span>BText</span><span> </span><span>string</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>type</span><span> </span><span>JSON</span><span><span>[</span><span>T</span><span> </span></span><span>any</span><span>] </span><span>struct</span><span> {</span></div></div><div><div><div>16</div></div><div><span>    </span><span>Data</span><span> </span><span>T</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div><div><div><div>18</div></div><div><span>func</span><span> (</span><span>JSON</span><span>[</span><span>T</span><span>]) </span><span>GormDataType</span><span>() </span><span>string</span><span> {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>return</span><span> </span><span>"json"</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div><div><div><div>21</div></div><div><span>func</span><span><span> (</span><span>m </span><span>*</span></span><span>JSON</span><span>[</span><span>T</span><span>]) </span><span>Scan</span><span><span>(</span><span>value</span><span> </span></span><span>interface</span><span>{}) </span><span>error</span><span> {</span></div></div><div><div><div>22</div></div><div><span>    </span><span>return</span><span> </span><span>json</span><span>.</span><span>Unmarshal</span><span>(</span><span>value</span><span>.([]</span><span>byte</span><span><span>), </span><span>&amp;</span></span><span>m</span><span>.</span><span>Data</span><span>)</span></div></div><div><div><div>23</div></div><div><span>}</span></div></div><div><div><div>24</div></div><div><span>func</span><span><span> (</span><span>m </span></span><span>JSON</span><span>[</span><span>T</span><span>]) </span><span>Value</span><span><span>() (</span><span>value</span><span> </span></span><span>driver</span><span>.</span><span>Value</span><span><span>, </span><span>err</span><span> </span></span><span>error</span><span>) {</span></div></div><div><div><div>25</div></div><div><span>    </span><span>src</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>json</span><span>.</span><span>Marshal</span><span>(</span><span>m</span><span>.</span><span>Data</span><span>)</span></div></div><div><div><div>26</div></div><div><span>    </span><span>return</span><span> </span><span>string</span><span>(</span><span>src</span><span>), </span><span>err</span></div></div><div><div><div>27</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>可以看到我这里定义了一个<code>JSON[T any]</code>的类型专门处理json类型，此后添加<code>C</code> <code>D</code>字段就只需要定义相关的结构体并且添加<code>JSON[C]</code> <code>JSON[D]</code>即可。</p><br /><p>其中<code>any</code>类型也是这次更新后的新类型字段，但<code>any</code>其实就是<code>interface</code>类型的别称</p><p>源码：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// src/builtin/builtin.go 95行</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>// any is an alias for interface{} and is equivalent to interface{} in all ways.</span></div></div><div><div><div>4</div></div><div><span>type</span><span> </span><span>any</span><span><span> </span><span>=</span><span> </span></span><span>interface</span><span>{}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>个人感觉<code>any</code>相比<code>interface</code>在传参等场合更直观</p><p>比如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>func</span><span> </span><span>Println</span><span><span>(</span><span>v</span><span> ...</span></span><span>any</span><span>){}</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>func</span><span> </span><span>Println</span><span><span>(</span><span>v</span><span> ...</span></span><span>interface</span><span>){}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>当然，在定义接口时还是得用<code>interface</code>字段</p><br /><section><h2>判断类型<a href="#判断类型"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>func</span><span><span> (</span><span>m </span><span>*</span></span><span>JSON</span><span>[</span><span>T</span><span>]) </span><span>Test</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>switch</span><span> </span><span>any</span><span>(</span><span>m</span><span>.</span><span>Data</span><span>).(</span><span>type</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>      </span><span>case</span><span> </span><span>A</span><span>:</span></div></div><div><div><div>4</div></div><div><span>        </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>"A"</span><span>)</span></div></div><div><div><div>5</div></div><div><span>      </span><span>case</span><span> </span><span>B</span><span>:</span></div></div><div><div><div>6</div></div><div><span>        </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>"B"</span><span>)</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><a href="https://github.com/golang/go/issues/45380#issuecomment-1014950980" target="_blank">#1014950980</a></p></section></section>
<section><h1>0x02 类型集合（Type Sets）<a href="#0x02-类型集合type-sets"><span>#</span></a></h1><p>类型集合允许定义一个类型具有不同类型的集合</p><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Test</span><span> </span><span>interface</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>int</span><span>|</span><span>float64</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>定义了一个<code>Test</code>类型，表示为<code>int</code> <code>float64</code>类型的集合</p><br /><p>如果不用泛型那怎么写呢</p><p>不使用泛型：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>func</span><span> </span><span>Add</span><span><span>(</span><span>a</span><span>, </span><span>b</span><span> </span></span><span>interface</span><span>{}) </span><span>interface</span><span>{} {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>switch</span><span> </span><span>a</span><span>.(</span><span>type</span><span>) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>case</span><span> </span><span>int</span><span>:</span></div></div><div><div><div>4</div></div><div><span>        </span><span>return</span><span> </span><span>a</span><span>.(</span><span>int</span><span><span>)</span><span>+</span></span><span>b</span><span>.(</span><span>int</span><span>)</span></div></div><div><div><div>5</div></div><div><span>    </span><span>case</span><span> </span><span>float64</span><span>:</span></div></div><div><div><div>6</div></div><div><span>        </span><span>return</span><span> </span><span>a</span><span>.(</span><span>float64</span><span><span>)</span><span>+</span></span><span>b</span><span>.(</span><span>float64</span><span>)</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div><span>    </span><span>return</span><span> </span><span>0</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用泛型：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>func</span><span> </span><span>Add</span><span><span>[</span><span>T</span><span> </span></span><span>int</span><span><span> </span><span>|</span><span> </span></span><span>float64</span><span><span>](</span><span>a</span><span>, </span><span>b</span><span> </span></span><span>T</span><span>) </span><span>T</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>return</span><span> </span><span>a</span><span><span> </span><span>+</span><span> </span></span><span>b</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这样一对比使用泛型就简洁多了</p><br /><p>应用：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Num</span><span> </span><span>interface</span><span> {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>int</span><span><span> </span><span>|</span><span> </span></span><span>int64</span><span><span> </span><span>|</span><span> </span></span><span>int32</span><span><span> </span><span>|</span></span></div></div><div><div><div>3</div></div><div><span>        </span><span>float64</span><span><span> </span><span>|</span><span> </span></span><span>float32</span><span><span> </span><span>|</span></span></div></div><div><div><div>4</div></div><div><span>        </span><span>uint</span><span><span> </span><span>|</span><span> </span></span><span>uint8</span><span><span> </span><span>|</span><span> </span></span><span>uint16</span><span><span> </span><span>|</span><span> </span></span><span>uint64</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>func</span><span> </span><span>Add</span><span><span>[</span><span>T</span><span> </span></span><span>Num</span><span><span>](</span><span>a</span><span>, </span><span>b</span><span> </span></span><span>T</span><span>) </span><span>T</span><span> {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>return</span><span> </span><span>a</span><span><span> </span><span>+</span><span> </span></span><span>b</span></div></div><div><div><div>9</div></div><div><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>func</span><span> </span><span>Sub</span><span><span>[</span><span>T</span><span> </span></span><span>Num</span><span><span>](</span><span>a</span><span>, </span><span>b</span><span> </span></span><span>T</span><span>) </span><span>T</span><span> {</span></div></div><div><div><div>12</div></div><div><span>    </span><span>return</span><span> </span><span>a</span><span><span> </span><span>-</span><span> </span></span><span>b</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><br /></section>
<section><h1>0x03 类型约束<a href="#0x03-类型约束"><span>#</span></a></h1><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>T</span><span> </span><span>interface</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>int</span><span><span> </span><span>|</span><span> </span></span><span>float64</span><span><span> </span><span>|</span><span> </span><span>~</span></span><span>string</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中的<code>~string</code>表示定义的<code>T</code>类型集合也支持底层类型是<code>string</code>的类型</p><p>比如：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>A</span><span> </span><span>interface</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>~</span><span>string</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>func</span><span> </span><span>Splic</span><span><span>[</span><span>T</span><span> </span></span><span>A</span><span><span>](</span><span>a</span><span>, </span><span>b</span><span> </span></span><span>T</span><span>) </span><span>T</span><span> {</span></div></div><div><div><div>6</div></div><div><span>  </span><span>return</span><span> </span><span>a</span><span><span> </span><span>+</span><span> </span></span><span>b</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>var</span><span> </span><span>BString</span><span> </span><span>string</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>12</div></div><div><span>  </span><span>var</span><span> </span><span>a</span><span> </span><span>string</span><span><span> </span><span>=</span><span> </span></span><span>"a"</span></div></div><div><div><div>13</div></div><div><span>  </span><span>var</span><span> </span><span>b</span><span> </span><span>BString</span><span><span> </span><span>=</span><span> </span></span><span>"b"</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>  </span><span>Splic</span><span>(</span><span>a</span><span>, </span><span>b</span><span>)</span></div></div><div><div><div>16</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>其中<code>BString</code>是自定义的一个底层为<code>string</code>的类型，如果没有加<code>~</code>的话会报错</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/252/</id>
      <title type="text">【树莓派】板载LED控制</title>
      <published>2022-01-10T14:10:00.000Z</published>
      <updated>2022-01-12T01:34:54.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/252/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>有两种方式控制树莓派板载的LED</p></section>
<section><h1>0x01 开机后方案<a href="#0x01-开机后方案"><span>#</span></a></h1><blockquote><p>重启会失效</p></blockquote><p>控制板载灯的有以下文件：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 状态灯</span></div></div><div><div><div>2</div></div><div><span>/sys/class/leds/led0/brightness</span></div></div><div><div><div>3</div></div><div><span>/sys/class/leds/led0/trigger</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span># 电源灯</span></div></div><div><div><div>6</div></div><div><span>/sys/class/leds/led1/brightness</span></div></div><div><div><div>7</div></div><div><span>/sys/class/leds/led1/trigger</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>就可以控制状态灯和电源灯</p><p>其中<code>brightness</code>文件是亮度控制，接受范围是0~255，数字越大越亮，默认是255</p><p><code>trigger</code>文件是控制灯的模式，可以通过<code>cat /sys/class/leds/led0/trigger</code>读取模式，我的系统是树莓派爱好者基地提供的<code>Debian-Pi-Aarch64</code>，其中模式共有：</p><blockquote><p>[none] usb-gadget usb-host rc-feedback kbd-scrolllock kbd-numlock kbd-capslock kbd-kanalock kbd-shiftlock kbd-altgrlock kbd-ctrllock kbd-altlock kbd-shiftllock kbd-shiftrlock kbd-ctrlllock kbd-ctrlrlock timer oneshot heartbeat backlight gpio cpu cpu0 cpu1 cpu2 cpu3 default-on input panic actpwr mmc1 mmc0 rfkill-any rfkill-none rfkill0 bluetooth-power hci0-power rfkill1</p></blockquote><p>默认下状态灯的模式是<code>cpu</code>，电源灯的模式是<code>hci0-power</code></p><p>将模式设为<code>none</code>就是关闭灯</p><p>示例：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># 关闭状态灯</span></div></div><div><div><div>2</div></div><div><span>echo</span><span> </span><span>none</span><span> | </span><span>sudo</span><span> </span><span>tee</span><span> </span><span>/sys/class/leds/led0/trigger</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 调节电源灯亮度</span></div></div><div><div><div>5</div></div><div><span>echo</span><span> </span><span>125</span><span> | </span><span>sudo</span><span> </span><span>tee</span><span> </span><span>/sys/class/leds/led1/brightness</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02 开机前方案<a href="#0x02-开机前方案"><span>#</span></a></h1><p>如果想要不重启失效，就需要通过修改<code>/boot/config.txt</code>文件来实现。</p><p>首先官方文档有说明：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>  </span></span><span># 状态灯</span></div></div><div><div><div>2</div></div><div><span><span>      </span></span><span>act_led_trigger         Choose which activity the LED tracks.</span></div></div><div><div><div>3</div></div><div><span><span>                                </span></span><span>Use "heartbeat" for a nice load indicator.</span></div></div><div><div><div>4</div></div><div><span><span>                                </span></span><span>(default "mmc")</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>act_led_activelow       Set to "on" to invert the sense of the LED</span></div></div><div><div><div>6</div></div><div><span><span>                                </span></span><span>(default "off")</span></div></div><div><div><div>7</div></div><div><span><span>                                </span></span><span>N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led</span></div></div><div><div><div>8</div></div><div><span><span>                                </span></span><span>overlay.</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>act_led_gpio            Set which GPIO to use for the activity LED</span></div></div><div><div><div>10</div></div><div><span><span>                                </span></span><span>(in case you want to connect it to an external</span></div></div><div><div><div>11</div></div><div><span><span>                                </span></span><span>device)</span></div></div><div><div><div>12</div></div><div><span><span>                                </span></span><span>(default "16" on a non-Plus board, "47" on a</span></div></div><div><div><div>13</div></div><div><span><span>                                </span></span><span>Plus or Pi 2)</span></div></div><div><div><div>14</div></div><div><span><span>                                </span></span><span>N.B. For Pi 3B, 3B+, 3A+ and 4B, use the act-led</span></div></div><div><div><div>15</div></div><div><span><span>                                </span></span><span>overlay</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span># 电源灯</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>pwr_led_trigger</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>pwr_led_activelow</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>pwr_led_gpio</span></div></div><div><div><div>20</div></div><div><span><span>                                </span></span><span>As for act_led_*, but using the PWR LED.</span></div></div><div><div><div>21</div></div><div><span><span>                                </span></span><span>Not available on Model A/B boards.</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span># 网络灯</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>eth_led0                Set mode of LED0 (usually orange) (default</span></div></div><div><div><div>24</div></div><div><span><span>                                </span></span><span>"1"). The legal values are:</span></div></div><div><div><div>25</div></div><div><span><span>                                </span></span><span>0=link/activity          1=link1000/activity</span></div></div><div><div><div>26</div></div><div><span><span>                                </span></span><span>2=link100/activity       3=link10/activity</span></div></div><div><div><div>27</div></div><div><span><span>                                </span></span><span>4=link100/1000/activity  5=link10/1000/activity</span></div></div><div><div><div>28</div></div><div><span><span>                                </span></span><span>6=link10/100/activity    14=off    15=on</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>eth_led1                Set mode of LED1 (usually green) (default</span></div></div><div><div><div>30</div></div><div><span><span>                                </span></span><span>"6"). See eth_led0 for legal values.</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>只需要在<code>/boot/config.txt</code>中添加相应的设置就可以实现</p><p>示例，关闭所有灯：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#设置状态灯为none模式</span></div></div><div><div><div>2</div></div><div><span>dtparam</span><span>=</span><span>act_led_trigger</span><span><span>=</span><span>none</span></span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>#设置电源灯为none模式</span></div></div><div><div><div>5</div></div><div><span>dtparam</span><span>=</span><span>pwr_led_trigger</span><span><span>=</span><span>none</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>#设置网口灯为off</span></div></div><div><div><div>8</div></div><div><span>dtparam</span><span>=</span><span>eth_led0</span><span><span>=</span><span>14</span></span></div></div><div><div><div>9</div></div><div><span>dtparam</span><span>=</span><span>eth_led1</span><span><span>=</span><span>14</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/251/</id>
      <title type="text">【树莓派】SD卡系统备份</title>
      <published>2022-01-09T09:39:00.000Z</published>
      <updated>2022-01-09T14:26:59.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/251/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00 前言<a href="#0x00-前言"><span>#</span></a></h1><p>一般常见简单的备份方式是是使用Win32DiskImager备份，但是有几个缺点：</p><ol>
<li>整卡备份，Win32DiskImager会将SD卡内的所有区块都会备份下来，就类似Linux的<code>dd</code>命令。一个SD卡是16G但里面的数据只有100M，那么备份下来的文件就是16G，生成的备份文件大小就是SD的大小，这无疑浪费了空间</li>
<li>备份时间长，前面提到Win32DiskImager会将SD卡的所有块都备份下来，因此备份时间也就长了。</li>
<li>恢复时卡的容量必须要和备份文件大小一致或更大，这样就会造成一个问题，原本一张16G的卡内只有100M的有效数据，现在如果想将数据恢复到一张8G的卡，那么通过这种备份的方式是行不通的。</li>
</ol><p>最后通过查找找到了一个更好方法，就是通过<code>dump</code>备份，恢复时也只恢复有效数据，因此只要恢复的SD卡比有效数据大就行了。</p></section>
<section><h1>0x01 需要的软件<a href="#0x01-需要的软件"><span>#</span></a></h1><ul>
<li>
<p><code>dump</code> 备份工具，用于备份系统</p>
</li>
<li>
<p><code>dosfstools</code> fat32格式化工具，引导文件分区是fat32格式的</p>
</li>
<li>
<p><code>parted</code> 分区调整工具</p>
</li>
<li>
<p><code>kpartx</code> 虚拟文件系统工具</p>
</li>
</ul><p>安装：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>dump</span><span> </span><span>-y</span><span> &amp;&amp;</span></div></div><div><div><div>2</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>dosfstools</span><span> </span><span>-y</span><span> &amp;&amp;</span></div></div><div><div><div>3</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>parted</span><span> </span><span>-y</span><span> &amp;&amp;</span></div></div><div><div><div>4</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>kpartx</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02 创建img文件<a href="#0x02-创建img文件"><span>#</span></a></h1><p>img是用于存储系统的镜像文件</p><p>首先使用<code>df -h</code>查看实际空间大小，再生成文件，比如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Filesystem      Size  Used Avail Use% Mounted on</span></div></div><div><div><div>2</div></div><div><span>/dev/root        15G  8.9G  5.0G  65% /</span></div></div><div><div><div>3</div></div><div><span>/dev/mmcblk0p1  252M   72M  180M  29% /boot</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>从上可以看出实际使用空间<code>8.9G</code>+<code>252M</code>的boot空间</p><p>需要注意这里显示的空间单位是<code>G</code>，这里的<code>G</code>是将大小舍入到接近<code>GiB</code>（<span><span>2302^{30}</span><span><span><span></span><span><span>2</span><span><span><span><span><span><span></span><span><span><span>30</span></span></span></span></span></span></span></span></span></span></span></span>字节），而不是<code>GB</code>(<span><span>10910^{9}</span><span><span><span></span><span>1</span><span><span>0</span><span><span><span><span><span><span></span><span><span><span>9</span></span></span></span></span></span></span></span></span></span></span></span>字节)。</p><p><code>GB</code>和<code>GiB</code>是两个有严格区别的单位，<code>GB</code>是方便10进制计算，<code>GiB</code>是方便2进制计算。</p><p>（插个题外话，Windows中默认的大小单位显示的是<code>KB</code>、<code>MB</code>、<code>GB</code>实际上计算的是<code>KiB</code>、<code>MiB</code>、<code>GiB</code>）</p><p>因此需要生成的img需要大于等于<code>8.9G</code>+<code>252M</code></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>dd</span><span> </span><span>if=/dev/zero</span><span> </span><span>of=raspi.img</span><span> </span><span>bs=1M</span><span> </span><span>count=</span><span>9570</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>if</code>是输入路径，这里选择使用0填充</p><p><code>of</code>是输出路径，就是创建img文件的路径</p><p><code>bs</code>是块大小，这里选择M，也就是MiB，这样生成的文件是512bytes的整数倍，为了与分区表对上</p><p><code>count</code>是块数，<code>bs</code>*<code>count</code>=真实大小</p><p>因为要生成的img文件需要大于等于<code>8.9G``+</code>252M<code>，而这里的</code>8.9G<code>是进行了大小舍入所以不精确，所以为了容纳误差而选择生成</code>9.1G`大小的系统。</p><p>因为<code>bs</code>是<code>M</code>，所以<code>count</code>为：<span><span>(9.1×230÷220)+252≈9570(9.1\times2^{30}\div2^{20})+252\approx9570</span><span><span><span></span><span>(</span><span>9.1</span><span></span><span>×</span><span></span></span><span><span></span><span><span>2</span><span><span><span><span><span><span></span><span><span><span>30</span></span></span></span></span></span></span></span></span><span></span><span>÷</span><span></span></span><span><span></span><span><span>2</span><span><span><span><span><span><span></span><span><span><span>20</span></span></span></span></span></span></span></span></span><span>)</span><span></span><span>+</span><span></span></span><span><span></span><span>252</span><span></span><span>≈</span><span></span></span><span><span></span><span>9570</span></span></span></span></p></section>
<section><h1>0x03 img镜像分区<a href="#0x03-img镜像分区"><span>#</span></a></h1><p>分区前通过<code>fdisk -l</code>查看树莓派分区</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Device         Boot  Start      End  Sectors  Size Id Type</span></div></div><div><div><div>2</div></div><div><span>/dev/mmcblk0p1 *      8192   524287   516096  252M  c W95 FAT32 (LBA)</span></div></div><div><div><div>3</div></div><div><span>/dev/mmcblk0p2      524288 31223807 30699520 14.7G 83 Linux</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>可以看到SD卡有两个分区，其中关键信息为：</p><ol>
<li><code>/dev/mmcblk0p1</code>是引导分区(boot)，分区类型是<code>fat32</code>，从<code>8192</code>柱面开始，到<code>524287</code>柱面结束。</li>
<li><code>/dev/mmcblk0p2</code>是系统分区，分区从<code>524288</code>柱面开始。</li>
</ol><p>接下来使用<code>parted</code>将刚生成的img文件进行分区</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>parted</span><span> </span><span>raspi.img</span><span> </span><span>-s</span><span>  </span><span>--</span><span> </span><span>mklabel</span><span> </span><span>msdos</span><span>   </span><span># 创建msdos分区表</span></div></div><div><div><div>2</div></div><div><span>parted</span><span> </span><span>raspi.img</span><span> </span><span>-s</span><span>  </span><span>--</span><span> </span><span>mkpart</span><span> </span><span>primary</span><span> </span><span>fat32</span><span> </span><span>8192s</span><span> </span><span>524287s</span><span>  </span><span># fat32分区从8192开始，到524287结束</span></div></div><div><div><div>3</div></div><div><span>parted</span><span> </span><span>raspi.img</span><span> </span><span>-s</span><span>  </span><span>--</span><span> </span><span>mkpart</span><span> </span><span>primary</span><span> </span><span>ext4</span><span> </span><span>524288s</span><span> </span><span>-1</span><span>  </span><span># 系统分区一般都是ext4类型，从524288开始，到最后</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x04 挂载img并格式化<a href="#0x04-挂载img并格式化"><span>#</span></a></h1><p>将img挂载为虚拟设备，并获取虚拟设备地址</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>loopdevice</span><span>=</span><span>`</span><span>losetup</span><span> </span><span>-f</span><span> </span><span>--show</span><span> raspi.img`</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用<code>kpartx</code>挂载为虚拟文件系统</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>device</span><span>=</span><span>`</span><span>kpartx</span><span> </span><span>-va</span><span> </span><span>$loopdevice</span><span> </span><span>|</span><span> </span><span>sed</span><span> '1!d' </span><span>|</span><span> </span><span>sed</span><span> </span><span>-E</span><span> 's/.*(loop[0-9])p.*/\1/g'`</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>地址拼接</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>device</span><span>=</span><span>"/dev/mapper/</span><span><span>${</span><span>device</span><span>}</span></span><span>"</span></div></div><div><div><div>2</div></div><div><span>imgBoot</span><span>=</span><span>"</span><span><span>${</span><span>device</span><span>}</span></span><span>p1"</span></div></div><div><div><div>3</div></div><div><span>imgRoot</span><span>=</span><span>"</span><span><span>${</span><span>device</span><span>}</span></span><span>p2"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>格式化</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>mkfs.vfat</span><span> </span><span>$imgBoot</span></div></div><div><div><div>2</div></div><div><span>mkfs.ext4</span><span> </span><span>$imgRoot</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x05 备份<a href="#0x05-备份"><span>#</span></a></h1><p>创建两个临时挂载目录，并挂载</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>mkdir</span><span> </span><span>tmpBoot</span><span> </span><span>tmpRoot</span></div></div><div><div><div>2</div></div><div><span>mount</span><span> </span><span>-t</span><span> </span><span>vfat</span><span> </span><span>$imgBoot</span><span> </span><span>tmpBoot</span></div></div><div><div><div>3</div></div><div><span>mount</span><span> </span><span>-t</span><span> </span><span>ext4</span><span> </span><span>$imgRoot</span><span> </span><span>tmpRoot</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>备份<code>Boot</code></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>cp</span><span> </span><span>-rfp</span><span> </span><span>/boot/</span><span>*</span><span> </span><span>tmpBoot</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>备份系统</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>cd</span><span> </span><span>tmpRoot</span></div></div><div><div><div>2</div></div><div><span>dump</span><span> </span><span>-0uaf</span><span> </span><span>-</span><span> </span><span>/</span><span> | </span><span>restore</span><span> </span><span>-rf</span><span> </span><span>-</span></div></div><div><div><div>3</div></div><div><span>cd</span><span> </span><span>-</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x06 修改启动文件<a href="#0x06-修改启动文件"><span>#</span></a></h1><p>因为树莓派启动需要对应分区的<code>PARTUUID</code>，所以需要修改<code>cmdline.txt</code>和<code>fstab</code>文件</p><p>首先使用<code>blkid</code>命令查看分区<code>PARTUUID</code></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>blkid</span><span> </span><span>-o</span><span> </span><span>export</span><span> </span><span>$imgBoot</span></div></div><div><div><div>2</div></div><div><span>blkid</span><span> </span><span>-o</span><span> </span><span>export</span><span> </span><span>$imgRoot</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>分别输出</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>DEVNAME=/dev/mapper/loop0p1</span></div></div><div><div><div>2</div></div><div><span>SEC_TYPE=msdos</span></div></div><div><div><div>3</div></div><div><span>UUID=161A-ED14</span></div></div><div><div><div>4</div></div><div><span>TYPE=vfat</span></div></div><div><div><div>5</div></div><div><span>PARTUUID=e74ab5ad-01</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>DEVNAME=/dev/mapper/loop0p2</span></div></div><div><div><div>8</div></div><div><span>UUID=20aa2e77-a211-4d43-996d-324f015e597c</span></div></div><div><div><div>9</div></div><div><span>TYPE=ext4</span></div></div><div><div><div>10</div></div><div><span>PARTUUID=e74ab5ad-02</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>可以看到<code>PARTUUID</code>分别为<code>e74ab5ad-01</code>（对应<code>boot</code>分区）和<code>e74ab5ad-02</code>（对应系统分区）。</p><p>将获取到的<code>PARTUUID</code>分别替换掉<code>cmdline.txt</code>和<code>fstab</code>文件中的<code>PARTUUID</code></p><p>路径：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>tmpBoot/cmdline.txt   # cmdline.txt</span></div></div><div><div><div>2</div></div><div><span>tmpRoot/etc/fstab     # fstab</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x07 END<a href="#0x07-end"><span>#</span></a></h1><p>卸载分区</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>cd</span><span> </span><span>~</span></div></div><div><div><div>2</div></div><div><span>umount</span><span> </span><span>tmpBoot/</span><span> </span><span>tmpRoot/</span></div></div><div><div><div>3</div></div><div><span>rm</span><span> </span><span>-rf</span><span> </span><span>tmpBoot/</span><span> </span><span>tmpRoot/</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>卸载虚拟设备</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>kpartx</span><span> </span><span>-d</span><span> </span><span>$loopdevice</span></div></div><div><div><div>2</div></div><div><span>losetup</span><span> </span><span>-d</span><span> </span><span>$loopdevice</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>至此系统备份就做好了，制作的img文件可以使用<code>Win32DiskImager</code>或<code>dd</code>刷入其他的SD卡了</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/250/</id>
      <title type="text">【Golang】关于time包的一些记录</title>
      <published>2022-01-04T15:09:06.000Z</published>
      <updated>2022-01-04T15:09:06.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/250/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00 时间格式化<a href="#0x00-时间格式化"><span>#</span></a></h1><p>相信都听说过Golang时间格式化规则layout<code>2006-01-02 15:04:05</code> 是Golang创始纪念日，以前我也是这样认为，还觉得golang太傲慢了（笑）。直到后面仔细观察后发现layout中年、月、日、时、分、秒的数字才发现事情没有那么简单，首先来观察这几组layout：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>2006-01-02 15:04:05   // 24小时格式 有0占位</span></div></div><div><div><div>2</div></div><div><span>2006-1-2 15:4:5       // 24小时格式 无0占位</span></div></div><div><div><div>3</div></div><div><span>2006-01-02 03:04:05   // 12小时格式 有0占位</span></div></div><div><div><div>4</div></div><div><span>2006-1-2 3:4:5        // 12小时格式 无0占位</span></div></div><div><div><div>5</div></div><div><span>2006  // 长年份</span></div></div><div><div><div>6</div></div><div><span>06    // 短年份 有0占位</span></div></div><div><div><div>7</div></div><div><span>6     // 短年份 无0占位</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>不知发现其中规则了没有，年、月、日、时、分、秒格式中除了表示占位的0和长年份的2以外，<strong>没有一个数字是重复的</strong>，也就是说只要检查layout中特定的数字就能解析出字块的意义。</p><p>为了验证我的猜想，来看一下time的源码：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// nextStdChunk finds the first occurrence of a std string in</span></div></div><div><div><div>2</div></div><div><span>// layout and returns the text before, the std string, and the text after.</span></div></div><div><div><div>3</div></div><div><span>func</span><span> </span><span>nextStdChunk</span><span><span>(</span><span>layout</span><span> </span></span><span>string</span><span><span>) (</span><span>prefix</span><span> </span></span><span>string</span><span><span>, </span><span>std</span><span> </span></span><span>int</span><span><span>, </span><span>suffix</span><span> </span></span><span>string</span><span>) {</span></div></div><div><div><div>4</div></div><div><span>  </span><span>for</span><span> </span><span>i</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>; </span><span>i</span><span><span> </span><span>&lt;</span><span> </span></span><span>len</span><span>(</span><span>layout</span><span>); </span><span>i</span><span><span>++</span><span> {</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>switch</span><span> </span><span>c</span><span><span> </span><span>:=</span><span> </span></span><span>int</span><span>(</span><span>layout</span><span>[</span><span>i</span><span>]); </span><span>c</span><span> {</span></div></div><div><div><div>6</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>J</span><span>'</span><span>: </span><span>// January, Jan</span></div></div><div><div><div>7</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>3</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>3</span><span><span>] </span><span>==</span><span> </span></span><span>"Jan"</span><span> {</span></div></div><div><div><div>8</div></div><div><span>        </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>7</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>7</span><span><span>] </span><span>==</span><span> </span></span><span>"January"</span><span> {</span></div></div><div><div><div>9</div></div><div><span>          </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdLongMonth</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>7</span><span>:]</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>11</div></div><div><span>        </span><span>if</span><span><span> </span><span>!</span></span><span>startsWithLowerCase</span><span>(</span><span>layout</span><span>[</span><span>i</span><span>+</span><span>3</span><span>:]) {</span></div></div><div><div><div>12</div></div><div><span>          </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdMonth</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>3</span><span>:]</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>M</span><span>'</span><span>: </span><span>// Monday, Mon, MST</span></div></div><div><div><div>17</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>3</span><span> {</span></div></div><div><div><div>18</div></div><div><span>        </span><span>if</span><span> </span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>3</span><span><span>] </span><span>==</span><span> </span></span><span>"Mon"</span><span> {</span></div></div><div><div><div>19</div></div><div><span>          </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>6</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>6</span><span><span>] </span><span>==</span><span> </span></span><span>"Monday"</span><span> {</span></div></div><div><div><div>20</div></div><div><span>            </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdLongWeekDay</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>6</span><span>:]</span></div></div><div><div><div>21</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>          </span><span>if</span><span><span> </span><span>!</span></span><span>startsWithLowerCase</span><span>(</span><span>layout</span><span>[</span><span>i</span><span>+</span><span>3</span><span>:]) {</span></div></div><div><div><div>23</div></div><div><span>            </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdWeekDay</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>3</span><span>:]</span></div></div><div><div><div>24</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span>        </span><span>if</span><span> </span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>3</span><span><span>] </span><span>==</span><span> </span></span><span>"MST"</span><span> {</span></div></div><div><div><div>27</div></div><div><span>          </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdTZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>3</span><span>:]</span></div></div><div><div><div>28</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>0</span><span>'</span><span>: </span><span>// 01, 02, 03, 04, 05, 06, 002</span></div></div><div><div><div>32</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>2</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>'</span><span>1</span><span>'</span><span><span> </span><span>&lt;=</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>&lt;=</span><span> </span></span><span>'</span><span>6</span><span>'</span><span> {</span></div></div><div><div><div>33</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>std0x</span><span>[</span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>]</span><span>-</span></span><span>'</span><span>1</span><span>'</span><span>], </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>2</span><span>:]</span></div></div><div><div><div>34</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>35</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>3</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>0</span><span>'</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>2</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>2</span><span>'</span><span> {</span></div></div><div><div><div>36</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdZeroYearDay</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>3</span><span>:]</span></div></div><div><div><div>37</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>38</div></div><div>
</div></div><div><div><div>39</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>1</span><span>'</span><span>: </span><span>// 15, 1</span></div></div><div><div><div>40</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>2</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>5</span><span>'</span><span> {</span></div></div><div><div><div>41</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdHour</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>2</span><span>:]</span></div></div><div><div><div>42</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>43</div></div><div><span>      </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdNumMonth</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span>:]</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>2</span><span>'</span><span>: </span><span>// 2006, 2</span></div></div><div><div><div>46</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>4</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>4</span><span><span>] </span><span>==</span><span> </span></span><span>"2006"</span><span> {</span></div></div><div><div><div>47</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdLongYear</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>4</span><span>:]</span></div></div><div><div><div>48</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>49</div></div><div><span>      </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdDay</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span>:]</span></div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>_</span><span>'</span><span>: </span><span>// _2, _2006, __2</span></div></div><div><div><div>52</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>2</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>2</span><span>'</span><span> {</span></div></div><div><div><div>53</div></div><div><span>        </span><span>//_2006 is really a literal _, followed by stdLongYear</span></div></div><div><div><div>54</div></div><div><span>        </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>5</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span>:</span><span>i</span><span>+</span><span>5</span><span><span>] </span><span>==</span><span> </span></span><span>"2006"</span><span> {</span></div></div><div><div><div>55</div></div><div><span>          </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span> : </span><span>i</span><span>+</span><span>1</span><span>], </span><span>stdLongYear</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>5</span><span>:]</span></div></div><div><div><div>56</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>57</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdUnderDay</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>2</span><span>:]</span></div></div><div><div><div>58</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>59</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>3</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>_</span><span>'</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>2</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>2</span><span>'</span><span> {</span></div></div><div><div><div>60</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdUnderYearDay</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>3</span><span>:]</span></div></div><div><div><div>61</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>62</div></div><div>
</div></div><div><div><div>63</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>3</span><span>'</span><span>:</span></div></div><div><div><div>64</div></div><div><span>      </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdHour12</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span>:]</span></div></div><div><div><div>65</div></div><div>
</div></div><div><div><div>66</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>4</span><span>'</span><span>:</span></div></div><div><div><div>67</div></div><div><span>      </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdMinute</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span>:]</span></div></div><div><div><div>68</div></div><div>
</div></div><div><div><div>69</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>5</span><span>'</span><span>:</span></div></div><div><div><div>70</div></div><div><span>      </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdSecond</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span>:]</span></div></div><div><div><div>71</div></div><div>
</div></div><div><div><div>72</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>P</span><span>'</span><span>: </span><span>// PM</span></div></div><div><div><div>73</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>2</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>M</span><span>'</span><span> {</span></div></div><div><div><div>74</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdPM</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>2</span><span>:]</span></div></div><div><div><div>75</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>76</div></div><div>
</div></div><div><div><div>77</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>p</span><span>'</span><span>: </span><span>// pm</span></div></div><div><div><div>78</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>2</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>m</span><span>'</span><span> {</span></div></div><div><div><div>79</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdpm</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>2</span><span>:]</span></div></div><div><div><div>80</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>81</div></div><div>
</div></div><div><div><div>82</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>-</span><span>'</span><span>: </span><span>// -070000, -07:00:00, -0700, -07:00, -07</span></div></div><div><div><div>83</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>7</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>7</span><span><span>] </span><span>==</span><span> </span></span><span>"-070000"</span><span> {</span></div></div><div><div><div>84</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdNumSecondsTz</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>7</span><span>:]</span></div></div><div><div><div>85</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>86</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>9</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>9</span><span><span>] </span><span>==</span><span> </span></span><span>"-07:00:00"</span><span> {</span></div></div><div><div><div>87</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdNumColonSecondsTZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>9</span><span>:]</span></div></div><div><div><div>88</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>89</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>5</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>5</span><span><span>] </span><span>==</span><span> </span></span><span>"-0700"</span><span> {</span></div></div><div><div><div>90</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdNumTZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>5</span><span>:]</span></div></div><div><div><div>91</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>92</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>6</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>6</span><span><span>] </span><span>==</span><span> </span></span><span>"-07:00"</span><span> {</span></div></div><div><div><div>93</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdNumColonTZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>6</span><span>:]</span></div></div><div><div><div>94</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>95</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>3</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>3</span><span><span>] </span><span>==</span><span> </span></span><span>"-07"</span><span> {</span></div></div><div><div><div>96</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdNumShortTZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>3</span><span>:]</span></div></div><div><div><div>97</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>98</div></div><div>
</div></div><div><div><div>99</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>Z</span><span>'</span><span>: </span><span>// Z070000, Z07:00:00, Z0700, Z07:00,</span></div></div><div><div><div>100</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>7</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>7</span><span><span>] </span><span>==</span><span> </span></span><span>"Z070000"</span><span> {</span></div></div><div><div><div>101</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdISO8601SecondsTZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>7</span><span>:]</span></div></div><div><div><div>102</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>103</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>9</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>9</span><span><span>] </span><span>==</span><span> </span></span><span>"Z07:00:00"</span><span> {</span></div></div><div><div><div>104</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdISO8601ColonSecondsTZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>9</span><span>:]</span></div></div><div><div><div>105</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>106</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>5</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>5</span><span><span>] </span><span>==</span><span> </span></span><span>"Z0700"</span><span> {</span></div></div><div><div><div>107</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdISO8601TZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>5</span><span>:]</span></div></div><div><div><div>108</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>109</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>6</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>6</span><span><span>] </span><span>==</span><span> </span></span><span>"Z07:00"</span><span> {</span></div></div><div><div><div>110</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdISO8601ColonTZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>6</span><span>:]</span></div></div><div><div><div>111</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>112</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&gt;=</span><span> </span></span><span>i</span><span>+</span><span>3</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>:</span><span>i</span><span>+</span><span>3</span><span><span>] </span><span>==</span><span> </span></span><span>"Z07"</span><span> {</span></div></div><div><div><div>113</div></div><div><span>        </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>stdISO8601ShortTZ</span><span>, </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>3</span><span>:]</span></div></div><div><div><div>114</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>115</div></div><div>
</div></div><div><div><div>116</div></div><div><span>    </span><span>case</span><span> </span><span>'</span><span>.</span><span>'</span><span>: </span><span>// .000 or .999 - repeated digits for fractional seconds.</span></div></div><div><div><div>117</div></div><div><span>      </span><span>if</span><span> </span><span>i</span><span>+</span><span>1</span><span><span> </span><span>&lt;</span><span> </span></span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&amp;&amp;</span><span> (</span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>0</span><span>'</span><span><span> </span><span>||</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>9</span><span>'</span><span>) {</span></div></div><div><div><div>118</div></div><div><span>        </span><span>ch</span><span><span> </span><span>:=</span><span> </span></span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span>]</span></div></div><div><div><div>119</div></div><div><span>        </span><span>j</span><span><span> </span><span>:=</span><span> </span></span><span>i</span><span><span> </span><span>+</span><span> </span></span><span>1</span></div></div><div><div><div>120</div></div><div><span>        </span><span>for</span><span> </span><span>j</span><span><span> </span><span>&lt;</span><span> </span></span><span>len</span><span>(</span><span>layout</span><span><span>) </span><span>&amp;&amp;</span><span> </span></span><span>layout</span><span>[</span><span>j</span><span><span>] </span><span>==</span><span> </span></span><span>ch</span><span> {</span></div></div><div><div><div>121</div></div><div><span>          </span><span>j</span><span>++</span></div></div><div><div><div>122</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>123</div></div><div><span>        </span><span>// String of digits must end here - only fractional second is all digits.</span></div></div><div><div><div>124</div></div><div><span>        </span><span>if</span><span><span> </span><span>!</span></span><span>isDigit</span><span>(</span><span>layout</span><span>, </span><span>j</span><span>) {</span></div></div><div><div><div>125</div></div><div><span>          </span><span>std</span><span><span> </span><span>:=</span><span> </span></span><span>stdFracSecond0</span></div></div><div><div><div>126</div></div><div><span>          </span><span>if</span><span> </span><span>layout</span><span>[</span><span>i</span><span>+</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>'</span><span>9</span><span>'</span><span> {</span></div></div><div><div><div>127</div></div><div><span>            </span><span>std</span><span><span> </span><span>=</span><span> </span></span><span>stdFracSecond9</span></div></div><div><div><div>128</div></div><div><span><span>          </span></span><span>}</span></div></div><div><div><div>129</div></div><div><span>          </span><span>std</span><span><span> </span><span>|=</span><span> (</span></span><span>j</span><span><span> </span><span>-</span><span> (</span></span><span>i</span><span><span> </span><span>+</span><span> </span></span><span>1</span><span><span>)) </span><span>&lt;&lt;</span><span> </span></span><span>stdArgShift</span></div></div><div><div><div>130</div></div><div><span>          </span><span>return</span><span> </span><span>layout</span><span>[</span><span>0</span><span>:</span><span>i</span><span>], </span><span>std</span><span>, </span><span>layout</span><span>[</span><span>j</span><span>:]</span></div></div><div><div><div>131</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>132</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>133</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>134</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>135</div></div><div><span>  </span><span>return</span><span> </span><span>layout</span><span>, </span><span>0</span><span>, </span><span>""</span></div></div><div><div><div>136</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>可以看到不光年月日时分秒没有重复，甚至连时区也不是重复的。只要遵循这个规则就可以随心自定义layout。</p><p>由此可见前面说这是Golang创始纪念日的说法完全是无稽之谈。</p><p>而这种设计实际上很科学也很好记。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/249/</id>
      <title type="text">【Golang】使用反射实现验证struct必填字段是否为空</title>
      <published>2021-08-20T09:41:00.000Z</published>
      <updated>2021-08-20T10:47:23.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/249/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x0<a href="#0x0"><span>#</span></a></h1><section><h2>反射：<a href="#反射"><span>#</span></a></h2><p>golang的reflect包实现了运行时的反射能力。reflect包中有两个重要函数：</p><ul>
<li><code>reflect.TypeOf</code> 获取数据类型信息，其类型为<code>reflect.Type</code></li>
<li><code>reflect.ValueOf</code> 获取数据运行时的信息，其类型为<code>reflect.Value</code></li>
</ul></section><section><h2>Tag<a href="#tag"><span>#</span></a></h2><p>golang的struct中的每一个字段(<code>field</code>)后添加一段注释，称为 <code>field tag</code>，最经典就是构建json的struct，例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Login</span><span> </span><span>struct</span><span>{</span></div></div><div><div><div>2</div></div><div><span>  </span><span>UserName</span><span> </span><span>string</span><span> </span><span>`json:"user_name"`</span></div></div><div><div><div>3</div></div><div><span>  </span><span>Password</span><span> </span><span>string</span><span> </span><span>`json:"password"`</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中 <code>json:"user_name" json:"password"</code>就是 <code>field tag</code></p></section></section>
<section><h1>0x1<a href="#0x1"><span>#</span></a></h1><p>假设现有一 <code>struct</code>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Note</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>Time</span><span>    </span><span>time</span><span>.</span><span>Time</span></div></div><div><div><div>3</div></div><div><span>  </span><span>Content</span><span> </span><span>string</span></div></div><div><div><div>4</div></div><div><span>  </span><span>Remarks</span><span> </span><span>string</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>我们想要指定一些字段非空，例如：<code>Content != ""</code></p><p>按照一般通用的方法就是一个一个用if判断：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>if</span><span> </span><span>content</span><span><span> </span><span>!=</span><span> </span></span><span>""</span><span> { ... } </span><span>else</span><span> { ... }</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果只有几个字段需要这样判断还可以这样写。但如果有许多个字段或不同字段有不同类型，这样写的话就是一堆 <code>if else</code>，就不是很优雅。</p></section>
<section><h1>0x2<a href="#0x2"><span>#</span></a></h1><p>现在可以使用反射来更为优雅实现这一功能。只需要在struct需要非空的字段后添加一个 <code>tag</code>来标记，这个<code>tag</code>可以自定义，如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Note</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>Time</span><span>    </span><span>time</span><span>.</span><span>Time</span><span> </span><span>`must:"true"`</span></div></div><div><div><div>3</div></div><div><span>  </span><span>Content</span><span> </span><span>string</span><span>    </span><span>`must:"true"`</span></div></div><div><div><div>4</div></div><div><span>  </span><span>Remarks</span><span> </span><span>string</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中 <code>must:"true"</code>为我们自定义的<code>tag</code>，表示该字段非空。</p></section>
<section><h1>0x3<a href="#0x3"><span>#</span></a></h1><p>我们可以通过反射来获取<code>struct</code>字段的<code>tag</code>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>reflect</span><span>.</span><span>TypeOf</span><span><span>(</span><span>&amp;</span></span><span>note</span><span>).</span><span>Elem</span><span>().</span><span>Field</span><span>(</span><span>0</span><span>).</span><span>Tag</span><span>.</span><span>Get</span><span>(</span><span>"must"</span><span>))  </span><span>//获取第一个字段tag中"must"的值</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x4<a href="#0x4"><span>#</span></a></h1><p>完整实现代码：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Note</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>Time</span><span>    </span><span>time</span><span>.</span><span>Time</span><span> </span><span>`must:"true"`</span></div></div><div><div><div>3</div></div><div><span>  </span><span>Content</span><span> </span><span>string</span><span>    </span><span>`must:"true"`</span></div></div><div><div><div>4</div></div><div><span>  </span><span>Remarks</span><span> </span><span>string</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>func</span><span> </span><span>validator</span><span><span>(</span><span>value</span><span> </span></span><span>interface</span><span>{}) {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>val</span><span><span> </span><span>:=</span><span> </span></span><span>reflect</span><span>.</span><span>ValueOf</span><span>(</span><span>value</span><span>).</span><span>Elem</span><span>() </span><span>//获取字段值</span></div></div><div><div><div>9</div></div><div><span>  </span><span>typ</span><span><span> </span><span>:=</span><span> </span></span><span>reflect</span><span>.</span><span>TypeOf</span><span>(</span><span>value</span><span>).</span><span>Elem</span><span>()  </span><span>//获取字段类型</span></div></div><div><div><div>10</div></div><div><span>  </span><span>// 遍历struct中的字段</span></div></div><div><div><div>11</div></div><div><span>  </span><span>for</span><span> </span><span>i</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>; </span><span>i</span><span><span> </span><span>&lt;</span><span> </span></span><span>typ</span><span>.</span><span>NumField</span><span>(); </span><span>i</span><span><span>++</span><span> {</span></span></div></div><div><div><div>12</div></div><div><span>    </span><span>// 当struct中的tag为 must:"true" 且当前字段值为空值时，输出</span></div></div><div><div><div>13</div></div><div><span>    </span><span>if</span><span> </span><span>typ</span><span>.</span><span>Field</span><span>(</span><span>i</span><span>).</span><span>Tag</span><span>.</span><span>Get</span><span>(</span><span>"must"</span><span><span>) </span><span>==</span><span> </span></span><span>"true"</span><span><span> </span><span>&amp;&amp;</span><span> </span></span><span>val</span><span>.</span><span>Field</span><span>(</span><span>i</span><span>).</span><span>IsZero</span><span>() {</span></div></div><div><div><div>14</div></div><div><span>      </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>"Fail:"</span><span>, </span><span>typ</span><span>.</span><span>Field</span><span>(</span><span>i</span><span>).</span><span>Name</span><span>, </span><span>"is null"</span><span>)</span></div></div><div><div><div>15</div></div><div><span>      </span><span>return</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>18</div></div><div><span>  </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>"Pass"</span><span>)</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>22</div></div><div><span>  </span><span>note1</span><span><span> </span><span>:=</span><span> </span></span><span>Note</span><span>{</span></div></div><div><div><div>23</div></div><div><span>    </span><span>Time</span><span>:    </span><span>time</span><span>.</span><span>Now</span><span>(),</span></div></div><div><div><div>24</div></div><div><span>    </span><span>Content</span><span>: </span><span>"content"</span><span>,</span></div></div><div><div><div>25</div></div><div><span>    </span><span>Remarks</span><span>: </span><span>""</span><span>,</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>27</div></div><div><span>  </span><span>validator</span><span><span>(</span><span>&amp;</span></span><span>note1</span><span>)</span></div></div><div><div><div>28</div></div><div><span>  </span><span>// Pass</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>  </span><span>note2</span><span><span> </span><span>:=</span><span> </span></span><span>Note</span><span>{</span></div></div><div><div><div>31</div></div><div><span>    </span><span>Time</span><span>:    </span><span>time</span><span>.</span><span>Now</span><span>(),</span></div></div><div><div><div>32</div></div><div><span>    </span><span>Content</span><span>: </span><span>""</span><span>,</span></div></div><div><div><div>33</div></div><div><span>    </span><span>Remarks</span><span>: </span><span>""</span><span>,</span></div></div><div><div><div>34</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>35</div></div><div><span>  </span><span>validator</span><span><span>(</span><span>&amp;</span></span><span>note2</span><span>)</span></div></div><div><div><div>36</div></div><div><span>  </span><span>// Fail: Content is null</span></div></div><div><div><div>37</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/248/</id>
      <title type="text">【杂项】使用gocv库实现视频转终端字符画</title>
      <published>2021-08-12T11:14:06.000Z</published>
      <updated>2021-08-12T11:14:06.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/248/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>main</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>import</span><span> (</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"bytes"</span></div></div><div><div><div>5</div></div><div><span>  </span><span>"fmt"</span></div></div><div><div><div>6</div></div><div><span>  </span><span>"gocv.io/x/gocv"</span></div></div><div><div><div>7</div></div><div><span>  </span><span>"golang.org/x/crypto/ssh/terminal"</span></div></div><div><div><div>8</div></div><div><span>  </span><span>"image"</span></div></div><div><div><div>9</div></div><div><span>  </span><span>"os"</span></div></div><div><div><div>10</div></div><div><span>  </span><span>"os/exec"</span></div></div><div><div><div>11</div></div><div><span>  </span><span>"time"</span></div></div><div><div><div>12</div></div><div><span>)</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>const</span><span> </span><span>pixels</span><span><span> </span><span>=</span><span> </span></span><span>` .,-'`</span><span><span> </span><span>+</span><span> </span></span><span>`:!1+*abcdefghijklmnopqrstuvwxyz&lt;&gt;()\/{}[]?234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ%&amp;@#$`</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>17</div></div><div><span>  </span><span>// 打开文件</span></div></div><div><div><div>18</div></div><div><span>  </span><span>c</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>gocv</span><span>.</span><span>VideoCaptureFile</span><span>(</span><span>"../1.mp4"</span><span>)</span></div></div><div><div><div>19</div></div><div><span>  </span><span>// 获取帧数</span></div></div><div><div><div>20</div></div><div><span>  </span><span>fps</span><span><span> </span><span>:=</span><span> </span></span><span>c</span><span>.</span><span>Get</span><span>(</span><span>gocv</span><span>.</span><span>VideoCaptureFPS</span><span>)</span></div></div><div><div><div>21</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>22</div></div><div><span>    </span><span>panic</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>  </span><span>mat</span><span><span> </span><span>:=</span><span> </span></span><span>gocv</span><span>.</span><span>NewMat</span><span>()</span></div></div><div><div><div>26</div></div><div><span>  </span><span>w</span><span>, </span><span>h</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>, </span><span>0</span></div></div><div><div><div>27</div></div><div><span>  </span><span>// 放大缩小倍率</span></div></div><div><div><div>28</div></div><div><span>  </span><span>b</span><span><span> </span><span>:=</span><span> </span></span><span>0</span></div></div><div><div><div>29</div></div><div><span>  </span><span>// 每一帧之间时长</span></div></div><div><div><div>30</div></div><div><span>  </span><span>s</span><span><span> </span><span>:=</span><span> </span></span><span>int64</span><span>((</span><span>1</span><span><span> </span><span>/</span><span> </span></span><span>fps</span><span><span>) </span><span>*</span><span> </span></span><span><span>1</span><span>e</span><span>6</span></span><span>)</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>  </span><span>var</span><span> </span><span>t</span><span> </span><span>time</span><span>.</span><span>Time</span></div></div><div><div><div>33</div></div><div><span>  </span><span>// 每一帧时长与每一帧计算时长之差</span></div></div><div><div><div>34</div></div><div><span>  </span><span>var</span><span> </span><span>sub</span><span> </span><span>int64</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>  </span><span>var</span><span> </span><span>buf</span><span> </span><span>bytes</span><span>.</span><span>Buffer</span></div></div><div><div><div>37</div></div><div><span>  </span><span>// 转化大小</span></div></div><div><div><div>38</div></div><div><span>  </span><span>point</span><span><span> </span><span>:=</span><span> </span></span><span>image</span><span>.</span><span>Point</span><span>{</span><span>Y</span><span>: </span><span>0</span><span>, </span><span>X</span><span>: </span><span>0</span><span>}</span></div></div><div><div><div>39</div></div><div><span>  </span><span>for</span><span> </span><span>c</span><span>.</span><span>Read</span><span><span>(</span><span>&amp;</span></span><span>mat</span><span>) {</span></div></div><div><div><div>40</div></div><div><span>    </span><span>t</span><span><span> </span><span>=</span><span> </span></span><span>time</span><span>.</span><span>Now</span><span>()</span></div></div><div><div><div>41</div></div><div><span>    </span><span>// 获取终端大小</span></div></div><div><div><div>42</div></div><div><span>    </span><span>wl</span><span>, </span><span>hl</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>terminal</span><span>.</span><span>GetSize</span><span>(</span><span>int</span><span>(</span><span>os</span><span>.</span><span>Stdout</span><span>.</span><span>Fd</span><span>()))</span></div></div><div><div><div>43</div></div><div><span>    </span><span>// 如果终端大小发生变化则重新计算放大缩小倍率</span></div></div><div><div><div>44</div></div><div><span>    </span><span>if</span><span> </span><span>wl</span><span><span> </span><span>!=</span><span> </span></span><span>w</span><span><span> </span><span>||</span><span> </span></span><span>hl</span><span><span> </span><span>!=</span><span> </span></span><span>h</span><span> {</span></div></div><div><div><div>45</div></div><div><span>      </span><span>w</span><span><span> </span><span>=</span><span> </span></span><span>wl</span></div></div><div><div><div>46</div></div><div><span>      </span><span>h</span><span><span> </span><span>=</span><span> </span></span><span>hl</span></div></div><div><div><div>47</div></div><div><span>      </span><span>x</span><span>, </span><span>y</span><span><span> </span><span>:=</span><span> </span></span><span>mat</span><span>.</span><span>Rows</span><span>(), </span><span>mat</span><span>.</span><span>Cols</span><span>()</span></div></div><div><div><div>48</div></div><div><span>      </span><span>if</span><span> </span><span>hl</span><span><span> </span><span>&gt;</span><span> </span></span><span>wl</span><span> {</span></div></div><div><div><div>49</div></div><div><span>        </span><span>if</span><span> </span><span>x</span><span><span> </span><span>&lt;</span><span> </span></span><span>wl</span><span> {</span></div></div><div><div><div>50</div></div><div><span>          </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>wl</span><span><span> </span><span>/</span><span> </span></span><span>x</span></div></div><div><div><div>51</div></div><div><span>          </span><span>x</span><span><span> </span><span>*=</span><span> </span></span><span>b</span></div></div><div><div><div>52</div></div><div><span>          </span><span>y</span><span><span> </span><span>*=</span><span> </span></span><span>b</span></div></div><div><div><div>53</div></div><div><span><span>        </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>54</div></div><div><span>          </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>x</span><span><span> </span><span>/</span><span> </span></span><span>wl</span></div></div><div><div><div>55</div></div><div><span>          </span><span>x</span><span><span> </span><span>/=</span><span> </span></span><span>b</span></div></div><div><div><div>56</div></div><div><span>          </span><span>y</span><span><span> </span><span>/=</span><span> </span></span><span>b</span></div></div><div><div><div>57</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>58</div></div><div><span><span>      </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>59</div></div><div><span>        </span><span>if</span><span> </span><span>y</span><span><span> </span><span>&lt;</span><span> </span></span><span>hl</span><span> {</span></div></div><div><div><div>60</div></div><div><span>          </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>hl</span><span><span> </span><span>/</span><span> </span></span><span>y</span></div></div><div><div><div>61</div></div><div><span>          </span><span>x</span><span><span> </span><span>*=</span><span> </span></span><span>b</span></div></div><div><div><div>62</div></div><div><span>          </span><span>y</span><span><span> </span><span>*=</span><span> </span></span><span>b</span></div></div><div><div><div>63</div></div><div><span><span>        </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>64</div></div><div><span>          </span><span>b</span><span><span> </span><span>=</span><span> </span></span><span>y</span><span><span> </span><span>/</span><span> </span></span><span>hl</span></div></div><div><div><div>65</div></div><div><span>          </span><span>x</span><span><span> </span><span>/=</span><span> </span></span><span>b</span></div></div><div><div><div>66</div></div><div><span>          </span><span>y</span><span><span> </span><span>/=</span><span> </span></span><span>b</span></div></div><div><div><div>67</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>68</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>69</div></div><div><span>      </span><span>point</span><span>.</span><span>X</span><span><span> </span><span>=</span><span> </span></span><span>x</span></div></div><div><div><div>70</div></div><div><span>      </span><span>point</span><span>.</span><span>Y</span><span><span> </span><span>=</span><span> </span></span><span>y</span></div></div><div><div><div>71</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>72</div></div><div><span>    </span><span>// 转灰度</span></div></div><div><div><div>73</div></div><div><span>    </span><span>gocv</span><span>.</span><span>CvtColor</span><span>(</span><span>mat</span><span><span>, </span><span>&amp;</span></span><span>mat</span><span>, </span><span>gocv</span><span>.</span><span>ColorBGRToGray</span><span>)</span></div></div><div><div><div>74</div></div><div><span>    </span><span>// resize图像大小</span></div></div><div><div><div>75</div></div><div><span>    </span><span>gocv</span><span>.</span><span>Resize</span><span>(</span><span>mat</span><span><span>, </span><span>&amp;</span></span><span>mat</span><span>, </span><span>point</span><span>, </span><span>0</span><span>, </span><span>0</span><span>, </span><span>gocv</span><span>.</span><span>InterpolationLinear</span><span>)</span></div></div><div><div><div>76</div></div><div><span>    </span><span>// 图像归一化</span></div></div><div><div><div>77</div></div><div><span>    </span><span>mat</span><span>.</span><span>DivideFloat</span><span>(</span><span>255</span><span><span> </span><span>/</span><span> </span></span><span>float32</span><span>(</span><span>len</span><span>(</span><span>pixels</span><span><span>)</span><span>-</span></span><span>1</span><span>))</span></div></div><div><div><div>78</div></div><div><span>    </span><span>cols</span><span>, </span><span>rows</span><span><span> </span><span>:=</span><span> </span></span><span>mat</span><span>.</span><span>Cols</span><span>(), </span><span>mat</span><span>.</span><span>Rows</span><span>()</span></div></div><div><div><div>79</div></div><div><span>    </span><span>buf</span><span>.</span><span>Reset</span><span>()</span></div></div><div><div><div>80</div></div><div><span>    </span><span>for</span><span> </span><span>i</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>; </span><span>i</span><span><span> </span><span>&lt;</span><span> </span></span><span>rows</span><span>; </span><span>i</span><span><span>++</span><span> {</span></span></div></div><div><div><div>81</div></div><div><span>      </span><span>for</span><span> </span><span>j</span><span><span> </span><span>:=</span><span> </span></span><span>0</span><span>; </span><span>j</span><span><span> </span><span>&lt;</span><span> </span></span><span>cols</span><span>; </span><span>j</span><span><span>++</span><span> {</span></span></div></div><div><div><div>82</div></div><div>
</div></div><div><div><div>83</div></div><div><span>        </span><span>// 图像转化字符</span></div></div><div><div><div>84</div></div><div><span>        </span><span>buf</span><span>.</span><span>WriteByte</span><span>(</span><span>pixels</span><span>[</span><span>mat</span><span>.</span><span>GetSCharAt</span><span>(</span><span>i</span><span>, </span><span>j</span><span>)])</span></div></div><div><div><div>85</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>86</div></div><div><span>      </span><span>buf</span><span>.</span><span>WriteByte</span><span>(</span><span>'</span><span>\n</span><span>'</span><span>)</span></div></div><div><div><div>87</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>88</div></div><div><span>    </span><span>sub</span><span><span>=</span><span> </span></span><span>time</span><span>.</span><span>Now</span><span>().</span><span>Sub</span><span>(</span><span>t</span><span>).</span><span>Microseconds</span><span>()</span></div></div><div><div><div>89</div></div><div><span>    </span><span>// 如果比较计算时间与每一帧图像时间</span></div></div><div><div><div>90</div></div><div><span>    </span><span>if</span><span> </span><span>sub</span><span><span> </span><span>&lt;</span><span> </span></span><span>s</span><span> {</span></div></div><div><div><div>91</div></div><div><span>      </span><span>// 休眠，使字符显示时间靠近源视频每一帧时间</span></div></div><div><div><div>92</div></div><div><span>      </span><span>time</span><span>.</span><span>Sleep</span><span>(</span><span>time</span><span>.</span><span>Duration</span><span>(</span><span>s</span><span>-</span><span>sub</span><span><span>) </span><span>*</span><span> </span></span><span>time</span><span>.</span><span>Microsecond</span><span>)</span></div></div><div><div><div>93</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>94</div></div><div><span>    </span><span>// 清屏</span></div></div><div><div><div>95</div></div><div><span>    </span><span>cmd</span><span><span> </span><span>:=</span><span> </span></span><span>exec</span><span>.</span><span>Command</span><span>(</span><span>"bash"</span><span>, </span><span>"-c"</span><span>, </span><span>"clear"</span><span>)</span></div></div><div><div><div>96</div></div><div><span>    </span><span>cmd</span><span>.</span><span>Stdout</span><span><span> </span><span>=</span><span> </span></span><span>os</span><span>.</span><span>Stdout</span></div></div><div><div><div>97</div></div><div><span>    </span><span>cmd</span><span>.</span><span>Run</span><span>()</span></div></div><div><div><div>98</div></div><div><span>    </span><span>fmt</span><span>.</span><span>Print</span><span>(</span><span>buf</span><span>.</span><span>String</span><span>())</span></div></div><div><div><div>99</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>100</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/247/</id>
      <title type="text">【杂项】x86机器使用docker交叉编译arm、arm64</title>
      <published>2021-08-09T11:40:46.000Z</published>
      <updated>2021-08-09T11:40:46.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/247/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>qemu是一款开源虚拟化软件，通过动态二进制转换来模拟CPU。</p><p>这次使用<a href="https://github.com/multiarch/qemu-user-static" target="_blank">qemu-arm-static</a>来模拟arm环境运行arm镜像。</p></section>
<section><h1>0x01 注册<a href="#0x01-注册"><span>#</span></a></h1><p>使用命令</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>docker</span><span> </span><span>run</span><span> </span><span>--rm</span><span> </span><span>--privileged</span><span> </span><span>multiarch/qemu-user-static</span><span> </span><span>--reset</span><span> </span><span>-p</span><span> </span><span>yes</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注册<code>qemu-arm-static</code>到docker。</p></section>
<section><h1>0x02 使用<a href="#0x02-使用"><span>#</span></a></h1><p>接下来就可以运行arm镜像了</p><div><div><div><figure><figcaption><span></span><span>Terminal window</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>docker</span><span> </span><span>run</span><span> </span><span>--rm</span><span> </span><span>-t</span><span> </span><span>arm32v6/alpine</span><span> </span><span>uname</span><span> </span><span>-m</span></div></div><div><div><div>2</div></div><div><span>armv7l</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>$</span><span> </span><span>docker</span><span> </span><span>run</span><span> </span><span>--rm</span><span> </span><span>-t</span><span> </span><span>ppc64le/debian</span><span> </span><span>uname</span><span> </span><span>-m</span></div></div><div><div><div>5</div></div><div><span>ppc64le</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>$</span><span> </span><span>docker</span><span> </span><span>run</span><span> </span><span>--rm</span><span> </span><span>-t</span><span> </span><span>s390x/ubuntu</span><span> </span><span>uname</span><span> </span><span>-m</span></div></div><div><div><div>8</div></div><div><span>s390x</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>$</span><span> </span><span>docker</span><span> </span><span>run</span><span> </span><span>--rm</span><span> </span><span>-t</span><span> </span><span>arm64v8/fedora</span><span> </span><span>uname</span><span> </span><span>-m</span></div></div><div><div><div>11</div></div><div><span>aarch64</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>$</span><span> </span><span>docker</span><span> </span><span>run</span><span> </span><span>--rm</span><span> </span><span>-t</span><span> </span><span>arm32v7/centos</span><span> </span><span>uname</span><span> </span><span>-m</span></div></div><div><div><div>14</div></div><div><span>armv7l</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>$</span><span> </span><span>docker</span><span> </span><span>run</span><span> </span><span>--rm</span><span> </span><span>-t</span><span> </span><span>ppc64le/busybox</span><span> </span><span>uname</span><span> </span><span>-m</span></div></div><div><div><div>17</div></div><div><span>ppc64le</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>$</span><span> </span><span>docker</span><span> </span><span>run</span><span> </span><span>--rm</span><span> </span><span>-t</span><span> </span><span>arm64v8/ubuntu</span><span> </span><span>uname</span><span> </span><span>-m</span></div></div><div><div><div>20</div></div><div><span>aarch64</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/246/</id>
      <title type="text">【Golang】使用gocv库编写三帧法</title>
      <published>2021-08-04T11:55:23.000Z</published>
      <updated>2021-08-04T11:55:23.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/246/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x0<a href="#0x0"><span>#</span></a></h1><p>三帧法运动检测属于帧间差分法，相关介绍在之前的文章中有介绍。<a href="/posts/233/">跳转</a></p><p>这次使用Golang的OpenCV库：gocv <a href="https://gocv.io/" target="_blank">跳转</a> 来编写，是最近为了练手gocv而写的第一个demo</p></section>
<section><h1>0x1<a href="#0x1"><span>#</span></a></h1><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>main</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>import</span><span> (</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"gocv.io/x/gocv"</span></div></div><div><div><div>5</div></div><div><span>)</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>8</div></div><div><span>  </span><span>c</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>gocv</span><span>.</span><span>VideoCaptureFile</span><span>(</span><span>"1.mp4"</span><span>)</span></div></div><div><div><div>9</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>10</div></div><div><span>    </span><span>panic</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>  </span><span>mat</span><span><span> </span><span>:=</span><span> </span></span><span>gocv</span><span>.</span><span>NewMat</span><span>()</span></div></div><div><div><div>13</div></div><div><span>  </span><span>aMat</span><span>, </span><span>bMat</span><span><span> </span><span>:=</span><span> </span></span><span>gocv</span><span>.</span><span>NewMat</span><span>(), </span><span>gocv</span><span>.</span><span>NewMat</span><span>()</span></div></div><div><div><div>14</div></div><div><span>  </span><span>ab</span><span>, </span><span>bc</span><span><span> </span><span>:=</span><span> </span></span><span>gocv</span><span>.</span><span>NewMat</span><span>(), </span><span>gocv</span><span>.</span><span>NewMat</span><span>()</span></div></div><div><div><div>15</div></div><div><span>  </span><span>f</span><span><span> </span><span>:=</span><span> </span></span><span>gocv</span><span>.</span><span>NewMat</span><span>()</span></div></div><div><div><div>16</div></div><div><span>  </span><span>w</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>gocv</span><span>.</span><span>VideoWriterFile</span><span>(</span><span>"test.mp4"</span><span>, </span><span>c</span><span>.</span><span>CodecString</span><span>(), </span><span>c</span><span>.</span><span>Get</span><span>(</span><span>gocv</span><span>.</span><span>VideoCaptureFPS</span><span>), </span><span>int</span><span>(</span><span>c</span><span>.</span><span>Get</span><span>(</span><span>gocv</span><span>.</span><span>VideoCaptureFrameWidth</span><span>)), </span><span>int</span><span>(</span><span>c</span><span>.</span><span>Get</span><span>(</span><span>gocv</span><span>.</span><span>VideoCaptureFrameHeight</span><span>)), </span><span>false</span><span>)</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>  </span><span>for</span><span> </span><span>c</span><span>.</span><span>Read</span><span><span>(</span><span>&amp;</span></span><span>mat</span><span>) {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>//灰度</span></div></div><div><div><div>20</div></div><div><span>    </span><span>gocv</span><span>.</span><span>CvtColor</span><span>(</span><span>mat</span><span><span>, </span><span>&amp;</span></span><span>mat</span><span>, </span><span>gocv</span><span>.</span><span>ColorBGRToGray</span><span>)</span></div></div><div><div><div>21</div></div><div><span>    </span><span>//二值</span></div></div><div><div><div>22</div></div><div><span>    </span><span>gocv</span><span>.</span><span>Threshold</span><span>(</span><span>mat</span><span><span>, </span><span>&amp;</span></span><span>mat</span><span>, </span><span>25</span><span>, </span><span>255</span><span>, </span><span>gocv</span><span>.</span><span>ThresholdBinary</span><span>)</span></div></div><div><div><div>23</div></div><div><span>    </span><span>if</span><span> </span><span>bMat</span><span>.</span><span>Empty</span><span>() {</span></div></div><div><div><div>24</div></div><div><span>      </span><span>if</span><span> </span><span>aMat</span><span>.</span><span>Empty</span><span>() {</span></div></div><div><div><div>25</div></div><div><span>        </span><span>mat</span><span>.</span><span>CopyTo</span><span><span>(</span><span>&amp;</span></span><span>aMat</span><span>)</span></div></div><div><div><div>26</div></div><div><span><span>      </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>27</div></div><div><span>        </span><span>mat</span><span>.</span><span>CopyTo</span><span><span>(</span><span>&amp;</span></span><span>bMat</span><span>)</span></div></div><div><div><div>28</div></div><div><span>        </span><span>gocv</span><span>.</span><span>AbsDiff</span><span>(</span><span>aMat</span><span>, </span><span>bMat</span><span><span>, </span><span>&amp;</span></span><span>ab</span><span>)</span></div></div><div><div><div>29</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>30</div></div><div><span>      </span><span>continue</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>32</div></div><div><span>    </span><span>gocv</span><span>.</span><span>AbsDiff</span><span>(</span><span>bMat</span><span>, </span><span>mat</span><span><span>, </span><span>&amp;</span></span><span>bc</span><span>)</span></div></div><div><div><div>33</div></div><div><span>    </span><span>gocv</span><span>.</span><span>BitwiseAnd</span><span>(</span><span>ab</span><span>, </span><span>bc</span><span><span>, </span><span>&amp;</span></span><span>f</span><span>)</span></div></div><div><div><div>34</div></div><div><span>    </span><span>w</span><span>.</span><span>Write</span><span>(</span><span>f</span><span>)</span></div></div><div><div><div>35</div></div><div><span>    </span><span>bc</span><span>.</span><span>CopyTo</span><span><span>(</span><span>&amp;</span></span><span>ab</span><span>)</span></div></div><div><div><div>36</div></div><div><span>    </span><span>bMat</span><span>.</span><span>CopyTo</span><span><span>(</span><span>&amp;</span></span><span>aMat</span><span>)</span></div></div><div><div><div>37</div></div><div><span>    </span><span>mat</span><span>.</span><span>CopyTo</span><span><span>(</span><span>&amp;</span></span><span>bMat</span><span>)</span></div></div><div><div><div>38</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>39</div></div><div><span>  </span><span>w</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>40</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/243/</id>
      <title type="text">【算法】动态规划</title>
      <published>2021-04-16T08:13:00.000Z</published>
      <updated>2021-04-16T08:17:56.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/243/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>动态规划（一）<a href="#动态规划一"><span>#</span></a></h1><p>动态规划（Dynamic Programming）其实是运筹学中一种优化方法，动态规划一般就是求最值，比如最少次数、最短距离等。</p><p>求解动态规划的核心问题其实就是 <code>穷举</code>。因为要求出问题的最值，所以需要穷举出每一种答案找到最值。</p><p>当存在重复子问题时，如果是暴力穷举就会重复计算，导致效率低下。而优化的方法是建立“备忘录”或“DP数组”，避免重复计算。</p><section><h2>例题：凑零钱问题<a href="#例题凑零钱问题"><span>#</span></a></h2><p>现有 <code>k</code>种面额的硬币，面值分别 <code>c1,c2,...,ck</code>，每种硬币的数量是无限的，现在有一个目标金额 <code>amount</code>，问<strong>最少</strong>需要多少枚硬币可以凑到这个金额，如果凑不出就返回 -1。</p><p>假如现有 <code>k=3</code>，面额为 <code>1,2,5</code>的三种硬币，目标金额 <code>amount = 11</code>，则最少需要3枚硬币凑出，即 <code>5 + 5 + 1 = 11</code>。</p><section><h3>子问题<a href="#子问题"><span>#</span></a></h3><p>子问题是原问题的划分，例如求f(8)需要求出f(7)，求f(7)需要求出f(6)以此类推，f(8)的子问题是f(7)，f(7)的子问题是f(6)。</p><p>凑零钱问题中，求目标 <code>11</code>最少硬币数量，子问题就是 <code>10</code>最少硬币数量，再次划分就是 <code>9</code>最少硬币数量以此类推。</p></section><section><h3>最优子结构<a href="#最优子结构"><span>#</span></a></h3><p>首先这是一个的动态规划问题，因为它具有“最优子结构”。“最优子结构”的子问题间必须相互独立、互不干扰。</p><p>比如：a = b + c，求a的最大值就需要求b和c的最大值，b和c互不干扰，因此这符合“最优子结构”。如果b与c互相干扰，比如增长b那么c就减小，那么就不是“最优子结构”。</p><p>凑零钱的问题中，各硬币的数量之间没有限制，硬币总数也是无限的。子问题之间是相互独立的。</p></section><section><h3>状态转移<a href="#状态转移"><span>#</span></a></h3><p>动态规划的核心是穷举最值，只有列举出正确的“状态转移方程”才能正确穷举。</p><p>思考确定状态转移方程：</p><ol>
<li><strong>确定 base case（最简情况）</strong>。在凑零钱中当<code>amount=0</code>时就返回0，表示不需要硬币了。</li>
<li><strong>确定“状态”，也是原问题和子问题的变量</strong>。因为硬币是无限的，硬币的面额也是确定的，当目标不断向base case靠近，所以唯一的“状态”就是目标<code>amount</code>。</li>
<li><strong>确定“选择”，也就是导致“状态”产生“变化”的行为</strong>。目标<code>amount</code>之所以会变，是因为“选择”了硬币。当选择了面额为1的硬币，那么目标<code>amount=11</code>就变为了<code>amount=10</code>，所以硬币的面额就是选择。</li>
<li><strong>明确dp函数/数组的定义</strong>。接下来会先展示递归，所以使用dp函数，dp函数中参数就是状态转移的变量，也就是“状态”，函数返回值就是计算的量。</li>
</ol></section><section><h3>一、暴力递归解法<a href="#一暴力递归解法"><span>#</span></a></h3><p>这道题中当目标金额为0 时，所需要的硬币为0；小于0时，无解，返回 -1。
状态转移方程：</p><p><span><span>dp(n)={0,n=0amount+1,n&lt;0min{dp(n−coin)+1∣coin∈coins)},n&gt;0dp(n)=\begin{cases}
0,n=0
\\ amount+1,n&lt;0
\\ min\{dp(n-coin)+1|coin \in coins)\},n&gt;0
\end{cases}</span><span><span><span></span><span>d</span><span>p</span><span>(</span><span>n</span><span>)</span><span></span><span>=</span><span></span></span><span><span></span><span><span><span><span><span><span><span><span></span><span><span>⎩</span></span></span><span><span></span><span></span></span><span><span></span><span><span>⎨</span></span></span><span><span></span><span></span></span><span><span></span><span><span>⎧</span></span></span></span><span>​</span></span><span><span><span></span></span></span></span></span></span><span><span><span><span><span><span><span><span></span><span><span>0</span><span>,</span><span></span><span>n</span><span></span><span>=</span><span></span><span>0</span></span></span><span><span></span><span><span>am</span><span>o</span><span>u</span><span>n</span><span>t</span><span></span><span>+</span><span></span><span>1</span><span>,</span><span></span><span>n</span><span></span><span>&lt;</span><span></span><span>0</span></span></span><span><span></span><span><span>min</span><span>{</span><span>d</span><span>p</span><span>(</span><span>n</span><span></span><span>−</span><span></span><span>co</span><span>in</span><span>)</span><span></span><span>+</span><span></span><span>1∣</span><span>co</span><span>in</span><span></span><span>∈</span><span></span><span>co</span><span>in</span><span>s</span><span>)}</span><span>,</span><span></span><span>n</span><span></span><span>&gt;</span><span></span><span>0</span></span></span></span><span>​</span></span><span><span><span></span></span></span></span></span></span></span><span></span></span></span></span></span>
代码：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//coins为硬币面额，amount为目标金额</span></div></div><div><div><div>2</div></div><div><span>//coins=[1,2,5]，amount=11</span></div></div><div><div><div>3</div></div><div><span>func</span><span> </span><span>dp</span><span><span>(</span><span>coins</span><span> []</span></span><span>int</span><span><span>,</span><span>amount</span><span> </span></span><span>int</span><span>)</span><span>int</span><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span> </span><span>n</span><span>==</span><span>0</span><span> {</span><span>return</span><span> </span><span>0</span><span>}  </span><span>// base case</span></div></div><div><div><div>5</div></div><div><span>    </span><span>if</span><span> </span><span>n</span><span>&lt;</span><span>0</span><span> {</span><span>return</span><span><span> </span><span>-</span></span><span>1</span><span>}</span></div></div><div><div><div>6</div></div><div><span>    </span><span>num</span><span>:=</span><span>amount</span><span>+</span><span>1</span><span>   </span><span>//因为凑出硬币的数量永远也不可能大于目标金额，所以amount+1表示无穷大。而求最小值，所以初始化无穷大。</span></div></div><div><div><div>7</div></div><div><span>    </span><span>//“选择”</span></div></div><div><div><div>8</div></div><div><span>    </span><span>for</span><span> </span><span>_</span><span>,</span><span>coin</span><span>:=</span><span>range</span><span> </span><span>coins</span><span>{</span></div></div><div><div><div>9</div></div><div><span>        </span><span>sub</span><span>:=</span><span>dp</span><span>(</span><span>coins</span><span>,</span><span>amount</span><span><span> </span><span>-</span><span> </span></span><span>coin</span><span>)</span></div></div><div><div><div>10</div></div><div><span>        </span><span>if</span><span> </span><span>sub</span><span><span> </span><span>==</span><span> </span><span>-</span></span><span>1</span><span>{</span><span>continue</span><span>}  </span><span>//子问题无解，跳过</span></div></div><div><div><div>11</div></div><div><span>        </span><span>//min()</span></div></div><div><div><div>12</div></div><div><span>        </span><span>if</span><span> </span><span>num</span><span><span> </span><span>&gt;</span><span> </span></span><span>1</span><span>+</span><span>sub</span><span>{</span></div></div><div><div><div>13</div></div><div><span>            </span><span>num</span><span><span> </span><span>=</span><span> </span></span><span>1</span><span>+</span><span>sub</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span>    </span><span>if</span><span> </span><span>num</span><span>==</span><span>amount</span><span>+</span><span>1</span><span>{   </span><span>//没有凑出</span></div></div><div><div><div>17</div></div><div><span>        </span><span>return</span><span><span> </span><span>-</span></span><span>1</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div><span>    </span><span>return</span><span> </span><span>num</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>递归树：</p><div><div><div><div><span><p>1</p></span></div><div><span><p>2</p></span></div><div><span></span></div><div><span><p>5</p></span></div><div><span><p>1</p></span></div><div><span><p>2</p></span></div><div><span></span></div><div><span><p>5</p></span></div><div><span></span></div><div><span><p>1</p></span></div><div><span><p>2</p></span></div><div><span><p>5</p></span></div><div><span><p>1</p></span></div><div><span></span></div><div><span><p>2</p></span></div><div><span><p>5</p></span></div><div><span></span></div><div><span><p>1</p></span></div><div><span><p>2</p></span></div><div><span><p>5</p></span></div><div><span><p>11</p></span></div><div><span><p>10</p></span></div><div><span><p>9</p></span></div><div><span><p>...</p></span></div><div><span><p>6</p></span></div><div><span><p>9</p></span></div><div><span><p>8</p></span></div><div><span><p>...</p></span></div><div><span><p>5</p></span></div><div><span><p>...</p></span></div><div><span><p>8</p></span></div><div><span><p>7</p></span></div><div><span><p>4</p></span></div><div><span><p>5</p></span></div><div><span><p>...</p></span></div><div><span><p>4</p></span></div><div><span><p>1</p></span></div><div><span><p>...</p></span></div><div><span><p>3</p></span></div><div><span><p>2</p></span></div><div><span><p>-1</p></span></div>
</div><div><div><span><p>1</p></span></div><div><span><p>2</p></span></div><div><span></span></div><div><span><p>5</p></span></div><div><span><p>1</p></span></div><div><span><p>2</p></span></div><div><span></span></div><div><span><p>5</p></span></div><div><span></span></div><div><span><p>1</p></span></div><div><span><p>2</p></span></div><div><span><p>5</p></span></div><div><span><p>1</p></span></div><div><span></span></div><div><span><p>2</p></span></div><div><span><p>5</p></span></div><div><span></span></div><div><span><p>1</p></span></div><div><span><p>2</p></span></div><div><span><p>5</p></span></div><div><span><p>11</p></span></div><div><span><p>10</p></span></div><div><span><p>9</p></span></div><div><span><p>...</p></span></div><div><span><p>6</p></span></div><div><span><p>9</p></span></div><div><span><p>8</p></span></div><div><span><p>...</p></span></div><div><span><p>5</p></span></div><div><span><p>...</p></span></div><div><span><p>8</p></span></div><div><span><p>7</p></span></div><div><span><p>4</p></span></div><div><span><p>5</p></span></div><div><span><p>...</p></span></div><div><span><p>4</p></span></div><div><span><p>1</p></span></div><div><span><p>...</p></span></div><div><span><p>3</p></span></div><div><span><p>2</p></span></div><div><span><p>-1</p></span></div>
</div></div></div><p>通过递归树可以看到，存在 <code>amount</code>相同的重复子问题，从而导致算法效率低下。</p><p><em><strong>递归算法时间复杂度 = 子问题总数时间复杂度 x 每个子问题时间复杂度</strong></em></p><p>在此暴力递归中，子问题总数时间复杂度为<span><span>O(nk)O(n^{k})</span><span><span><span></span><span>O</span><span>(</span><span><span>n</span><span><span><span><span><span><span></span><span><span><span>k</span></span></span></span></span></span></span></span></span><span>)</span></span></span></span>，每个子问题时间复杂度为<span><span>O(k)O(k)</span><span><span><span></span><span>O</span><span>(</span><span>k</span><span>)</span></span></span></span>。因此本暴力递归的中时间复杂度为<span><span>O(knk)O(kn^{k})</span><span><span><span></span><span>O</span><span>(</span><span>k</span><span><span>n</span><span><span><span><span><span><span></span><span><span><span>k</span></span></span></span></span></span></span></span></span><span>)</span></span></span></span>。</p></section><section><h3>二、带“备忘录”的递归解法<a href="#二带备忘录的递归解法"><span>#</span></a></h3><p>从上述的暴力递归树中可以看出，存在许多重复的子问题，这些重复的子问题就是导致算法效率低的主要原因。那么针对这个问题，我们可以建立一个“备忘录”来存储每个子问题计算的结果，在计算子问题之前先查询是有结果存在“备忘录”中，如果存在就直接使用“备忘录”中的值而不再去计算。</p><p><em>一般“备忘录”可以使用数组或哈希表来建立。</em></p><p>代码：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span> </span><span>tab</span><span> []</span><span>int</span><span>   </span><span>//备忘录</span></div></div><div><div><div>2</div></div><div><span>func</span><span> </span><span>dp</span><span><span>(</span><span>coins</span><span> []</span></span><span>int</span><span><span>,</span><span>amount</span><span> </span></span><span>int</span><span>)</span><span>int</span><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>//初始化备忘录</span></div></div><div><div><div>4</div></div><div><span>    </span><span>if</span><span> </span><span>tab</span><span><span> </span><span>==</span><span> </span></span><span>nil</span><span>{</span><span>tab</span><span>=</span><span>make</span><span>([]</span><span>int</span><span>,</span><span>len</span><span>(</span><span>coins</span><span>))}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>    </span><span>if</span><span> </span><span>n</span><span>==</span><span>0</span><span> {</span><span>return</span><span> </span><span>0</span><span>}</span></div></div><div><div><div>7</div></div><div><span>    </span><span>if</span><span> </span><span>n</span><span>&lt;</span><span>0</span><span> {</span><span>return</span><span><span> </span><span>-</span></span><span>1</span><span>}</span></div></div><div><div><div>8</div></div><div><span>    </span><span>num</span><span>:=</span><span>amount</span><span>+</span><span>1</span></div></div><div><div><div>9</div></div><div><span>    </span><span>for</span><span> </span><span>_</span><span>,</span><span>coin</span><span>:=</span><span>range</span><span> </span><span>coins</span><span>{</span></div></div><div><div><div>10</div></div><div><span>        </span><span>i</span><span><span> </span><span>:=</span><span> </span></span><span>amount</span><span><span> </span><span>-</span><span> </span></span><span>coin</span></div></div><div><div><div>11</div></div><div><span>        </span><span>//查表，若结果不存在的话就进行计算</span></div></div><div><div><div>12</div></div><div><span>        </span><span>if</span><span> </span><span>tab</span><span>[</span><span>i</span><span><span>]</span><span>==</span></span><span>0</span><span>{</span></div></div><div><div><div>13</div></div><div><span>            </span><span>tab</span><span>[</span><span>i</span><span><span>] </span><span>=</span><span> </span></span><span>dp</span><span>(</span><span>coins</span><span>,</span><span>i</span><span>)</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>        </span><span>if</span><span> </span><span>tab</span><span>[</span><span>i</span><span><span>] </span><span>==</span><span> </span><span>-</span></span><span>1</span><span>{</span><span>continue</span><span>}</span></div></div><div><div><div>16</div></div><div><span>        </span><span>//min()</span></div></div><div><div><div>17</div></div><div><span>        </span><span>if</span><span> </span><span>num</span><span><span> </span><span>&gt;</span><span> </span></span><span>1</span><span><span> </span><span>+</span><span> </span></span><span>tab</span><span>[</span><span>i</span><span>]{</span></div></div><div><div><div>18</div></div><div><span>            </span><span>num</span><span><span> </span><span>=</span><span> </span></span><span>1</span><span><span> </span><span>+</span><span> </span></span><span>tab</span><span>[</span><span>i</span><span>]</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>21</div></div><div><span>    </span><span>if</span><span> </span><span>num</span><span>==</span><span>amount</span><span>+</span><span>1</span><span>{</span></div></div><div><div><div>22</div></div><div><span>        </span><span>return</span><span><span> </span><span>-</span></span><span>1</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span>    </span><span>return</span><span> </span><span>num</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>带有“备忘录”的递归就解决了重复子问题冗余的问题,因此子问题的个数不会超过目标金额<span><span>nn</span><span><span><span></span><span>n</span></span></span></span>，因此带“备忘录”的递归的总时间复杂度为<span><span>O(kn)O(kn)</span><span><span><span></span><span>O</span><span>(</span><span>k</span><span>n</span><span>)</span></span></span></span>。</p></section><section><h3>三、dp数组迭代解法<a href="#三dp数组迭代解法"><span>#</span></a></h3><p>以上递归都是自顶向下的解法，“状态”<code>amount</code>的变化为：11、10、…、0
而dp数组迭代则是自底向上的解法，“状态”<code>amount</code>的变化为：1、2、…、11</p><p>dp数组的定义：当目标金额为 <code>n</code>时，最多需要 <code>dp[n]</code>枚硬币。</p><p>代码：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>func</span><span> </span><span>coinChange</span><span><span>(</span><span>coins</span><span> []</span></span><span>int</span><span><span>,</span><span>amount</span><span> </span></span><span>int</span><span>)</span><span>int</span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>//创建dp数组，长度为amount+1</span></div></div><div><div><div>3</div></div><div><span>    </span><span>dp</span><span><span> </span><span>:=</span><span> </span></span><span>make</span><span>([]</span><span>int</span><span>,</span><span>amount</span><span>+</span><span>1</span><span>)</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>//初始化dp数组，除dp[0]以外都赋值amount+1</span></div></div><div><div><div>6</div></div><div><span>    </span><span>//以dp数组下标为各“状态”目标金额。</span></div></div><div><div><div>7</div></div><div><span>    </span><span>//当“状态”为0时，结果为零，因此dp[0]=0。base case</span></div></div><div><div><div>8</div></div><div><span>    </span><span>//除0其他以外，都赋值amount+1。amount+1为硬币永远也达不到的数量，本题求最少硬币数量，因此amount+1表示无穷大。</span></div></div><div><div><div>9</div></div><div><span>    </span><span>for</span><span> </span><span>i</span><span>:=</span><span>1</span><span>;</span><span>i</span><span>&lt;</span><span>amount</span><span>+</span><span>1</span><span>;</span><span>i</span><span><span>++</span><span>{</span></span></div></div><div><div><div>10</div></div><div><span>        </span><span>dp</span><span>[</span><span>i</span><span><span>] </span><span>=</span><span> </span></span><span>amount</span><span>+</span><span>1</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>    </span><span>//变量所有状态取值</span></div></div><div><div><div>13</div></div><div><span>    </span><span>for</span><span> </span><span>i</span><span>:=</span><span>0</span><span>;</span><span>i</span><span>&lt;</span><span>len</span><span>(</span><span>dp</span><span>);</span><span>i</span><span><span>++</span><span>{</span></span></div></div><div><div><div>14</div></div><div><span>        </span><span>//寻找最少硬币数量</span></div></div><div><div><div>15</div></div><div><span>        </span><span>for</span><span> </span><span>_</span><span>,</span><span>coin</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>coins</span><span>{</span></div></div><div><div><div>16</div></div><div><span>            </span><span>// 子问题无解，跳过</span></div></div><div><div><div>17</div></div><div><span>            </span><span>if</span><span> </span><span>i</span><span>-</span><span>coin</span><span>&lt;</span><span>0</span><span> {</span></div></div><div><div><div>18</div></div><div><span>                </span><span>continue</span></div></div><div><div><div>19</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span>            </span><span>//min()</span></div></div><div><div><div>21</div></div><div><span>            </span><span>if</span><span> </span><span>dp</span><span>[</span><span>i</span><span><span>] </span><span>&gt;</span><span> </span></span><span>1</span><span>+</span><span>dp</span><span>[</span><span>i</span><span>-</span><span>coin</span><span>]{</span></div></div><div><div><div>22</div></div><div><span>                </span><span>dp</span><span>[</span><span>i</span><span><span>] </span><span>=</span><span> </span></span><span>1</span><span>+</span><span>dp</span><span>[</span><span>i</span><span>-</span><span>coin</span><span>]</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>24</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>26</div></div><div><span>    </span><span>//结果为amount+1“无穷大”为无解返回-1</span></div></div><div><div><div>27</div></div><div><span>    </span><span>if</span><span> </span><span>dp</span><span>[</span><span>amount</span><span><span>] </span><span>==</span><span> </span></span><span>amount</span><span>+</span><span>1</span><span>{</span></div></div><div><div><div>28</div></div><div><span>        </span><span>return</span><span><span> </span><span>-</span></span><span>1</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>30</div></div><div><span>    </span><span>return</span><span> </span><span>dp</span><span>[</span><span>amount</span><span>]</span></div></div><div><div><div>31</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/242/</id>
      <title type="text">【计算机网络】UDP打洞</title>
      <published>2021-02-28T10:59:00.000Z</published>
      <updated>2021-04-06T11:57:49.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/242/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>UDP打洞<a href="#udp打洞"><span>#</span></a></h1><p>指用于NAT穿越的一种技术，也即<code>内网穿透</code>技术。</p><section><h2>背景介绍<a href="#背景介绍"><span>#</span></a></h2><section><h3>IPv4枯竭<a href="#ipv4枯竭"><span>#</span></a></h3><p>现阶段大多网络设备是用IPv4地址作为互联网通信地址，IPv4使用32位（4字节）地址，因此只有4,294,967,296（2<sup>32</sup>）个地址可供使用，其间有一些地址是为特殊用途而保留的，如专用网络（约1800万个地址）和多播网络（约2.7个地址），这将减少了互联网中可用的地址。随着时间的变化，接入互联网的设备越来越多，出现了IPv4地址的枯竭的问题。</p></section><section><h3>NAT技术<a href="#nat技术"><span>#</span></a></h3><p>NAT全称：<code>Network Address Translation</code>，网络地址转换。是一种在IP数据包通过路由器或防火墙时重写来源IP或目的IP的技术。<strong>该技术可以实现多个网络设备共用一个对外IP或公网IP</strong>。</p><p>因此NAT技术可以缓解IPv4枯竭的问题，目前基本上家用宽带运营商都使用NAT技术为用户赋予IP地址，通常是一层或一栋楼共用一个公网IP（详情根据当地运营商而定）。</p><p></p><figure><img alt="NAT.jpg" loading="lazy" width="487" height="121" src="/_astro/242.1.COgkI6y0_Z5QdFz.webp" /><figcaption>NAT.jpg</figcaption></figure><p></p><p>假如现有内网设备<code>A</code>、NAT(1.1.1.2)和公网服务器(1.1.1.1)</p><ol>
<li>A向服务器发送请求包。</li>
<li>A请求包经过NAT，NAT从中得到请求的目的地址（1.1.1.1）。</li>
<li>NAT保存A的地址和A的目的地址（1.1.1.1），并给A随机分配映射一个端口（1234）。</li>
<li>NAT将A请求包的源地址（A的地址）和源端口，替换为NAT的公网IP和分配给A的端口（1234）。</li>
<li>NAT将请求包向公网服务器（1.1.1.1）发出。</li>
<li>服务器（1.1.1.1）接收到请求包并返回回应包。</li>
<li>NAT接收到回应包，并从中得到回应的端口（1234）。</li>
<li>NAT找查记录，发现与端口（1234）对应的设备是A，并且回应包发送者的IP（1.1.1.1）也在其中。（若两者其中一个不满足就会将此包丢弃）</li>
<li>NAT将回应包的目的IP（1.1.1.2）和目的端口（1234）改为A的地址。</li>
<li>NAT将回应包发送给A。</li>
</ol><p>默认情况下在NAT内网的设备可以主动访问公网IP的设备，但公网IP设备却不能主动访问NAT内网的设备（因为NAT没有记录，对应上述例子第8步）.</p></section></section><section><h2>打洞<a href="#打洞"><span>#</span></a></h2><p>因为NAT技术的原因，造成两个NAT内网的设备无法直接通信（例如：不能直接访问没有公网IP的电脑）。
<strong>打洞</strong>顾名思义，就是在NAT内网中打出一个洞，让两个不同内网的设备直接访问。</p><section><h3>原理<a href="#原理"><span>#</span></a></h3><p>从上述NAT技术的第4步和第9步，可以看出NAT需要将内网设备映射到一个端口并保存其访问的公网地址和端口，才可以使内网设备和公网设备通信。所以打洞给关键一步就是让两个设备相互访问对方公网对应的IP和端口，让自己的NAT保存记录。</p><p>假如现有内网设备A、NAT A(1.1.1.2)、内网设备B、NAT B(1.1.1.3)以及公网服务器(1.1.1.1)，内网设备A和内网设备B想要直接通信。</p><p></p><figure><img alt="UDPASS.jpg" loading="lazy" width="541" height="240" src="/_astro/242.2.C4K18eJ1_7qO1C.webp" /><figcaption>UDPASS.jpg</figcaption></figure><p></p><ol>
<li>A和B向服务器访问，NAT A和NAT B分别为AB分配映射端口<code>4530</code>与<code>6540</code>。</li>
<li>服务器收到请求后，保存IP和端口（<code>1.1.1.2:4530</code>，<code>1.1.1.3:6540</code>）。</li>
<li>服务器向A返回B的IP和端口，向B返回A的IP和端口。</li>
<li>A向B的地址发送数据（NAT B因为没有A的地址记录会丢弃A的包，但是这一步为的是让NAT A记住B的地址，让NAT A以后将带有B地址的包转发给A）。</li>
<li>B再向A发送数据。（这一步也是让NAT B记住A的地址，但上一步NAT A已经有了B的地址，所以这一次B发送的数据可以正常到达A）。</li>
<li>从此A和B就可以直接双向发送数据，洞就被打通了。</li>
</ol></section><section><h3>UDP<a href="#udp"><span>#</span></a></h3><p>UDP全称：User Datagram Protocol，用户数据报协议。是一种无连接的协议。</p><p>UDP负责将数据发送出去，但对方有没有接收到就不是UDP责任了（就算是错误的IP或端口，UDP也照样发送），因此也是一种不可靠的协议。</p><p>但是就很适合使用UDP来做NAT打洞，因为在上述原理第4步的过程中，NAT B没有A的记录就将A的包给丢弃了，在计划里这一步丢包是必然的，而UDP不管对方收到或丢弃。若是用其他可靠协议比如TCP，可能会造成打洞失败的情况，而解决办法就是修改系统内核，但这又非常麻烦。</p></section></section><section><h2>代码实现<a href="#代码实现"><span>#</span></a></h2><p>这里使用Golang进行网络编程。</p><p>客户端之所以使用<code>net.ListenUDP()</code>而不是<code>net.DialUDP()</code>，是因为<code>net.ListenUDP()</code>的<code>*UDPConn</code>是<code>unconnected</code>，而<code>net.DialUDP()</code>的<code>*UDPConn</code>是<code>connected</code>的。</p><p>如果<code>*UDPConn</code>是<code>connected</code>,读写方法是<code>Read</code>和<code>Write</code>。</p><p>如果<code>*UDPConn</code>是<code>unconnected</code>,读写方法是<code>ReadFromUDP</code>和<code>WriteToUDP</code>（以及<code>ReadFrom</code>和<code>WriteTo</code>)。</p><p>使用<code>ReadFromUDP</code>和<code>WriteToUDP</code>进行读写可以指定读写任何UDP地址，而且<code>net.ListenUDP()</code>还可以固定本机UDP端口不被系统更换。</p><section><h3>服务端demo<a href="#服务端demo"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>j</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>Name</span><span> </span><span>string</span><span> </span><span>`json:"name"`</span><span>   </span><span>//客户端名</span></div></div><div><div><div>3</div></div><div><span>  </span><span>Addr</span><span> </span><span>string</span><span> </span><span>`json:"addr"`</span><span>   </span><span>//地址</span></div></div><div><div><div>4</div></div><div><span>  </span><span>To</span><span>   </span><span>string</span><span> </span><span>`json:"to"`</span><span>     </span><span>//要连接的客户端名</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>dev</span><span><span> </span><span>:=</span><span> </span></span><span>make</span><span>(</span><span>map</span><span>[</span><span>string</span><span>]</span><span>string</span><span>)  </span><span>//客户端地址</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>addr</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>net</span><span>.</span><span>ResolveUDPAddr</span><span>(</span><span>"udp"</span><span>, </span><span>"0.0.0.0:7091"</span><span>)    </span><span>//服务器端口为7091</span></div></div><div><div><div>9</div></div><div><span>conn</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>net</span><span>.</span><span>ListenUDP</span><span>(</span><span>"udp"</span><span>, </span><span>addr</span><span>)</span></div></div><div><div><div>10</div></div><div><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>11</div></div><div><span>  </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>12</div></div><div><span>  </span><span>os</span><span>.</span><span>Exit</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div><span>defer</span><span> </span><span>conn</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>15</div></div><div><span>for</span><span> {</span></div></div><div><div><div>16</div></div><div><span>  </span><span>data</span><span><span> </span><span>:=</span><span> </span></span><span>make</span><span>([]</span><span>byte</span><span>, </span><span>512</span><span>)</span></div></div><div><div><div>17</div></div><div><span>  </span><span>n</span><span>, </span><span>remoteAddr</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>conn</span><span>.</span><span>ReadFromUDP</span><span>(</span><span>data</span><span>)    </span><span>//获取客户端地址</span></div></div><div><div><div>18</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>19</div></div><div><span>    </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>"f"</span><span>, </span><span>err</span><span>)</span></div></div><div><div><div>20</div></div><div><span>    </span><span>return</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>22</div></div><div><span>  </span><span>var</span><span> </span><span>J</span><span> </span><span>j</span></div></div><div><div><div>23</div></div><div><span>  </span><span>json</span><span>.</span><span>Unmarshal</span><span>(</span><span>data</span><span>[:</span><span>n</span><span><span>], </span><span>&amp;</span></span><span>J</span><span>)</span></div></div><div><div><div>24</div></div><div><span>  </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>J</span><span>)</span></div></div><div><div><div>25</div></div><div><span>  </span><span>dev</span><span>[</span><span>J</span><span>.</span><span>Name</span><span><span>] </span><span>=</span><span> </span></span><span>remoteAddr</span><span>.</span><span>String</span><span>()   </span><span>//客户端注册</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>  </span><span>if</span><span><span> </span><span>!</span></span><span>strings</span><span>.</span><span>EqualFold</span><span>(</span><span>J</span><span>.</span><span>To</span><span>, </span><span>""</span><span><span>)</span><span>&amp;&amp;</span><span> </span></span><span>dev</span><span>[</span><span>J</span><span>.</span><span>To</span><span><span>]</span><span>!=</span></span><span>""</span><span> {</span></div></div><div><div><div>28</div></div><div><span>    </span><span>outA</span><span>,</span><span>_</span><span>:=</span><span>json</span><span>.</span><span>Marshal</span><span><span>(</span><span>&amp;</span></span><span>j</span><span>{</span></div></div><div><div><div>29</div></div><div><span>      </span><span>Name</span><span>: </span><span>J</span><span>.</span><span>To</span><span>,</span></div></div><div><div><div>30</div></div><div><span>      </span><span>Addr</span><span>: </span><span>dev</span><span>[</span><span>J</span><span>.</span><span>To</span><span>],</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>})</span></div></div><div><div><div>32</div></div><div><span>    </span><span>outB</span><span>,</span><span>_</span><span>:=</span><span>json</span><span>.</span><span>Marshal</span><span><span>(</span><span>&amp;</span></span><span>j</span><span>{</span></div></div><div><div><div>33</div></div><div><span>      </span><span>Name</span><span>: </span><span>J</span><span>.</span><span>Name</span><span>,</span></div></div><div><div><div>34</div></div><div><span>      </span><span>Addr</span><span>: </span><span>remoteAddr</span><span>.</span><span>String</span><span>(),</span></div></div><div><div><div>35</div></div><div><span><span>    </span></span><span>})</span></div></div><div><div><div>36</div></div><div><span>    </span><span>conn</span><span>.</span><span>WriteToUDP</span><span>(</span><span>outA</span><span>,</span><span>remoteAddr</span><span>)</span></div></div><div><div><div>37</div></div><div><span>    </span><span>adr</span><span>,</span><span>_</span><span>:=</span><span>net</span><span>.</span><span>ResolveUDPAddr</span><span>(</span><span>"udp"</span><span>,</span><span>dev</span><span>[</span><span>J</span><span>.</span><span>To</span><span>])</span></div></div><div><div><div>38</div></div><div><span>    </span><span>conn</span><span>.</span><span>WriteToUDP</span><span>(</span><span>outB</span><span>,</span><span>adr</span><span>)</span></div></div><div><div><div>39</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>40</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h3>客户端demo<a href="#客户端demo"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>j</span><span> </span><span>struct</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>Name</span><span> </span><span>string</span><span> </span><span>`json:"name"`</span></div></div><div><div><div>3</div></div><div><span>  </span><span>Addr</span><span> </span><span>string</span><span> </span><span>`json:"addr"`</span></div></div><div><div><div>4</div></div><div><span>  </span><span>To</span><span>   </span><span>string</span><span> </span><span>`json:"to"`</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>var</span><span> </span><span>name</span><span><span> </span><span>=</span><span> </span></span><span>flag</span><span>.</span><span>String</span><span>(</span><span>"name"</span><span>, </span><span>""</span><span>, </span><span>""</span><span>)  </span><span>//客户端名</span></div></div><div><div><div>7</div></div><div><span>var</span><span> </span><span>to</span><span><span> </span><span>=</span><span> </span></span><span>flag</span><span>.</span><span>String</span><span>(</span><span>"to"</span><span>, </span><span>""</span><span>, </span><span>""</span><span>)      </span><span>//要连接的客户端</span></div></div><div><div><div>8</div></div><div><span>var</span><span> </span><span>msg</span><span><span> </span><span>=</span><span> </span></span><span>flag</span><span>.</span><span>String</span><span>(</span><span>"msg"</span><span>, </span><span>""</span><span>, </span><span>""</span><span>)    </span><span>//发送消息</span></div></div><div><div><div>9</div></div><div><span>var</span><span> </span><span>server_ip</span><span><span> </span><span>=</span><span> </span></span><span>flag</span><span>.</span><span>String</span><span>(</span><span>"server"</span><span>, </span><span>"1.1.1.1"</span><span>, </span><span>""</span><span>)    </span><span>//服务器IP</span></div></div><div><div><div>10</div></div><div><span>var</span><span> </span><span>server_port</span><span><span> </span><span>=</span><span> </span></span><span>flag</span><span>.</span><span>Int</span><span>(</span><span>"sport"</span><span>, </span><span>9091</span><span>, </span><span>""</span><span>)                   </span><span>//服务器端口</span></div></div><div><div><div>11</div></div><div><span>flag</span><span>.</span><span>Parse</span><span>()</span></div></div><div><div><div>12</div></div><div><span>conn</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>net</span><span>.</span><span>ListenUDP</span><span>(</span><span>"udp"</span><span><span>, </span><span>&amp;</span></span><span>net</span><span>.</span><span>UDPAddr</span><span>{</span></div></div><div><div><div>13</div></div><div><span>  </span><span>IP</span><span>:   </span><span>net</span><span>.</span><span>ParseIP</span><span>(</span><span>"0.0.0.0"</span><span>),</span></div></div><div><div><div>14</div></div><div><span>  </span><span>Port</span><span>: </span><span>9091</span><span>,</span></div></div><div><div><div>15</div></div><div><span>})</span></div></div><div><div><div>16</div></div><div><span>defer</span><span> </span><span>conn</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>17</div></div><div><span>put</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>json</span><span>.</span><span>Marshal</span><span><span>(</span><span>&amp;</span></span><span>j</span><span>{</span></div></div><div><div><div>18</div></div><div><span>  </span><span>Name</span><span><span>: </span><span>*</span></span><span>name</span><span>,</span></div></div><div><div><div>19</div></div><div><span>  </span><span>To</span><span><span>:   </span><span>*</span></span><span>to</span><span>,</span></div></div><div><div><div>20</div></div><div><span>})</span></div></div><div><div><div>21</div></div><div><span>conn</span><span>.</span><span>WriteToUDP</span><span>(</span><span>put</span><span><span>, </span><span>&amp;</span></span><span>net</span><span>.</span><span>UDPAddr</span><span>{</span></div></div><div><div><div>22</div></div><div><span>  </span><span>IP</span><span>:   </span><span>net</span><span>.</span><span>ParseIP</span><span><span>(</span><span>*</span></span><span>server_ip</span><span>),</span></div></div><div><div><div>23</div></div><div><span>  </span><span>Port</span><span><span>: </span><span>*</span></span><span>server_port</span><span>,</span></div></div><div><div><div>24</div></div><div><span>})</span></div></div><div><div><div>25</div></div><div><span>res</span><span><span> </span><span>:=</span><span> </span></span><span>make</span><span>([]</span><span>byte</span><span>, </span><span>128</span><span>)</span></div></div><div><div><div>26</div></div><div><span>n</span><span>, </span><span>_</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>conn</span><span>.</span><span>ReadFromUDP</span><span>(</span><span>res</span><span>)</span></div></div><div><div><div>27</div></div><div><span>var</span><span> </span><span>J</span><span> </span><span>j</span></div></div><div><div><div>28</div></div><div><span>json</span><span>.</span><span>Unmarshal</span><span>(</span><span>res</span><span>[:</span><span>n</span><span><span>], </span><span>&amp;</span></span><span>J</span><span>)</span></div></div><div><div><div>29</div></div><div><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>string</span><span>(</span><span>res</span><span>[:</span><span>n</span><span>]))</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>if</span><span><span> </span><span>*</span></span><span>to</span><span><span> </span><span>!=</span><span> </span></span><span>""</span><span> {</span></div></div><div><div><div>32</div></div><div><span>  </span><span>time</span><span>.</span><span>Sleep</span><span>(</span><span>1</span><span><span> </span><span>*</span><span> </span></span><span>time</span><span>.</span><span>Second</span><span>)</span></div></div><div><div><div>33</div></div><div><span>}</span></div></div><div><div><div>34</div></div><div><span>adr</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>net</span><span>.</span><span>ResolveUDPAddr</span><span>(</span><span>"udp"</span><span>, </span><span>J</span><span>.</span><span>Addr</span><span>)</span></div></div><div><div><div>35</div></div><div><span>conn</span><span>.</span><span>WriteToUDP</span><span>([]</span><span>byte</span><span>(</span><span>"qwe"</span><span>), </span><span>adr</span><span>)</span></div></div><div><div><div>36</div></div><div><span>n</span><span>, </span><span>_</span><span>, </span><span>_</span><span><span> </span><span>=</span><span> </span></span><span>conn</span><span>.</span><span>ReadFromUDP</span><span>(</span><span>res</span><span>)</span></div></div><div><div><div>37</div></div><div><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>string</span><span>(</span><span>res</span><span>[:</span><span>n</span><span>]))</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>使用：
A运行：<code>./main -name A</code>
B运行：<code>./main -name B -to A -msg "qwe"</code></p></section></section><section><h2>参考<a href="#参考"><span>#</span></a></h2><p><a href="./images/242.1.avif">1</a> <a href="https://zh.wikipedia.org/wiki/%E7%BD%91%E7%BB%9C%E5%9C%B0%E5%9D%80%E8%BD%AC%E6%8D%A2" target="_blank">NAT - wikipedia</a></p><p><a href="./images/242.2.avif">2</a> <a href="https://zh.wikipedia.org/wiki/%E7%94%A8%E6%88%B7%E6%95%B0%E6%8D%AE%E6%8A%A5%E5%8D%8F%E8%AE%AE" target="_blank">UDP - wikipedia</a></p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/239/</id>
      <title type="text">【Lua】WOL原理与实现</title>
      <published>2021-02-26T05:16:00.000Z</published>
      <updated>2021-02-26T05:20:43.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/239/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>WOL<a href="#wol"><span>#</span></a></h1><p>WOL全称为Wake-on-LAN，它的功效在于让休眠状态或关机状态的电脑，透过局域网的另一台电脑对其发令，使其唤醒、恢复成运作状态，或从关机状态转成引导状态[<sup>1</sup>]。</p><p>简单来说，WOL就是通过网络唤醒开启电脑。</p><section><h2>原理<a href="#原理"><span>#</span></a></h2><p>支持WOL的主板在通电时会监听并分析同一网络下的广播信息（xxx.xxx.xxx.255），在一般的局域网使用有限广播地址即可（255.255.255.255），当发现了“魔法包”（Magic Packet）就会对其进行解读。</p><p>魔法包是以广播的形式发送，作用于当前局域网（LAN），也可以是子网（Subnet）。</p></section><section><h2>魔法包介绍<a href="#魔法包介绍"><span>#</span></a></h2><p>Magic Packet，是一种广播帧（frame），使用无连接协议，例如：<code>UDP</code>，发送的端口没有限制，可以使用任何端口进行发送，但一般约定俗成使用7或9号端口发送。大部分情况下，魔法包在数据链路层（OSI第2层）发送，使用广播地址进行广播，但也可以使用特定IP地址进行发送（OSI第3层）。</p><p><em><strong>由于采用的是无连接协议，所以不保证数据包被目标机接收。</strong></em></p></section><section><h2>魔法包结构<a href="#魔法包结构"><span>#</span></a></h2><p>魔法包最简单的构成是6个十六进制的<code>255</code>（ff ff ff ff ff ff）共6字节为数据包的头部标识，后面是目标机的十六进制<code>MAC</code>地址，并将<code>MAC</code>重复16次，到此数据包共<code>102</code>字节。有时数据包内还会紧接着4-6字节的密码信息。这个帧片段可以包含在任何协议中，最常见的是包含在 UDP 中。[<sup>2</sup>]</p><p>例如目标机MAC为：<code>1a:2b:3c:4d:5e:6f</code></p>

<table><thead><tr><th>6字节头</th><th>96字节信息=MAC信息x12</th><th>4-6字节密码（可空）</th></tr></thead><tbody><tr><td>ff ff ff ff ff ff</td><td>1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f 1a2b3c4d5e6f</td><td>密码</td></tr></tbody></table></section><section><h2>代码实现<a href="#代码实现"><span>#</span></a></h2><p>我是用的是esp8266，刷入NodeMCU固件，是用LUA进行编程实现。</p><p><em><strong>NodeMCU编译时起码需要编译<code>net</code>和<code>wifi</code>两个模块，并正确配置和连上wifi。</strong></em></p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>mac</span><span> = </span><span>'1a2b3c4d5e6f'    </span><span>-- 要进行目标主机的MAC地址</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>bip</span><span> = </span><span>'255.255.255.255' </span><span>-- 路由器广播地址</span></div></div><div><div><div>4</div></div><div><span>head</span><span> = </span><span>'FFFFFFFFFFFF'   </span><span>-- 数据头</span></div></div><div><div><div>5</div></div><div><span>head</span><span> = </span><span>to</span><span>(</span><span>head</span><span>)</span></div></div><div><div><div>6</div></div><div><span>mac</span><span> = </span><span>to</span><span>(</span><span>mac</span><span>)</span></div></div><div><div><div>7</div></div><div><span>for</span><span> </span><span>i</span><span> = </span><span>1</span><span>, </span><span>16</span><span> </span><span>do</span></div></div><div><div><div>8</div></div><div><span>    </span><span>head</span><span> = </span><span>head</span><span> .. </span><span>mac</span></div></div><div><div><div>9</div></div><div><span>end</span></div></div><div><div><div>10</div></div><div><span>u</span><span> = </span><span>net</span><span>.</span><span>createUDPSocket</span><span>()</span></div></div><div><div><div>11</div></div><div><span>u</span><span>:</span><span>send</span><span>(</span><span>1234</span><span>, </span><span>bip</span><span>, </span><span>head</span><span>)    </span><span>-- 是用9号端口</span></div></div><div><div><div>12</div></div><div><span>u</span><span>:</span><span>close</span><span>()</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>-- 将两个一组字符串表示的十六进制转为十六进制的字符串</span></div></div><div><div><div>15</div></div><div><span>-- 'ff'(66 66) -&gt; 0xff -&gt; '.'(255)</span></div></div><div><div><div>16</div></div><div><span>function</span><span> </span><span>to</span><span><span>(</span><span>str</span><span>)</span></span></div></div><div><div><div>17</div></div><div><span>    </span><span>ret</span><span> = </span><span>''</span></div></div><div><div><div>18</div></div><div><span>    </span><span>for</span><span> </span><span>i</span><span> = </span><span>1</span><span>, </span><span>string.len</span><span>(</span><span>str</span><span>), </span><span>2</span><span> </span><span>do</span></div></div><div><div><div>19</div></div><div><span>        </span><span>byte</span><span> = (</span><span>'0x' </span><span>.. </span><span>string.sub</span><span>(</span><span>str</span><span>, </span><span>0</span><span> + </span><span>i</span><span>, </span><span>1</span><span> + </span><span>i</span><span>))</span></div></div><div><div><div>20</div></div><div><span>        </span><span>a</span><span> = </span><span>tonumber</span><span>(</span><span>byte</span><span>)</span></div></div><div><div><div>21</div></div><div><span>        </span><span>ret</span><span> = </span><span>ret</span><span> .. </span><span>string.char</span><span>(</span><span>a</span><span>)</span></div></div><div><div><div>22</div></div><div><span>    </span><span>end</span></div></div><div><div><div>23</div></div><div><span>    </span><span>return</span><span> </span><span>ret</span></div></div><div><div><div>24</div></div><div><span>end</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section><section><h2>参考<a href="#参考"><span>#</span></a></h2><ul>
<li>
<p>[1] <a href="https://zh.wikipedia.org/wiki/%E7%B6%B2%E8%B7%AF%E5%96%9A%E9%86%92" target="_blank">wikipedia</a></p>
</li>
<li>
<p>[2] <a href="https://www.cnblogs.com/zhanggaoxing/p/9657545.html" target="_blank">网络唤醒（WOL）全解指南：原理篇</a></p>
</li>
</ul></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/238/</id>
      <title type="text">【python】查看v2ray流量统计脚本</title>
      <published>2020-12-11T07:39:00.000Z</published>
      <updated>2020-12-11T07:41:18.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/238/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>查看v2ray多用户流量统计</p>
<p>使用前需要开启v2ray自带的统计工具，配置方法：<a href="https://guide.v2fly.org/advanced/traffic.html#%E9%85%8D%E7%BD%AE%E7%BB%9F%E8%AE%A1%E5%8A%9F%E8%83%BD" target="_blank">https://guide.v2fly.org/advanced/traffic.html#%E9%85%8D%E7%BD%AE%E7%BB%9F%E8%AE%A1%E5%8A%9F%E8%83%BD</a></p>
<p>本脚本使用email作为用户标识，使用tag作为组标识</p>
<section><h3>获取<a href="#获取"><span>#</span></a></h3><ol>
<li><a href="https://github.com/Rehtt/v2ray-tools/blob/main/v2ray-flow.py" target="_blank">Github</a></li>
<li><code>wget https://raw.githubusercontent.com/Rehtt/v2ray-tools/main/v2ray-flow.py</code></li>
<li>复制下方代码</li>
</ol></section>
<section><h3>使用<a href="#使用"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>v2ray-flow.py [-h] [-g &lt;tag&gt;] [-c &lt;file&gt;] [-s &lt;server&gt;]</span></div></div><div><div><div>2</div></div><div><span>默认显示全部用户</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>-h,--help       显示帮助</span></div></div><div><div><div>5</div></div><div><span>-g &lt;tag&gt;        显示组的流量</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>-g A            (显示tag:A组的流量)</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>-c &lt;file&gt;       输入v2ray配置文件</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>-c /etc/v2ray/config.json</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>-s &lt;server&gt;     输入v2ctl api server地址</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>-s 127.0.0.1:53844</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h3>代码<a href="#代码"><span>#</span></a></h3><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/python3</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># Created by Rehtt on 2020/12/11</span></div></div><div><div><div>4</div></div><div><span># 查看v2ray多用户流量统计</span></div></div><div><div><div>5</div></div><div><span># 使用前需要开启v2ray自带的统计工具，配置方法：https://guide.v2fly.org/advanced/traffic.html#%E9%85%8D%E7%BD%AE%E7%BB%9F%E8%AE%A1%E5%8A%9F%E8%83%BD</span></div></div><div><div><div>6</div></div><div><span># 本脚本使用email作为用户标识，使用tag作为组标识</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>import</span><span> re</span></div></div><div><div><div>9</div></div><div><span>import</span><span> os</span></div></div><div><div><div>10</div></div><div><span>import</span><span> json</span></div></div><div><div><div>11</div></div><div><span>import</span><span> getopt</span></div></div><div><div><div>12</div></div><div><span>import</span><span> sys</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>v2ConfigFile </span><span>=</span><span> </span></span><span>'/etc/v2ray/config.json'</span><span>  </span><span># v2ray配置文件位置</span></div></div><div><div><div>15</div></div><div><span><span>v2ctlServer </span><span>=</span><span> </span></span><span>'127.0.0.1:53844'</span><span>  </span><span># v2ctl api配置信息</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>def</span><span> </span><span>dataSize</span><span>(</span><span>size</span><span>,</span><span><span> </span><span>i</span></span><span>=</span><span>0</span><span>):</span></div></div><div><div><div>19</div></div><div><span>    </span><span>if</span><span><span> size </span><span>&gt;</span><span> </span></span><span>1e3</span><span>:</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>size </span><span>/=</span><span> </span><span>1e3</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>s </span><span>=</span><span> </span><span>dataSize</span><span>(size, i</span><span>+</span><span>1</span><span>)</span></div></div><div><div><div>22</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>23</div></div><div><span><span>        </span></span><span>size </span><span>=</span><span> </span><span>round</span><span>(size, </span><span>2</span><span>)</span></div></div><div><div><div>24</div></div><div><span>        </span><span>if</span><span><span> i </span><span>==</span><span> </span></span><span>1</span><span>:</span></div></div><div><div><div>25</div></div><div><span><span>            </span></span><span>s </span><span>=</span><span> </span><span>str</span><span><span>(size)</span><span>+</span></span><span>'KB'</span></div></div><div><div><div>26</div></div><div><span>        </span><span>elif</span><span><span> i </span><span>==</span><span> </span></span><span>2</span><span>:</span></div></div><div><div><div>27</div></div><div><span><span>            </span></span><span>s </span><span>=</span><span> </span><span>str</span><span><span>(size)</span><span>+</span></span><span>'MB'</span></div></div><div><div><div>28</div></div><div><span>        </span><span>elif</span><span><span> i </span><span>&gt;=</span><span> </span></span><span>3</span><span>:</span></div></div><div><div><div>29</div></div><div><span><span>            </span></span><span>s </span><span>=</span><span> </span><span>str</span><span><span>(size)</span><span>+</span></span><span>'GB'</span></div></div><div><div><div>30</div></div><div><span>    </span><span>return</span><span> s</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>def</span><span> </span><span>red</span><span>(</span><span>f</span><span>):</span></div></div><div><div><div>34</div></div><div><span>    </span><span>return</span><span> </span><span>'</span><span>\033</span><span>[31m'</span><span><span>+</span><span>f</span><span>+</span></span><span>'</span><span>\033</span><span>[0m'</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div>
</div></div><div><div><div>37</div></div><div><span>def</span><span> </span><span>help</span><span>():</span></div></div><div><div><div>38</div></div><div><span>    </span><span>print</span><span>(</span><span>"v2ray-flow.py [-h] [-g &lt;tag&gt;] [-c &lt;file&gt;] [-s &lt;server&gt;]"</span><span>)</span></div></div><div><div><div>39</div></div><div><span>    </span><span>print</span><span>(</span><span>"默认显示全部用户</span><span>\n</span><span>"</span><span>)</span></div></div><div><div><div>40</div></div><div><span>    </span><span>print</span><span>(</span><span>"-h,--help</span><span>\t</span><span>显示帮助"</span><span>)</span></div></div><div><div><div>41</div></div><div><span>    </span><span>print</span><span>(</span><span>"-g &lt;tag&gt;</span><span>\t</span><span>显示组的流量"</span><span>)</span></div></div><div><div><div>42</div></div><div><span>    </span><span>print</span><span>(</span><span>"</span><span>\t</span><span>-g A</span><span>\t\t</span><span>(显示tag:A组的流量)</span><span>\n</span><span>"</span><span>)</span></div></div><div><div><div>43</div></div><div><span>    </span><span># print("-u &lt;email&gt;\t显示单个用户流量")</span></div></div><div><div><div>44</div></div><div><span>    </span><span># print("\t-u rehtt@qq.com\t(显示email为rehtt@qq.com的流量)\n")</span></div></div><div><div><div>45</div></div><div><span>    </span><span>print</span><span>(</span><span>"-c &lt;file&gt;</span><span>\t</span><span>输入v2ray配置文件"</span><span>)</span></div></div><div><div><div>46</div></div><div><span>    </span><span>print</span><span>(</span><span>"</span><span>\t</span><span>-c /etc/v2ray/config.json</span><span>\n</span><span>"</span><span>)</span></div></div><div><div><div>47</div></div><div><span>    </span><span>print</span><span>(</span><span>"-s &lt;server&gt;</span><span>\t</span><span>输入v2ctl api server地址"</span><span>)</span></div></div><div><div><div>48</div></div><div><span>    </span><span>print</span><span>(</span><span>"</span><span>\t</span><span>-s 127.0.0.1:53844"</span><span>)</span></div></div><div><div><div>49</div></div><div>
</div></div><div><div><div>50</div></div><div>
</div></div><div><div><div>51</div></div><div><span>def</span><span> </span><span>getDownUp</span><span>(</span><span>name</span><span>,</span><span><span> </span><span>res</span></span><span>):</span></div></div><div><div><div>52</div></div><div><span><span>    </span></span><span>i </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>53</div></div><div><span><span>    </span></span><span>z </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>54</div></div><div><span><span>    </span></span><span>down </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>55</div></div><div><span><span>    </span></span><span>up </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>56</div></div><div><span>    </span><span>try</span><span>:</span></div></div><div><div><div>57</div></div><div><span>        </span><span>for</span><span> r </span><span>in</span><span> res:</span></div></div><div><div><div>58</div></div><div><span><span>            </span></span><span>i </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>59</div></div><div><span>            </span><span>if</span><span> name </span><span>in</span><span> r:</span></div></div><div><div><div>60</div></div><div><span><span>                </span></span><span>z </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>61</div></div><div><span>                </span><span>if</span><span> </span><span>'downlink'</span><span> </span><span>in</span><span> r:</span></div></div><div><div><div>62</div></div><div><span><span>                    </span></span><span>down </span><span>=</span><span> </span><span>dataSize</span><span>(</span><span>float</span><span><span>(re.</span><span>sub</span><span>(</span></span><span>'\D'</span><span>, </span><span>''</span><span>, res[i])))</span></div></div><div><div><div>63</div></div><div><span>                </span><span>else</span><span>:</span></div></div><div><div><div>64</div></div><div><span><span>                    </span></span><span>up </span><span>=</span><span> </span><span>dataSize</span><span>(</span><span>float</span><span><span>(re.</span><span>sub</span><span>(</span></span><span>'\D'</span><span>, </span><span>''</span><span>, res[i])))</span></div></div><div><div><div>65</div></div><div><span>                </span><span>if</span><span><span> z </span><span>==</span><span> </span></span><span>2</span><span>:</span></div></div><div><div><div>66</div></div><div><span>                    </span><span>break</span></div></div><div><div><div>67</div></div><div><span>    </span><span>except</span><span>:</span></div></div><div><div><div>68</div></div><div><span>        </span><span>pass</span></div></div><div><div><div>69</div></div><div><span>    </span><span>return</span><span> down, up</span></div></div><div><div><div>70</div></div><div>
</div></div><div><div><div>71</div></div><div>
</div></div><div><div><div>72</div></div><div><span>def</span><span> </span><span>main</span><span>(</span><span>argv</span><span>):</span></div></div><div><div><div>73</div></div><div><span>    </span><span>global</span><span> v2ctlServer, v2ConfigFile</span></div></div><div><div><div>74</div></div><div><span><span>    </span></span><span>c </span><span>=</span><span> </span><span>'/usr/bin/v2ray/v2ctl api --server=</span><span>{server}</span><span> StatsService.QueryStats </span><span>\'</span><span>pattern: "</span><span>{q}</span><span>" reset: false</span><span>\'</span><span>'</span></div></div><div><div><div>75</div></div><div><span>    </span><span>try</span><span>:</span></div></div><div><div><div>76</div></div><div><span><span>        </span></span><span>opts, args </span><span>=</span><span> getopt.</span><span>getopt</span><span>(argv, </span><span>"hg:c:s:u:"</span><span>, [</span><span>"help"</span><span>])</span></div></div><div><div><div>77</div></div><div><span>    </span><span>except</span><span> getopt.GetoptError:</span></div></div><div><div><div>78</div></div><div><span>        </span><span>help</span><span>()</span></div></div><div><div><div>79</div></div><div><span><span>        </span></span><span>sys.</span><span>exit</span><span>(</span><span>2</span><span>)</span></div></div><div><div><div>80</div></div><div><span><span>    </span></span><span>q </span><span>=</span><span> </span><span>'user'</span></div></div><div><div><div>81</div></div><div><span><span>    </span></span><span>G </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>82</div></div><div><span>    </span><span>for</span><span> opt, arg </span><span>in</span><span> opts:</span></div></div><div><div><div>83</div></div><div><span>        </span><span>if</span><span> opt </span><span>in</span><span> (</span><span>'-h'</span><span>, </span><span>'--help'</span><span>):</span></div></div><div><div><div>84</div></div><div><span>            </span><span>help</span><span>()</span></div></div><div><div><div>85</div></div><div><span><span>            </span></span><span>sys.</span><span>exit</span><span>()</span></div></div><div><div><div>86</div></div><div><span>        </span><span>elif</span><span><span> opt </span><span>==</span><span> </span></span><span>'-g'</span><span>:</span></div></div><div><div><div>87</div></div><div><span><span>            </span></span><span>q </span><span>=</span><span> arg</span></div></div><div><div><div>88</div></div><div><span><span>            </span></span><span>G </span><span>=</span><span> </span><span>1</span></div></div><div><div><div>89</div></div><div><span>        </span><span># elif opt == '-u':</span></div></div><div><div><div>90</div></div><div><span>        </span><span>#     q = arg</span></div></div><div><div><div>91</div></div><div><span>        </span><span>#     G = 2</span></div></div><div><div><div>92</div></div><div><span>        </span><span>if</span><span><span> opt </span><span>==</span><span> </span></span><span>'-c'</span><span>:</span></div></div><div><div><div>93</div></div><div><span><span>            </span></span><span>v2ConfigFile </span><span>=</span><span> arg</span></div></div><div><div><div>94</div></div><div><span>        </span><span>if</span><span><span> opt </span><span>==</span><span> </span></span><span>'-s'</span><span>:</span></div></div><div><div><div>95</div></div><div><span><span>            </span></span><span>v2ctlServer </span><span>=</span><span> arg</span></div></div><div><div><div>96</div></div><div><span><span>    </span></span><span>tags </span><span>=</span><span> {}</span></div></div><div><div><div>97</div></div><div>
</div></div><div><div><div>98</div></div><div><span><span>    </span></span><span>c </span><span>=</span><span> c.</span><span>format</span><span>(</span><span>server</span><span><span>=</span><span>v2ctlServer, </span></span><span>q</span><span><span>=</span><span>q)</span></span></div></div><div><div><div>99</div></div><div><span><span>    </span></span><span>res </span><span>=</span><span> os.</span><span>popen</span><span>(c).</span><span>readlines</span><span>()</span></div></div><div><div><div>100</div></div><div><span>    </span><span>if</span><span><span> G </span><span>==</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>101</div></div><div><span>        </span><span>with</span><span> </span><span>open</span><span>(v2ConfigFile, </span><span>'r'</span><span>) </span><span>as</span><span> f:</span></div></div><div><div><div>102</div></div><div><span><span>            </span></span><span>data </span><span>=</span><span> json.</span><span>load</span><span>(f)</span></div></div><div><div><div>103</div></div><div><span>            </span><span>for</span><span> i </span><span>in</span><span> data[</span><span>'inbounds'</span><span>]:</span></div></div><div><div><div>104</div></div><div><span>                </span><span>if</span><span> i[</span><span>'tag'</span><span><span>] </span><span>!=</span><span> </span></span><span>'api'</span><span>:</span></div></div><div><div><div>105</div></div><div><span><span>                    </span></span><span>emails </span><span>=</span><span> []</span></div></div><div><div><div>106</div></div><div><span>                    </span><span>for</span><span> email </span><span>in</span><span> i[</span><span>'settings'</span><span>][</span><span>'clients'</span><span>]:</span></div></div><div><div><div>107</div></div><div><span><span>                        </span></span><span>emails.</span><span>append</span><span>(email[</span><span>'email'</span><span>])</span></div></div><div><div><div>108</div></div><div><span><span>                    </span></span><span>tags[i[</span><span>'tag'</span><span><span>]] </span><span>=</span><span> emails</span></span></div></div><div><div><div>109</div></div><div><span>        </span><span>for</span><span> tag </span><span>in</span><span> tags:</span></div></div><div><div><div>110</div></div><div><span>            </span><span>for</span><span> email </span><span>in</span><span> tags[tag]:</span></div></div><div><div><div>111</div></div><div><span><span>                </span></span><span>down, up </span><span>=</span><span> </span><span>getDownUp</span><span>(email, res)</span></div></div><div><div><div>112</div></div><div><span>                </span><span>print</span><span>(</span><span>'Email:'</span><span><span>, </span><span>red</span><span>(email), </span></span><span>'</span><span>\t</span><span>Tag:'</span><span><span>+</span><span>red</span><span>(tag))</span></span></div></div><div><div><div>113</div></div><div><span>                </span><span>print</span><span>(</span><span>'上传:'</span><span>, up, </span><span>'</span><span>\t</span><span>下载:'</span><span>, down, </span><span>'</span><span>\n</span><span>'</span><span>)</span></div></div><div><div><div>114</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>115</div></div><div><span>        </span><span>if</span><span><span> G</span><span>==</span></span><span>1</span><span>:</span></div></div><div><div><div>116</div></div><div><span>            </span><span>print</span><span>(</span><span>'Tag:'</span><span><span>, </span><span>red</span><span>(q))</span></span></div></div><div><div><div>117</div></div><div><span><span>            </span></span><span>down, up </span><span>=</span><span> </span><span>getDownUp</span><span>(q, res)</span></div></div><div><div><div>118</div></div><div><span>        </span><span># else:</span></div></div><div><div><div>119</div></div><div><span>        </span><span>#     print('Email:', red(q))</span></div></div><div><div><div>120</div></div><div><span>        </span><span>print</span><span>(</span><span>'上传:'</span><span>, up, </span><span>'</span><span>\t</span><span>下载:'</span><span>, down, </span><span>'</span><span>\n</span><span>'</span><span>)</span></div></div><div><div><div>121</div></div><div>
</div></div><div><div><div>122</div></div><div>
</div></div><div><div><div>123</div></div><div>
</div></div><div><div><div>124</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>"__main__"</span><span>:</span></div></div><div><div><div>125</div></div><div><span><span>    </span></span><span>main</span><span>(sys.argv[</span><span>1</span><span>:])</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/237/</id>
      <title type="text">【杂项】PSP作为PC电脑的WiFi手柄</title>
      <published>2020-10-16T15:00:00.000Z</published>
      <updated>2020-10-16T15:51:06.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/237/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>使用软件：</p><ul>
<li>WiFi Controller（PSP）（<a href="https://www.brewology.com/downloads/get.php?id=7789" target="_blank">下载</a>）</li>
<li>PPJoy （PC）（<a href="https://github.com/elitak/PPJoy/releases/download/v0.8.4.6/PPJoySetup-0.8.4.6.zip" target="_blank">下载</a>）</li>
</ul><p>实现原理是在通过PSP上运行<code>WiFi Controller</code>，将PSP的按键传送到PC上，PC再使用PPJoy将PSP的按键映射为一个虚拟的游戏手柄。</p><div><div><div></div><div>Warning</div></div><div><p>PSP的按键数量相对目前主流游戏手柄少。主要缺少LT、RT和右摇杆</p></div></div></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><section><h2>PSP<a href="#psp"><span>#</span></a></h2><p>下载<code>WiFi Controller</code>解压并进入文件夹，找到对应PSP版本的文件夹（分别为：1.00  1.50  3.40），修改文件夹中的<code>wifi.cfg</code>，将<code>address</code>改为PC的IP地址。
最后将文件夹复制到PSP内存卡中。</p></section><section><h2>PC<a href="#pc"><span>#</span></a></h2><p>下载<code>PPJoy</code>解压，进入文件夹并执行安装程序，安装流畅一路next。安装途中会有两次驱动安装的警告，选择允许安装。</p><div><div><div></div><div>Warning</div></div><div><p>安装会重启PC，重启后会进入测试模式（PC桌面右下角会有显示）</p></div></div><p>安装完成后会运行<code>Parallel Port Joysticks</code>程序（手动在控制面板开启：‘控制面板’ -&gt; ‘硬件和声音’ -&gt; ‘Parallel Port Joysticks（32位）‘）新建虚拟手柄。</p><p>新建虚拟手柄：</p><ol>
<li>新建一个虚拟手柄点击<code>Add...</code>-&gt;<code>add</code>。</li>
<li>选中刚刚创建的手柄点击<code>Mapping...</code>。</li>
<li>选中<code>Set a custom mapping for this controller</code>，点击<code>下一步</code>。</li>
<li></li>
</ol><ul>
<li><code>Axes</code>改为<code>2</code>，<code>Axis 1</code>和<code>Axis 2</code>分别为<code>X Axis</code>和<code>Y Axis</code></li>
<li><code>Buttons</code>改为<code>9</code></li>
<li><code>POV hats</code>改为<code>1</code>。</li>
</ul><ol>
<li></li>
</ol><ul>
<li><code>X Axis</code>为<code>Analog 0</code></li>
<li><code>Y Axis</code>为<code>Analog 1</code></li>
</ul><ol>
<li>修改</li>
</ol><ul>
<li><code>Button 1</code>为<code>nothing</code></li>
<li><code>Button 2</code>为<code>Digital 0</code></li>
<li><code>Button 3</code>为<code>Digital 1</code></li>
<li><code>Button 4</code>为<code>Digital 2</code></li>
<li><code>Button 5</code>为<code>Digital 3</code></li>
<li><code>Button 6</code>为<code>Digital 4</code></li>
<li><code>Button 7</code>为<code>Digital 5</code></li>
<li><code>Button 8</code>为<code>Digital 11</code></li>
<li><code>Button 9</code>为<code>Digital 10</code></li>
</ul></section></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><section><h2>PC<a href="#pc-1"><span>#</span></a></h2><p>进入<code>WiFi Controller</code>解压的文件夹<code>PC</code>内，双击执行<code>Start WiFiServer for Controller 1.bat</code>（文件夹内其他的bat文件对应其他的虚拟手柄，通过上述<code>新建虚拟手柄</code>的方式创建）。</p></section><section><h2>PSP<a href="#psp-1"><span>#</span></a></h2><p>打开PSP，运行<code>WiFi Controller</code>，稍等片刻，出现键位示意画面即连接成功。</p><p>从PC<code>控制面板</code>中的<code>游戏控制器</code>-&gt;<code>属性</code>-&gt;<code>测试</code>中可以看见具体的映射情况。</p></section></section>
<section><h1>END<a href="#end"><span>#</span></a></h1></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/236/</id>
      <title type="text">【Docker】macvlan网络模式下容器与宿主机互通</title>
      <published>2020-09-08T14:32:00.000Z</published>
      <updated>2020-09-08T14:32:39.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/236/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>一般在macvlan模式下同网段的其他机器可以和容器互通，但宿主不能和容器互通，这是在macvlan模式设计的时候为了安全而禁止了宿主机和容器直接通信。</p><p>如果想要实现互通，有个曲线救国的方法，就是macvlan与macvlan之间可以互通，只需要在宿主机再创建一个macvlan网络，然后修改路由，让数据经过这个macvlan达到互通的目的。</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>假设现有网段为<code>192.168.1.0/24</code>的网络：</p>

<table><thead><tr><th>名字</th><th>ip</th><th>接口</th></tr></thead><tbody><tr><td>宿主机</td><td>192.168.1.10</td><td>eth0</td></tr><tr><td>容器</td><td>192.168.1.20</td><td>macvlan</td></tr></tbody></table><p>建立一个名为<code>macvlan2</code>的<code>macvlan</code>接口，并分配一个ip：</p>

<table><thead><tr><th>名字</th><th>ip</th><th>接口</th></tr></thead><tbody><tr><td>macvlan2</td><td>192.168.1.15</td><td>macvlan</td></tr></tbody></table><p>命令：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ip</span><span> </span><span>link</span><span> </span><span>add</span><span> </span><span>macvlan2</span><span> </span><span>link</span><span> </span><span>eth0</span><span> </span><span>type</span><span> </span><span>macvlan</span><span> </span><span>mode</span><span> </span><span>bridge</span></div></div><div><div><div>2</div></div><div><span>ip</span><span> </span><span>addr</span><span> </span><span>add</span><span> </span><span>192.168.1.15</span><span> </span><span>dev</span><span> </span><span>macvlan2</span></div></div><div><div><div>3</div></div><div><span>ip</span><span> </span><span>link</span><span> </span><span>set</span><span> </span><span>macvlan2</span><span> </span><span>up</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>修改路由，让宿主机到容器<code>(192.168.1.20)</code>的数据经过<code>macvlan2</code>:</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ip</span><span> </span><span>route</span><span> </span><span>add</span><span> </span><span>192.168.1.20</span><span> </span><span>dev</span><span> </span><span>macvlan2</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>宿主机 访问 容器的ip：<code>192.168.1.20</code></p><p>容器 访问 宿主机ip：<code>192.168.1.15</code></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/235/</id>
      <title type="text">【树莓派】温控风扇脚本（shell版）</title>
      <published>2020-09-06T02:59:00.000Z</published>
      <updated>2025-01-04T07:24:10.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/235/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<blockquote><p>一个简单的脚本，和python版的一样，只是去除python版的RPi库的依赖。
较为完善的是Golang版</p></blockquote>
<p>配合crontab做定时任务</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#每五分钟执行一次</span></div></div><div><div><div>2</div></div><div><span>*/5 * * * * /home/pi/fen.sh</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>fen.sh文件</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/bash</span></div></div><div><div><div>2</div></div><div><span>a</span><span><span>=</span><span>$(</span></span><span>cat</span><span> </span><span>/sys/class/thermal/thermal_zone0/temp</span><span>)</span></div></div><div><div><div>3</div></div><div><span>temp</span><span><span>=</span><span>$((</span></span><span>a/1000</span><span>))</span></div></div><div><div><div>4</div></div><div><span>pin</span><span>=</span><span>14</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>if</span><span><span> [ </span><span>!</span><span> </span><span>-d</span><span> </span></span><span>"/sys/class/gpio/gpio</span><span><span>${</span><span>pin</span><span>}</span></span><span>"</span><span> ]</span></div></div><div><div><div>7</div></div><div><span>then</span></div></div><div><div><div>8</div></div><div><span>        </span><span>echo</span><span> </span><span>$pin</span><span> &gt; </span><span>/sys/class/gpio/export</span></div></div><div><div><div>9</div></div><div><span>fi</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>if</span><span> [ </span><span>$temp</span><span><span> </span><span>-lt</span><span> </span></span><span>50</span><span> ]</span></div></div><div><div><div>12</div></div><div><span>then</span></div></div><div><div><div>13</div></div><div><span>        </span><span>echo</span><span> </span><span>low</span><span> &gt; </span><span>/sys/class/gpio/gpio</span><span><span>${</span><span>pin</span><span>}</span></span><span>/direction</span></div></div><div><div><div>14</div></div><div><span>elif</span><span> [ </span><span>$temp</span><span><span> </span><span>-gt</span><span> </span></span><span>55</span><span> ]</span></div></div><div><div><div>15</div></div><div><span>then</span></div></div><div><div><div>16</div></div><div><span>        </span><span>echo</span><span> </span><span>high</span><span> &gt; </span><span>/sys/class/gpio/gpio</span><span><span>${</span><span>pin</span><span>}</span></span><span>/direction</span></div></div><div><div><div>17</div></div><div><span>fi</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<section><h2>新版本系统使用上述脚本失败，使用下面脚本<a href="#新版本系统使用上述脚本失败使用下面脚本"><span>#</span></a></h2><p>2025-01-04</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/bash</span></div></div><div><div><div>2</div></div><div><span>a</span><span><span>=</span><span>$(</span></span><span>cat</span><span> </span><span>/sys/class/thermal/thermal_zone0/temp</span><span>)</span></div></div><div><div><div>3</div></div><div><span>temp</span><span><span>=</span><span>$((</span></span><span>a/1000</span><span>))</span></div></div><div><div><div>4</div></div><div><span>pin</span><span>=</span><span>14</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>if</span><span> [ </span><span>$temp</span><span><span> </span><span>-lt</span><span> </span></span><span>50</span><span> ]</span></div></div><div><div><div>7</div></div><div><span>then</span></div></div><div><div><div>8</div></div><div><span>  </span><span>pinctrl</span><span> </span><span>set</span><span> </span><span>$pin</span><span> </span><span>ip</span><span> </span><span>pd</span></div></div><div><div><div>9</div></div><div><span>elif</span><span> [ </span><span>$temp</span><span><span> </span><span>-gt</span><span> </span></span><span>55</span><span> ]</span></div></div><div><div><div>10</div></div><div><span>then</span></div></div><div><div><div>11</div></div><div><span>  </span><span>pinctrl</span><span> </span><span>set</span><span> </span><span>$pin</span><span> </span><span>op</span><span> </span><span>dh</span></div></div><div><div><div>12</div></div><div><span>fi</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/233/</id>
      <title type="text">【算法/图像处理】运动检测--帧间差分法</title>
      <published>2020-07-24T10:01:00.000Z</published>
      <updated>2021-08-04T11:41:04.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/233/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>帧间差分法顾名思义，就是将视频的前后帧对应的像素点进行差运算得出差值。</p><section><h2>0x01 原理<a href="#0x01-原理"><span>#</span></a></h2><p>首先将视频每帧画面转为二值图（即只有“白”与“黑”两种颜色的图），再将前后帧进行差运算。当前后帧的同一个像素点的差值不为零，并且差值的绝对值超过设定的阈值时，就可以判断画面发生了移动。</p></section><section><h2>0x02 优点<a href="#0x02-优点"><span>#</span></a></h2><ul>
<li>算法简单，程序实现的难度不高</li>
<li>对光线的变化感知不明显（只要光线变化不是太大，二值化后的图像基本相同）</li>
<li>能够适应各种动态变化的图像，稳健性较强</li>
</ul></section><section><h2>0x03 缺点<a href="#0x03-缺点"><span>#</span></a></h2><ul>
<li>对于快速移动的物体，画面容易变“糊”，过快的话甚至会被认为是两个物体</li>
<li>对于慢速移动的物体，由于速度过慢导致前后帧几乎重合，而检测不到物体</li>
<li>检测出的物体有“空洞”，只能检测出移动物体的外边，而且检测出来的外边要比物体实际的轮廓大</li>
</ul></section></section>
<section><h1>0x10 相邻帧间差分法<a href="#0x10-相邻帧间差分法"><span>#</span></a></h1><p>相邻帧间差分法就是二帧法，对相邻的两帧图像做差运算，取差值的绝对值构成移动物体。</p><p>其优点是实时性高，运算快速。但光照突变的情况下效果不好。</p><section><h2>0x11 代码实现<a href="#0x11-代码实现"><span>#</span></a></h2><p>使用 <code>opencv-python</code>进行演示</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> cv2</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>#上一帧</span></div></div><div><div><div>4</div></div><div><span><span>lastFram </span><span>=</span><span> </span></span><span>None</span></div></div><div><div><div>5</div></div><div><span>#我这的视频源是使用网络摄像头</span></div></div><div><div><div>6</div></div><div><span><span>cap </span><span>=</span><span> cv2.</span><span>VideoCapture</span><span>(</span></span><span>"rtsp://admin:admin@192.168.31.89:8445/live"</span><span>)</span></div></div><div><div><div>7</div></div><div><span>while</span><span><span> (cap.</span><span>isOpened</span><span>()):</span></span></div></div><div><div><div>8</div></div><div><span>    </span><span>#逐帧读取摄像头画面</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>ret, fram </span><span>=</span><span> cap.</span><span>read</span><span>()</span></div></div><div><div><div>10</div></div><div><span>    </span><span>#转为灰度图</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>fram </span><span>=</span><span> cv2.</span><span>cvtColor</span><span>(fram, cv2.</span><span>COLOR_BGR2GRAY</span><span>)</span></div></div><div><div><div>12</div></div><div><span>    </span><span>#转为二值图</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>fram </span><span>=</span><span> cv2.</span><span>threshold</span><span>(fram, </span><span>25</span><span>, </span><span>255</span><span><span>, cv2.</span><span>THRESH_BINARY</span><span>)[</span></span><span>1</span><span>]</span></div></div><div><div><div>14</div></div><div><span>    </span><span>#初始帧</span></div></div><div><div><div>15</div></div><div><span>    </span><span>if</span><span> lastFram </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>lastFram </span><span>=</span><span> fram</span></div></div><div><div><div>17</div></div><div><span>        </span><span>continue</span></div></div><div><div><div>18</div></div><div><span>    </span><span>#将上一帧与当前帧做差运算</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>frameDelta </span><span>=</span><span> cv2.</span><span>absdiff</span><span>(lastFram, fram)</span></div></div><div><div><div>20</div></div><div><span>    </span><span>#当前帧设为上一帧</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>lastFram </span><span>=</span><span> fram.</span><span>copy</span><span>()</span></div></div><div><div><div>22</div></div><div><span>    </span><span>#显示</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>cv2.</span><span>imshow</span><span>(</span><span>"f"</span><span>, fram)</span></div></div><div><div><div>24</div></div><div><span>    </span><span>if</span><span><span> cv2.</span><span>waitKey</span><span>(</span></span><span>1</span><span><span>) </span><span>&amp;</span><span> </span></span><span>0x</span><span>FF</span><span><span> </span><span>==</span><span> </span></span><span>ord</span><span>(</span><span>'q'</span><span>):</span></div></div><div><div><div>25</div></div><div><span>        </span><span>break</span></div></div><div><div><div>26</div></div><div><span><span>cap.</span><span>release</span><span>()</span></span></div></div><div><div><div>27</div></div><div><span><span>cv2.</span><span>destroyAllWindows</span><span>()</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p></p><figure><img alt="1.png" loading="lazy" width="1605" height="942" src="/_astro/233.1.BxpRk-Mw_uacbr.webp" /><figcaption>1.png</figcaption></figure><p></p></section></section>
<section><h1>0x20 三帧法<a href="#0x20-三帧法"><span>#</span></a></h1><p>三帧就是在二帧让的基础上，进行与运算。</p><p>假设有A、B、C三帧，AB做差运算，BC做差运算，再将两个差运算做与运算。</p><p>相比二帧更适用于移动较快的情况。</p><section><h2>0x21 程序实现<a href="#0x21-程序实现"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> cv2</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>#A帧</span></div></div><div><div><div>4</div></div><div><span><span>aFram </span><span>=</span><span> </span></span><span>None</span></div></div><div><div><div>5</div></div><div><span>#B帧</span></div></div><div><div><div>6</div></div><div><span><span>bFram </span><span>=</span><span> </span></span><span>None</span></div></div><div><div><div>7</div></div><div><span>#我这的视频源是使用网络摄像头</span></div></div><div><div><div>8</div></div><div><span><span>cap </span><span>=</span><span> cv2.</span><span>VideoCapture</span><span>(</span></span><span>"rtsp://admin:admin@192.168.31.89:8445/live"</span><span>)</span></div></div><div><div><div>9</div></div><div><span>while</span><span><span> (cap.</span><span>isOpened</span><span>()):</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>#逐帧读取摄像头画面</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>ret, fram </span><span>=</span><span> cap.</span><span>read</span><span>()</span></div></div><div><div><div>12</div></div><div><span>    </span><span>#转为灰度图</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>fram </span><span>=</span><span> cv2.</span><span>cvtColor</span><span>(fram, cv2.</span><span>COLOR_BGR2GRAY</span><span>)</span></div></div><div><div><div>14</div></div><div><span>    </span><span>#转为二值图</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>fram </span><span>=</span><span> cv2.</span><span>threshold</span><span>(fram, </span><span>25</span><span>, </span><span>255</span><span><span>, cv2.</span><span>THRESH_BINARY</span><span>)[</span></span><span>1</span><span>]</span></div></div><div><div><div>16</div></div><div><span>    </span><span>#初始帧</span></div></div><div><div><div>17</div></div><div><span>    </span><span>if</span><span> bFram </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>18</div></div><div><span>        </span><span>if</span><span> aFram </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>19</div></div><div><span><span>            </span></span><span>aFram </span><span>=</span><span> fram.</span><span>copy</span><span>()</span></div></div><div><div><div>20</div></div><div><span>        </span><span>else</span><span>:</span></div></div><div><div><div>21</div></div><div><span><span>            </span></span><span>bFram </span><span>=</span><span> fram.</span><span>copy</span><span>()</span></div></div><div><div><div>22</div></div><div><span>            </span><span>global</span><span> abFram</span></div></div><div><div><div>23</div></div><div><span><span>            </span></span><span>abFram </span><span>=</span><span> cv2.</span><span>absdiff</span><span>(aFram, bFram)</span></div></div><div><div><div>24</div></div><div><span>        </span><span>continue</span></div></div><div><div><div>25</div></div><div>
</div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>bcFram </span><span>=</span><span> cv2.</span><span>absdiff</span><span>(bFram, fram)</span></div></div><div><div><div>27</div></div><div><span>    </span><span>#与运算</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>thresh </span><span>=</span><span> cv2.</span><span>bitwise_and</span><span>(adFram,bcFram)</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>abFram </span><span>=</span><span> bcFram.</span><span>copy</span><span>()</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>aFram </span><span>=</span><span> bFram.</span><span>copy</span><span>()</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>bFram </span><span>=</span><span> fram.</span><span>copy</span><span>()</span></div></div><div><div><div>33</div></div><div><span>    </span><span>#显示</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>cv2.</span><span>imshow</span><span>(</span><span>"f"</span><span>, thresh)</span></div></div><div><div><div>35</div></div><div><span>    </span><span>if</span><span><span> cv2.</span><span>waitKey</span><span>(</span></span><span>1</span><span><span>) </span><span>&amp;</span><span> </span></span><span>0x</span><span>FF</span><span><span> </span><span>==</span><span> </span></span><span>ord</span><span>(</span><span>'q'</span><span>):</span></div></div><div><div><div>36</div></div><div><span>        </span><span>break</span></div></div><div><div><div>37</div></div><div><span><span>cap.</span><span>release</span><span>()</span></span></div></div><div><div><div>38</div></div><div><span><span>cv2.</span><span>destroyAllWindows</span><span>()</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/230/</id>
      <title type="text">【杂项】Windows10 深色模式下文件资源管理器有一条白线</title>
      <published>2020-05-26T09:26:00.000Z</published>
      <updated>2020-07-23T07:36:40.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/230/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>Windows 10的深色模式下文件管理器的地址栏下有一条白线
</p><figure><img alt="QQ截图20200526155002.jpg" loading="lazy" width="1689" height="267" src="/_astro/230.1.DJ_8-3Xe_lg2k.webp" /><figcaption>QQ截图20200526155002.jpg</figcaption></figure><p></p></section>
<section><h1>0x01 解决方法<a href="#0x01-解决方法"><span>#</span></a></h1><p>打开IE浏览器，右键栏选择<code>锁定工具栏</code>
</p><figure><img alt="批注 2020-05-26 171922.png" loading="lazy" width="730" height="390" src="/_astro/230.2.mT5mEZVf_1jVHaG.webp" /><figcaption>批注 2020-05-26 171922.png</figcaption></figure><p></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/227/</id>
      <title type="text">【Golang】使用CGO交叉编译</title>
      <published>2020-04-08T10:23:00.000Z</published>
      <updated>2020-04-12T07:32:44.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/227/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>0x00<a href="#0x00"><span>#</span></a></h2><p>Golang可以在一个平台交叉编译多个平台的程序，但是在默认情况下Golang中编译C语言的<code>CGO</code>不支持交叉编译。
通过查询资料和阅读官方文档了解到<code>CGO</code>默认使用本地计算机自带的<code>gcc</code>和<code>g++</code>编译器，所以可以修改默认的编译器使用自己准备的编译器来进行交叉编译。</p><p>这里演示的是使用CGO在Linux下编译Windows程序
我在这里环境是WSL/Kali (Windows是最好的Linux发行版（滑稽）)
我之所以选择WSL是因为Linux的包相对Windows好管理，而且windows下有一些软件都是linux的移植版比如<code>gcc</code>编译器等，并且WSL的开销比传统虚拟机要小。</p></section>
<section><h2>0x01 安装<a href="#0x01-安装"><span>#</span></a></h2><p>首先在安装Linux编译Windows的交叉编译器<code>mingw-w64</code></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>mingw-w64</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这句命令主要安装了:</p><ul>
<li>32位windows编译器<code>i686-w64-mingw32-gcc</code>和<code>i686-w64-mingw32-g++</code></li>
<li>64位windows编译器<code>x86_64-w64-mingw32-gcc</code>和<code>x86_64-w64-mingw32-g++</code></li>
</ul><section><h3>单独安装<a href="#单独安装"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>gcc-mingw-w64-x86-64-win32</span><span> </span><span>g++-mingw-w64-x86-64-win32</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>gcc-mingw-w64-i686-win32</span><span> </span><span>g++-mingw-w64-i686-win32</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>0x02 使用<a href="#0x02-使用"><span>#</span></a></h2><p>进行编译时配置环境变量</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>编译64位windows程序</span></div></div><div><div><div>2</div></div><div><span>export</span><span> </span><span>GOOS</span><span>=</span><span>windows</span></div></div><div><div><div>3</div></div><div><span>export</span><span> </span><span>GOARCH</span><span>=</span><span>amd64</span></div></div><div><div><div>4</div></div><div><span>export</span><span> </span><span>CC</span><span>=</span><span>x86_64-w64-mingw32-gcc</span></div></div><div><div><div>5</div></div><div><span>export</span><span> </span><span>CXX</span><span>=</span><span>x86_64-w64-mingw32-g</span><span>++</span></div></div><div><div><div>6</div></div><div><span>export</span><span> </span><span>CGO_ENABLED</span><span>=</span><span>1</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>编译32位windows程序</span></div></div><div><div><div>9</div></div><div><span>export</span><span> </span><span>GOOS</span><span>=</span><span>windows</span></div></div><div><div><div>10</div></div><div><span>export</span><span> </span><span>GOARCH</span><span>=</span><span>386</span></div></div><div><div><div>11</div></div><div><span>export</span><span> </span><span>CC</span><span>=</span><span>i686-w64-mingw32-gcc</span></div></div><div><div><div>12</div></div><div><span>export</span><span> </span><span>CXX</span><span>=</span><span>i686-w64-mingw32-g</span><span>++</span></div></div><div><div><div>13</div></div><div><span>export</span><span> </span><span>CGO_ENABLED</span><span>=</span><span>1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>最后使用<code>go build</code>等命令进行编译</p></section>
<section><h2>0x03 实用脚本<a href="#0x03-实用脚本"><span>#</span></a></h2><section><h3>64位编译<a href="#64位编译"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/bash</span></div></div><div><div><div>2</div></div><div><span>export</span><span> </span><span>GOOS</span><span>=</span><span>windows</span></div></div><div><div><div>3</div></div><div><span>export</span><span> </span><span>GOARCH</span><span>=</span><span>amd64</span></div></div><div><div><div>4</div></div><div><span>export</span><span> </span><span>CC</span><span>=</span><span>x86_64-w64-mingw32-gcc</span></div></div><div><div><div>5</div></div><div><span>export</span><span> </span><span>CXX</span><span>=</span><span>x86_64-w64-mingw32-g</span><span>++</span></div></div><div><div><div>6</div></div><div><span>export</span><span> </span><span>CGO_ENABLED</span><span>=</span><span>1</span></div></div><div><div><div>7</div></div><div><span>cd</span><span> $(</span><span>pwd</span><span>)</span></div></div><div><div><div>8</div></div><div><span>go</span><span> </span><span>build</span><span> </span><span>$*</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>32位编译<a href="#32位编译"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/bash</span></div></div><div><div><div>2</div></div><div><span>export</span><span> </span><span>GOOS</span><span>=</span><span>windows</span></div></div><div><div><div>3</div></div><div><span>export</span><span> </span><span>GOARCH</span><span>=</span><span>386</span></div></div><div><div><div>4</div></div><div><span>export</span><span> </span><span>CC</span><span>=</span><span>i686-w64-mingw32-gcc</span></div></div><div><div><div>5</div></div><div><span>export</span><span> </span><span>CXX</span><span>=</span><span>i686-w64-mingw32-g</span><span>++</span></div></div><div><div><div>6</div></div><div><span>export</span><span> </span><span>CGO_ENABLED</span><span>=</span><span>1</span></div></div><div><div><div>7</div></div><div><span>cd</span><span> $(</span><span>pwd</span><span>)</span></div></div><div><div><div>8</div></div><div><span>go</span><span> </span><span>build</span><span> </span><span>$*</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>将代码保存文件，编译时在要进行编译的源码目录直接执行这个文件，例如：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>例如文件保存路径为/bin/cgo-w64-x86_64</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>在进行编译的目录下执行</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>$</span><span> </span><span>/bin/cgo-w64-x86_64</span></div></div><div><div><div>6</div></div><div><span>等同于</span></div></div><div><div><div>7</div></div><div><span>$</span><span> </span><span>go</span><span> </span><span>build</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>$</span><span> </span><span>/bin/cgo-w64-x86_64</span><span> </span><span>-ldflags=</span><span>"-X pkg.variable1=value -X pkg.variable2=value"</span></div></div><div><div><div>10</div></div><div><span>等同于</span></div></div><div><div><div>11</div></div><div><span>$</span><span> </span><span>go</span><span> </span><span>build</span><span> </span><span>-ldflags=</span><span>"-X pkg.variable1=value -X pkg.variable2=value"</span></div></div><div><div><div>12</div></div><div><span>其他以此类推</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h2>0x04 其他架构的编译器<a href="#0x04-其他架构的编译器"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>gccgo-aarch64-linux-gnu</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>gccgo-alpha-linux-gnu</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>gccgo-arm-linux-gnueabi</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>gccgo-arm-linux-gnueabihf</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>gccgo-i686-linux-gnu</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>gccgo-multilib-i686-linux-gnu</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>gccgo-multilib-powerpc-linux-gnu</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>gccgo-multilib-powerpc64-linux-gnu</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>gccgo-multilib-s390x-linux-gnu</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>gccgo-multilib-sparc64-linux-gnu</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>gccgo-multilib-x86-64-linux-gnux32</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>gccgo-powerpc-linux-gnu</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>gccgo-powerpc64-linux-gnu</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>gccgo-powerpc64le-linux-gnu</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>gccgo-riscv64-linux-gnu</span></div></div><div><div><div>30</div></div><div>
</div></div><div><div><div>31</div></div><div><span>gccgo-s390x-linux-gnu</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>gccgo-sparc64-linux-gnu</span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span>gccgo-x86-64-linux-gnux32</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/226/</id>
      <title type="text">【Linux】man显示中文</title>
      <published>2020-04-04T05:56:24.000Z</published>
      <updated>2020-04-04T05:56:24.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/226/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>0x00
man是个非常有用的linux命令帮助工具，里面有非常详细的帮助文档，但对于英语不好的人来说学习起来就比较困难。</p>
<p>0x01
man -M /usr/share/man/zh_CN可以将内容显示为中文。</p>
<p>在.bashrc中增加 cman=‘man -M /usr//share/man/zh_CN’</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/225/</id>
      <title type="text">【杂项】Virtualbox 6与Hyper-V共存</title>
      <published>2020-02-15T09:11:00.000Z</published>
      <updated>2020-02-15T10:23:54.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/225/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>0x00<a href="#0x00"><span>#</span></a></h2><p>Virualbox（以下均称Vbox）以小巧开源免费等优势与VM和Hyper-v同台竞技。
而Hyper-v靠着“巨硬”这个爸爸在Windows平台上也有非常优秀的表现，特别是最近Windows10新更新的“Windows沙盒”与“WSL2”这两个非常棒的工具就是使用Hyper-v虚拟技术实现的。
但是这又会遇到一个“致命”问题，那就是Hyper-v不能与vbox和vm共存，原因是Hyper-v的虚拟方式不一样，开启Hyper-v后会将用户的桌面系统给虚拟化，用户的桌面系统就会成为Hyper-v的虚拟系统，而Hyper-v的虚拟系统是不允许再开虚拟机的，因此开启Hyper-v后VM和Vbox就不能运行。
</p><figure><img alt="虚拟方式" loading="lazy" width="728" height="474" src="/_astro/225.1.vNWYc3yx_Z2oB5y0.webp" /><figcaption>虚拟方式</figcaption></figure>
而Vbox在第六个版本（Vbox6.0）中新增了利用Hyper-v的api进行虚拟化系统<p></p><div><div><div></div><div>Caution</div></div><div><p>这个功能还是实验性的功能，可能会出现意想不到的问题，出现问题请向官方反馈以助于完善。</p></div></div></section>
<section><h2>0x01<a href="#0x01"><span>#</span></a></h2><p>由于这个功能还是实验性的功能，所以没有现成的GUI按钮或界面开启这个功能，需要使用命令行开启。
找到vbox的安装目录，确定目录下有<code>VBoxManage.exe</code>
在该目录打开命令行工具（目录空白位置按住shift 鼠标点击右键，选择<code>在此处打开命令窗口</code>或<code>在此处打开PwerShell窗口</code>）
命令窗口(cmd)输入：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>#指定vbox下的虚拟系统开启这个功能</span></div></div><div><div><div>2</div></div><div><span>VBoxManage</span><span> </span><span>setextradata</span><span> </span><span>"&lt;虚拟机名字&gt;"</span><span> </span><span>"VBoxInternal/NEM/UseRing0Runloop"</span><span> </span><span>0</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>#或指定vbox所有虚拟系统开启</span></div></div><div><div><div>5</div></div><div><span>VBoxManage</span><span> </span><span>setextradata</span><span> </span><span>global</span><span> </span><span>"VBoxInternal/NEM/UseRing0Runloop"</span><span> </span><span>0</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>PowerShell需要加<code>./</code>和<code>.exe</code></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>#指定vbox下的虚拟系统开启这个功能</span></div></div><div><div><div>2</div></div><div><span><span>.</span><span>/</span></span><span>VBoxManage.exe</span><span> setextradata </span><span>"&lt;虚拟机名字&gt;"</span><span> </span><span>"VBoxInternal/NEM/UseRing0Runloop"</span><span> </span><span>0</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>#或指定vbox所有虚拟系统开启</span></div></div><div><div><div>5</div></div><div><span><span>.</span><span>/</span></span><span>VBoxManage.exe</span><span> setextradata global </span><span>"VBoxInternal/NEM/UseRing0Runloop"</span><span> </span><span>0</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>0x02<a href="#0x02"><span>#</span></a></h2><p>开启后 就可以体验Hyper-v与Vbox双开的快乐了。
但VM暂时还没有和Hyper-v共存的方法</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/193/</id>
      <title type="text">[杂项]handsome主题美化</title>
      <published>2020-02-12T10:23:00.000Z</published>
      <updated>2020-02-13T05:32:06.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/193/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>0x00<a href="#0x00"><span>#</span></a></h2><p>handsome主题是基于Typecho博客框架打造的一款强大的付费主题
<img src="https://assets.ihewro.com/usr/uploads/sina/5cc07ecd95bcb.jpg" alt="" />
<a href="https://www.ihewro.com/archives/489/" target="_blank">主题页面</a></p></section>
<section><h2>0x01 Mac风格代码高亮<a href="#0x01-mac风格代码高亮"><span>#</span></a></h2><p><a href="https://www.xcnte.com/archives/523/" target="_blank">作者页面</a></p></section>
<section><h2>0x02 底部页脚标签样式<a href="#0x02-底部页脚标签样式"><span>#</span></a></h2><p><img alt="" loading="lazy" width="372" height="69" src="/_astro/193.2.Dnj3i9fR_1l5jL4.webp" /></p><ol>
<li>将以下添加至<code>自定义CSS</code>中</li>
</ol><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/*底部页脚*/</span></div></div><div><div><div>2</div></div><div><span>.github-badge</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>display: </span><span>inline-block</span><span>;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>border-radius: </span><span><span>4</span><span>px</span></span><span>;</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>text-shadow: </span><span>none</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>font-size: </span><span><span>12</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>color: </span><span>#</span><span>fff</span><span>;</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>line-height: </span><span><span>15</span><span>px</span></span><span>;</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>abbac3</span><span>;</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>margin-bottom: </span><span><span>5</span><span>px</span></span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>.github-badge</span><span> </span><span>.badge-subject</span><span> {</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>display: </span><span>inline-block</span><span>;</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>4d4d4d</span><span>;</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>padding: </span><span><span>4</span><span>px</span></span><span> </span><span><span>4</span><span>px</span></span><span> </span><span><span>4</span><span>px</span></span><span> </span><span><span>6</span><span>px</span></span><span>;</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>border-top-left-radius: </span><span><span>4</span><span>px</span></span><span>;</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>border-bottom-left-radius: </span><span><span>4</span><span>px</span></span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>.github-badge</span><span> </span><span>.badge-value</span><span> {</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>display: </span><span>inline-block</span><span>;</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>padding: </span><span><span>4</span><span>px</span></span><span> </span><span><span>6</span><span>px</span></span><span> </span><span><span>4</span><span>px</span></span><span> </span><span><span>4</span><span>px</span></span><span>;</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>border-top-right-radius: </span><span><span>4</span><span>px</span></span><span>;</span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>border-bottom-right-radius: </span><span><span>4</span><span>px</span></span></div></div><div><div><div>26</div></div><div><span>}</span></div></div><div><div><div>27</div></div><div>
</div></div><div><div><div>28</div></div><div><span>.github-badge</span><span> </span><span>.bg-blue</span><span> {</span></div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>007ec6</span></div></div><div><div><div>30</div></div><div><span>}</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span>.github-badge</span><span> </span><span>.bg-orange</span><span> {</span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>ffa500</span></div></div><div><div><div>34</div></div><div><span>}</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>.github-badge</span><span> </span><span>.bg-red</span><span> {</span></div></div><div><div><div>37</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>f00</span></div></div><div><div><div>38</div></div><div><span>}</span></div></div><div><div><div>39</div></div><div>
</div></div><div><div><div>40</div></div><div><span>.github-badge</span><span> </span><span>.bg-green</span><span> {</span></div></div><div><div><div>41</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>3bca6e</span></div></div><div><div><div>42</div></div><div><span>}</span></div></div><div><div><div>43</div></div><div>
</div></div><div><div><div>44</div></div><div><span>.github-badge</span><span> </span><span>.bg-purple</span><span> {</span></div></div><div><div><div>45</div></div><div><span><span>  </span></span><span>background-color: </span><span>#</span><span>ab34e9</span></div></div><div><div><div>46</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><ol>
<li>将以下内容添加至<code>博客底部左侧信息</code>,将内容改成自己的</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"github-badge"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"./"</span><span> </span><span>title</span><span>=</span><span><span>"©2019</span><span>&amp;</span></span><span>nbsp</span><span><span>;</span><span>Alvin"</span></span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"badge-subject"</span><span>&gt;Copyright&lt;/</span><span>span</span><span>&gt;&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"badge-value bg-blue"</span><span>&gt;©2019</span><span>&amp;nbsp;</span><span>Alvin&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&amp;nbsp;</span><span>|</span><span>&amp;nbsp;</span></div></div><div><div><div>7</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"github-badge"</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"http://www.miitbeian.gov.cn/"</span><span> </span><span>target</span><span>=</span><span>"_blank"</span><span> </span><span>title</span><span>=</span><span>"粤ICP备 xxx号"</span><span> </span><span>style</span><span>=</span><span>"</span><span>cursor: url(</span><span>&amp;</span><span>quot</span><span>;</span><span>/usr/plugins/HoerMouse/static/image/dew/link.cur</span><span>&amp;</span><span>quot</span><span>;</span><span>), pointer;</span><span>"</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span>&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"badge-subject"</span><span>&gt;粤ICP备&lt;/</span><span>span</span><span>&gt;&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"badge-value bg-green"</span><span>&gt;xxx号&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>将以下内容添加至<code>博客底部右侧信息</code></li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"github-badge"</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"http://www.typecho.org"</span><span> </span><span>target</span><span>=</span><span>"_blank"</span><span> </span><span>title</span><span>=</span><span>"由 Typecho 强力驱动"</span><span> </span><span>style</span><span>=</span><span>"</span><span>cursor: url(</span><span>&amp;</span><span>quot</span><span>;</span><span>/usr/plugins/HoerMouse/static/image/dew/link.cur</span><span>&amp;</span><span>quot</span><span>;</span><span>), pointer;</span><span>"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span>&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"badge-subject"</span><span>&gt;Powered&lt;/</span><span>span</span><span>&gt;&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"badge-value bg-blue"</span><span>&gt;Typecho&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span>&amp;nbsp;</span><span>|</span><span>&amp;nbsp;</span></div></div><div><div><div>7</div></div><div><span>&lt;</span><span>div</span><span> </span><span>class</span><span>=</span><span>"github-badge"</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span>&lt;</span><span>a</span><span> </span><span>href</span><span>=</span><span>"https://www.ihewro.com/archives/489/"</span><span> </span><span>target</span><span>=</span><span>"_blank"</span><span> </span><span>title</span><span>=</span><span>"站点使用 handsome 主题，作者：友人C"</span><span> </span><span>style</span><span>=</span><span>"</span><span>cursor: url(</span><span>&amp;</span><span>quot</span><span>;</span><span>/usr/plugins/HoerMouse/static/image/dew/link.cur</span><span>&amp;</span><span>quot</span><span>;</span><span>), pointer;</span><span>"</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span>&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"badge-subject"</span><span>&gt;Theme&lt;/</span><span>span</span><span>&gt;&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"badge-value bg-orange"</span><span>&gt;Handsome&lt;/</span><span>span</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span>&lt;/</span><span>a</span><span>&gt;</span></div></div><div><div><div>11</div></div><div><span>&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ol>
<li>修改<code>handsome\component\footer.php</code>文件
删除</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Powered by &lt;</span><span>a</span><span> </span><span>target</span><span>=</span><span>"blank"</span><span> </span><span>href</span><span>=</span><span>"http://www.typecho.org"</span><span>&gt;Typecho&lt;/</span><span>a</span><span>&gt;</span><span>&amp;nbsp;</span><span>|</span><span>&amp;nbsp;</span><span>Theme by &lt;</span><span>a</span><span> </span><span>target</span><span>=</span><span>"blank"</span><span> </span><span>href</span><span>=</span><span>"https://www.ihewro.com/archives/489/"</span><span>&gt;handsome&lt;/</span><span>a</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>删除代码:<code>&amp;copy;&amp;nbsp;&lt;?php echo date("Y");?&gt; Copyright&amp;nbsp;</code></p></section>
<section><h2>0x03 评论获取用户信息插件<a href="#0x03-评论获取用户信息插件"><span>#</span></a></h2><p><img alt="" loading="lazy" width="633" height="169" src="/_astro/193.3.BUMpCoZ5_Z197gVm.webp" />
<a href="https://doge.uk/coding/useragent-modify.html" target="_blank">作者页面</a></p></section>
<section><h2>0x04 文本框打字机特效<a href="#0x04-文本框打字机特效"><span>#</span></a></h2><p>添加代码至<code>自定义js</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>(</span><span>function</span><span> </span><span>webpackUniversalModuleDefinition</span><span><span>(</span><span>a</span><span>,</span><span>b</span><span>){</span></span><span>if</span><span>(</span><span>typeof</span><span> </span><span>exports</span><span>===</span><span>"object"</span><span><span>&amp;&amp;</span><span>typeof</span></span><span> </span><span>module</span><span>===</span><span>"object"</span><span>){</span><span>module</span><span>.</span><span>exports</span><span>=</span><span>b</span><span>()}</span><span>else</span><span>{</span><span>if</span><span>(</span><span>typeof</span><span><span> </span><span>define</span></span><span>===</span><span>"function"</span><span>&amp;&amp;</span><span><span>define</span><span>.</span></span><span>amd</span><span>){</span><span>define</span><span><span>([],</span><span>b</span><span>)}</span></span><span>else</span><span>{</span><span>if</span><span>(</span><span>typeof</span><span> </span><span>exports</span><span>===</span><span>"object"</span><span>){</span><span>exports</span><span>[</span><span>"POWERMODE"</span><span>]</span><span>=</span><span>b</span><span>()}</span><span>else</span><span><span>{</span><span>a</span><span>[</span></span><span>"POWERMODE"</span><span>]</span><span>=</span><span>b</span><span>()}}}})(</span><span>this</span><span>,</span><span>function</span><span>(){</span><span>return</span><span>(</span><span>function</span><span><span>(</span><span>a</span><span>){</span></span><span>var</span><span><span> </span><span>b</span></span><span>=</span><span>{};</span><span>function</span><span> </span><span>c</span><span><span>(</span><span>e</span><span>){</span></span><span>if</span><span><span>(</span><span>b</span><span>[</span><span>e</span><span>]){</span></span><span>return</span><span><span> </span><span>b</span><span>[</span><span>e</span><span>].</span></span><span>exports</span><span>}</span><span>var</span><span><span> </span><span>d</span></span><span>=</span><span><span>b</span><span>[</span><span>e</span><span>]</span></span><span>=</span><span>{</span><span>exports</span><span>:</span><span>{},</span><span>id</span><span>:</span><span><span>e</span><span>,</span></span><span>loaded</span><span>:</span><span>false</span><span><span>};</span><span>a</span><span>[</span><span>e</span><span>].</span></span><span>call</span><span><span>(</span><span>d</span><span>.</span></span><span>exports</span><span><span>,</span><span>d</span><span>,</span><span>d</span><span>.</span></span><span>exports</span><span><span>,</span><span>c</span><span>);</span><span>d</span><span>.</span></span><span>loaded</span><span>=</span><span>true</span><span>;</span><span>return</span><span><span> </span><span>d</span><span>.</span></span><span>exports</span><span><span>}</span><span>c</span><span>.</span></span><span>m</span><span>=</span><span><span>a</span><span>;</span><span>c</span><span>.</span></span><span>c</span><span>=</span><span><span>b</span><span>;</span><span>c</span><span>.</span></span><span>p</span><span>=</span><span>""</span><span>;</span><span>return</span><span> </span><span>c</span><span>(</span><span>0</span><span>)})([</span><span>function</span><span><span>(</span><span>c</span><span>,</span><span>g</span><span>,</span><span>b</span><span>){</span></span><span>var</span><span><span> </span><span>d</span></span><span>=</span><span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"canvas"</span><span><span>);</span><span>d</span><span>.</span></span><span>width</span><span>=</span><span><span>window</span><span>.</span></span><span>innerWidth</span><span><span>;</span><span>d</span><span>.</span></span><span>height</span><span>=</span><span><span>window</span><span>.</span></span><span>innerHeight</span><span><span>;</span><span>d</span><span>.</span></span><span>style</span><span>.</span><span>cssText</span><span>=</span><span>"position:fixed;top:0;left:0;pointer-events:none;z-index:999999"</span><span><span>;</span><span>window</span><span>.</span></span><span>addEventListener</span><span>(</span><span>"resize"</span><span>,</span><span>function</span><span><span>(){</span><span>d</span><span>.</span></span><span>width</span><span>=</span><span><span>window</span><span>.</span></span><span>innerWidth</span><span><span>;</span><span>d</span><span>.</span></span><span>height</span><span>=</span><span><span>window</span><span>.</span></span><span>innerHeight</span><span><span>});</span><span>document</span><span>.</span></span><span>body</span><span>.</span><span>appendChild</span><span><span>(</span><span>d</span><span>);</span></span><span>var</span><span><span> </span><span>a</span></span><span>=</span><span><span>d</span><span>.</span></span><span>getContext</span><span>(</span><span>"2d"</span><span>);</span><span>var</span><span><span> </span><span>n</span></span><span>=</span><span>[];</span><span>var</span><span><span> </span><span>j</span></span><span>=</span><span>0</span><span>;</span><span>var</span><span><span> </span><span>k</span></span><span>=</span><span>120</span><span>;</span><span>var</span><span><span> </span><span>f</span></span><span>=</span><span><span>k</span><span>;</span></span><span>var</span><span><span> </span><span>p</span></span><span>=</span><span>false</span><span><span>;</span><span>o</span><span>.</span></span><span>shake</span><span>=</span><span>true</span><span>;</span><span>function</span><span> </span><span>l</span><span><span>(</span><span>r</span><span>,</span><span>q</span><span>){</span></span><span>return</span><span><span> </span><span>Math</span><span>.</span></span><span>random</span><span>()</span><span>*</span><span><span>(</span><span>q</span></span><span>-</span><span><span>r</span><span>)</span></span><span>+</span><span><span>r</span><span>}</span></span><span>function</span><span> </span><span>m</span><span><span>(</span><span>r</span><span>){</span></span><span>if</span><span><span>(</span><span>o</span><span>.</span></span><span>colorful</span><span>){</span><span>var</span><span><span> </span><span>q</span></span><span>=</span><span>l</span><span>(</span><span>0</span><span>,</span><span>360</span><span>);</span><span>return</span><span>"hsla("</span><span>+</span><span>l</span><span><span>(</span><span>q</span></span><span>-</span><span>10</span><span><span>,</span><span>q</span></span><span>+</span><span>10</span><span>)</span><span>+</span><span>", 100%, "</span><span>+</span><span>l</span><span>(</span><span>50</span><span>,</span><span>80</span><span>)</span><span>+</span><span>"%, "</span><span>+</span><span>1</span><span>+</span><span>")"</span><span>}</span><span>else</span><span>{</span><span>return</span><span><span> </span><span>window</span><span>.</span></span><span>getComputedStyle</span><span><span>(</span><span>r</span><span>).</span></span><span>color</span><span>}}</span><span>function</span><span> </span><span>e</span><span>(){</span><span>var</span><span><span> </span><span>t</span></span><span>=</span><span><span>document</span><span>.</span></span><span>activeElement</span><span>;</span><span>var</span><span><span> </span><span>v</span><span>;</span></span><span>if</span><span><span>(</span><span>t</span><span>.</span></span><span>tagName</span><span>===</span><span>"TEXTAREA"</span><span>||</span><span><span>(</span><span>t</span><span>.</span></span><span>tagName</span><span>===</span><span>"INPUT"</span><span>&amp;&amp;</span><span><span>t</span><span>.</span></span><span>getAttribute</span><span>(</span><span>"type"</span><span>)</span><span>===</span><span>"text"</span><span>)){</span><span>var</span><span><span> </span><span>u</span></span><span>=</span><span>b</span><span>(</span><span>1</span><span><span>)(</span><span>t</span><span>,</span><span>t</span><span>.</span></span><span>selectionStart</span><span><span>);</span><span>v</span></span><span>=</span><span><span>t</span><span>.</span></span><span>getBoundingClientRect</span><span>();</span><span>return</span><span>{</span><span>x</span><span>:</span><span><span>u</span><span>.</span></span><span>left</span><span>+</span><span><span>v</span><span>.</span></span><span>left</span><span>,</span><span>y</span><span>:</span><span><span>u</span><span>.</span></span><span>top</span><span>+</span><span><span>v</span><span>.</span></span><span>top</span><span>,</span><span>color</span><span>:</span><span>m</span><span><span>(</span><span>t</span><span>)}}</span></span><span>var</span><span><span> </span><span>s</span></span><span>=</span><span><span>window</span><span>.</span></span><span>getSelection</span><span>();</span><span>if</span><span><span>(</span><span>s</span><span>.</span></span><span>rangeCount</span><span>){</span><span>var</span><span><span> </span><span>q</span></span><span>=</span><span><span>s</span><span>.</span></span><span>getRangeAt</span><span>(</span><span>0</span><span>);</span><span>var</span><span><span> </span><span>r</span></span><span>=</span><span><span>q</span><span>.</span></span><span>startContainer</span><span>;</span><span>if</span><span><span>(</span><span>r</span><span>.</span></span><span>nodeType</span><span>===</span><span><span>document</span><span>.</span></span><span>TEXT_NODE</span><span><span>){</span><span>r</span></span><span>=</span><span><span>r</span><span>.</span></span><span>parentNode</span><span><span>}</span><span>v</span></span><span>=</span><span><span>q</span><span>.</span></span><span>getBoundingClientRect</span><span>();</span><span>return</span><span>{</span><span>x</span><span>:</span><span><span>v</span><span>.</span></span><span>left</span><span>,</span><span>y</span><span>:</span><span><span>v</span><span>.</span></span><span>top</span><span>,</span><span>color</span><span>:</span><span>m</span><span><span>(</span><span>r</span><span>)}}</span></span><span>return</span><span>{</span><span>x</span><span>:</span><span>0</span><span>,</span><span>y</span><span>:</span><span>0</span><span>,</span><span>color</span><span>:</span><span>"transparent"</span><span>}}</span><span>function</span><span> </span><span>h</span><span><span>(</span><span>q</span><span>,</span><span>s</span><span>,</span><span>r</span><span>){</span></span><span>return</span><span>{</span><span>x</span><span>:</span><span><span>q</span><span>,</span></span><span>y</span><span>:</span><span><span>s</span><span>,</span></span><span>alpha</span><span>:</span><span>1</span><span>,</span><span>color</span><span>:</span><span><span>r</span><span>,</span></span><span>velocity</span><span>:</span><span>{</span><span>x</span><span><span>:</span><span>-</span></span><span>1</span><span>+</span><span><span>Math</span><span>.</span></span><span>random</span><span>()</span><span>*</span><span>2</span><span>,</span><span>y</span><span><span>:</span><span>-</span></span><span>3.5</span><span>+</span><span><span>Math</span><span>.</span></span><span>random</span><span>()</span><span>*</span><span>2</span><span>}}}</span><span>function</span><span> </span><span>o</span><span>(){</span><span>var</span><span><span> </span><span>t</span></span><span>=</span><span>e</span><span>();</span><span>var</span><span><span> </span><span>s</span></span><span>=</span><span>5</span><span>+</span><span><span>Math</span><span>.</span></span><span>round</span><span><span>(</span><span>Math</span><span>.</span></span><span>random</span><span>()</span><span>*</span><span>10</span><span>);</span><span>while</span><span><span>(</span><span>s</span></span><span>--</span><span><span>){</span><span>n</span><span>[</span><span>j</span><span>]</span></span><span>=</span><span>h</span><span><span>(</span><span>t</span><span>.</span></span><span>x</span><span><span>,</span><span>t</span><span>.</span></span><span>y</span><span><span>,</span><span>t</span><span>.</span></span><span>color</span><span><span>);</span><span>j</span></span><span>=</span><span><span>(</span><span>j</span></span><span>+</span><span>1</span><span>)</span><span>%</span><span>500</span><span><span>}</span><span>f</span></span><span>=</span><span><span>k</span><span>;</span></span><span>if</span><span>(</span><span>!</span><span><span>p</span><span>){</span></span><span>requestAnimationFrame</span><span><span>(</span><span>i</span><span>)}</span></span><span>if</span><span><span>(</span><span>o</span><span>.</span></span><span>shake</span><span>){</span><span>var</span><span><span> </span><span>r</span></span><span>=</span><span>1</span><span>+</span><span>2</span><span>*</span><span><span>Math</span><span>.</span></span><span>random</span><span>();</span><span>var</span><span><span> </span><span>q</span></span><span>=</span><span>r</span><span>*</span><span><span>(</span><span>Math</span><span>.</span></span><span>random</span><span>()</span><span>&gt;</span><span>0.5</span><span><span>?</span><span>-</span></span><span>1</span><span>:</span><span>1</span><span>);</span><span>var</span><span><span> </span><span>u</span></span><span>=</span><span>r</span><span>*</span><span><span>(</span><span>Math</span><span>.</span></span><span>random</span><span>()</span><span>&gt;</span><span>0.5</span><span><span>?</span><span>-</span></span><span>1</span><span>:</span><span>1</span><span><span>);</span><span>document</span><span>.</span></span><span>body</span><span>.</span><span>style</span><span>.</span><span>marginLeft</span><span>=</span><span>q</span><span>+</span><span>"px"</span><span><span>;</span><span>document</span><span>.</span></span><span>body</span><span>.</span><span>style</span><span>.</span><span>marginTop</span><span>=</span><span>u</span><span>+</span><span>"px"</span><span>;</span><span>setTimeout</span><span>(</span><span>function</span><span><span>(){</span><span>document</span><span>.</span></span><span>body</span><span>.</span><span>style</span><span>.</span><span>marginLeft</span><span>=</span><span>""</span><span><span>;</span><span>document</span><span>.</span></span><span>body</span><span>.</span><span>style</span><span>.</span><span>marginTop</span><span>=</span><span>""</span><span>},</span><span>75</span><span><span>)}}</span><span>o</span><span>.</span></span><span>colorful</span><span>=</span><span>false</span><span>;</span><span>function</span><span> </span><span>i</span><span>(){</span><span>if</span><span><span>(</span><span>f</span></span><span>&gt;</span><span>0</span><span>){</span><span>requestAnimationFrame</span><span><span>(</span><span>i</span><span>);</span><span>f</span></span><span>--</span><span><span>;</span><span>p</span></span><span>=</span><span>true</span><span>}</span><span>else</span><span><span>{</span><span>p</span></span><span>=</span><span>false</span><span><span>}</span><span>a</span><span>.</span></span><span>clearRect</span><span>(</span><span>0</span><span>,</span><span>0</span><span><span>,</span><span>d</span><span>.</span></span><span>width</span><span><span>,</span><span>d</span><span>.</span></span><span>height</span><span>);</span><span>for</span><span>(</span><span>var</span><span><span> </span><span>q</span></span><span>=</span><span>0</span><span><span>;</span><span>q</span></span><span>&lt;</span><span><span>n</span><span>.</span></span><span>length</span><span>;</span><span>++</span><span><span>q</span><span>){</span></span><span>var</span><span><span> </span><span>r</span></span><span>=</span><span><span>n</span><span>[</span><span>q</span><span>];</span></span><span>if</span><span><span>(</span><span>r</span><span>.</span></span><span>alpha</span><span>&lt;=</span><span>0.1</span><span>){</span><span>continue</span><span><span>}</span><span>r</span><span>.</span></span><span>velocity</span><span>.</span><span>y</span><span>+=</span><span>0.075</span><span><span>;</span><span>r</span><span>.</span></span><span>x</span><span>+=</span><span><span>r</span><span>.</span></span><span>velocity</span><span>.</span><span>x</span><span><span>;</span><span>r</span><span>.</span></span><span>y</span><span>+=</span><span><span>r</span><span>.</span></span><span>velocity</span><span>.</span><span>y</span><span><span>;</span><span>r</span><span>.</span></span><span>alpha</span><span>*=</span><span>0.96</span><span><span>;</span><span>a</span><span>.</span></span><span>globalAlpha</span><span>=</span><span><span>r</span><span>.</span></span><span>alpha</span><span><span>;</span><span>a</span><span>.</span></span><span>fillStyle</span><span>=</span><span><span>r</span><span>.</span></span><span>color</span><span><span>;</span><span>a</span><span>.</span></span><span>fillRect</span><span><span>(</span><span>Math</span><span>.</span></span><span>round</span><span><span>(</span><span>r</span><span>.</span></span><span>x</span><span>-</span><span>1.5</span><span><span>),</span><span>Math</span><span>.</span></span><span>round</span><span><span>(</span><span>r</span><span>.</span></span><span>y</span><span>-</span><span>1.5</span><span>),</span><span>3</span><span>,</span><span>3</span><span>)}}</span><span>requestAnimationFrame</span><span><span>(</span><span>i</span><span>);</span><span>c</span><span>.</span></span><span>exports</span><span>=</span><span><span>o</span><span>},</span></span><span>function</span><span><span>(</span><span>b</span><span>,</span><span>a</span><span>){(</span></span><span>function</span><span>(){</span><span>var</span><span><span> </span><span>d</span></span><span>=</span><span>[</span><span>"direction"</span><span>,</span><span>"boxSizing"</span><span>,</span><span>"width"</span><span>,</span><span>"height"</span><span>,</span><span>"overflowX"</span><span>,</span><span>"overflowY"</span><span>,</span><span>"borderTopWidth"</span><span>,</span><span>"borderRightWidth"</span><span>,</span><span>"borderBottomWidth"</span><span>,</span><span>"borderLeftWidth"</span><span>,</span><span>"borderStyle"</span><span>,</span><span>"paddingTop"</span><span>,</span><span>"paddingRight"</span><span>,</span><span>"paddingBottom"</span><span>,</span><span>"paddingLeft"</span><span>,</span><span>"fontStyle"</span><span>,</span><span>"fontVariant"</span><span>,</span><span>"fontWeight"</span><span>,</span><span>"fontStretch"</span><span>,</span><span>"fontSize"</span><span>,</span><span>"fontSizeAdjust"</span><span>,</span><span>"lineHeight"</span><span>,</span><span>"fontFamily"</span><span>,</span><span>"textAlign"</span><span>,</span><span>"textTransform"</span><span>,</span><span>"textIndent"</span><span>,</span><span>"textDecoration"</span><span>,</span><span>"letterSpacing"</span><span>,</span><span>"wordSpacing"</span><span>,</span><span>"tabSize"</span><span>,</span><span>"MozTabSize"</span><span>];</span><span>var</span><span><span> </span><span>e</span></span><span>=</span><span><span>window</span><span>.</span></span><span>mozInnerScreenX</span><span>!=</span><span>null</span><span>;</span><span>function</span><span> </span><span>c</span><span><span>(</span><span>k</span><span>,</span><span>l</span><span>,</span><span>o</span><span>){</span></span><span>var</span><span><span> </span><span>h</span></span><span>=</span><span>o</span><span>&amp;&amp;</span><span><span>o</span><span>.</span></span><span>debug</span><span>||</span><span>false</span><span>;</span><span>if</span><span><span>(</span><span>h</span><span>){</span></span><span>var</span><span><span> </span><span>i</span></span><span>=</span><span><span>document</span><span>.</span></span><span>querySelector</span><span>(</span><span>"#input-textarea-caret-position-mirror-div"</span><span>);</span><span>if</span><span><span>(</span><span>i</span><span>){</span><span>i</span><span>.</span></span><span>parentNode</span><span>.</span><span>removeChild</span><span><span>(</span><span>i</span><span>)}}</span></span><span>var</span><span><span> </span><span>f</span></span><span>=</span><span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"div"</span><span><span>);</span><span>f</span><span>.</span></span><span>id</span><span>=</span><span>"input-textarea-caret-position-mirror-div"</span><span><span>;</span><span>document</span><span>.</span></span><span>body</span><span>.</span><span>appendChild</span><span><span>(</span><span>f</span><span>);</span></span><span>var</span><span><span> </span><span>g</span></span><span>=</span><span><span>f</span><span>.</span></span><span>style</span><span>;</span><span>var</span><span><span> </span><span>j</span></span><span>=</span><span><span>window</span><span>.</span></span><span>getComputedStyle</span><span>?</span><span>getComputedStyle</span><span><span>(</span><span>k</span><span>)</span></span><span>:</span><span><span>k</span><span>.</span></span><span>currentStyle</span><span><span>;</span><span>g</span><span>.</span></span><span>whiteSpace</span><span>=</span><span>"pre-wrap"</span><span>;</span><span>if</span><span><span>(</span><span>k</span><span>.</span></span><span>nodeName</span><span>!==</span><span>"INPUT"</span><span><span>){</span><span>g</span><span>.</span></span><span>wordWrap</span><span>=</span><span>"break-word"</span><span><span>}</span><span>g</span><span>.</span></span><span>position</span><span>=</span><span>"absolute"</span><span>;</span><span>if</span><span>(</span><span>!</span><span><span>h</span><span>){</span><span>g</span><span>.</span></span><span>visibility</span><span>=</span><span>"hidden"</span><span><span>}</span><span>d</span><span>.</span></span><span>forEach</span><span>(</span><span>function</span><span><span>(</span><span>p</span><span>){</span><span>g</span><span>[</span><span>p</span><span>]</span></span><span>=</span><span><span>j</span><span>[</span><span>p</span><span>]});</span></span><span>if</span><span><span>(</span><span>e</span><span>){</span></span><span>if</span><span><span>(</span><span>k</span><span>.</span></span><span>scrollHeight</span><span>&gt;</span><span>parseInt</span><span><span>(</span><span>j</span><span>.</span></span><span>height</span><span><span>)){</span><span>g</span><span>.</span></span><span>overflowY</span><span>=</span><span>"scroll"</span><span>}}</span><span>else</span><span><span>{</span><span>g</span><span>.</span></span><span>overflow</span><span>=</span><span>"hidden"</span><span><span>}</span><span>f</span><span>.</span></span><span>textContent</span><span>=</span><span><span>k</span><span>.</span></span><span>value</span><span>.</span><span>substring</span><span>(</span><span>0</span><span><span>,</span><span>l</span><span>);</span></span><span>if</span><span><span>(</span><span>k</span><span>.</span></span><span>nodeName</span><span>===</span><span>"INPUT"</span><span><span>){</span><span>f</span><span>.</span></span><span>textContent</span><span>=</span><span><span>f</span><span>.</span></span><span>textContent</span><span>.</span><span>replace</span><span>(</span><span>/</span><span>\s</span><span>/</span><span>g</span><span>,</span><span>"</span><span>\u00a0</span><span>"</span><span>)}</span><span>var</span><span><span> </span><span>n</span></span><span>=</span><span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"span"</span><span><span>);</span><span>n</span><span>.</span></span><span>textContent</span><span>=</span><span><span>k</span><span>.</span></span><span>value</span><span>.</span><span>substring</span><span><span>(</span><span>l</span><span>)</span></span><span>||</span><span>"."</span><span><span>;</span><span>f</span><span>.</span></span><span>appendChild</span><span><span>(</span><span>n</span><span>);</span></span><span>var</span><span><span> </span><span>m</span></span><span>=</span><span>{</span><span>top</span><span>:</span><span><span>n</span><span>.</span></span><span>offsetTop</span><span>+</span><span>parseInt</span><span><span>(</span><span>j</span><span>[</span></span><span>"borderTopWidth"</span><span>]),</span><span>left</span><span>:</span><span><span>n</span><span>.</span></span><span>offsetLeft</span><span>+</span><span>parseInt</span><span><span>(</span><span>j</span><span>[</span></span><span>"borderLeftWidth"</span><span>])};</span><span>if</span><span><span>(</span><span>h</span><span>){</span><span>n</span><span>.</span></span><span>style</span><span>.</span><span>backgroundColor</span><span>=</span><span>"#aaa"</span><span>}</span><span>else</span><span><span>{</span><span>document</span><span>.</span></span><span>body</span><span>.</span><span>removeChild</span><span><span>(</span><span>f</span><span>)}</span></span><span>return</span><span><span> </span><span>m</span><span>}</span></span><span>if</span><span>(</span><span>typeof</span><span><span> </span><span>b</span></span><span>!=</span><span>"undefined"</span><span><span>&amp;&amp;</span><span>typeof</span></span><span><span> </span><span>b</span><span>.</span></span><span>exports</span><span>!=</span><span>"undefined"</span><span><span>){</span><span>b</span><span>.</span></span><span>exports</span><span>=</span><span><span>c</span><span>}</span></span><span>else</span><span><span>{</span><span>window</span><span>.</span></span><span>getCaretCoordinates</span><span>=</span><span><span>c</span><span>}}())}])});</span></span></div></div><div><div><div>2</div></div><div><span>POWERMODE</span><span>.</span><span>colorful</span><span>=</span><span>true</span><span>;</span><span>POWERMODE</span><span>.</span><span>shake</span><span>=</span><span>false</span><span><span>;</span><span>document</span><span>.</span></span><span>body</span><span>.</span><span>addEventListener</span><span>(</span><span>"input"</span><span>,</span><span>POWERMODE</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>0x05 博主介绍闪字特效<a href="#0x05-博主介绍闪字特效"><span>#</span></a></h2><p>添加代码至<code>博主的介绍</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;!--博主介绍的闪字特效--&gt;</span></div></div><div><div><div>2</div></div><div><span>&lt;</span><span>span</span><span> </span><span>class</span><span>=</span><span>"text-muted text-xs block"</span><span>&gt;&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"chakhsu"</span><span>&gt;&lt;/</span><span>div</span><span>&gt; &lt;</span><span>script</span><span>&gt; </span><span>var</span><span> </span><span>chakhsu</span><span> </span><span>=</span><span> </span><span>function</span><span><span> (</span><span>r</span><span>) {</span></span><span>function</span><span> </span><span>t</span><span>() {</span><span>return</span><span><span> </span><span>b</span><span>[</span><span>Math</span><span>.</span></span><span>floor</span><span><span>(</span><span>Math</span><span>.</span></span><span>random</span><span>() </span><span>*</span><span><span> </span><span>b</span><span>.</span></span><span>length</span><span>)]} </span><span>function</span><span> </span><span>e</span><span>() {</span><span>return</span><span><span> </span><span>String</span><span>.</span></span><span>fromCharCode</span><span>(</span><span>94</span><span> </span><span>*</span><span><span> </span><span>Math</span><span>.</span></span><span>random</span><span>() </span><span>+</span><span> </span><span>33</span><span>)} </span><span>function</span><span> </span><span>n</span><span><span>(</span><span>r</span><span>) {</span></span><span>for</span><span> (</span><span>var</span><span><span> </span><span>n</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createDocumentFragment</span><span><span>(), </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>r</span><span> </span></span><span>&gt;</span><span><span> </span><span>i</span><span>; </span><span>i</span></span><span>++</span><span>) { </span><span>var</span><span><span> </span><span>l</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>createElement</span><span>(</span><span>"span"</span><span><span>); </span><span>l</span><span>.</span></span><span>textContent</span><span> </span><span>=</span><span> </span><span>e</span><span><span>(), </span><span>l</span><span>.</span></span><span>style</span><span>.</span><span>color</span><span> </span><span>=</span><span> </span><span>t</span><span><span>(), </span><span>n</span><span>.</span></span><span>appendChild</span><span><span>(</span><span>l</span><span>) } </span></span><span>return</span><span><span> </span><span>n</span><span>}</span></span><span>function</span><span> </span><span>i</span><span>() {</span><span>var</span><span><span> </span><span>t</span><span> </span></span><span>=</span><span><span> </span><span>o</span><span>[</span><span>c</span><span>.</span></span><span>skillI</span><span><span>]; </span><span>c</span><span>.</span></span><span>step</span><span> </span><span>?</span><span><span> </span><span>c</span><span>.</span></span><span>step</span><span>--</span><span> </span><span>:</span><span><span> (</span><span>c</span><span>.</span></span><span>step</span><span> </span><span>=</span><span><span> </span><span>g</span><span>, </span><span>c</span><span>.</span></span><span>prefixP</span><span> </span><span>&lt;</span><span><span> </span><span>l</span><span>.</span></span><span>length</span><span> </span><span>?</span><span><span> (</span><span>c</span><span>.</span></span><span>prefixP</span><span> </span><span>&gt;=</span><span> </span><span>0</span><span> </span><span>&amp;&amp;</span><span><span> (</span><span>c</span><span>.</span></span><span>text</span><span> </span><span>+=</span><span><span> </span><span>l</span><span>[</span><span>c</span><span>.</span></span><span>prefixP</span><span><span>]), </span><span>c</span><span>.</span></span><span>prefixP</span><span>++</span><span>) </span><span>:</span><span> </span><span>"forward"</span><span> </span><span>===</span><span><span> </span><span>c</span><span>.</span></span><span>direction</span><span> </span><span>?</span><span><span> </span><span>c</span><span>.</span></span><span>skillP</span><span> </span><span>&lt;</span><span><span> </span><span>t</span><span>.</span></span><span>length</span><span> </span><span>?</span><span><span> (</span><span>c</span><span>.</span></span><span>text</span><span> </span><span>+=</span><span><span> </span><span>t</span><span>[</span><span>c</span><span>.</span></span><span>skillP</span><span><span>], </span><span>c</span><span>.</span></span><span>skillP</span><span>++</span><span>) </span><span>:</span><span><span> </span><span>c</span><span>.</span></span><span>delay</span><span> </span><span>?</span><span><span> </span><span>c</span><span>.</span></span><span>delay</span><span>--</span><span> </span><span>:</span><span><span> (</span><span>c</span><span>.</span></span><span>direction</span><span> </span><span>=</span><span> </span><span>"backward"</span><span><span>, </span><span>c</span><span>.</span></span><span>delay</span><span> </span><span>=</span><span><span> </span><span>a</span><span>) </span></span><span>:</span><span><span> </span><span>c</span><span>.</span></span><span>skillP</span><span> </span><span>&gt;</span><span> </span><span>0</span><span> </span><span>?</span><span><span> (</span><span>c</span><span>.</span></span><span>text</span><span> </span><span>=</span><span><span> </span><span>c</span><span>.</span></span><span>text</span><span>.</span><span>slice</span><span>(</span><span>0</span><span>, </span><span>-</span><span>1</span><span><span>), </span><span>c</span><span>.</span></span><span>skillP</span><span>--</span><span>) </span><span>:</span><span><span> (</span><span>c</span><span>.</span></span><span>skillI</span><span> </span><span>=</span><span><span> (</span><span>c</span><span>.</span></span><span>skillI</span><span> </span><span>+</span><span> </span><span>1</span><span>) </span><span>%</span><span><span> </span><span>o</span><span>.</span></span><span>length</span><span><span>, </span><span>c</span><span>.</span></span><span>direction</span><span> </span><span>=</span><span> </span><span>"forward"</span><span><span>)), </span><span>r</span><span>.</span></span><span>textContent</span><span> </span><span>=</span><span><span> </span><span>c</span><span>.</span></span><span>text</span><span><span>, </span><span>r</span><span>.</span></span><span>appendChild</span><span>(</span><span>n</span><span><span>(</span><span>c</span><span>.</span></span><span>prefixP</span><span> </span><span>&lt;</span><span><span> </span><span>l</span><span>.</span></span><span>length</span><span> </span><span>?</span><span><span> </span><span>Math</span><span>.</span></span><span>min</span><span><span>(</span><span>s</span><span>, </span><span>s</span><span> </span></span><span>+</span><span><span> </span><span>c</span><span>.</span></span><span>prefixP</span><span>) </span><span>:</span><span><span> </span><span>Math</span><span>.</span></span><span>min</span><span><span>(</span><span>s</span><span>, </span><span>t</span><span>.</span></span><span>length</span><span> </span><span>-</span><span><span> </span><span>c</span><span>.</span></span><span>skillP</span><span>))), </span><span>setTimeout</span><span><span>(</span><span>i</span><span>, </span><span>d</span><span>) } </span></span><span>/*以下内容自定义修改*/</span><span> </span><span>var</span><span><span> </span><span>l</span><span> </span></span><span>=</span><span> </span><span>""</span><span><span>, </span><span>o</span><span> </span></span><span>=</span><span> [</span><span>"Keep Fighting"</span><span> ].</span><span>map</span><span>(</span><span>function</span><span><span> (</span><span>r</span><span>) {</span></span><span>return</span><span><span> </span><span>r</span><span> </span></span><span>+</span><span> </span><span>""</span><span><span>}), </span><span>a</span><span> </span></span><span>=</span><span> </span><span>2</span><span><span>, </span><span>g</span><span> </span></span><span>=</span><span> </span><span>1</span><span><span>, </span><span>s</span><span> </span></span><span>=</span><span> </span><span>5</span><span><span>, </span><span>d</span><span> </span></span><span>=</span><span> </span><span>75</span><span><span>, </span><span>b</span><span> </span></span><span>=</span><span> [</span><span>"rgb(110,64,170)"</span><span>, </span><span>"rgb(150,61,179)"</span><span>, </span><span>"rgb(191,60,175)"</span><span>, </span><span>"rgb(228,65,157)"</span><span>, </span><span>"rgb(254,75,131)"</span><span>, </span><span>"rgb(255,94,99)"</span><span>, </span><span>"rgb(255,120,71)"</span><span>, </span><span>"rgb(251,150,51)"</span><span>, </span><span>"rgb(226,183,47)"</span><span>, </span><span>"rgb(198,214,60)"</span><span>, </span><span>"rgb(175,240,91)"</span><span>, </span><span>"rgb(127,246,88)"</span><span>, </span><span>"rgb(82,246,103)"</span><span>, </span><span>"rgb(48,239,130)"</span><span>, </span><span>"rgb(29,223,163)"</span><span>, </span><span>"rgb(26,199,194)"</span><span>, </span><span>"rgb(35,171,216)"</span><span>, </span><span>"rgb(54,140,225)"</span><span>, </span><span>"rgb(76,110,219)"</span><span>, </span><span>"rgb(96,84,200)"</span><span><span>], </span><span>c</span><span> </span></span><span>=</span><span> {</span><span>text</span><span>:</span><span> </span><span>""</span><span>, </span><span>prefixP</span><span>:</span><span> </span><span>-</span><span><span>s</span><span>, </span></span><span>skillI</span><span>:</span><span> </span><span>0</span><span>, </span><span>skillP</span><span>:</span><span> </span><span>0</span><span>, </span><span>direction</span><span>:</span><span> </span><span>"forward"</span><span>, </span><span>delay</span><span>:</span><span><span> </span><span>a</span><span>, </span></span><span>step</span><span>:</span><span><span> </span><span>g</span><span>}; </span></span><span>i</span><span>() }; </span><span>chakhsu</span><span><span>(</span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'chakhsu'</span><span>)); &lt;/</span><span>script</span><span>&gt; &lt;/</span><span>span</span><span>&gt; &lt;/</span><span>span</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>0x06 复制提示特效<a href="#0x06-复制提示特效"><span>#</span></a></h2><p>添加代码至<code>自定义js</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>script</span><span> </span><span>defer</span><span> </span><span>src</span><span>=</span><span>"https://cdn.staticfile.org/limonte-sweetalert2/8.11.8/sweetalert2.all.min.js"</span><span>&gt;&lt;/</span><span>script</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>document</span><span>.</span></span><span>body</span><span>.</span><span>oncopy</span><span> </span><span>=</span><span> </span><span>function</span><span><span>(){</span><span>Swal</span><span>.</span></span><span>fire</span><span>({</span><span>allowOutsideClick</span><span>:</span><span>false</span><span>,</span><span>type</span><span>:</span><span>'success'</span><span>,</span><span>title</span><span>:</span><span> </span><span>'复制成功,如转载请注明出处！'</span><span>,</span><span>showConfirmButton</span><span>:</span><span> </span><span>false</span><span>,</span><span>timer</span><span>:</span><span> </span><span>2000</span><span>});};</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>0x07 文章底部赞赏图标跳动<a href="#0x07-文章底部赞赏图标跳动"><span>#</span></a></h2><p>添加代码至<code>自定义css</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/*赞赏图标跳动*/</span></div></div><div><div><div>2</div></div><div><span>.btn-pay</span><span> {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>animation: star </span><span><span>0.5</span><span>s</span></span><span><span> </span><span>ease-in-out</span><span> </span><span>infinite</span><span> </span><span>alternate</span><span>;</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>@keyframes</span><span><span> </span><span>star</span><span> {</span></span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>from {</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>transform: </span><span>scale</span><span>(</span><span>1</span><span>);</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>to {</span></div></div><div><div><div>12</div></div><div><span><span>        </span></span><span>transform: </span><span>scale</span><span>(</span><span>1.1</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>0x07 彩色标签云<a href="#0x07-彩色标签云"><span>#</span></a></h2><p>添加至<code>自定义js</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>let</span><span><span> </span><span>tags</span><span> </span></span><span>=</span><span><span> </span><span>document</span><span>.</span></span><span>querySelectorAll</span><span>(</span><span>"#tag_cloud-2 a"</span><span>);</span></div></div><div><div><div>2</div></div><div><span>let</span><span><span> </span><span>colorArr</span><span> </span></span><span>=</span><span> [</span><span>"#428BCA"</span><span>, </span><span>"#AEDCAE"</span><span>, </span><span>"#ECA9A7"</span><span>, </span><span>"#DA99FF"</span><span>, </span><span>"#FFB380"</span><span>, </span><span>"#D9B999"</span><span>];</span></div></div><div><div><div>3</div></div><div><span><span>tags</span><span>.</span></span><span>forEach</span><span><span>(</span><span>tag</span><span> </span></span><span>=&gt;</span><span> {</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>tagsColor</span><span> </span><span>=</span><span><span> </span><span>colorArr</span><span>[</span><span>Math</span><span>.</span></span><span>floor</span><span><span>(</span><span>Math</span><span>.</span></span><span>random</span><span>() </span><span>*</span><span><span> </span><span>colorArr</span><span>.</span></span><span>length</span><span>)];</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>tag</span><span>.</span><span>style</span><span>.</span><span>backgroundColor</span><span> </span><span>=</span><span><span> </span><span>tagsColor</span><span>;</span></span></div></div><div><div><div>6</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果主题中启用了pjax，还需要将上面代码添加到pjax-pjax回调函数中</p></section>
<section><h2>0x08 首页文章列表悬停上浮<a href="#0x08-首页文章列表悬停上浮"><span>#</span></a></h2><p>添加至<code>自定义CSS</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.blog-post</span><span> </span><span><span>.panel</span><span>:not</span></span><span>(</span><span>article</span><span>)</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>transition: </span><span>all</span><span> </span><span><span>0.3</span><span>s</span></span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.blog-post</span><span> </span><span><span>.panel</span><span>:not</span></span><span>(</span><span>article</span><span>)</span><span>:hover</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>transform: </span><span>translateY</span><span>(</span><span><span>-10</span><span>px</span></span><span>);</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>box-shadow: </span><span>0</span><span> </span><span><span>8</span><span>px</span></span><span> </span><span><span>10</span><span>px</span></span><span> </span><span>rgba</span><span>(</span><span>73</span><span>, </span><span>90</span><span>, </span><span>47</span><span>, </span><span>0.47</span><span>);</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>0x09 首页文章列表头图悬停放大并将超出范围隐藏<a href="#0x09-首页文章列表头图悬停放大并将超出范围隐藏"><span>#</span></a></h2><p>添加至<code>自定义CSS</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.index-post-img</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>overflow: </span><span>hidden</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>.item-thumb</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>transition: </span><span>all</span><span> </span><span><span>0.3</span><span>s</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>.item-thumb</span><span>:hover</span></span><span> {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>transform: </span><span>scale</span><span>(</span><span>1.1</span><span>)</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>0x10 文章内头图和文章图片悬停放大并将超出范围隐藏<a href="#0x10-文章内头图和文章图片悬停放大并将超出范围隐藏"><span>#</span></a></h2><p>添加代码至<code>自定义CSS</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.entry-thumbnail</span><span> {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>overflow: </span><span>hidden</span><span>;</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>#post-content</span><span> </span><span>img</span><span> {</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>border-radius: </span><span><span>10</span><span>px</span></span><span>;</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>transition: </span><span><span>0.5</span><span>s</span></span><span>;</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>#post-content</span><span> </span><span>img</span><span>:hover</span><span> {</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>transform: </span><span>scale</span><span>(</span><span>1.05</span><span>);</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h2>0x11 使用qq头像<a href="#0x11-使用qq头像"><span>#</span></a></h2><p><code>https://q1.qlogo.cn/g?b=qq&amp;nk=1033853263&amp;s=640</code>
改为自己的qq号即可</p></section>
<section><h2>0x12 Markdown 编辑器 Editor.md for Typecho<a href="#0x12-markdown-编辑器-editormd-for-typecho"><span>#</span></a></h2><p><a href="https://dt27.org/php/editormd-for-typecho/" target="_blank">作者页面</a></p></section>
<section><h2>0x13 LoveKKComment-Typecho评论邮件提醒插件<a href="#0x13-lovekkcomment-typecho评论邮件提醒插件"><span>#</span></a></h2><p><a href="https://qqdie.com/archives/lovekkcomment-typecho-plugin.html" target="_blank">作者页面</a></p></section>
<section><h2>0x14 更换网站光标<a href="#0x14-更换网站光标"><span>#</span></a></h2><p>添加css代码：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/** 鼠标样式 开始**/</span></div></div><div><div><div>2</div></div><div><span>/** 普通指针样式**/</span></div></div><div><div><div>3</div></div><div><span>body</span><span> {</span></div></div><div><div><div>4</div></div><div><span>cursor: </span><span>url</span><span><span>(</span><span>https://rehtt.com/css/光标/S1.cur</span><span>), </span><span>default</span><span>;</span></span></div></div><div><div><div>5</div></div><div><span>}</span></div></div><div><div><div>6</div></div><div><span>/** 链接指针样式**/</span></div></div><div><div><div>7</div></div><div><span>a</span><span>:hover</span><span>{cursor:</span><span>url</span><span><span>(</span><span>https://rehtt.com/css/光标/S2.cur</span><span>), </span><span>pointer</span><span>;}</span></span></div></div><div><div><div>8</div></div><div><span>/** 鼠标样式 结束**/</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>光标文件：
<a href="4">指针</a>
<a href="5">链接指针</a></p></section>
<section><h2>0x15 鼠标点击特效<a href="#0x15-鼠标点击特效"><span>#</span></a></h2><p><img alt="" loading="lazy" width="588" height="336" src="/_astro/193.4.Ds_LMPG-_2eoLvn.webp" />
js代码：</p><div><div><div></div><div>Caution</div></div><div><p>代码中包含了sketch.min.js的源码，如果你的网站已经引用了，请删掉下面的6到7行。</p></div></div><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/*</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>* 鼠标点击特效，canvas点击效果，第二版</span></div></div><div><div><div>3</div></div><div><span><span> </span></span><span>* 原文地址：https://www.iowen.cn/canvas-click-effect-second-edition</span></div></div><div><div><div>4</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>/* Copyright (C) 2013 Justin Windle sketch.min.js, http://soulwire.co.uk */</span></div></div><div><div><div>7</div></div><div><span>var</span><span> </span><span>Sketch</span><span>=</span><span>function</span><span>(){</span><span>"use strict"</span><span>;</span><span>function</span><span> </span><span>e</span><span><span>(</span><span>e</span><span>){</span></span><span>return</span><span>"[object Array]"</span><span>==</span><span>Object</span><span>.</span><span>prototype</span><span>.</span><span>toString</span><span>.</span><span>call</span><span><span>(</span><span>e</span><span>)}</span></span><span>function</span><span> </span><span>t</span><span><span>(</span><span>e</span><span>){</span></span><span>return</span><span>"function"</span><span><span>==</span><span>typeof</span></span><span><span> </span><span>e</span><span>}</span></span><span>function</span><span> </span><span>n</span><span><span>(</span><span>e</span><span>){</span></span><span>return</span><span>"number"</span><span><span>==</span><span>typeof</span></span><span><span> </span><span>e</span><span>}</span></span><span>function</span><span> </span><span>o</span><span><span>(</span><span>e</span><span>){</span></span><span>return</span><span>"string"</span><span><span>==</span><span>typeof</span></span><span><span> </span><span>e</span><span>}</span></span><span>function</span><span> </span><span>r</span><span><span>(</span><span>e</span><span>){</span></span><span>return</span><span> </span><span>E</span><span><span>[</span><span>e</span><span>]</span></span><span>||</span><span><span>String</span><span>.</span></span><span>fromCharCode</span><span><span>(</span><span>e</span><span>)}</span></span><span>function</span><span> </span><span>i</span><span><span>(</span><span>e</span><span>,</span><span>t</span><span>,</span><span>n</span><span>){</span></span><span>for</span><span>(</span><span>var</span><span><span> </span><span>o</span><span> </span></span><span>in</span><span><span> </span><span>t</span><span>)(</span><span>n</span></span><span>||!</span><span><span>e</span><span>.</span></span><span>hasOwnProperty</span><span><span>(</span><span>o</span><span>))</span></span><span>&amp;&amp;</span><span><span>(</span><span>e</span><span>[</span><span>o</span><span>]</span></span><span>=</span><span><span>t</span><span>[</span><span>o</span><span>]);</span></span><span>return</span><span><span> </span><span>e</span><span>}</span></span><span>function</span><span> </span><span>u</span><span><span>(</span><span>e</span><span>,</span><span>t</span><span>){</span></span><span>return</span><span> </span><span>function</span><span><span>(){</span><span>e</span><span>.</span></span><span>apply</span><span><span>(</span><span>t</span><span>,</span></span><span>arguments</span><span>)}}</span><span>function</span><span> </span><span>a</span><span><span>(</span><span>e</span><span>){</span></span><span>var</span><span><span> </span><span>n</span></span><span>=</span><span>{};</span><span>for</span><span>(</span><span>var</span><span><span> </span><span>o</span><span> </span></span><span>in</span><span><span> </span><span>e</span><span>)</span><span>n</span><span>[</span><span>o</span><span>]</span></span><span>=</span><span>t</span><span><span>(</span><span>e</span><span>[</span><span>o</span><span>])</span></span><span>?</span><span>u</span><span><span>(</span><span>e</span><span>[</span><span>o</span><span>],</span><span>e</span><span>)</span></span><span>:</span><span><span>e</span><span>[</span><span>o</span><span>];</span></span><span>return</span><span><span> </span><span>n</span><span>}</span></span><span>function</span><span> </span><span>c</span><span><span>(</span><span>e</span><span>){</span></span><span>function</span><span> </span><span>n</span><span><span>(</span><span>n</span><span>){</span></span><span>t</span><span><span>(</span><span>n</span><span>)</span></span><span>&amp;&amp;</span><span><span>n</span><span>.</span></span><span>apply</span><span><span>(</span><span>e</span><span>,[].</span></span><span>splice</span><span>.</span><span>call</span><span>(</span><span>arguments</span><span>,</span><span>1</span><span>))}</span><span>function</span><span> </span><span>u</span><span><span>(</span><span>e</span><span>){</span></span><span>for</span><span><span>(</span><span>_</span></span><span>=</span><span>0</span><span><span>;</span><span>_</span></span><span>&lt;</span><span>J</span><span>.</span><span>length</span><span><span>;</span><span>_</span></span><span>++</span><span>)</span><span>G</span><span>=</span><span>J</span><span><span>[</span><span>_</span><span>],</span></span><span>o</span><span>(</span><span>G</span><span>)</span><span>?</span><span>O</span><span><span>[(</span><span>e</span></span><span>?</span><span>"add"</span><span>:</span><span>"remove"</span><span>)</span><span>+</span><span>"EventListener"</span><span>].</span><span>call</span><span>(</span><span>O</span><span>,</span><span>G</span><span><span>,</span><span>k</span><span>,</span></span><span>!</span><span>1</span><span>)</span><span>:</span><span>t</span><span>(</span><span>G</span><span>)</span><span>?</span><span>k</span><span>=</span><span>G</span><span>:</span><span>O</span><span>=</span><span>G</span><span>}</span><span>function</span><span> </span><span>c</span><span>(){</span><span>L</span><span>(</span><span>T</span><span>),</span><span>T</span><span>=</span><span>I</span><span><span>(</span><span>c</span><span>),</span></span><span>U</span><span>||</span><span>(</span><span>n</span><span><span>(</span><span>e</span><span>.</span></span><span>setup</span><span>),</span><span>U</span><span>=</span><span>t</span><span><span>(</span><span>e</span><span>.</span></span><span>setup</span><span>),</span><span>n</span><span><span>(</span><span>e</span><span>.</span></span><span>resize</span><span><span>)),</span><span>e</span><span>.</span></span><span>running</span><span>&amp;&amp;!</span><span>j</span><span>&amp;&amp;</span><span><span>(</span><span>e</span><span>.</span></span><span>dt</span><span>=</span><span>(</span><span>B</span><span>=+</span><span>new</span><span><span> </span><span>Date</span><span>)</span></span><span>-</span><span><span>e</span><span>.</span></span><span>now</span><span><span>,</span><span>e</span><span>.</span></span><span>millis</span><span>+=</span><span><span>e</span><span>.</span></span><span>dt</span><span><span>,</span><span>e</span><span>.</span></span><span>now</span><span>=</span><span>B</span><span>,</span><span>n</span><span><span>(</span><span>e</span><span>.</span></span><span>update</span><span><span>),</span><span>e</span><span>.</span></span><span>autoclear</span><span>&amp;&amp;</span><span>K</span><span>&amp;&amp;</span><span><span>e</span><span>.</span></span><span>clear</span><span>(),</span><span>n</span><span><span>(</span><span>e</span><span>.</span></span><span>draw</span><span><span>)),</span><span>j</span></span><span>=++</span><span>j</span><span>%</span><span><span>e</span><span>.</span></span><span>interval</span><span>}</span><span>function</span><span> </span><span>l</span><span>(){</span><span>O</span><span>=</span><span>Y</span><span>?</span><span><span>e</span><span>.</span></span><span>style</span><span>:</span><span><span>e</span><span>.</span></span><span>canvas</span><span>,</span><span>D</span><span>=</span><span>Y</span><span>?</span><span>"px"</span><span>:</span><span>""</span><span><span>,</span><span>e</span><span>.</span></span><span>fullscreen</span><span>&amp;&amp;</span><span><span>(</span><span>e</span><span>.</span></span><span>height</span><span>=</span><span><span>w</span><span>.</span></span><span>innerHeight</span><span><span>,</span><span>e</span><span>.</span></span><span>width</span><span>=</span><span><span>w</span><span>.</span></span><span>innerWidth</span><span>),</span><span>O</span><span>.</span><span>height</span><span>=</span><span><span>e</span><span>.</span></span><span>height</span><span>+</span><span>D</span><span>,</span><span>O</span><span>.</span><span>width</span><span>=</span><span><span>e</span><span>.</span></span><span>width</span><span>+</span><span>D</span><span><span>,</span><span>e</span><span>.</span></span><span>retina</span><span>&amp;&amp;</span><span>K</span><span>&amp;&amp;</span><span>X</span><span>&amp;&amp;</span><span>(</span><span>O</span><span>.</span><span>height</span><span>=</span><span><span>e</span><span>.</span></span><span>height</span><span>*</span><span>X</span><span>,</span><span>O</span><span>.</span><span>width</span><span>=</span><span><span>e</span><span>.</span></span><span>width</span><span>*</span><span>X</span><span>,</span><span>O</span><span>.</span><span>style</span><span>.</span><span>height</span><span>=</span><span><span>e</span><span>.</span></span><span>height</span><span>+</span><span>"px"</span><span>,</span><span>O</span><span>.</span><span>style</span><span>.</span><span>width</span><span>=</span><span><span>e</span><span>.</span></span><span>width</span><span>+</span><span>"px"</span><span><span>,</span><span>e</span><span>.</span></span><span>scale</span><span>(</span><span>X</span><span>,</span><span>X</span><span>)),</span><span>U</span><span>&amp;&amp;</span><span>n</span><span><span>(</span><span>e</span><span>.</span></span><span>resize</span><span>)}</span><span>function</span><span> </span><span>s</span><span><span>(</span><span>e</span><span>,</span><span>t</span><span>){</span></span><span>return</span><span> </span><span>N</span><span>=</span><span><span>t</span><span>.</span></span><span>getBoundingClientRect</span><span><span>(),</span><span>e</span><span>.</span></span><span>x</span><span>=</span><span><span>e</span><span>.</span></span><span>pageX</span><span>-</span><span>N</span><span>.</span><span>left</span><span>-</span><span><span>w</span><span>.</span></span><span>scrollX</span><span><span>,</span><span>e</span><span>.</span></span><span>y</span><span>=</span><span><span>e</span><span>.</span></span><span>pageY</span><span>-</span><span>N</span><span>.</span><span>top</span><span>-</span><span><span>w</span><span>.</span></span><span>scrollY</span><span><span>,</span><span>e</span><span>}</span></span><span>function</span><span> </span><span>f</span><span><span>(</span><span>t</span><span>,</span><span>n</span><span>){</span></span><span>return</span><span> </span><span>s</span><span><span>(</span><span>t</span><span>,</span><span>e</span><span>.</span></span><span>element</span><span><span>),</span><span>n</span></span><span>=</span><span>n</span><span>||</span><span><span>{},</span><span>n</span><span>.</span></span><span>ox</span><span>=</span><span><span>n</span><span>.</span></span><span>x</span><span>||</span><span><span>t</span><span>.</span></span><span>x</span><span><span>,</span><span>n</span><span>.</span></span><span>oy</span><span>=</span><span><span>n</span><span>.</span></span><span>y</span><span>||</span><span><span>t</span><span>.</span></span><span>y</span><span><span>,</span><span>n</span><span>.</span></span><span>x</span><span>=</span><span><span>t</span><span>.</span></span><span>x</span><span><span>,</span><span>n</span><span>.</span></span><span>y</span><span>=</span><span><span>t</span><span>.</span></span><span>y</span><span><span>,</span><span>n</span><span>.</span></span><span>dx</span><span>=</span><span><span>n</span><span>.</span></span><span>x</span><span>-</span><span><span>n</span><span>.</span></span><span>ox</span><span><span>,</span><span>n</span><span>.</span></span><span>dy</span><span>=</span><span><span>n</span><span>.</span></span><span>y</span><span>-</span><span><span>n</span><span>.</span></span><span>oy</span><span><span>,</span><span>n</span><span>}</span></span><span>function</span><span> </span><span>g</span><span><span>(</span><span>e</span><span>){</span></span><span>if</span><span><span>(</span><span>e</span><span>.</span></span><span>preventDefault</span><span>(),</span><span>W</span><span>=</span><span>a</span><span><span>(</span><span>e</span><span>),</span></span><span>W</span><span>.</span><span>originalEvent</span><span>=</span><span><span>e</span><span>,</span></span><span>W</span><span>.</span><span>touches</span><span>)</span><span>for</span><span>(</span><span>M</span><span>.</span><span>length</span><span>=</span><span>W</span><span>.</span><span>touches</span><span>.</span><span>length</span><span><span>,</span><span>_</span></span><span>=</span><span>0</span><span><span>;</span><span>_</span></span><span>&lt;</span><span>W</span><span>.</span><span>touches</span><span>.</span><span>length</span><span><span>;</span><span>_</span></span><span>++</span><span>)</span><span>M</span><span><span>[</span><span>_</span><span>]</span></span><span>=</span><span>f</span><span>(</span><span>W</span><span>.</span><span>touches</span><span><span>[</span><span>_</span><span>],</span></span><span>M</span><span><span>[</span><span>_</span><span>]);</span></span><span>else</span><span> </span><span>M</span><span>.</span><span>length</span><span>=</span><span>0</span><span>,</span><span>M</span><span>[</span><span>0</span><span>]</span><span>=</span><span>f</span><span>(</span><span>W</span><span>,</span><span>V</span><span>);</span><span>return</span><span> </span><span>i</span><span>(</span><span>V</span><span>,</span><span>M</span><span>[</span><span>0</span><span>],</span><span>!</span><span>0</span><span>),</span><span>W</span><span>}</span><span>function</span><span> </span><span>h</span><span><span>(</span><span>t</span><span>){</span></span><span>for</span><span><span>(</span><span>t</span></span><span>=</span><span>g</span><span><span>(</span><span>t</span><span>),</span><span>q</span></span><span>=</span><span>(</span><span>Q</span><span>=</span><span>J</span><span>.</span><span>indexOf</span><span><span>(</span><span>z</span></span><span>=</span><span><span>t</span><span>.</span></span><span>type</span><span>))</span><span>-</span><span>1</span><span><span>,</span><span>e</span><span>.</span></span><span>dragging</span><span>=</span><span><span>/down</span><span>|</span><span>start/</span></span><span>.</span><span>test</span><span><span>(</span><span>z</span><span>)</span></span><span><span>?</span><span>!</span></span><span>0</span><span>:</span><span><span>/up</span><span>|</span><span>end/</span></span><span>.</span><span>test</span><span><span>(</span><span>z</span><span>)</span></span><span><span>?</span><span>!</span></span><span>1</span><span>:</span><span><span>e</span><span>.</span></span><span>dragging</span><span><span>;</span><span>q</span><span>;)</span></span><span>o</span><span>(</span><span>J</span><span><span>[</span><span>q</span><span>])</span></span><span>?</span><span>n</span><span><span>(</span><span>e</span><span>[</span></span><span>J</span><span><span>[</span><span>q</span></span><span>--</span><span><span>]],</span><span>t</span><span>)</span></span><span>:</span><span>o</span><span>(</span><span>J</span><span>[</span><span>Q</span><span>])</span><span>?</span><span>n</span><span><span>(</span><span>e</span><span>[</span></span><span>J</span><span>[</span><span>Q</span><span>++</span><span><span>]],</span><span>t</span><span>)</span></span><span>:</span><span>q</span><span>=</span><span>0</span><span>}</span><span>function</span><span> </span><span>p</span><span><span>(</span><span>t</span><span>){</span></span><span>F</span><span>=</span><span><span>t</span><span>.</span></span><span>keyCode</span><span>,</span><span>H</span><span>=</span><span>"keyup"</span><span>==</span><span><span>t</span><span>.</span></span><span>type</span><span>,</span><span>Z</span><span>[</span><span>F</span><span>]</span><span>=</span><span>Z</span><span>[</span><span>r</span><span>(</span><span>F</span><span>)]</span><span>=!</span><span>H</span><span>,</span><span>n</span><span><span>(</span><span>e</span><span>[</span><span>t</span><span>.</span></span><span>type</span><span><span>],</span><span>t</span><span>)}</span></span><span>function</span><span> </span><span>v</span><span><span>(</span><span>t</span><span>){</span><span>e</span><span>.</span></span><span>autopause</span><span>&amp;&amp;</span><span>(</span><span>"blur"</span><span>==</span><span><span>t</span><span>.</span></span><span>type</span><span>?</span><span>b</span><span>:</span><span>C</span><span>)(),</span><span>n</span><span><span>(</span><span>e</span><span>[</span><span>t</span><span>.</span></span><span>type</span><span><span>],</span><span>t</span><span>)}</span></span><span>function</span><span> </span><span>C</span><span><span>(){</span><span>e</span><span>.</span></span><span>now</span><span>=+</span><span>new</span><span><span> </span><span>Date</span><span>,</span><span>e</span><span>.</span></span><span>running</span><span>=!</span><span>0</span><span>}</span><span>function</span><span> </span><span>b</span><span><span>(){</span><span>e</span><span>.</span></span><span>running</span><span>=!</span><span>1</span><span>}</span><span>function</span><span> </span><span>P</span><span><span>(){(</span><span>e</span><span>.</span></span><span>running</span><span>?</span><span>b</span><span>:</span><span>C</span><span>)()}</span><span>function</span><span> </span><span>A</span><span>(){</span><span>K</span><span>&amp;&amp;</span><span><span>e</span><span>.</span></span><span>clearRect</span><span>(</span><span>0</span><span>,</span><span>0</span><span><span>,</span><span>e</span><span>.</span></span><span>width</span><span><span>,</span><span>e</span><span>.</span></span><span>height</span><span>)}</span><span>function</span><span> </span><span>S</span><span>(){</span><span>R</span><span>=</span><span><span>e</span><span>.</span></span><span>element</span><span>.</span><span>parentNode</span><span><span>,</span><span>_</span></span><span>=</span><span><span>x</span><span>.</span></span><span>indexOf</span><span><span>(</span><span>e</span><span>),</span></span><span>R</span><span>&amp;&amp;</span><span>R</span><span>.</span><span>removeChild</span><span><span>(</span><span>e</span><span>.</span></span><span>element</span><span>),</span><span>~</span><span>_</span><span>&amp;&amp;</span><span><span>x</span><span>.</span></span><span>splice</span><span><span>(</span><span>_</span><span>,</span></span><span>1</span><span>),</span><span>u</span><span>(</span><span>!</span><span>1</span><span>),</span><span>b</span><span>()}</span><span>var</span><span> </span><span>T</span><span><span>,</span><span>k</span><span>,</span></span><span>O</span><span>,</span><span>R</span><span>,</span><span>N</span><span><span>,</span><span>_</span><span>,</span></span><span>D</span><span>,</span><span>B</span><span>,</span><span>G</span><span>,</span><span>W</span><span><span>,</span><span>z</span><span>,</span></span><span>F</span><span>,</span><span>H</span><span><span>,</span><span>q</span><span>,</span></span><span>Q</span><span><span>,</span><span>j</span></span><span>=</span><span>0</span><span>,</span><span>M</span><span>=</span><span>[],</span><span>U</span><span>=!</span><span>1</span><span>,</span><span>X</span><span>=</span><span><span>w</span><span>.</span></span><span>devicePixelRatio</span><span>,</span><span>Y</span><span>=</span><span><span>e</span><span>.</span></span><span>type</span><span>==</span><span><span>m</span><span>,</span></span><span>K</span><span>=</span><span><span>e</span><span>.</span></span><span>type</span><span>==</span><span><span>d</span><span>,</span></span><span>V</span><span>=</span><span>{</span><span>x</span><span>:</span><span>0</span><span>,</span><span>y</span><span>:</span><span>0</span><span>,</span><span>ox</span><span>:</span><span>0</span><span>,</span><span>oy</span><span>:</span><span>0</span><span>,</span><span>dx</span><span>:</span><span>0</span><span>,</span><span>dy</span><span>:</span><span>0</span><span>},</span><span>J</span><span>=</span><span><span>[</span><span>e</span><span>.</span></span><span>element</span><span><span>,</span><span>h</span><span>,</span></span><span>"mousedown"</span><span>,</span><span>"touchstart"</span><span><span>,</span><span>h</span><span>,</span></span><span>"mousemove"</span><span>,</span><span>"touchmove"</span><span><span>,</span><span>h</span><span>,</span></span><span>"mouseup"</span><span>,</span><span>"touchend"</span><span><span>,</span><span>h</span><span>,</span></span><span>"click"</span><span><span>,</span><span>y</span><span>,</span><span>p</span><span>,</span></span><span>"keydown"</span><span>,</span><span>"keyup"</span><span><span>,</span><span>w</span><span>,</span><span>v</span><span>,</span></span><span>"focus"</span><span>,</span><span>"blur"</span><span><span>,</span><span>l</span><span>,</span></span><span>"resize"</span><span>],</span><span>Z</span><span>=</span><span>{};</span><span>for</span><span>(</span><span>F</span><span> </span><span>in</span><span> </span><span>E</span><span>)</span><span>Z</span><span>[</span><span>E</span><span>[</span><span>F</span><span>]]</span><span>=!</span><span>1</span><span>;</span><span>return</span><span> </span><span>i</span><span><span>(</span><span>e</span><span>,{</span></span><span>touches</span><span>:</span><span>M</span><span>,</span><span>mouse</span><span>:</span><span>V</span><span>,</span><span>keys</span><span>:</span><span>Z</span><span>,</span><span>dragging</span><span><span>:</span><span>!</span></span><span>1</span><span>,</span><span>running</span><span><span>:</span><span>!</span></span><span>1</span><span>,</span><span>millis</span><span>:</span><span>0</span><span>,</span><span>now</span><span>:</span><span>0</span><span>/</span><span>0</span><span>,</span><span>dt</span><span>:</span><span>0</span><span>/</span><span>0</span><span>,</span><span>destroy</span><span>:</span><span>S</span><span>,</span><span>toggle</span><span>:</span><span>P</span><span>,</span><span>clear</span><span>:</span><span>A</span><span>,</span><span>start</span><span>:</span><span>C</span><span>,</span><span>stop</span><span>:</span><span><span>b</span><span>}),</span><span>x</span><span>.</span></span><span>push</span><span><span>(</span><span>e</span><span>),</span><span>e</span><span>.</span></span><span>autostart</span><span>&amp;&amp;</span><span>C</span><span>(),</span><span>u</span><span>(</span><span>!</span><span>0</span><span>),</span><span>l</span><span>(),</span><span>c</span><span><span>(),</span><span>e</span><span>}</span></span><span>for</span><span>(</span><span>var</span><span><span> </span><span>l</span><span>,</span><span>s</span><span>,</span><span>f</span></span><span>=</span><span>"E LN10 LN2 LOG2E LOG10E PI SQRT1_2 SQRT2 abs acos asin atan ceil cos exp floor log round sin sqrt tan atan2 pow max min"</span><span>.</span><span>split</span><span>(</span><span>" "</span><span><span>),</span><span>g</span></span><span>=</span><span>"__hasSketch"</span><span><span>,</span><span>h</span></span><span>=</span><span><span>Math</span><span>,</span><span>d</span></span><span>=</span><span>"canvas"</span><span><span>,</span><span>p</span></span><span>=</span><span>"webgl"</span><span><span>,</span><span>m</span></span><span>=</span><span>"dom"</span><span><span>,</span><span>y</span></span><span>=</span><span><span>document</span><span>,</span><span>w</span></span><span>=</span><span><span>window</span><span>,</span><span>x</span></span><span>=</span><span><span>[],</span><span>v</span></span><span>=</span><span>{</span><span>fullscreen</span><span><span>:</span><span>!</span></span><span>0</span><span>,</span><span>autostart</span><span><span>:</span><span>!</span></span><span>0</span><span>,</span><span>autoclear</span><span><span>:</span><span>!</span></span><span>0</span><span>,</span><span>autopause</span><span><span>:</span><span>!</span></span><span>0</span><span>,</span><span>container</span><span>:</span><span><span>y</span><span>.</span></span><span>body</span><span>,</span><span>interval</span><span>:</span><span>1</span><span>,</span><span>globals</span><span><span>:</span><span>!</span></span><span>0</span><span>,</span><span>retina</span><span><span>:</span><span>!</span></span><span>1</span><span>,</span><span>type</span><span>:</span><span><span>d</span><span>},</span></span><span>E</span><span>=</span><span>{</span><span>8</span><span>:</span><span>"BACKSPACE"</span><span>,</span><span>9</span><span>:</span><span>"TAB"</span><span>,</span><span>13</span><span>:</span><span>"ENTER"</span><span>,</span><span>16</span><span>:</span><span>"SHIFT"</span><span>,</span><span>27</span><span>:</span><span>"ESCAPE"</span><span>,</span><span>32</span><span>:</span><span>"SPACE"</span><span>,</span><span>37</span><span>:</span><span>"LEFT"</span><span>,</span><span>38</span><span>:</span><span>"UP"</span><span>,</span><span>39</span><span>:</span><span>"RIGHT"</span><span>,</span><span>40</span><span>:</span><span>"DOWN"</span><span>},</span><span>C</span><span>=</span><span>{</span><span>CANVAS</span><span>:</span><span><span>d</span><span>,</span></span><span>WEB_GL</span><span>:</span><span><span>p</span><span>,</span></span><span>WEBGL</span><span>:</span><span><span>p</span><span>,</span></span><span>DOM</span><span>:</span><span><span>m</span><span>,</span></span><span>instances</span><span>:</span><span><span>x</span><span>,</span></span><span>install</span><span>:</span><span>function</span><span><span>(</span><span>t</span><span>){</span></span><span>if</span><span>(</span><span>!</span><span><span>t</span><span>[</span><span>g</span><span>]){</span></span><span>for</span><span>(</span><span>var</span><span><span> </span><span>o</span></span><span>=</span><span>0</span><span><span>;</span><span>o</span></span><span>&lt;</span><span><span>f</span><span>.</span></span><span>length</span><span><span>;</span><span>o</span></span><span>++</span><span><span>)</span><span>t</span><span>[</span><span>f</span><span>[</span><span>o</span><span>]]</span></span><span>=</span><span><span>h</span><span>[</span><span>f</span><span>[</span><span>o</span><span>]];</span></span><span>i</span><span><span>(</span><span>t</span><span>,{</span></span><span>TWO_PI</span><span>:</span><span>2</span><span>*</span><span><span>h</span><span>.</span></span><span>PI</span><span>,</span><span>HALF_PI</span><span>:</span><span><span>h</span><span>.</span></span><span>PI</span><span>/</span><span>2</span><span>,</span><span>QUATER_PI</span><span>:</span><span><span>h</span><span>.</span></span><span>PI</span><span>/</span><span>4</span><span>,</span><span>random</span><span>:</span><span>function</span><span><span>(</span><span>t</span><span>,</span><span>o</span><span>){</span></span><span>return</span><span> </span><span>e</span><span><span>(</span><span>t</span><span>)</span></span><span>?</span><span><span>t</span><span>[</span></span><span>~~</span><span><span>(</span><span>h</span><span>.</span></span><span>random</span><span>()</span><span>*</span><span><span>t</span><span>.</span></span><span>length</span><span>)]</span><span>:</span><span>(</span><span>n</span><span><span>(</span><span>o</span><span>)</span></span><span>||</span><span><span>(</span><span>o</span></span><span>=</span><span>t</span><span>||</span><span>1</span><span><span>,</span><span>t</span></span><span>=</span><span>0</span><span><span>),</span><span>t</span></span><span>+</span><span><span>h</span><span>.</span></span><span>random</span><span>()</span><span>*</span><span><span>(</span><span>o</span></span><span>-</span><span><span>t</span><span>))},</span></span><span>lerp</span><span>:</span><span>function</span><span><span>(</span><span>e</span><span>,</span><span>t</span><span>,</span><span>n</span><span>){</span></span><span>return</span><span><span> </span><span>e</span></span><span>+</span><span>n</span><span>*</span><span><span>(</span><span>t</span></span><span>-</span><span><span>e</span><span>)},</span></span><span>map</span><span>:</span><span>function</span><span><span>(</span><span>e</span><span>,</span><span>t</span><span>,</span><span>n</span><span>,</span><span>o</span><span>,</span><span>r</span><span>){</span></span><span>return</span><span><span>(</span><span>e</span></span><span>-</span><span><span>t</span><span>)</span></span><span>/</span><span><span>(</span><span>n</span></span><span>-</span><span><span>t</span><span>)</span></span><span>*</span><span><span>(</span><span>r</span></span><span>-</span><span><span>o</span><span>)</span></span><span>+</span><span><span>o</span><span>}}),</span><span>t</span><span>[</span><span>g</span><span>]</span></span><span>=!</span><span>0</span><span>}},</span><span>create</span><span>:</span><span>function</span><span><span>(</span><span>e</span><span>){</span></span><span>return</span><span><span> </span><span>e</span></span><span>=</span><span>i</span><span><span>(</span><span>e</span></span><span>||</span><span><span>{},</span><span>v</span><span>),</span><span>e</span><span>.</span></span><span>globals</span><span>&amp;&amp;</span><span>C</span><span>.</span><span>install</span><span><span>(</span><span>self</span><span>),</span><span>l</span></span><span>=</span><span><span>e</span><span>.</span></span><span>element</span><span>=</span><span><span>e</span><span>.</span></span><span>element</span><span>||</span><span><span>y</span><span>.</span></span><span>createElement</span><span><span>(</span><span>e</span><span>.</span></span><span>type</span><span>===</span><span>m</span><span>?</span><span>"div"</span><span>:</span><span>"canvas"</span><span><span>),</span><span>s</span></span><span>=</span><span><span>e</span><span>.</span></span><span>context</span><span>=</span><span><span>e</span><span>.</span></span><span>context</span><span>||</span><span>function</span><span>(){</span><span>switch</span><span><span>(</span><span>e</span><span>.</span></span><span>type</span><span>){</span><span>case</span><span><span> </span><span>d</span><span>:</span></span><span>return</span><span><span> </span><span>l</span><span>.</span></span><span>getContext</span><span>(</span><span>"2d"</span><span><span>,</span><span>e</span><span>);</span></span><span>case</span><span><span> </span><span>p</span><span>:</span></span><span>return</span><span><span> </span><span>l</span><span>.</span></span><span>getContext</span><span>(</span><span>"webgl"</span><span><span>,</span><span>e</span><span>)</span></span><span>||</span><span><span>l</span><span>.</span></span><span>getContext</span><span>(</span><span>"experimental-webgl"</span><span><span>,</span><span>e</span><span>);</span></span><span>case</span><span><span> </span><span>m</span><span>:</span></span><span>return</span><span><span> </span><span>l</span><span>.</span></span><span>canvas</span><span>=</span><span><span>l</span><span>}}(),</span><span>e</span><span>.</span></span><span>container</span><span>.</span><span>appendChild</span><span><span>(</span><span>l</span><span>),</span></span><span>C</span><span>.</span><span>augment</span><span><span>(</span><span>s</span><span>,</span><span>e</span><span>)},</span></span><span>augment</span><span>:</span><span>function</span><span><span>(</span><span>e</span><span>,</span><span>t</span><span>){</span></span><span>return</span><span><span> </span><span>t</span></span><span>=</span><span>i</span><span><span>(</span><span>t</span></span><span>||</span><span><span>{},</span><span>v</span><span>),</span><span>t</span><span>.</span></span><span>element</span><span>=</span><span><span>e</span><span>.</span></span><span>canvas</span><span>||</span><span><span>e</span><span>,</span><span>t</span><span>.</span></span><span>element</span><span>.</span><span>className</span><span>+=</span><span>" sketch"</span><span>,</span><span>i</span><span><span>(</span><span>e</span><span>,</span><span>t</span><span>,</span></span><span>!</span><span>0</span><span>),</span><span>c</span><span><span>(</span><span>e</span><span>)}},</span><span>b</span></span><span>=</span><span>[</span><span>"ms"</span><span>,</span><span>"moz"</span><span>,</span><span>"webkit"</span><span>,</span><span>"o"</span><span>],</span><span>P</span><span>=</span><span><span>self</span><span>,</span></span><span>A</span><span>=</span><span>0</span><span>,</span><span>S</span><span>=</span><span>"AnimationFrame"</span><span>,</span><span>T</span><span>=</span><span>"request"</span><span>+</span><span>S</span><span><span>,</span><span>k</span></span><span>=</span><span>"cancel"</span><span>+</span><span>S</span><span>,</span><span>I</span><span>=</span><span>P</span><span>[</span><span>T</span><span>],</span><span>L</span><span>=</span><span>P</span><span><span>[</span><span>k</span><span>],</span></span><span>O</span><span>=</span><span>0</span><span>;</span><span>O</span><span>&lt;</span><span><span>b</span><span>.</span></span><span>length</span><span>&amp;&amp;!</span><span>I</span><span>;</span><span>O</span><span>++</span><span>)</span><span>I</span><span>=</span><span>P</span><span><span>[</span><span>b</span><span>[</span></span><span>O</span><span>]</span><span>+</span><span>"Request"</span><span>+</span><span>S</span><span>],</span><span>L</span><span>=</span><span>P</span><span><span>[</span><span>b</span><span>[</span></span><span>O</span><span>]</span><span>+</span><span>"Cancel"</span><span>+</span><span>T</span><span>];</span><span>return</span><span> </span><span>P</span><span>[</span><span>T</span><span>]</span><span>=</span><span>I</span><span>=</span><span>I</span><span>||</span><span>function</span><span><span>(</span><span>e</span><span>){</span></span><span>var</span><span><span> </span><span>t</span></span><span>=+</span><span>new</span><span><span> </span><span>Date</span><span>,</span><span>n</span></span><span>=</span><span><span>h</span><span>.</span></span><span>max</span><span>(</span><span>0</span><span>,</span><span>16</span><span>-</span><span><span>(</span><span>t</span></span><span>-</span><span>A</span><span><span>)),</span><span>o</span></span><span>=</span><span>setTimeout</span><span>(</span><span>function</span><span>(){</span><span>e</span><span><span>(</span><span>t</span></span><span>+</span><span><span>n</span><span>)},</span><span>n</span><span>);</span></span><span>return</span><span> </span><span>A</span><span>=</span><span>t</span><span>+</span><span><span>n</span><span>,</span><span>o</span><span>},</span></span><span>P</span><span><span>[</span><span>k</span><span>]</span></span><span>=</span><span>L</span><span>=</span><span>L</span><span>||</span><span>function</span><span><span>(</span><span>e</span><span>){</span></span><span>clearTimeout</span><span><span>(</span><span>e</span><span>)},</span></span><span>C</span><span>}();</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>//---</span></div></div><div><div><div>11</div></div><div><span>if</span><span><span>(</span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>"clickCanvas"</span><span>)) {</span></div></div><div><div><div>12</div></div><div><span>    </span><span>function</span><span> </span><span>Particle</span><span><span>(</span><span>x</span><span>, </span><span>y</span><span>, </span><span>radius</span><span>) {</span></span></div></div><div><div><div>13</div></div><div><span>        </span><span>this</span><span>.</span><span>init</span><span><span>(</span><span>x</span><span>, </span><span>y</span><span>, </span><span>radius</span><span>);</span></span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span>    </span><span>Particle</span><span>.</span><span>prototype</span><span> </span><span>=</span><span> {</span></div></div><div><div><div>16</div></div><div><span>        </span><span>init</span><span> </span><span>:</span><span> </span><span>function</span><span><span>(</span><span>x</span><span>, </span><span>y</span><span>, </span><span>radius</span><span>) {</span></span></div></div><div><div><div>17</div></div><div><span>            </span><span>this</span><span>.</span><span>alive</span><span> </span><span>=</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>18</div></div><div><span>            </span><span>this</span><span>.</span><span>radius</span><span> </span><span>=</span><span><span> </span><span>radius</span><span> </span></span><span>||</span><span> </span><span>10</span><span>;</span></div></div><div><div><div>19</div></div><div><span>            </span><span>this</span><span>.</span><span>wander</span><span> </span><span>=</span><span> </span><span>0.15</span><span>;</span></div></div><div><div><div>20</div></div><div><span>            </span><span>this</span><span>.</span><span>theta</span><span> </span><span>=</span><span> </span><span>random</span><span>(</span><span>TWO_PI</span><span>);</span></div></div><div><div><div>21</div></div><div><span>            </span><span>this</span><span>.</span><span>drag</span><span> </span><span>=</span><span> </span><span>0.92</span><span>;</span></div></div><div><div><div>22</div></div><div><span>            </span><span>this</span><span>.</span><span>color</span><span> </span><span>=</span><span> </span><span>'#ffeb3b'</span><span>;</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>            </span><span>this</span><span>.</span><span>x</span><span> </span><span>=</span><span><span> </span><span>x</span><span> </span></span><span>||</span><span> </span><span>0.0</span><span>;</span></div></div><div><div><div>25</div></div><div><span>            </span><span>this</span><span>.</span><span>y</span><span> </span><span>=</span><span><span> </span><span>y</span><span> </span></span><span>||</span><span> </span><span>0.0</span><span>;</span></div></div><div><div><div>26</div></div><div><span>            </span><span>this</span><span>.</span><span>vx</span><span> </span><span>=</span><span> </span><span>0.0</span><span>;</span></div></div><div><div><div>27</div></div><div><span>            </span><span>this</span><span>.</span><span>vy</span><span> </span><span>=</span><span> </span><span>0.0</span><span>;</span></div></div><div><div><div>28</div></div><div><span><span>        </span></span><span>},</span></div></div><div><div><div>29</div></div><div><span>        </span><span>move</span><span> </span><span>:</span><span> </span><span>function</span><span>() {</span></div></div><div><div><div>30</div></div><div><span>            </span><span>this</span><span>.</span><span>x</span><span> </span><span>+=</span><span> </span><span>this</span><span>.</span><span>vx</span><span>;</span></div></div><div><div><div>31</div></div><div><span>            </span><span>this</span><span>.</span><span>y</span><span> </span><span>+=</span><span> </span><span>this</span><span>.</span><span>vy</span><span>;</span></div></div><div><div><div>32</div></div><div><span>            </span><span>this</span><span>.</span><span>vx</span><span> </span><span>*=</span><span> </span><span>this</span><span>.</span><span>drag</span><span>;</span></div></div><div><div><div>33</div></div><div><span>            </span><span>this</span><span>.</span><span>vy</span><span> </span><span>*=</span><span> </span><span>this</span><span>.</span><span>drag</span><span>;</span></div></div><div><div><div>34</div></div><div><span>            </span><span>this</span><span>.</span><span>theta</span><span> </span><span>+=</span><span> </span><span>random</span><span>(</span><span>-</span><span>0.5</span><span>, </span><span>0.5</span><span>) </span><span>*</span><span> </span><span>this</span><span>.</span><span>wander</span><span>;</span></div></div><div><div><div>35</div></div><div><span>            </span><span>this</span><span>.</span><span>vx</span><span> </span><span>+=</span><span> </span><span>sin</span><span>(</span><span>this</span><span>.</span><span>theta</span><span>) </span><span>*</span><span> </span><span>0.1</span><span>;</span></div></div><div><div><div>36</div></div><div><span>            </span><span>this</span><span>.</span><span>vy</span><span> </span><span>+=</span><span> </span><span>cos</span><span>(</span><span>this</span><span>.</span><span>theta</span><span>) </span><span>*</span><span> </span><span>0.1</span><span>;</span></div></div><div><div><div>37</div></div><div><span>            </span><span>this</span><span>.</span><span>radius</span><span> </span><span>*=</span><span> </span><span>0.96</span><span>;</span></div></div><div><div><div>38</div></div><div><span>            </span><span>this</span><span>.</span><span>alive</span><span> </span><span>=</span><span> </span><span>this</span><span>.</span><span>radius</span><span> </span><span>&gt;</span><span> </span><span>0.5</span><span>;</span></div></div><div><div><div>39</div></div><div><span><span>        </span></span><span>},</span></div></div><div><div><div>40</div></div><div><span>        </span><span>draw</span><span> </span><span>:</span><span> </span><span>function</span><span><span>(</span><span>ctx</span><span>) {</span></span></div></div><div><div><div>41</div></div><div><span><span>            </span></span><span>ctx</span><span>.</span><span>beginPath</span><span>();</span></div></div><div><div><div>42</div></div><div><span><span>            </span></span><span>ctx</span><span>.</span><span>arc</span><span>(</span><span>this</span><span>.</span><span>x</span><span>, </span><span>this</span><span>.</span><span>y</span><span>, </span><span>this</span><span>.</span><span>radius</span><span>, </span><span>0</span><span>, </span><span>TWO_PI</span><span>);</span></div></div><div><div><div>43</div></div><div><span><span>            </span></span><span>ctx</span><span>.</span><span>fillStyle</span><span> </span><span>=</span><span> </span><span>this</span><span>.</span><span>color</span><span>;</span></div></div><div><div><div>44</div></div><div><span><span>            </span></span><span>ctx</span><span>.</span><span>fill</span><span>();</span></div></div><div><div><div>45</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>46</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>47</div></div><div><span>    </span><span>var</span><span> </span><span>MAX_PARTICLES</span><span> </span><span>=</span><span> </span><span>50</span><span>;</span></div></div><div><div><div>48</div></div><div><span>    </span><span>//圆点颜色库</span></div></div><div><div><div>49</div></div><div><span>    </span><span>var</span><span> </span><span>COLOURS</span><span> </span><span>=</span><span> [ </span><span>"#5ee4ff"</span><span>, </span><span>"#f44033"</span><span>, </span><span>"#ffeb3b"</span><span>, </span><span>"#F38630"</span><span>, </span><span>"#FA6900"</span><span>, </span><span>"#f403e8"</span><span>, </span><span>"#F9D423"</span><span> ];</span></div></div><div><div><div>50</div></div><div><span>    </span><span>var</span><span><span> </span><span>particles</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>51</div></div><div><span>    </span><span>var</span><span><span> </span><span>pool</span><span> </span></span><span>=</span><span> [];</span></div></div><div><div><div>52</div></div><div><span>    </span><span>var</span><span><span> </span><span>clickparticle</span><span> </span></span><span>=</span><span><span> </span><span>Sketch</span><span>.</span></span><span>create</span><span>({</span></div></div><div><div><div>53</div></div><div><span>        </span><span>container </span><span>:</span><span><span> </span><span>document</span><span>.</span></span><span>getElementById</span><span>(</span><span>'clickCanvas'</span><span>)</span></div></div><div><div><div>54</div></div><div><span><span>    </span></span><span>});</span></div></div><div><div><div>55</div></div><div><span><span>    </span></span><span>clickparticle</span><span>.</span><span>spawn</span><span> </span><span>=</span><span> </span><span>function</span><span><span>(</span><span>x</span><span>, </span><span>y</span><span>) {</span></span></div></div><div><div><div>56</div></div><div><span>        </span><span>if</span><span><span> (</span><span>particles</span><span>.</span></span><span>length</span><span> </span><span>&gt;=</span><span> </span><span>MAX_PARTICLES</span><span>)</span></div></div><div><div><div>57</div></div><div><span><span>            </span></span><span>pool</span><span>.</span><span>push</span><span><span>(</span><span>particles</span><span>.</span></span><span>shift</span><span>());</span></div></div><div><div><div>58</div></div><div><span><span>        </span></span><span>particle</span><span> </span><span>=</span><span><span> </span><span>pool</span><span>.</span></span><span>length</span><span> </span><span>?</span><span><span> </span><span>pool</span><span>.</span></span><span>pop</span><span>() </span><span>:</span><span> </span><span>new</span><span> </span><span>Particle</span><span>();</span></div></div><div><div><div>59</div></div><div><span><span>        </span></span><span>particle</span><span>.</span><span>init</span><span><span>(</span><span>x</span><span>, </span><span>y</span><span>, </span></span><span>random</span><span>(</span><span>5</span><span>, </span><span>20</span><span>));</span><span>//圆点大小范围</span></div></div><div><div><div>60</div></div><div><span><span>        </span></span><span>particle</span><span>.</span><span>wander</span><span> </span><span>=</span><span> </span><span>random</span><span>(</span><span>0.5</span><span>, </span><span>2.0</span><span>);</span></div></div><div><div><div>61</div></div><div><span><span>        </span></span><span>particle</span><span>.</span><span>color</span><span> </span><span>=</span><span> </span><span>random</span><span>(</span><span>COLOURS</span><span>);</span></div></div><div><div><div>62</div></div><div><span><span>        </span></span><span>particle</span><span>.</span><span>drag</span><span> </span><span>=</span><span> </span><span>random</span><span>(</span><span>0.9</span><span>, </span><span>0.99</span><span>);</span></div></div><div><div><div>63</div></div><div><span><span>        </span></span><span>theta</span><span> </span><span>=</span><span> </span><span>random</span><span>(</span><span>TWO_PI</span><span>);</span></div></div><div><div><div>64</div></div><div><span><span>        </span></span><span>force</span><span> </span><span>=</span><span> </span><span>random</span><span>(</span><span>1</span><span>, </span><span>5</span><span>);</span></div></div><div><div><div>65</div></div><div><span><span>        </span></span><span>particle</span><span>.</span><span>vx</span><span> </span><span>=</span><span> </span><span>sin</span><span><span>(</span><span>theta</span><span>) </span></span><span>*</span><span><span> </span><span>force</span><span>;</span></span></div></div><div><div><div>66</div></div><div><span><span>        </span></span><span>particle</span><span>.</span><span>vy</span><span> </span><span>=</span><span> </span><span>cos</span><span><span>(</span><span>theta</span><span>) </span></span><span>*</span><span><span> </span><span>force</span><span>;</span></span></div></div><div><div><div>67</div></div><div><span><span>        </span></span><span>particles</span><span>.</span><span>push</span><span><span>(</span><span>particle</span><span>);</span></span></div></div><div><div><div>68</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>69</div></div><div><span><span>    </span></span><span>clickparticle</span><span>.</span><span>update</span><span> </span><span>=</span><span> </span><span>function</span><span>() {</span></div></div><div><div><div>70</div></div><div><span>        </span><span>var</span><span><span> </span><span>i</span><span>, </span><span>particle</span><span>;</span></span></div></div><div><div><div>71</div></div><div><span>        </span><span>for</span><span><span> (</span><span>i</span><span> </span></span><span>=</span><span><span> </span><span>particles</span><span>.</span></span><span>length</span><span> </span><span>-</span><span> </span><span>1</span><span><span>; </span><span>i</span><span> </span></span><span>&gt;=</span><span> </span><span>0</span><span><span>; </span><span>i</span></span><span>--</span><span>) {</span></div></div><div><div><div>72</div></div><div><span><span>            </span></span><span>particle</span><span> </span><span>=</span><span><span> </span><span>particles</span><span>[</span><span>i</span><span>];</span></span></div></div><div><div><div>73</div></div><div><span>            </span><span>if</span><span><span> (</span><span>particle</span><span>.</span></span><span>alive</span><span>)</span></div></div><div><div><div>74</div></div><div><span><span>                </span></span><span>particle</span><span>.</span><span>move</span><span>();</span></div></div><div><div><div>75</div></div><div><span>            </span><span>else</span></div></div><div><div><div>76</div></div><div><span><span>                </span></span><span>pool</span><span>.</span><span>push</span><span><span>(</span><span>particles</span><span>.</span></span><span>splice</span><span><span>(</span><span>i</span><span>, </span></span><span>1</span><span>)[</span><span>0</span><span>]);</span></div></div><div><div><div>77</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>78</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>79</div></div><div><span><span>    </span></span><span>clickparticle</span><span>.</span><span>draw</span><span> </span><span>=</span><span> </span><span>function</span><span>() {</span></div></div><div><div><div>80</div></div><div><span><span>        </span></span><span>clickparticle</span><span>.</span><span>globalCompositeOperation</span><span> </span><span>=</span><span> </span><span>'lighter'</span><span>;</span></div></div><div><div><div>81</div></div><div><span>        </span><span>for</span><span> ( </span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span><span> </span><span>particles</span><span>.</span></span><span>length</span><span> </span><span>-</span><span> </span><span>1</span><span><span>; </span><span>i</span><span> </span></span><span>&gt;=</span><span> </span><span>0</span><span><span>; </span><span>i</span></span><span>--</span><span>) {</span></div></div><div><div><div>82</div></div><div><span><span>            </span></span><span>particles</span><span>[</span><span>i</span><span>].</span><span>draw</span><span><span>(</span><span>clickparticle</span><span>);</span></span></div></div><div><div><div>83</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>84</div></div><div><span><span>    </span></span><span>};</span></div></div><div><div><div>85</div></div><div><span>    </span><span>//按下时显示效果，mousedown 换成 click 为点击时显示效果（我用的 click）</span></div></div><div><div><div>86</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>addEventListener</span><span>(</span><span>"mousedown"</span><span>, </span><span>function</span><span><span>(</span><span>e</span><span>) {</span></span></div></div><div><div><div>87</div></div><div><span>        </span><span>var</span><span><span> </span><span>max</span><span>, </span><span>j</span><span>;</span></span></div></div><div><div><div>88</div></div><div><span>        </span><span>//排除一些元素</span></div></div><div><div><div>89</div></div><div><span>        </span><span>"TEXTAREA"</span><span> </span><span>!==</span><span><span> </span><span>e</span><span>.</span></span><span>target</span><span>.</span><span>nodeName</span><span> </span><span>&amp;&amp;</span><span> </span><span>"INPUT"</span><span> </span><span>!==</span><span><span> </span><span>e</span><span>.</span></span><span>target</span><span>.</span><span>nodeName</span><span> </span><span>&amp;&amp;</span><span> </span><span>"A"</span><span> </span><span>!==</span><span><span> </span><span>e</span><span>.</span></span><span>target</span><span>.</span><span>nodeName</span><span> </span><span>&amp;&amp;</span><span> </span><span>"I"</span><span> </span><span>!==</span><span><span> </span><span>e</span><span>.</span></span><span>target</span><span>.</span><span>nodeName</span><span> </span><span>&amp;&amp;</span><span> </span><span>"IMG"</span><span> </span><span>!==</span><span><span> </span><span>e</span><span>.</span></span><span>target</span><span>.</span><span>nodeName</span></div></div><div><div><div>90</div></div><div><span>        </span><span>&amp;&amp;</span><span> </span><span>function</span><span>() {</span></div></div><div><div><div>91</div></div><div><span>            </span><span>for</span><span><span> (</span><span>max</span><span> </span></span><span>=</span><span> </span><span>random</span><span>(</span><span>15</span><span>, </span><span>20</span><span><span>), </span><span>j</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>j</span><span> </span></span><span>&lt;</span><span><span> </span><span>max</span><span>; </span><span>j</span></span><span>++</span><span>)</span></div></div><div><div><div>92</div></div><div><span><span>            </span></span><span>clickparticle</span><span>.</span><span>spawn</span><span><span>(</span><span>e</span><span>.</span></span><span>clientX</span><span><span>, </span><span>e</span><span>.</span></span><span>clientY</span><span>);</span></div></div><div><div><div>93</div></div><div><span><span>        </span></span><span>}();</span></div></div><div><div><div>94</div></div><div><span><span>    </span></span><span>});</span></div></div><div><div><div>95</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>接着在<code>body</code>中引入：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>div</span><span> </span><span>id</span><span>=</span><span>"clickCanvas"</span><span> </span><span>style</span><span>=</span><span>"</span><span> position:fixed;left:0;top:0;z-index:999999999;pointer-events:none;</span><span>"</span><span>&gt;&lt;/</span><span>div</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/221/</id>
      <title type="text">【杂项】win10专属快捷键</title>
      <published>2020-02-10T11:57:00.000Z</published>
      <updated>2020-02-10T11:58:48.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/221/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>数字键<a href="#数字键"><span>#</span></a></h2>

<table><thead><tr><th>按键</th><th>说明</th></tr></thead><tbody><tr><td>win + 数字键</td><td>切换任务栏应用</td></tr><tr><td>win + ctrl + f4</td><td>删除最近打开的桌面</td></tr></tbody></table></section>
<section><h2>第一排字母键<a href="#第一排字母键"><span>#</span></a></h2>

<table><thead><tr><th>按键</th><th>说明</th></tr></thead><tbody><tr><td>win + q</td><td>搜索</td></tr><tr><td>win + w</td><td>手写笔</td></tr><tr><td>win + e</td><td>文件管理器</td></tr><tr><td>win + r</td><td>运行</td></tr><tr><td>win + t</td><td>选择任务栏</td></tr><tr><td>win + u</td><td>win设置-显示</td></tr><tr><td>win + i</td><td>win设置</td></tr><tr><td>win + p</td><td>投影</td></tr><tr><td>win + tab</td><td>任务切换</td></tr></tbody></table></section>
<section><h2>第二排字母键<a href="#第二排字母键"><span>#</span></a></h2>

<table><thead><tr><th>按键</th><th>说明</th></tr></thead><tbody><tr><td>win + a</td><td>管理面板</td></tr><tr><td>win + s</td><td>搜索</td></tr><tr><td>win + shift + s</td><td>截屏</td></tr><tr><td>win + d</td><td>显示桌面</td></tr><tr><td>win + ctrl + d</td><td>创建桌面</td></tr><tr><td>win + f</td><td>反馈中心</td></tr><tr><td>win + g</td><td>xbox</td></tr><tr><td>win + h</td><td>语音听写</td></tr><tr><td>win + k</td><td>连接视频/音频设备</td></tr><tr><td>win + l</td><td>锁屏</td></tr><tr><td>win + ;</td><td>表情符号</td></tr></tbody></table></section>
<section><h2>第三排字母键<a href="#第三排字母键"><span>#</span></a></h2>

<table><thead><tr><th>按键</th><th>说明</th></tr></thead><tbody><tr><td>win + x</td><td>“右击开始”</td></tr><tr><td>win + c</td><td>语音助手（中国不可用）</td></tr><tr><td>win + v</td><td>剪切板</td></tr><tr><td>win + b</td><td>选择状态栏</td></tr><tr><td>win + m</td><td>最小化所有窗口</td></tr><tr><td>win + &lt;</td><td>快速浏览桌面</td></tr><tr><td>win + &gt;</td><td>表情符号</td></tr></tbody></table></section>
<section><h2>最后一排<a href="#最后一排"><span>#</span></a></h2>

<table><thead><tr><th>按键</th><th>说明</th></tr></thead><tbody><tr><td>win + 空格</td><td>切换输入法</td></tr><tr><td>win + 左/右</td><td>应用靠左/右</td></tr><tr><td>win + shift + 左/右</td><td>应用转移到另一显示屏</td></tr><tr><td>win + 上</td><td>应用全屏</td></tr><tr><td>win + 下</td><td>应用窗口化</td></tr></tbody></table></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/220/</id>
      <title type="text">【Golang】实现文件服务器断点续传</title>
      <published>2020-02-05T04:24:00.000Z</published>
      <updated>2020-02-24T14:36:31.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/220/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>下载文件时暂停后可以继续接着下载，在线看视频时可以随意拖动进度条，这些都是断点续传所实现的应用。
http1.1支持<strong>Range</strong>属性从而实现断点续传，客户端在暂停时记录了已经下载的文件范围，当继续下载时就向服务器发送文件剩余的范围(Range)，服务器则根据客户端请求的范围(Range)返回相应文件的部分数据，而不用将整个文件返回给客户端。</p><p>多线程下载器就是利用这个属性进行多线程下载，下载器将服务器返回的文件数据范围进行分割，然后根据分割后的范围向服务器索取数据。</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>首先要告诉客户端支持Range断点续传，然后客户端才能发起Range请求。
这需要在服务器返回http的head以下内容：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Accept-ranges"</span><span>, </span><span>"bytes"</span><span>)   </span><span>//告诉客户端支持Range，并且是bytes级的断点续传</span></div></div><div><div><div>2</div></div><div><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Content-Length"</span><span>, </span><span>文件大小</span><span>)     </span><span>//文件的总体大小</span></div></div><div><div><div>3</div></div><div><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Content-Disposition"</span><span>, </span><span>"attachment; filename=文件名称“)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>若客户端请求Ranges，服务器就返回<code>Content-Range</code>,<code>Content-Range</code>的内容是0~(文件大小-1)/文件大小
例如一个大小为1024的文件，<code>Content-Range</code>内容为<code>0-1023/1024</code></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>//</span></div></div><div><div><div>2</div></div><div><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Content-Range"</span><span>, </span><span>"bytes 0-1023/1024"</span><span>)</span></div></div><div><div><div>3</div></div><div><span>//断点</span></div></div><div><div><div>4</div></div><div><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Content-Range"</span><span>, </span><span>"bytes 200-1023/1024"</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>服务器要从客户端的请求的Range判断是否是有效的范围。
<strong>如果是有效的范围就要将相应状态码设为206 (Partial Content)，否则就设为416 (Request Range Not Satisfiable)</strong></p></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>代码实现：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>func</span><span> </span><span>sendFile</span><span><span>(</span><span>writer</span><span> </span></span><span>http</span><span>.</span><span>ResponseWriter</span><span><span>, </span><span>request</span><span> </span><span>*</span></span><span>http</span><span>.</span><span>Request</span><span><span>, </span><span>f</span><span> </span><span>*</span></span><span>os</span><span>.</span><span>File</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>defer</span><span> </span><span>f</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>3</div></div><div><span>  </span><span>info</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>f</span><span>.</span><span>Stat</span><span>()</span></div></div><div><div><div>4</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>5</div></div><div><span>    </span><span>log</span><span>.</span><span>Println</span><span>(</span><span>"sendFile1"</span><span>, </span><span>err</span><span>.</span><span>Error</span><span>())</span></div></div><div><div><div>6</div></div><div><span>    </span><span>http</span><span>.</span><span>NotFound</span><span>(</span><span>writer</span><span>, </span><span>request</span><span>)</span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>  </span><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Accept-Ranges"</span><span>, </span><span>"bytes"</span><span>)</span></div></div><div><div><div>10</div></div><div><span>  </span><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Content-Disposition"</span><span>, </span><span>"attachment; filename="</span><span>+</span><span>info</span><span>.</span><span>Name</span><span>())</span></div></div><div><div><div>11</div></div><div><span>  </span><span>var</span><span> </span><span>start</span><span>, </span><span>end</span><span> </span><span>int64</span></div></div><div><div><div>12</div></div><div><span>  </span><span>//fmt.Println(request.Header,"\n")</span></div></div><div><div><div>13</div></div><div><span>  </span><span>if</span><span> </span><span>r</span><span><span> </span><span>:=</span><span> </span></span><span>request</span><span>.</span><span>Header</span><span>.</span><span>Get</span><span>(</span><span>"Range"</span><span>); </span><span>r</span><span><span> </span><span>!=</span><span> </span></span><span>""</span><span> {</span></div></div><div><div><div>14</div></div><div><span>    </span><span>if</span><span> </span><span>strings</span><span>.</span><span>Contains</span><span>(</span><span>r</span><span>, </span><span>"bytes="</span><span><span>) </span><span>&amp;&amp;</span><span> </span></span><span>strings</span><span>.</span><span>Contains</span><span>(</span><span>r</span><span>, </span><span>"-"</span><span>) {</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>      </span><span>fmt</span><span>.</span><span>Sscanf</span><span>(</span><span>r</span><span>, </span><span>"bytes=</span><span>%d</span><span>-</span><span>%d</span><span>"</span><span><span>, </span><span>&amp;</span></span><span>start</span><span><span>, </span><span>&amp;</span></span><span>end</span><span>)</span></div></div><div><div><div>17</div></div><div><span>      </span><span>if</span><span> </span><span>end</span><span><span> </span><span>==</span><span> </span></span><span>0</span><span> {</span></div></div><div><div><div>18</div></div><div><span>        </span><span>end</span><span><span> </span><span>=</span><span> </span></span><span>info</span><span>.</span><span>Size</span><span><span>() </span><span>-</span><span> </span></span><span>1</span></div></div><div><div><div>19</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>20</div></div><div><span>      </span><span>if</span><span> </span><span>start</span><span><span> </span><span>&gt;</span><span> </span></span><span>end</span><span><span> </span><span>||</span><span> </span></span><span>start</span><span><span> </span><span>&lt;</span><span> </span></span><span>0</span><span><span> </span><span>||</span><span> </span></span><span>end</span><span><span> </span><span>&lt;</span><span> </span></span><span>0</span><span><span> </span><span>||</span><span> </span></span><span>end</span><span><span> </span><span>&gt;=</span><span> </span></span><span>info</span><span>.</span><span>Size</span><span>() {</span></div></div><div><div><div>21</div></div><div><span>        </span><span>writer</span><span>.</span><span>WriteHeader</span><span>(</span><span>http</span><span>.</span><span>StatusRequestedRangeNotSatisfiable</span><span>)</span></div></div><div><div><div>22</div></div><div><span>        </span><span>log</span><span>.</span><span>Println</span><span>(</span><span>"sendFile2 start:"</span><span>, </span><span>start</span><span>, </span><span>"end:"</span><span>, </span><span>end</span><span>, </span><span>"size:"</span><span>, </span><span>info</span><span>.</span><span>Size</span><span>())</span></div></div><div><div><div>23</div></div><div><span>        </span><span>return</span></div></div><div><div><div>24</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>25</div></div><div><span>      </span><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Content-Length"</span><span>, </span><span>strconv</span><span>.</span><span>FormatInt</span><span>(</span><span>end</span><span>-</span><span>start</span><span>+</span><span>1</span><span>, </span><span>10</span><span>))</span></div></div><div><div><div>26</div></div><div><span>      </span><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Content-Range"</span><span>, </span><span>fmt</span><span>.</span><span>Sprintf</span><span>(</span><span>"bytes </span><span>%v</span><span>-</span><span>%v</span><span>/</span><span>%v</span><span>"</span><span>, </span><span>start</span><span>, </span><span>end</span><span>, </span><span>info</span><span>.</span><span>Size</span><span>()))</span></div></div><div><div><div>27</div></div><div><span>      </span><span>writer</span><span>.</span><span>WriteHeader</span><span>(</span><span>http</span><span>.</span><span>StatusPartialContent</span><span>)</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>29</div></div><div><span>      </span><span>writer</span><span>.</span><span>WriteHeader</span><span>(</span><span>http</span><span>.</span><span>StatusBadRequest</span><span>)</span></div></div><div><div><div>30</div></div><div><span>      </span><span>return</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>32</div></div><div><span><span>  </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>33</div></div><div><span>    </span><span>writer</span><span>.</span><span>Header</span><span>().</span><span>Add</span><span>(</span><span>"Content-Length"</span><span>, </span><span>strconv</span><span>.</span><span>FormatInt</span><span>(</span><span>info</span><span>.</span><span>Size</span><span>(), </span><span>10</span><span>))</span></div></div><div><div><div>34</div></div><div><span>    </span><span>start</span><span><span> </span><span>=</span><span> </span></span><span>0</span></div></div><div><div><div>35</div></div><div><span>    </span><span>end</span><span><span> </span><span>=</span><span> </span></span><span>info</span><span>.</span><span>Size</span><span><span>() </span><span>-</span><span> </span></span><span>1</span></div></div><div><div><div>36</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>37</div></div><div><span>  </span><span>_</span><span>, </span><span>err</span><span><span> </span><span>=</span><span> </span></span><span>f</span><span>.</span><span>Seek</span><span>(</span><span>start</span><span>, </span><span>0</span><span>)</span></div></div><div><div><div>38</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>39</div></div><div><span>    </span><span>log</span><span>.</span><span>Println</span><span>(</span><span>"sendFile3"</span><span>, </span><span>err</span><span>.</span><span>Error</span><span>())</span></div></div><div><div><div>40</div></div><div><span>    </span><span>writer</span><span>.</span><span>WriteHeader</span><span>(</span><span>http</span><span>.</span><span>StatusInternalServerError</span><span>)</span></div></div><div><div><div>41</div></div><div><span>    </span><span>return</span></div></div><div><div><div>42</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>43</div></div><div><span>  </span><span>n</span><span><span> </span><span>:=</span><span> </span></span><span>512</span></div></div><div><div><div>44</div></div><div><span>  </span><span>buf</span><span><span> </span><span>:=</span><span> </span></span><span>make</span><span>([]</span><span>byte</span><span>, </span><span>n</span><span>)</span></div></div><div><div><div>45</div></div><div><span>  </span><span>for</span><span> {</span></div></div><div><div><div>46</div></div><div><span>    </span><span>if</span><span> </span><span>end</span><span>-</span><span>start</span><span>+</span><span>1</span><span><span> </span><span>&lt;</span><span> </span></span><span>int64</span><span>(</span><span>n</span><span>) {</span></div></div><div><div><div>47</div></div><div><span>      </span><span>n</span><span><span> </span><span>=</span><span> </span></span><span>int</span><span>(</span><span>end</span><span><span> </span><span>-</span><span> </span></span><span>start</span><span><span> </span><span>+</span><span> </span></span><span>1</span><span>)</span></div></div><div><div><div>48</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>49</div></div><div><span>    </span><span>_</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>f</span><span>.</span><span>Read</span><span>(</span><span>buf</span><span>[:</span><span>n</span><span>])</span></div></div><div><div><div>50</div></div><div><span>    </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>51</div></div><div><span>      </span><span>log</span><span>.</span><span>Println</span><span>(</span><span>"1:"</span><span>, </span><span>err</span><span>)</span></div></div><div><div><div>52</div></div><div><span>      </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>io</span><span>.</span><span>EOF</span><span> {</span></div></div><div><div><div>53</div></div><div><span>        </span><span>log</span><span>.</span><span>Println</span><span>(</span><span>"error:"</span><span>, </span><span>err</span><span>)</span></div></div><div><div><div>54</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>55</div></div><div><span>      </span><span>return</span></div></div><div><div><div>56</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>57</div></div><div><span>    </span><span>err</span><span><span> </span><span>=</span><span> </span></span><span>nil</span></div></div><div><div><div>58</div></div><div><span>    </span><span>_</span><span>, </span><span>err</span><span><span> </span><span>=</span><span> </span></span><span>writer</span><span>.</span><span>Write</span><span>(</span><span>buf</span><span>[:</span><span>n</span><span>])</span></div></div><div><div><div>59</div></div><div><span>    </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>60</div></div><div><span>      </span><span>//log.Println(err, start, end, info.Size(), n)</span></div></div><div><div><div>61</div></div><div><span>      </span><span>return</span></div></div><div><div><div>62</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>63</div></div><div><span>    </span><span>start</span><span><span> </span><span>+=</span><span> </span></span><span>int64</span><span>(</span><span>n</span><span>)</span></div></div><div><div><div>64</div></div><div><span>    </span><span>if</span><span> </span><span>start</span><span><span> </span><span>&gt;=</span><span> </span></span><span>end</span><span>+</span><span>1</span><span> {</span></div></div><div><div><div>65</div></div><div><span>      </span><span>return</span></div></div><div><div><div>66</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>67</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>68</div></div><div>
</div></div><div><div><div>69</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/219/</id>
      <title type="text">【Golang】简易的编译脚本</title>
      <published>2020-01-20T03:14:47.000Z</published>
      <updated>2020-01-20T03:14:47.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/219/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>GOPATH</span><span>=</span><span><span>${</span><span>PWD</span><span>}</span></span></div></div><div><div><div>2</div></div><div><span>if</span><span><span> [ </span><span>-n</span><span> </span></span><span>"</span><span>$1</span><span>"</span><span> ]; </span><span>then</span></div></div><div><div><div>3</div></div><div><span>    </span><span>export</span><span> </span><span>GOOS</span><span><span>=</span><span>$1</span></span></div></div><div><div><div>4</div></div><div><span>fi</span></div></div><div><div><div>5</div></div><div><span>if</span><span><span> [ </span><span>-n</span><span> </span></span><span>"</span><span>$2</span><span>"</span><span> ]; </span><span>then</span></div></div><div><div><div>6</div></div><div><span>    </span><span>export</span><span> </span><span>GOARCH</span><span><span>=</span><span>$2</span></span></div></div><div><div><div>7</div></div><div><span>fi</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>go</span><span> </span><span>install</span><span> </span><span><span>${</span><span>PWD</span></span><span>##*/</span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/214/</id>
      <title type="text">【Termux】使用atilo安装linux报错解决方案</title>
      <published>2019-12-18T09:21:18.000Z</published>
      <updated>2019-12-18T09:21:18.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/214/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00 安装时出现proot容器错误<a href="#0x00-安装时出现proot容器错误"><span>#</span></a></h1><section><h2>0.发现问题<a href="#0发现问题"><span>#</span></a></h2><p>已经termux-chroot授权运行</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>atilo</span><span> </span><span>install</span><span> (liunx版本)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>时出现类似<code>proot No such file or directory</code>等报错。</p></section><section><h2>1.查找问题<a href="#1查找问题"><span>#</span></a></h2><p>通过查看atilo运行信息发现解压文件信息有明显的错误</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>[ Extracting ]</span></div></div><div><div><div>2</div></div><div><span>64.0KiB 0:00:00 [ 235KiB/s] [&gt;        ]  0%</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>一般系统文件都有几十兆大小，而这个解压信息小得离谱
再翻阅atilo代码时发现安装时会在<code>~/.atilo/tmp</code>中存放下载的系统文件，查看目录下的文件大小发现也是非常小的，这说明之前下载文件失败。</p></section><section><h2>2.解决方案<a href="#2解决方案"><span>#</span></a></h2><p>有了这个思路之后编辑<code>atilo</code>源码找到要下载的系统的链接，我这里使用安装<code>kali</code>来示范</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>找到</span></div></div><div><div><div>2</div></div><div><span>kali</span><span>)</span></div></div><div><div><div>3</div></div><div><span>    </span><span>aarch64</span><span>=</span><span>https://raw.githubusercontent.com/EXALAB/AnLinux-Resources/master/Rootfs/Kali/arm64/kali-rootfs-armhf.tar.gz</span></div></div><div><div><div>4</div></div><div><span>    </span><span>arm</span><span>=</span><span>https://raw.githubusercontent.com/EXALAB/AnLinux-Resources/master/Rootfs/Kali/armhf/kali-rootfs-armhf.tar.gz</span></div></div><div><div><div>5</div></div><div><span>    </span><span>amd64</span><span>=</span><span>https://raw.githubusercontent.com/EXALAB/AnLinux-Resources/master/Rootfs/Kali/amd64/kali-rootfs-amd64.tar.gz</span></div></div><div><div><div>6</div></div><div><span>    </span><span>i386</span><span>=</span><span>https://raw.githubusercontent.com/EXALAB/AnLinux-Resources/master/Rootfs/Kali/i386/kali-rootfs-i386.tar.gz</span></div></div><div><div><div>7</div></div><div><span>    </span><span>zip</span><span>=</span><span>xz</span></div></div><div><div><div>8</div></div><div><span>    </span><span>upgrade</span><span>=</span><span>"apt update"</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>;;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>因为我的手机cpu是arm64架构的，所已更改aarch64的地址，将它替换为清华源<code>https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/kali/current/arm64/default/20191216_17%3A14/rootfs.tar.xz</code>
因为清华源提供的是<code>.tar.xz</code>的包，所已也要更改<code>zip=xz</code>为<code>zip=Jx</code>
其他系统或架构的需要替换对应的<a href="https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/" target="_blank">清华源</a></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>kali</span><span>)</span></div></div><div><div><div>2</div></div><div><span>    </span><span>aarch64</span><span>=</span><span>https://mirrors.tuna.tsinghua.edu.cn/lxc-images/images/kali/current/arm64/default/20191216_17%3A14/rootfs.tar.xz</span></div></div><div><div><div>3</div></div><div><span>    </span><span>arm</span><span>=</span><span>https://raw.githubusercontent.com/EXALAB/AnLinux-Resources/master/Rootfs/Kali/armhf/kali-rootfs-armhf.tar.gz</span></div></div><div><div><div>4</div></div><div><span>    </span><span>amd64</span><span>=</span><span>https://raw.githubusercontent.com/EXALAB/AnLinux-Resources/master/Rootfs/Kali/amd64/kali-rootfs-amd64.tar.gz</span></div></div><div><div><div>5</div></div><div><span>    </span><span>i386</span><span>=</span><span>https://raw.githubusercontent.com/EXALAB/AnLinux-Resources/master/Rootfs/Kali/i386/kali-rootfs-i386.tar.gz</span></div></div><div><div><div>6</div></div><div><span>    </span><span>zip</span><span>=</span><span>Jx</span></div></div><div><div><div>7</div></div><div><span>    </span><span>upgrade</span><span>=</span><span>"apt update"</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>;;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果提供的是其他格式的包就要对应修改<code>zip</code>的内容</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.tar.gz -&gt; zip=xz</span></div></div><div><div><div>2</div></div><div><span>.tar.xz -&gt; zip=Jx</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重新运行安装之前要记得<code>rm ~/.atilo/tmp/*</code>删除下载失败的包</p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/213/</id>
      <title type="text">【Golang】简单的树莓派GPIO库</title>
      <published>2019-11-24T15:24:00.000Z</published>
      <updated>2020-12-11T05:44:39.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/213/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p><a href="https://github.com/Rehtt/gogpio" target="_blank">Github</a>
版本：v0.3
对GPIO简单的操作
功能：
1.设置指定的GPIO口是发射还是接收口（in/out）
2.设置发射口是高电平还是低电平（1/0）
3.释放GPIO口（Close()）
4.软件实现PWM（实验性，频率越高越消耗cpu资源）
示例：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>main</span></div></div><div><div><div>2</div></div><div><span>import</span><span> (</span></div></div><div><div><div>3</div></div><div><span>    </span><span>gogpio</span><span> </span><span>"github.com/Rehtt/gogpio"</span></div></div><div><div><div>4</div></div><div><span>    </span><span>"log"</span></div></div><div><div><div>5</div></div><div><span>    </span><span>"time"</span></div></div><div><div><div>6</div></div><div><span>)</span></div></div><div><div><div>7</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>8</div></div><div><span>//绑定针脚号(BCM)</span></div></div><div><div><div>9</div></div><div><span>pin1</span><span>, </span><span>err1</span><span><span> </span><span>:=</span><span> </span></span><span>gogpio</span><span>.</span><span>PinBind</span><span>(</span><span>20</span><span>)</span></div></div><div><div><div>10</div></div><div><span>pin2</span><span>, </span><span>err2</span><span><span> </span><span>:=</span><span> </span></span><span>gogpio</span><span>.</span><span>PinBind</span><span>(</span><span>21</span><span>)</span></div></div><div><div><div>11</div></div><div><span>pin3</span><span>, </span><span>err3</span><span><span> </span><span>:=</span><span> </span></span><span>gogpio</span><span>.</span><span>PinBind</span><span>(</span><span>22</span><span>)</span></div></div><div><div><div>12</div></div><div><span>pin4</span><span>, </span><span>err4</span><span><span> </span><span>:=</span><span> </span></span><span>gogpio</span><span>.</span><span>PinBind</span><span>(</span><span>23</span><span>)</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>//声明针脚为out输出</span></div></div><div><div><div>15</div></div><div><span>if</span><span> </span><span>err1</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>16</div></div><div><span>log</span><span>.</span><span>Println</span><span>(</span><span>err1</span><span>)</span></div></div><div><div><div>17</div></div><div><span>}</span></div></div><div><div><div>18</div></div><div><span>out</span><span><span> </span><span>:=</span><span> </span></span><span>pin1</span><span>.</span><span>SetOut</span><span>()</span></div></div><div><div><div>19</div></div><div><span>out</span><span>.</span><span>High</span><span>() </span><span>//输出高电平</span></div></div><div><div><div>20</div></div><div><span>out</span><span>.</span><span>Low</span><span>()  </span><span>//输出低电平</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>//声明针脚为in输入</span></div></div><div><div><div>23</div></div><div><span>if</span><span> </span><span>err2</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>24</div></div><div><span>log</span><span>.</span><span>Println</span><span>(</span><span>err2</span><span>)</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div><div><div><div>26</div></div><div><span>in</span><span><span> </span><span>:=</span><span> </span></span><span>pin2</span><span>.</span><span>SetIn</span><span>()</span></div></div><div><div><div>27</div></div><div><span>log</span><span>.</span><span>Println</span><span>(</span><span>in</span><span>.</span><span>Read</span><span>()) </span><span>//读取输入的数据</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>//不声明，直接读取数据。时合在其他程序使用此针脚时读取其数据</span></div></div><div><div><div>30</div></div><div><span>if</span><span> </span><span>err3</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>31</div></div><div><span>log</span><span>.</span><span>Println</span><span>(</span><span>err3</span><span>)</span></div></div><div><div><div>32</div></div><div><span>}</span></div></div><div><div><div>33</div></div><div><span>log</span><span>.</span><span>Println</span><span>(</span><span>pin3</span><span>.</span><span>Read</span><span>())</span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span>//声明为PWM（此功能为实验性功能，这里的PWM由软件生成，所以运行时会占用一定的cpu资源，频率越高cpu占用也越高）</span></div></div><div><div><div>36</div></div><div><span>if</span><span> </span><span>err4</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>37</div></div><div><span>log</span><span>.</span><span>Println</span><span>(</span><span>err4</span><span>)</span></div></div><div><div><div>38</div></div><div><span>}</span></div></div><div><div><div>39</div></div><div><span>pwm</span><span><span> </span><span>:=</span><span> </span></span><span>pin4</span><span>.</span><span>SetPWM</span><span>()</span></div></div><div><div><div>40</div></div><div><span>err</span><span><span> </span><span>=</span><span> </span></span><span>pwm</span><span>.</span><span>SetFreq</span><span>(</span><span>5</span><span>) </span><span>//频率单位为Hz，数值 &gt; 0.0</span></div></div><div><div><div>41</div></div><div><span>err</span><span><span> </span><span>=</span><span> </span></span><span>pwm</span><span>.</span><span>SetDC</span><span>(</span><span>20</span><span>) </span><span>//占空比单位为% ，0.0 &lt; 数值 &lt; 100</span></div></div><div><div><div>42</div></div><div><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>43</div></div><div><span>log</span><span>.</span><span>Println</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>44</div></div><div><span>}</span></div></div><div><div><div>45</div></div><div><span>pwm</span><span>.</span><span>StartPWM</span><span>() </span><span>//开启PWM</span></div></div><div><div><div>46</div></div><div><span>pwm</span><span>.</span><span>StopPWM</span><span>() </span><span>//关闭PWM</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>//释放</span></div></div><div><div><div>49</div></div><div><span>pin1</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>50</div></div><div><span>pin2</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>51</div></div><div><span>pin3</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>52</div></div><div><span>pin4</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>53</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/212/</id>
      <title type="text">【Golang】程序通过服务的形式常驻后台</title>
      <published>2019-11-07T09:08:00.000Z</published>
      <updated>2019-11-07T10:01:49.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/212/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>0x00<a href="#0x00"><span>#</span></a></h2><div><div><div></div><div>Warning</div></div><div><p>此教程只在Linux和Windows上试验过，Mac可自行实验</p></div></div><p>一般使用命令带<code>&amp;</code>实现后台运行，或使用守护进程来实现后台运行。
其实golang自己也可以实现以服务的形式常驻后台。</p><section><h3>需要的库<a href="#需要的库"><span>#</span></a></h3><p>这里使用库:<code>github.com/kardianos/service</code></p><p>其中<code>golang.org/x/...</code>的库国内很难下载，将<code>golang.org/x/</code>替换为<code>github.com/golang/</code>进行下载，最后将<code>github.com</code>-&gt;<code>golang</code>文件目录替换为<code>golang.org</code>-&gt;<code>x</code>文件目录即可。</p></section><section><h3>接口定义<a href="#接口定义"><span>#</span></a></h3><p>这个库有两个接口定义：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Service</span><span> </span><span>interface</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>// Run should be called shortly after the program entry point.</span></div></div><div><div><div>3</div></div><div><span>  </span><span>// After Interface.Stop has finished running, Run will stop blocking.</span></div></div><div><div><div>4</div></div><div><span>  </span><span>// After Run stops blocking, the program must exit shortly after.</span></div></div><div><div><div>5</div></div><div><span>  </span><span>Run</span><span>() </span><span>error</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>  </span><span>// Start signals to the OS service manager the given service should start.</span></div></div><div><div><div>8</div></div><div><span>  </span><span>Start</span><span>() </span><span>error</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>  </span><span>// Stop signals to the OS service manager the given service should stop.</span></div></div><div><div><div>11</div></div><div><span>  </span><span>Stop</span><span>() </span><span>error</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>  </span><span>// Restart signals to the OS service manager the given service should stop then start.</span></div></div><div><div><div>14</div></div><div><span>  </span><span>Restart</span><span>() </span><span>error</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>  </span><span>// Install setups up the given service in the OS service manager. This may require</span></div></div><div><div><div>17</div></div><div><span>  </span><span>// greater rights. Will return an error if it is already installed.</span></div></div><div><div><div>18</div></div><div><span>  </span><span>Install</span><span>() </span><span>error</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>  </span><span>// Uninstall removes the given service from the OS service manager. This may require</span></div></div><div><div><div>21</div></div><div><span>  </span><span>// greater rights. Will return an error if the service is not present.</span></div></div><div><div><div>22</div></div><div><span>  </span><span>Uninstall</span><span>() </span><span>error</span></div></div><div><div><div>23</div></div><div>
</div></div><div><div><div>24</div></div><div><span>  </span><span>// Opens and returns a system logger. If the user program is running</span></div></div><div><div><div>25</div></div><div><span>  </span><span>// interactively rather then as a service, the returned logger will write to</span></div></div><div><div><div>26</div></div><div><span>  </span><span>// os.Stderr. If errs is non-nil errors will be sent on errs as well as</span></div></div><div><div><div>27</div></div><div><span>  </span><span>// returned from Logger's functions.</span></div></div><div><div><div>28</div></div><div><span>  </span><span>Logger</span><span><span>(</span><span>errs</span><span> </span></span><span>chan</span><span><span>&lt;-</span><span> </span></span><span>error</span><span>) (</span><span>Logger</span><span>, </span><span>error</span><span>)</span></div></div><div><div><div>29</div></div><div>
</div></div><div><div><div>30</div></div><div><span>  </span><span>// SystemLogger opens and returns a system logger. If errs is non-nil errors</span></div></div><div><div><div>31</div></div><div><span>  </span><span>// will be sent on errs as well as returned from Logger's functions.</span></div></div><div><div><div>32</div></div><div><span>  </span><span>SystemLogger</span><span><span>(</span><span>errs</span><span> </span></span><span>chan</span><span><span>&lt;-</span><span> </span></span><span>error</span><span>) (</span><span>Logger</span><span>, </span><span>error</span><span>)</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>  </span><span>// String displays the name of the service. The display name if present,</span></div></div><div><div><div>35</div></div><div><span>  </span><span>// otherwise the name.</span></div></div><div><div><div>36</div></div><div><span>  </span><span>String</span><span>() </span><span>string</span></div></div><div><div><div>37</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>Interface</span><span> </span><span>interface</span><span> {</span></div></div><div><div><div>2</div></div><div><span>  </span><span>// Start provides a place to initiate the service. The service doesn't not</span></div></div><div><div><div>3</div></div><div><span>  </span><span>// signal a completed start until after this function returns, so the</span></div></div><div><div><div>4</div></div><div><span>  </span><span>// Start function must not take more then a few seconds at most.</span></div></div><div><div><div>5</div></div><div><span>  </span><span>Start</span><span><span>(</span><span>s</span><span> </span></span><span>Service</span><span>) </span><span>error</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>  </span><span>// Stop provides a place to clean up program execution before it is terminated.</span></div></div><div><div><div>8</div></div><div><span>  </span><span>// It should not take more then a few seconds to execute.</span></div></div><div><div><div>9</div></div><div><span>  </span><span>// Stop should not call os.Exit directly in the function.</span></div></div><div><div><div>10</div></div><div><span>  </span><span>Stop</span><span><span>(</span><span>s</span><span> </span></span><span>Service</span><span>) </span><span>error</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>这里只需实现<code>start</code>和<code>stop</code>接口就行</p></section></section>
<section><h2>0x01 简单实例<a href="#0x01-简单实例"><span>#</span></a></h2><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>type</span><span> </span><span>program</span><span> </span><span>struct</span><span>{}</span></div></div><div><div><div>2</div></div><div><span>func</span><span><span> (</span><span>p </span><span>*</span></span><span>program</span><span>) </span><span>Start</span><span><span>(</span><span>s</span><span> </span></span><span>service</span><span>.</span><span>Service</span><span>) </span><span>error</span><span> {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>log</span><span>.</span><span>Println</span><span>(</span><span>"开始服务"</span><span>)</span></div></div><div><div><div>4</div></div><div><span>    </span><span>go</span><span> </span><span>p</span><span>.</span><span>run</span><span>()</span></div></div><div><div><div>5</div></div><div><span>    </span><span>return</span><span> </span><span>nil</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div><div><div><div>7</div></div><div><span>func</span><span><span> (</span><span>p </span><span>*</span></span><span>program</span><span>) </span><span>Stop</span><span><span>(</span><span>s</span><span> </span></span><span>service</span><span>.</span><span>Service</span><span>) </span><span>error</span><span> {</span></div></div><div><div><div>8</div></div><div><span>    </span><span>log</span><span>.</span><span>Println</span><span>(</span><span>"停止服务"</span><span>)</span></div></div><div><div><div>9</div></div><div><span>    </span><span>return</span><span> </span><span>nil</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div><span>func</span><span><span> (</span><span>p </span><span>*</span></span><span>program</span><span>) </span><span>run</span><span>() {</span></div></div><div><div><div>12</div></div><div><span>    </span><span>// 这里放置程序要执行的代码……</span></div></div><div><div><div>13</div></div><div><span>}</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>func</span><span> </span><span>main</span><span>(){</span></div></div><div><div><div>16</div></div><div><span>//服务初始化</span></div></div><div><div><div>17</div></div><div><span>    </span><span>//服务的配置信息</span></div></div><div><div><div>18</div></div><div><span>    </span><span>cfg</span><span><span> </span><span>:=</span><span> </span><span>&amp;</span></span><span>service</span><span>.</span><span>Config</span><span>{</span></div></div><div><div><div>19</div></div><div><span>        </span><span>Name</span><span>:        </span><span>"simple"</span><span>,</span></div></div><div><div><div>20</div></div><div><span>        </span><span>DisplayName</span><span>: </span><span>"a simple service"</span><span>,</span></div></div><div><div><div>21</div></div><div><span>        </span><span>Description</span><span>: </span><span>"This is an example Go service."</span><span>,</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>23</div></div><div><span>    </span><span>// Interface 接口</span></div></div><div><div><div>24</div></div><div><span>    </span><span>prg</span><span><span> </span><span>:=</span><span> </span><span>&amp;</span></span><span>program</span><span>{}</span></div></div><div><div><div>25</div></div><div><span>    </span><span>// 构建服务对象</span></div></div><div><div><div>26</div></div><div><span>    </span><span>s</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>service</span><span>.</span><span>New</span><span>(</span><span>prg</span><span>, </span><span>cfg</span><span>)</span></div></div><div><div><div>27</div></div><div><span>    </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>28</div></div><div><span>        </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>30</div></div><div><span>    </span><span>// logger 用于记录系统日志</span></div></div><div><div><div>31</div></div><div><span>    </span><span>logger</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>s</span><span>.</span><span>Logger</span><span>(</span><span>nil</span><span>)</span></div></div><div><div><div>32</div></div><div><span>    </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>33</div></div><div><span>        </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>35</div></div><div><span>    </span><span>if</span><span> </span><span>len</span><span>(</span><span>os</span><span>.</span><span>Args</span><span><span>) </span><span>==</span><span> </span></span><span>2</span><span> { </span><span>//如果有命令则执行</span></div></div><div><div><div>36</div></div><div><span>        </span><span>err</span><span><span> </span><span>=</span><span> </span></span><span>service</span><span>.</span><span>Control</span><span>(</span><span>s</span><span>, </span><span>os</span><span>.</span><span>Args</span><span>[</span><span>1</span><span>])</span></div></div><div><div><div>37</div></div><div><span>        </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>38</div></div><div><span>            </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>39</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>40</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> { </span><span>//否则说明是方法启动了</span></div></div><div><div><div>41</div></div><div><span>        </span><span>err</span><span><span> </span><span>=</span><span> </span></span><span>s</span><span>.</span><span>Run</span><span>()</span></div></div><div><div><div>42</div></div><div><span>        </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>43</div></div><div><span>            </span><span>logger</span><span>.</span><span>Error</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>45</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>46</div></div><div><span>    </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>47</div></div><div><span>        </span><span>logger</span><span>.</span><span>Error</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>48</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>49</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/211/</id>
      <title type="text">【网络】Caddy + PHP7.3</title>
      <published>2019-11-05T05:59:32.000Z</published>
      <updated>2019-11-05T05:59:32.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/211/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>0x00<a href="#0x00"><span>#</span></a></h2><p>Caddy是一个使用Go编写的开源的支持HTTP / 2的Web服务器。 Caddy可以运行在各种系统上，包括运行Linux，Windows，Mac OS，Android和BSD操作系统的系统。 Caddy有很多功能，可以作为Web服务器安装，也可以作为应用程序的反向代理。 最显着的Caddy网络服务器功能是默认启用的自动HTTPS，无需额外配置。</p></section>
<section><h2>0x01 Caddy<a href="#0x01-caddy"><span>#</span></a></h2><section><h3>安装<a href="#安装"><span>#</span></a></h3><p>使用一键安装脚本，如果想要安装其他扩展可以把名字加到命令后面（<code>bash caddy_install.sh install xxx,xxx,xxx</code>，扩展列表<a href="https://caddyserver.com/download" target="_blank">点击查看</a>）</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>wget</span><span> </span><span>-N</span><span> </span><span>--no-check-certificate</span><span> </span><span>https://www.moerats.com/usr/shell/Caddy/caddy_install.sh</span><span> &amp;&amp; </span><span>chmod</span><span> </span><span>+x</span><span> </span><span>caddy_install.sh</span><span> &amp;&amp; </span><span>bash</span><span> </span><span>caddy_install.sh</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>使用说明<a href="#使用说明"><span>#</span></a></h3><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>启动：/etc/init.d/caddy start</span></div></div><div><div><div>2</div></div><div><span>停止：/etc/init.d/caddy stop</span></div></div><div><div><div>3</div></div><div><span>重启：/etc/init.d/caddy restart</span></div></div><div><div><div>4</div></div><div><span>查看状态：/etc/init.d/caddy status</span></div></div><div><div><div>5</div></div><div><span>查看Caddy启动日志：tail -f /tmp/caddy.log</span></div></div><div><div><div>6</div></div><div><span>安装目录：/usr/local/caddy</span></div></div><div><div><div>7</div></div><div><span>Caddy配置文件位置：/usr/local/caddy/Caddyfile</span></div></div><div><div><div>8</div></div><div><span>Caddy自动申请SSL证书位置：/.caddy/acme/acme-v01.api.letsencrypt.org/sites/xxx.xxx(域名)/</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>升级Caddy或更新扩展<a href="#升级caddy或更新扩展"><span>#</span></a></h3><p>只需要重新执行你当初安装时候用的命令即可，会覆盖安装最新的Caddy+扩展。</p></section><section><h3>卸载<a href="#卸载"><span>#</span></a></h3><p>卸载不会删除虚拟主机的内容，只会删除Caddy自身和配置文件。</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>wget</span><span> </span><span>-N</span><span> </span><span>--no-check-certificate</span><span> </span><span>https://www.moerats.com/usr/shell/Caddy/caddy_install.sh</span><span> &amp;&amp; </span><span>bash</span><span> </span><span>caddy_install.sh</span><span> </span><span>uninstall</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>网站配置文件<a href="#网站配置文件"><span>#</span></a></h3><p>配置文件为Caddyfile，列举几种caddy的conf的写法</p><p>1、本地访问80</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>:80</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>2、单网站访问</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>example.com</span></div></div><div><div><div>2</div></div><div><span>root /usr/local/caddy/www</span></div></div><div><div><div>3</div></div><div><span>//更多模块</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>2、多网站</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>example.com {</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>gzip</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>root /usr/local/caddy/www</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>//更多模块</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>常用基本组成模块，均写入到conf站点配置中。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#log日志</span></div></div><div><div><div>2</div></div><div><span>log /usr/local/caddy/www/example.log</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>#目录访问</span></div></div><div><div><div>5</div></div><div><span>browse</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>#gzip压缩</span></div></div><div><div><div>8</div></div><div><span>gzip</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>#自主ssl证书</span></div></div><div><div><div>11</div></div><div><span>tls /path/ssl/example.com.crt /path/ssl/example.com.key</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>#访问口令认证（用户emiria，密码abc123）</span></div></div><div><div><div>14</div></div><div><span>basicauth / emiria abc123</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>#跳转功能</span></div></div><div><div><div>17</div></div><div><span>redir http://example.com{url}</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>#自定义错误页面</span></div></div><div><div><div>20</div></div><div><span>errors {</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>404 404.html</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>500 /usr/local/caddy/www/500.html</span></div></div><div><div><div>23</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>例如，通过IP即80端口访问目录：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>:80 {</span></div></div><div><div><div>2</div></div><div><span><span>     </span></span><span>root /usr/local/caddy/www</span></div></div><div><div><div>3</div></div><div><span><span>     </span></span><span>gzip</span></div></div><div><div><div>4</div></div><div><span><span>     </span></span><span>browse</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>也可以直接执行命令写入，以下是一个命令，直接复制粘贴即可。</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>echo</span><span> </span><span>":80 {</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>root /usr/local/caddy/www</span></div></div><div><div><div>3</div></div><div><span><span> </span></span><span>gzip</span></div></div><div><div><div>4</div></div><div><span><span> </span></span><span>browse</span></div></div><div><div><div>5</div></div><div><span>}"</span><span> &gt; </span><span>/usr/local/caddy/Caddyfile</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>更多配置参考：<a href="https://caddyserver.com/tutorial/caddyfile" target="_blank">https://caddyserver.com/tutorial/caddyfile</a>
设置文档参考：<a href="https://caddyserver.com/docs" target="_blank">https://caddyserver.com/docs</a></p></section><section><h3>常见问题<a href="#常见问题"><span>#</span></a></h3><p>1、Caddy启动失败，打开ip访问地址显示的是 It works !
一些系统会自带apache2，而apache2会占用80端口，导致Caddy无法绑定端口，所以只要关掉就好了。</p><div><div><div><figure><figcaption><span></span><span>Terminal window</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>netstat</span><span> </span><span>-lntp</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># 我们可以通过这个命令查看是不是被其他软件占用了80端口。</span></div></div><div><div><div>4</div></div><div><span>不过apache2会默认开机自启动，如果不需要可以关闭自启动或者卸载apache2。</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>停止Apache2</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># CentOS系统</span></div></div><div><div><div>9</div></div><div><span>/etc/init.d/httpd</span><span> </span><span>stop</span></div></div><div><div><div>10</div></div><div><span># Debian/Ubuntu系统</span></div></div><div><div><div>11</div></div><div><span>/etc/init.d/apache2</span><span> </span><span>stop</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 尝试使用上面代码关闭，如果没效果或者提示什么错误无法关闭，那就用下面这个强行关闭进程。</span></div></div><div><div><div>14</div></div><div><span>kill</span><span> </span><span>-9</span><span> $(</span><span>ps</span><span> </span><span>-ef</span><span>|</span><span>grep</span><span> </span><span>"apache2"</span><span>|</span><span>grep</span><span> </span><span>-v</span><span> </span><span>"grep"</span><span>|</span><span>awk</span><span> </span><span>'{print $2}'</span><span>)</span></div></div><div><div><div>15</div></div><div><span>取消开机自启动</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span># CentOS 系统</span></div></div><div><div><div>18</div></div><div><span>chkconfig</span><span> </span><span>--del</span><span> </span><span>httpd</span></div></div><div><div><div>19</div></div><div><span># Debian/Ubuntu 系统</span></div></div><div><div><div>20</div></div><div><span>update-rc.d</span><span> </span><span>-f</span><span> </span><span>apache2</span><span> </span><span>remove</span></div></div><div><div><div>21</div></div><div><span>卸载Apache2</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span># CentOS 系统</span></div></div><div><div><div>24</div></div><div><span>yum</span><span> </span><span>remove</span><span> </span><span>httpd</span></div></div><div><div><div>25</div></div><div><span># Debian/Ubuntu 系统</span></div></div><div><div><div>26</div></div><div><span>apt-get</span><span> </span><span>remove</span><span> </span><span>--purge</span><span> </span><span>apache2</span></div></div><div><div><div>27</div></div><div><span>关闭Apache2后，就可以尝试启动Caddy，并试试能不能打开网页。</span></div></div><div><div><div>28</div></div><div>
</div></div><div><div><div>29</div></div><div><span>/etc/init.d/caddy</span><span> </span><span>start</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>2、启动Caddy后，无法访问
这个可能是防火墙的问题，开放防火墙端口即可。</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>iptables</span><span> </span><span>-I</span><span> </span><span>INPUT</span><span> </span><span>-m</span><span> </span><span>state</span><span> </span><span>--state</span><span> </span><span>NEW</span><span> </span><span>-m</span><span> </span><span>tcp</span><span> </span><span>-p</span><span> </span><span>tcp</span><span> </span><span>--dport</span><span> </span><span>端口</span><span> </span><span>-j</span><span> </span><span>ACCEPT</span></div></div><div><div><div>2</div></div><div><span>iptables</span><span> </span><span>-I</span><span> </span><span>INPUT</span><span> </span><span>-m</span><span> </span><span>state</span><span> </span><span>--state</span><span> </span><span>NEW</span><span> </span><span>-m</span><span> </span><span>udp</span><span> </span><span>-p</span><span> </span><span>udp</span><span> </span><span>--dport</span><span> </span><span>端口</span><span> </span><span>-j</span><span> </span><span>ACCEPT</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span># 删除防火墙规则，内容一样把 -I 换成 -D 就行了：</span></div></div><div><div><div>5</div></div><div><span>iptables</span><span> </span><span>-D</span><span> </span><span>INPUT</span><span> </span><span>-m</span><span> </span><span>state</span><span> </span><span>--state</span><span> </span><span>NEW</span><span> </span><span>-m</span><span> </span><span>tcp</span><span> </span><span>-p</span><span> </span><span>tcp</span><span> </span><span>--dport</span><span> </span><span>端口</span><span> </span><span>-j</span><span> </span><span>ACCEPT</span></div></div><div><div><div>6</div></div><div><span>iptables</span><span> </span><span>-D</span><span> </span><span>INPUT</span><span> </span><span>-m</span><span> </span><span>state</span><span> </span><span>--state</span><span> </span><span>NEW</span><span> </span><span>-m</span><span> </span><span>udp</span><span> </span><span>-p</span><span> </span><span>udp</span><span> </span><span>--dport</span><span> </span><span>端口</span><span> </span><span>-j</span><span> </span><span>ACCEPT</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>3、SSL证书签发失败
比如报错<code>acme: error: 400 :: urn:ietf:params:acme:error:connection :: Error getting validation data, url:</code>，检查下防火墙端口，需要开启80和443端口，然后重启即可。</p></section></section>
<section><h2>0x02 PHP<a href="#0x02-php"><span>#</span></a></h2><section><h3>安装<a href="#安装-1"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>-y</span><span> </span><span>php7.3</span><span> </span><span>php7.3-fpm</span><span> </span><span>php7.3-cli</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>配置<a href="#配置"><span>#</span></a></h3><p>编辑<code>www.conf</code>文件</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>nano</span><span> </span><span>/etc/php/7.3/fpm/pool.d/www.conf</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>取消下面的注释。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>listen.owner</span><span><span> </span><span>=</span><span> www-data</span></span></div></div><div><div><div>2</div></div><div><span>listen.group</span><span><span> </span><span>=</span><span> www-data</span></span></div></div><div><div><div>3</div></div><div><span>listen.mode</span><span><span> </span><span>=</span><span> 0660</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>保存并退出</p><p>将caddy添加至<code>www-data</code>组</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>usermod</span><span> </span><span>-a</span><span> </span><span>-G</span><span> </span><span>www-data</span><span> </span><span>caddy</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>开机启动</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>systemctl</span><span> </span><span>start</span><span> </span><span>php7.3-fpm</span></div></div><div><div><div>2</div></div><div><span>systemctl</span><span> </span><span>enable</span><span> </span><span>php7.3-fpm</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>配置<code>Caddyfile</code>php</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#添加语句</span></div></div><div><div><div>2</div></div><div><span>fastcgi / /run/php/php7.3-fpm.sock php {</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>ext .php</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>split .php</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>index index.php</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>例如：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>http://example.com {</span></div></div><div><div><div>2</div></div><div><span><span>     </span></span><span>root /var/www/html</span></div></div><div><div><div>3</div></div><div><span><span>     </span></span><span>log /var/log/caddy/hakase-labs.log</span></div></div><div><div><div>4</div></div><div><span><span>     </span></span><span>errors /var/log/caddy/errors.log</span></div></div><div><div><div>5</div></div><div><span><span>     </span></span><span>tls off</span></div></div><div><div><div>6</div></div><div><span><span>     </span></span><span>gzip</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span><span>     </span></span><span># PHP-FPM Configuration for Caddy</span></div></div><div><div><div>9</div></div><div><span><span>     </span></span><span>fastcgi / /run/php/php7.0-fpm.sock php {</span></div></div><div><div><div>10</div></div><div><span><span>         </span></span><span>ext .php</span></div></div><div><div><div>11</div></div><div><span><span>         </span></span><span>split .php</span></div></div><div><div><div>12</div></div><div><span><span>         </span></span><span>index index.php</span></div></div><div><div><div>13</div></div><div><span><span>     </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重启Caddy和php-fpm即可。</p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/210/</id>
      <title type="text">[Golang]ssh登录及执行命令</title>
      <published>2019-11-04T11:01:00.000Z</published>
      <updated>2019-11-04T12:24:08.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/210/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>main</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>import</span><span> (</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"fmt"</span></div></div><div><div><div>5</div></div><div><span>  </span><span>"github.com/mitchellh/go-homedir"</span></div></div><div><div><div>6</div></div><div><span>  </span><span>"golang.org/x/crypto/ssh"</span></div></div><div><div><div>7</div></div><div><span>  </span><span>"io/ioutil"</span></div></div><div><div><div>8</div></div><div><span>  </span><span>"log"</span></div></div><div><div><div>9</div></div><div><span>  </span><span>"time"</span></div></div><div><div><div>10</div></div><div><span>)</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>13</div></div><div><span>  </span><span>re</span><span>,</span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>sshL</span><span>(</span><span>"192.168.199.1"</span><span>,</span><span>"root"</span><span>,</span><span>"rehttPassword"</span><span>,</span><span>"password"</span><span>,</span><span>""</span><span>,</span><span>"uname -a"</span><span>,</span><span>22</span><span>)</span></div></div><div><div><div>14</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span>{</span></div></div><div><div><div>15</div></div><div><span>  </span><span>fmt</span><span>.</span><span>println</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span>  </span><span>fmt</span><span>.</span><span>println</span><span>(</span><span>string</span><span>(</span><span>re</span><span>))</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>func</span><span> </span><span>sshL</span><span><span>(</span><span>sshHost</span><span>,</span><span>sshUser</span><span>,</span><span>sshPassword</span><span>,</span><span>sshType</span><span>,</span><span>sshKeyPath</span><span>,</span><span>command</span><span> </span></span><span>string</span><span><span>,</span><span>sshPort</span><span> </span></span><span>int</span><span>) ([]</span><span>byte</span><span>,</span><span>error</span><span>) {</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>  </span><span>//创建sshp登陆配置</span></div></div><div><div><div>23</div></div><div><span>  </span><span>config</span><span><span> </span><span>:=</span><span> </span><span>&amp;</span></span><span>ssh</span><span>.</span><span>ClientConfig</span><span>{</span></div></div><div><div><div>24</div></div><div><span>    </span><span>Timeout</span><span>:         </span><span>time</span><span>.</span><span>Second</span><span>,</span><span>//ssh 连接time out 时间一秒钟, 如果ssh验证错误 会在一秒内返回</span></div></div><div><div><div>25</div></div><div><span>    </span><span>User</span><span>:            </span><span>sshUser</span><span>,</span></div></div><div><div><div>26</div></div><div><span>    </span><span>HostKeyCallback</span><span>: </span><span>ssh</span><span>.</span><span>InsecureIgnoreHostKey</span><span>(), </span><span>//这个可以， 但是不够安全</span></div></div><div><div><div>27</div></div><div><span>    </span><span>//HostKeyCallback: hostKeyCallBackFunc(h.Host),</span></div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span>  </span><span>if</span><span> </span><span>sshType</span><span><span> </span><span>==</span><span> </span></span><span>"password"</span><span> {</span></div></div><div><div><div>30</div></div><div><span>    </span><span>config</span><span>.</span><span>Auth</span><span><span> </span><span>=</span><span> []</span></span><span>ssh</span><span>.</span><span>AuthMethod</span><span>{</span><span>ssh</span><span>.</span><span>Password</span><span>(</span><span>sshPassword</span><span>)}</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>32</div></div><div><span>    </span><span>config</span><span>.</span><span>Auth</span><span><span> </span><span>=</span><span> []</span></span><span>ssh</span><span>.</span><span>AuthMethod</span><span>{</span><span>publicKeyAuthFunc</span><span>(</span><span>sshKeyPath</span><span>)}</span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div>
</div></div><div><div><div>37</div></div><div><span>  </span><span>//dial 获取ssh client</span></div></div><div><div><div>38</div></div><div><span>  </span><span>addr</span><span><span> </span><span>:=</span><span> </span></span><span>fmt</span><span>.</span><span>Sprintf</span><span>(</span><span>"</span><span>%s</span><span>:</span><span>%d</span><span>"</span><span>, </span><span>sshHost</span><span>, </span><span>sshPort</span><span>)</span></div></div><div><div><div>39</div></div><div><span>  </span><span>sshClient</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>ssh</span><span>.</span><span>Dial</span><span>(</span><span>"tcp"</span><span>, </span><span>addr</span><span>, </span><span>config</span><span>)</span></div></div><div><div><div>40</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>41</div></div><div><span>    </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>"创建ssh client 失败"</span><span>,</span><span>err</span><span>)</span></div></div><div><div><div>42</div></div><div><span>    </span><span>return</span><span> </span><span>nil</span><span>,</span><span>err</span></div></div><div><div><div>43</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>44</div></div><div><span>  </span><span>defer</span><span> </span><span>sshClient</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>45</div></div><div>
</div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span>  </span><span>//创建ssh-session</span></div></div><div><div><div>48</div></div><div><span>  </span><span>session</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>sshClient</span><span>.</span><span>NewSession</span><span>()</span></div></div><div><div><div>49</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>50</div></div><div><span>    </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>"创建ssh session 失败"</span><span>,</span><span>err</span><span>)</span></div></div><div><div><div>51</div></div><div><span>    </span><span>return</span><span> </span><span>nil</span><span>,</span><span>err</span></div></div><div><div><div>52</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>53</div></div><div><span>  </span><span>defer</span><span> </span><span>session</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>54</div></div><div><span>  </span><span>//执行远程命令</span></div></div><div><div><div>55</div></div><div><span>  </span><span>combo</span><span>,</span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>session</span><span>.</span><span>CombinedOutput</span><span>(</span><span>command</span><span>)</span></div></div><div><div><div>56</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>57</div></div><div><span>    </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>"远程执行cmd 失败"</span><span>,</span><span>err</span><span>)</span></div></div><div><div><div>58</div></div><div><span>    </span><span>return</span><span> </span><span>nil</span><span>,</span><span>err</span></div></div><div><div><div>59</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>60</div></div><div><span>  </span><span>return</span><span> </span><span>combo</span><span>,</span><span>nil</span></div></div><div><div><div>61</div></div><div><span>}</span></div></div><div><div><div>62</div></div><div>
</div></div><div><div><div>63</div></div><div><span>func</span><span> </span><span>publicKeyAuthFunc</span><span><span>(</span><span>kPath</span><span> </span></span><span>string</span><span>) </span><span>ssh</span><span>.</span><span>AuthMethod</span><span> {</span></div></div><div><div><div>64</div></div><div><span>  </span><span>keyPath</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>homedir</span><span>.</span><span>Expand</span><span>(</span><span>kPath</span><span>)</span></div></div><div><div><div>65</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>66</div></div><div><span>    </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>"find key's home dir failed"</span><span>, </span><span>err</span><span>)</span></div></div><div><div><div>67</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>68</div></div><div><span>  </span><span>key</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>ioutil</span><span>.</span><span>ReadFile</span><span>(</span><span>keyPath</span><span>)</span></div></div><div><div><div>69</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>70</div></div><div><span>    </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>"ssh key file read failed"</span><span>, </span><span>err</span><span>)</span></div></div><div><div><div>71</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>72</div></div><div><span>  </span><span>// Create the Signer for this private key.</span></div></div><div><div><div>73</div></div><div><span>  </span><span>signer</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>ssh</span><span>.</span><span>ParsePrivateKey</span><span>(</span><span>key</span><span>)</span></div></div><div><div><div>74</div></div><div><span>  </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>75</div></div><div><span>    </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>"ssh key signer failed"</span><span>, </span><span>err</span><span>)</span></div></div><div><div><div>76</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>77</div></div><div><span>  </span><span>return</span><span> </span><span>ssh</span><span>.</span><span>PublicKeys</span><span>(</span><span>signer</span><span>)</span></div></div><div><div><div>78</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/206/</id>
      <title type="text">[杂项]handsome启用随机图片,将首页头图与文章头图设为一致</title>
      <published>2019-10-26T13:57:00.000Z</published>
      <updated>2019-10-26T14:07:32.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/206/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>0x00<a href="#0x00"><span>#</span></a></h2><p>handsome启用随机图片时,头图会被随机更换,但不能达到首页和文章头图一致</p></section>
<section><h2>0x01 思路<a href="#0x01-思路"><span>#</span></a></h2><p>通过JS在首页刷新完后获取对应文章的随机头图地址,再将头图地址放在文章的地址后面<code>p_i</code>里
加载文章时通过<code>p_i</code>将首页头图显示出来
</p><figure><img alt="随机图片" loading="lazy" width="1126" height="763" src="/_astro/206.1.ti4lTqHP_bGFnB.webp" /><figcaption>随机图片</figcaption></figure><p></p><p></p><figure><img alt="随机图片" loading="lazy" width="1137" height="756" src="/_astro/206.2.DN-4K0EG_Z1Tgej.webp" /><figcaption>随机图片</figcaption></figure><p></p><p></p><figure><img alt="固定一致图片" loading="lazy" width="1158" height="922" src="/_astro/206.3.B0IHVZJI_Z1aAWs5.webp" /><figcaption>固定一致图片</figcaption></figure><p></p></section>
<section><h2>0x02 代码<a href="#0x02-代码"><span>#</span></a></h2><p>适用于<code>/archives/{cid}/</code>永久链接
随机头图存放地址<code>/usr/themes/handsome/usr/img/sj/</code>
可根据自己实际情况更改
将代码放进<code>自定义js</code>和PJAX中</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>if</span><span><span> (</span><span>window</span><span>.</span></span><span>location</span><span>.</span><span>pathname</span><span> </span><span>===</span><span> </span><span>"/"</span><span>) {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>var</span><span><span> </span><span>img</span><span> </span></span><span>=</span><span><span>document</span><span>.</span></span><span>getElementsByClassName</span><span>(</span><span>"item-thumb lazy"</span><span>);</span></div></div><div><div><div>3</div></div><div><span>    </span><span>var</span><span><span> </span><span>a</span></span><span>=</span><span><span>document</span><span>.</span></span><span>getElementsByClassName</span><span>(</span><span>"index-post-img"</span><span>)</span></div></div><div><div><div>4</div></div><div><span>    </span><span>for</span><span> (</span><span>var</span><span><span> </span><span>i</span><span> </span></span><span>=</span><span> </span><span>0</span><span><span>; </span><span>i</span><span> </span></span><span>&lt;</span><span><span> </span><span>a</span><span>.</span></span><span>length</span><span><span>; </span><span>i</span></span><span>++</span><span>) {</span></div></div><div><div><div>5</div></div><div><span>        </span><span>var</span><span><span> </span><span>yurl</span><span> </span></span><span>=</span><span><span> </span><span>a</span><span>[</span><span>i</span><span>].</span></span><span>getElementsByTagName</span><span>(</span><span>"a"</span><span>)[</span><span>0</span><span>].</span><span>getAttribute</span><span>(</span><span>"href"</span><span>);</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>url</span><span>=</span><span><span>img</span><span>[</span><span>i</span><span>].</span></span><span>style</span><span>.</span><span>backgroundImage</span><span>.</span><span>split</span><span>(</span><span>"</span><span>\"</span><span>"</span><span>)[</span><span>1</span><span>].</span><span>split</span><span>(</span><span>"/"</span><span>)[</span><span>9</span><span>].</span><span>split</span><span>(</span><span>"."</span><span>)[</span><span>0</span><span>]</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>a</span><span>[</span><span>i</span><span>].</span><span>getElementsByTagName</span><span>(</span><span>"a"</span><span>)[</span><span>0</span><span>].</span><span>setAttribute</span><span>(</span><span>"href"</span><span><span>,</span><span>yurl</span></span><span>+</span><span>"?p_i="</span><span>+</span><span><span>url</span><span>);</span></span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span>}</span><span>else</span><span> </span><span>if</span><span> (</span><span>GetQueryString</span><span>(</span><span>"p_i"</span><span>)</span><span>!==</span><span>null</span><span>) {</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>document</span><span>.</span><span>getElementsByClassName</span><span>(</span><span>"item-thumb lazy"</span><span>)[</span><span>0</span><span>].</span><span>style</span><span>.</span><span>backgroundImage</span><span>=</span><span>"url(</span><span>\"</span><span>/usr/themes/handsome/usr/img/sj/"</span><span>+</span><span>GetQueryString</span><span>(</span><span>"p_i"</span><span>)</span><span>+</span><span>".jpg</span><span>\"</span><span>)"</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>}</span></div></div><div><div><div>13</div></div><div><span>function</span><span> </span><span>GetQueryString</span><span><span>(</span><span>name</span><span>)</span></span></div></div><div><div><div>14</div></div><div><span>{</span></div></div><div><div><div>15</div></div><div><span>     </span><span>var</span><span><span> </span><span>reg</span><span> </span></span><span>=</span><span> </span><span>new</span><span> </span><span>RegExp</span><span>(</span><span>"(^|&amp;)"</span><span>+</span><span><span> </span><span>name</span><span> </span></span><span>+</span><span>"=([^&amp;]*)(&amp;|$)"</span><span>);</span></div></div><div><div><div>16</div></div><div><span>     </span><span>var</span><span><span> </span><span>r</span><span> </span></span><span>=</span><span><span> </span><span>window</span><span>.</span></span><span>location</span><span>.</span><span>search</span><span>.</span><span>substr</span><span>(</span><span>1</span><span>).</span><span>match</span><span><span>(</span><span>reg</span><span>);</span></span></div></div><div><div><div>17</div></div><div><span>     </span><span>if</span><span><span>(</span><span>r</span></span><span>!=</span><span>null</span><span>)</span><span>return</span><span>  </span><span>unescape</span><span><span>(</span><span>r</span><span>[</span></span><span>2</span><span>]); </span><span>return</span><span> </span><span>null</span><span>;</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/196/</id>
      <title type="text">[杂项]修复handsome透明模式bug</title>
      <published>2019-10-25T05:49:00.000Z</published>
      <updated>2019-10-25T06:09:02.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/196/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>0x00<a href="#0x00"><span>#</span></a></h2><p>handsome开启了炫酷透明模式后,<code>搜索框</code>,<code>音乐栏</code>和<code>提示栏</code>会变透明而看不清字.</p></section>
<section><h2>0x01 修复<a href="#0x01-修复"><span>#</span></a></h2><p>在<code>自定义CSS</code>添加代码:</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#skPlayer</span><span> </span><span>.skPlayer-list</span><span> {</span></div></div><div><div><div>2</div></div><div><span>background-color: </span><span>rgba</span><span>(</span><span>0</span><span>,</span><span>0</span><span>,</span><span>0</span><span>,</span><span>0.8</span><span>)</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span> </span><span>.dropdown-menu</span><span>{</span></div></div><div><div><div>6</div></div><div><span>background-color: </span><span>rgba</span><span>(</span><span>0</span><span>,</span><span>0</span><span>,</span><span>0</span><span>,</span><span>0.8</span><span>)</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>前面<code>0,0,0</code>是rgb,后面<code>0.8</code>是透明度,可自行调整
</p><figure><img alt="1.png" loading="lazy" width="417" height="445" src="/_astro/196.1.BaTXCYj9_3PoR3.webp" /><figcaption>1.png</figcaption></figure><p></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/188/</id>
      <title type="text">[杂项]handsome主题提示php函数损坏或主题文件缺失</title>
      <published>2019-10-24T15:18:34.000Z</published>
      <updated>2019-10-24T15:18:51.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/188/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>提示<code>php缺失函数或者模块支持或者主题不完整,请联系作者.</code>
原因是文件权限出了问题
将主题目录下面的<code>lisence</code>文件给777权限即可</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/185/</id>
      <title type="text">[杂项]去除handsome主题的时光机头图的蒙层</title>
      <published>2019-10-24T15:09:00.000Z</published>
      <updated>2019-10-24T16:34:31.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/185/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p><img alt="" loading="lazy" width="1221" height="394" src="/_astro/185.1.CRhDtBlv_ZebgkK.webp" />
如图,图片上有一层”灰蒙蒙”的蒙版,控制它的class name是<code>bg-while-opacity</code>,只需要添加JS代码将它去除即可.</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>代码:</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>try</span><span>{</span></div></div><div><div><div>2</div></div><div><span><span>document</span><span>.</span></span><span>getElementsByClassName</span><span>(</span><span>"wrapper-lg bg-white-opacity"</span><span>)[</span><span>0</span><span>].</span><span>classList</span><span>.</span><span>remove</span><span>(</span><span>"bg-white-opacity"</span><span>);</span></div></div><div><div><div>3</div></div><div><span>}</span><span>catch</span><span><span>(</span><span>err</span><span>){}</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>去除效果:
<img alt="" loading="lazy" width="1206" height="329" src="/_astro/185.2.B8OmJg1A_ZxbDT.webp" /></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/178/</id>
      <title type="text">【Linux】所遇问题及解答</title>
      <published>2019-10-20T00:00:00.000Z</published>
      <updated>2019-10-24T08:39:50.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/178/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>用户权限<a href="#用户权限"><span>#</span></a></h1><section><h2>0x00 “This account is currently not available”<a href="#0x00-this-account-is-currently-not-available"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># usermod -s /bin/bash userName</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>0x01 使用指定用户运行命令<a href="#0x01-使用指定用户运行命令"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># su - userName -c "Command"</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>SSH<a href="#ssh"><span>#</span></a></h1><section><h2>0x00 使用代理<a href="#0x00-使用代理"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-o</span><span> </span><span>ProxyCommand="nc -x proxyIp:port %h %p"</span><span> </span><span>user@server</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/177/</id>
      <title type="text">【Arduino】ProMicro开发板</title>
      <published>2019-09-03T00:00:00.000Z</published>
      <updated>2019-10-24T08:39:09.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/177/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>这块Arduino板优点是价格相对便宜（淘宝10-20），引脚相对较多，体积较小（18mm*33mm)，其核心是ATmega32U4（兼容Arduino Leonardo)可用与模拟HID设备。</p></section>
<section><h1>0x01 开发环境<a href="#0x01-开发环境"><span>#</span></a></h1><p>在Arduino IDE中，打开“首选项”，在“附加开发板管理器网站”中添加网站后保存:</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>打开“开发板管理器”，搜索并安装“SparkFun AVR Boards”
在“开发板”中选择“SparkFun Pro Micro”，在“处理器”根据板子标注的频率选择对应的处理器。</p><p>当然也可以直接使用Arduino IDE“开发板”中的“Arduino Leonardo”</p></section>
<section><h1>0x02 “无法识别的USB设备”问题<a href="#0x02-无法识别的usb设备问题"><span>#</span></a></h1><p>当刷入程序失败时会导致Windows无法识别开发板，插入电脑识别不出USB串口
这时需要短接”GND”与”RST”进入Bootloader模式进行刷入程序
Bootloader模式只有几秒钟的时间，所以选择端口刷入的速度要快
步骤：</p><ol>
<li>Arduino IDE新建一个工程</li>
<li>点击上传，等待编译完成后显示“上传…”时，将开发板插入电脑</li>
<li>短接”GND”与”RST”，选择正确的端口</li>
<li>等待上传完成</li>
</ol></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/173/</id>
      <title type="text">【树莓派】使用GPS模块</title>
      <published>2019-07-31T00:00:00.000Z</published>
      <updated>2019-10-24T08:38:04.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/173/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>使用的GPS模块是ATGM336H-5N模块+IPX陶瓷有源天线</p><blockquote><p>ATGM336H-5N系列模块是小尺寸的高性能BDS/GNSS全星座定位 导航模块系列的总称。该系列模块产品都是基于中科微第四代低功耗GNSS SOC单芯片—AT6558，支持多种卫星导航系统，包括中国的BDS（北斗卫星 导航系统），美国的GPS，俄罗斯的GLONASS，欧盟的GALILEO，日本的QZSS 以及卫星增强系统SBAS（WAAS，EGNOS，GAGAN，MSAS）。AT6558 是一 款真正意义的六合一多模卫星导航定位芯片，包含32 个跟踪通道，可以同时接 收六个卫星导航系统的GNSS 信号，并且实现联合定位、导航与授时。 ATGM336H-5N本系列模块具有高灵敏度、低功耗、低成本等优势，适用于 车载导航、手持定位、可穿戴设备，可以直接替换Ublox MAX系列模块。</p></blockquote><p></p><figure><img alt="1.jpg" loading="lazy" width="4656" height="3496" src="/_astro/173.1.vldMa9rH_Z2b4yLa.webp" /><figcaption>1.jpg</figcaption></figure><p></p></section>
<section><h1>0x01接线<a href="#0x01接线"><span>#</span></a></h1><p></p><figure><img alt="2.jpg" loading="lazy" width="432" height="473" src="/_astro/173.2.CcTnJ_9i_Z1afh5t.webp" /><figcaption>2.jpg</figcaption></figure>
剩下的pps口暂时用不到，所以不接<p></p></section>
<section><h1>0x02配置<a href="#0x02配置"><span>#</span></a></h1><p>树莓派终端输入<code>sudo raspi-config</code>,选择<code>Interfacing Options</code>&gt;&gt;<code>Serial</code>。
在”Would you like a login shell to be accessible over serial?”选择<code>No</code>。
在”Would you like the serial port hardware to be enabled?”选择<code>Yes</code>。
重启</p><section><h3>手动配置<a href="#手动配置"><span>#</span></a></h3><p>打开<code>/boot</code>文件夹。
编辑<code>config.txt</code>文件，末尾添加</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>enable_uart</span><span><span>=</span><span>1</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编辑<code>cmdline.txt</code>文件，作以下修改</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>删除</span></div></div><div><div><div>2</div></div><div><span>console=serial0,115200</span></div></div><div><div><div>3</div></div><div><span>quiet</span></div></div><div><div><div>4</div></div><div><span>init=/usr/lib/raspi-config/init_resize.sh</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>0x03测试<a href="#0x03测试"><span>#</span></a></h1><p>串口接口为：<code>/dev/ttyS0</code>
这里使用<code>minicom</code>进行串口调试，没有的话使用apt安装即可。
命令行输入：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>minicom</span><span> </span><span>-b</span><span> </span><span>9600</span><span> </span><span>-D</span><span> </span><span>/dev/ttyS0</span></div></div><div><div><div>2</div></div><div><span># -b 波特率，ATGM336H-5N的波特率是9600</span></div></div><div><div><div>3</div></div><div><span># -D 接口</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果正常的话会显示这些：
</p><figure><img alt="3.jpg" loading="lazy" width="993" height="519" src="/_astro/173.3.B2xgCgT__16V4TS.webp" /><figcaption>3.jpg</figcaption></figure>
第一次使用这个模块、模块的距离与上次使用时的距离过远或模块电池电量耗尽时，需要等一分钟左右同步卫星信息。<p></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/171/</id>
      <title type="text">【Linux】记录命令操作</title>
      <published>2019-07-10T00:00:00.000Z</published>
      <updated>2019-10-24T08:35:11.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/171/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>在Linux上完整记录屏幕上的输入命令和输出结果，效果和屏幕录制差不多不过是记录命令行的。</p><p>主要用到<code>script</code>和<code>scriptreplay</code>这两个命令，一般在linux发行版都默认安装了。</p></section>
<section><h1>0x01 录制与播放<a href="#0x01-录制与播放"><span>#</span></a></h1><section><h2>录制<a href="#录制"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>script</span><span> </span><span>-t</span><span> 2&gt;</span><span>time.file</span><span> </span><span>-a</span><span> </span><span>scriptfile</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中<code>time.file</code>是时序记录文件，记录执行命令的时间；<code>scriptfile</code>是命令执行记录文件，记录所执行的命令。这些记录文件的名字可以自定义。</p><p>执行这句命令后，接下来的所有操作都会被记录下来。</p><p>加上<code>-q ,--quiet</code>参数可以是script一静默模式运行，不显示script启动和exit退出的命令，用户可以在完全察觉不到的情况下记录。</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>script</span><span> </span><span>-q</span><span> </span><span>-t</span><span> 2&gt;</span><span>time.file</span><span> </span><span>-a</span><span> </span><span>scriptfile</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>要使script停止下来，可以按下组合键<code>Ctrl+D</code>结束记录，也可以执行<code>exit</code>结束记录。</p></section><section><h2>播放<a href="#播放"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>scriptreplay</span><span> </span><span>time.file</span><span> </span><span>scriptfile</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>时序文件在前，命令文件在后。</p><p>添加参数<code>-d, --divisor &lt;num&gt;</code>可以调整播放速度的倍数（大于1：加快；小于1大于0：放慢）
加快10倍速播放：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>scriptreplay</span><span> </span><span>-d</span><span> </span><span>10</span><span> </span><span>time.file</span><span> </span><span>scriptfile</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>0x02 同步演示<a href="#0x02-同步演示"><span>#</span></a></h1><p>同步演示可以做到类似“直播”的效果。
使用参数<code>-f,--flush</code>在每次操作后立即刷新缓存进行实时写入文件。
使用端：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>script</span><span> </span><span>-f</span><span> </span><span>demo</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>演示端：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>scriptreplay</span><span> </span><span>-f</span><span> </span><span>demo</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>有些版本的<code>scriptreplay</code>没有<code>-f</code>参数，但可以使用<code>tail -f</code>来代替<code>scriptreplay</code>。</p></section>
<section><h1>0x03 录制命令执行过程<a href="#0x03-录制命令执行过程"><span>#</span></a></h1><p>使用参数<code>-c,--command</code>直接执行命令，不过执行的命令不是交互式的shell</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>script</span><span> </span><span>-qa</span><span> </span><span>log.out</span><span> </span><span>-c</span><span> </span><span>"echo hello"</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x04 用户登录后自动触发实时监控<a href="#0x04-用户登录后自动触发实时监控"><span>#</span></a></h1><p>这样可以监控用户登录后的操作。
原理就是让<code>script</code>命令在用户登录后自动运行。</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>#建立记录文件夹</span></div></div><div><div><div>2</div></div><div><span>mkdir</span><span> </span><span>-p</span><span> </span><span>/var/log/user_record</span></div></div><div><div><div>3</div></div><div><span>#编辑启动文件</span></div></div><div><div><div>4</div></div><div><span>nano</span><span> </span><span>/etc/profile</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在<code>profile</code>文件末尾添加</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>script</span><span> </span><span>-t</span><span> </span><span>-f</span><span> </span><span>-q</span><span> 2&gt;</span><span>/var/log/user_record/</span><span>$USER</span><span>-</span><span>$UID</span><span>-`</span><span>date</span><span> +%Y%m%d%H%M%S`</span><span>.time</span><span> </span><span>-a</span><span> </span><span>/var/log/user_record/</span><span>$USER</span><span>-</span><span>$UID</span><span>-`</span><span>date</span><span> +%Y%m%d%H%M%S`</span><span>.his</span></div></div><div><div><div>2</div></div><div><span>if</span><span> [ </span><span>"</span><span>$SHLVL</span><span>"</span><span><span> </span><span>=</span><span> </span></span><span>1</span><span> ]; </span><span>then</span></div></div><div><div><div>3</div></div><div><span>   </span><span>exit</span></div></div><div><div><div>4</div></div><div><span>fi</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/168/</id>
      <title type="text">【Golang】GO项目结构</title>
      <published>2019-06-25T00:00:00.000Z</published>
      <updated>2019-10-24T08:35:38.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/168/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>一般语言没有规定项目目录结构，但golang有规定，这样可以保证一致性。</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>Golang提供两个关键路径：</p><ul>
<li><code>GOROOT</code>指向GO的安装路径</li>
<li><code>GOPATH</code>指向项目路径</li>
</ul><p>一般GO安装好后<code>GOROOT</code>会自动指向安装路径，所以一般不需要动。除非你安装了几个不同版本的GO，<code>GOROOT</code>设置为指定版本的路径即可。</p><p><code>GOPATH</code>指向的项目目录目录结构：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>项目目录    &lt;-GOPATH指向的路径</span></div></div><div><div><div>2</div></div><div><span>├─bin       &lt;-编译后的可以执行文件存放的位置</span></div></div><div><div><div>3</div></div><div><span>├─pkg       &lt;-编译的中间文件存放位置</span></div></div><div><div><div>4</div></div><div><span>└─src       &lt;-项目源代码存放位置</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>├─项目          &lt;-项目源代码存放位置</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>└─vendor        &lt;-第三方开源代码存放位置</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>一般只需要创建<code>src</code>，<code>bin</code> <code>pkg</code>编译时会自动创建。
指定GOPATH:</p><p>Windows：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>set</span><span> </span><span>GOPATH</span><span><span>=</span><span>项目目录路径</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>Linux：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>export</span><span> </span><span>GOPATH</span><span><span>=</span><span>项目目录路径</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>假如项目名为<code>test</code>，使用<code>go install test</code>进行编译
其项目文件结构：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>.</span></div></div><div><div><div>2</div></div><div><span>├─bin       &lt;-bin目录会自动生成</span></div></div><div><div><div>3</div></div><div><span>|   └─test      &lt;-编译后的可执行文件</span></div></div><div><div><div>4</div></div><div><span>└─src</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>└─test</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>├─main.go       &lt;-作为入口，必须命名为main.go</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>└─Hello         &lt;-文件夹名随意</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>└─hello.go  &lt;-文件名随意</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption><span>main.go</span></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>main</span><span>        </span><span>//项目目录根目录和main.go的包名都为main</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>import</span><span> (</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"test/Hello"</span><span>    </span><span>//指定目录</span></div></div><div><div><div>5</div></div><div><span>)</span></div></div><div><div><div>6</div></div><div><span>func</span><span> </span><span>main</span><span>()  {</span></div></div><div><div><div>7</div></div><div><span>  </span><span>Hello</span><span>.</span><span>Hello</span><span>()   </span><span>//调用Hello目录的hello.go中的Hello()函数</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption><span>hello.go</span></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>Hello</span><span>   </span><span>//包名为该文件所在的目录名</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>import</span><span> </span><span>"fmt"</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>func</span><span> </span><span>Hello</span><span>() {  </span><span>//被跨目录调用的函数名首字母需要大写</span></div></div><div><div><div>6</div></div><div><span>  </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>"hello!!!"</span><span>)</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>快捷编译脚本,将脚本放在项目目录根目录下（<code>src</code>同目录下）:</p><div><div><div><figure><figcaption><span>install.sh</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/usr/bin/env bash</span></div></div><div><div><div>2</div></div><div><span>if</span><span><span> [ </span><span>!</span><span> </span><span>-f</span><span> install ]; </span></span><span>then</span></div></div><div><div><div>3</div></div><div><span>echo</span><span> </span><span>'install must be run within its container folder'</span><span> 1&gt;&amp;2</span></div></div><div><div><div>4</div></div><div><span>exit</span><span> </span><span>1</span></div></div><div><div><div>5</div></div><div><span>fi</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>CURDIR</span><span>=</span><span>`</span><span>pwd</span><span>`</span></div></div><div><div><div>8</div></div><div><span>OLDGOPATH</span><span>=</span><span>"</span><span>$GOPATH</span><span>"</span></div></div><div><div><div>9</div></div><div><span>export</span><span> </span><span>GOPATH</span><span>=</span><span>"</span><span>$CURDIR</span><span>"</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>gofmt</span><span> </span><span>-w</span><span> </span><span>src</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>go</span><span> </span><span>install</span><span> </span><span>test</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>export</span><span> </span><span>GOPATH</span><span>=</span><span>"</span><span>$OLDGOPATH</span><span>"</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>echo</span><span> </span><span>'finished'</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><div><div><figure><figcaption><span>install.bat</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>@</span><span>echo</span><span> </span><span>off</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>setlocal</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>if</span><span> </span><span>exist</span><span> install.bat </span><span>goto</span><span> ok</span></div></div><div><div><div>6</div></div><div><span>echo</span><span> install.bat must be run from its folder</span></div></div><div><div><div>7</div></div><div><span>goto</span><span> end</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>: ok</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>set</span><span> </span><span>OLDGOPATH</span><span>=</span><span>%GOPATH%</span></div></div><div><div><div>12</div></div><div><span>set</span><span> </span><span>GOPATH</span><span><span>=</span><span>%~dp0</span></span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>gofmt -w src</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span>go install test</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>:</span><span>end</span></div></div><div><div><div>19</div></div><div><span>echo</span><span> finished</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/167/</id>
      <title type="text">【Linux】Oh My ZSH</title>
      <published>2019-06-17T00:00:00.000Z</published>
      <updated>2019-10-24T08:32:22.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/167/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p><code>shell</code>有许多种类型，linux里默认的是<code>bash</code>。虽然<code>bash</code>的功能非常强大，但界面不怎么炫酷，提示功能也不怎么强大.</p><p>而<code>zsh</code>的功能强大DIY性强，但又因配置过于复杂，使得大多数人望而止步只有少部分极客使用。</p><p>后来有人创建了<code>oh-my-zsh</code>开源项目，由用户社区共同维护。<code>oh-my-zsh</code>将zsh配置简化，就算是小白也能简单快速配置使用。
配置完成后，你可以充分利用数百个强大的插件和漂亮的主题。在咖啡馆陌生人会问你:“这真是太棒了！你是计算机天才吗？”（滑稽）</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>环境要求：</p><ul>
<li>MacOS或Linux类Unix系统</li>
<li>需要提前安装zsh，且版本需高于v4.3.9，ubuntu与debain系操作系统输入<code>apt install zsh</code>即可安装成功，其他系统这里<a href="https://github.com/robbyrussell/oh-my-zsh/wiki/Installing-ZSH" target="_blank">安装方法</a>。</li>
<li>系统要有<code>wget</code>或<code>curl</code>工具</li>
<li>需要<code>git</code>工具</li>
</ul><section><h2>安装<a href="#安装"><span>#</span></a></h2><p>使用<code>wget</code>或<code>curl</code>，选择一个即可</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sh</span><span> </span><span>-c</span><span> </span><span>"$(</span><span>wget</span><span> </span><span>-O-</span><span> https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sh</span><span> </span><span>-c</span><span> </span><span>"$(</span><span>curl</span><span> </span><span>-fsSL</span><span> https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>脚本无误执行完即安装成功。</p></section></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><section><h2>主题<a href="#主题"><span>#</span></a></h2><p><code>oh-my-zsh</code>自带大量炫酷主题，这里<a href="https://github.com/robbyrussell/oh-my-zsh/wiki/Themes" target="_blank">查看相关主题截图</a>。</p><section><h3>更改主题<a href="#更改主题"><span>#</span></a></h3><p>编辑文件<code>~/.zshrc</code>找到：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ZSH_THEME</span><span>=</span><span>"robbyrussell"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>将引号内文字替换为想要换的主题名字即可。</p><section><h4>替换字体<a href="#替换字体"><span>#</span></a></h4><p>有些主题需要替换<code>Powerline Fonts</code>字体，否则个别符号会显示错误。
ubuntu/debain:</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>fonts-powerline</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>WSL (使用PowerShell):</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span><span>git clone https:</span><span>//</span></span><span>github.com</span><span><span>/</span><span>powerline</span><span>/</span><span>fonts.git</span></span></div></div><div><div><div>2</div></div><div><span>cd fonts</span></div></div><div><div><div>3</div></div><div><span><span>.</span><span>/</span><span>install.sp1</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其他Linux或MacOS：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>git</span><span> </span><span>clone</span><span> </span><span>https://github.com/powerline/fonts.git</span></div></div><div><div><div>2</div></div><div><span>cd</span><span> </span><span>fonts</span></div></div><div><div><div>3</div></div><div><span>./install.sh</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>安装完字体后在终端设置进行设置即可。</p></section></section></section><section><h2>插件<a href="#插件"><span>#</span></a></h2><p>Oh My ZSH有许多插件
这里安装一个命令自动补全插件<a href="http://mimosa-pudica.net/zsh-incremental.html" target="_blank">incr.zsh</a></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>wget</span><span> </span><span>http://mimosa-pudica.net/src/incr-0.2.zsh</span></div></div><div><div><div>2</div></div><div><span>mkdir</span><span> </span><span>~/.oh-my-zsh/plugins/incr</span></div></div><div><div><div>3</div></div><div><span>mv</span><span> </span><span>incr-0.2.zsh</span><span> </span><span>~/.oh-my-zsh/plugins/incr/</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>修改<code>.zshrc</code>文件，在最后一行添加：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>source</span><span> </span><span>~/.oh-my-zsh/plugins/incr/incr</span><span>*</span><span>.zsh</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>更新配置：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>source</span><span> </span><span>~/.zshrc</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/162/</id>
      <title type="text">【计算机网络】通过ssh端口转发建立网络隧道</title>
      <published>2019-05-22T00:00:00.000Z</published>
      <updated>2019-10-24T08:31:39.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/162/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><section><h2>概述<a href="#概述"><span>#</span></a></h2><blockquote><p>SSH 会自动加密和解密所有 SSH 客户端与服务端之间的网络数据。但是，SSH 还同时提供了一个非常有用的功能，这就是端口转发。它能够将其他 TCP 端口的网络数据通过 SSH 链接来转发，并且自动提供了相应的加密及解密服务。这一过程有时也被叫做“隧道”（tunneling）。这是因为 SSH 为其他 TCP 连接提供了一个安全的通道，避免了用户名，密码以及隐私信息的明文传输。例如，Telnet，SMTP，LDAP 这些 TCP 应用。</p></blockquote><p>某些特殊的网络环境中的防火墙限制访问一些端口，但能进行ssh连接，在这种情况下可以使用ssh将限制访问的tcp进行转发访问。</p></section></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><section><h2>本地转发<a href="#本地转发"><span>#</span></a></h2><p>将服务器的限制访问的端口转发到客户端本地。
</p><figure><img alt="1.jpg" loading="lazy" width="403" height="203" src="/_astro/162.1.DKd_Ba5w_ytwdU.webp" /><figcaption>1.jpg</figcaption></figure>
当没有服务器ssh登录的权限时，但有其他可以访问被限制的服务器端口的设备的ssh登录权限时，将此台设备作为跳板来访问。
<figure><img alt="2.jpg" loading="lazy" width="528" height="192" src="/_astro/162.2.fhFZbhqH_Z2bKG9H.webp" /><figcaption>2.jpg</figcaption></figure><p></p><p>命令规则：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-L</span><span> [local </span><span>host:]&lt;local</span><span> </span><span>port&gt;:&lt;remote</span><span> </span><span>host&gt;:&lt;remote</span><span> </span><span>port&gt;</span><span> </span><span>&lt;ssh</span><span> </span><span>hostname&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>实例&amp;解释：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-L</span><span> </span><span>8001（指定本地端口）:服务器ip:8000（被限制访问的端口）</span><span> </span><span>root@服务器ip</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>ssh</span><span> </span><span>-L</span><span> </span><span>8001（指定本地端口）:服务器ip:8000（被限制访问的端口）</span><span> </span><span>root@跳板机ip</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>当ssh登录成功后就已经将服务器端口转发到客户端本地端口了，上面实例客户端访问地址：127.0.0.1&lt;8001&gt;</p><section><h3>注意<a href="#注意"><span>#</span></a></h3><ul>
<li>在上面的命令加一个<code>-g</code>可以让其他设备访问客户端</li>
</ul><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-L</span><span> </span><span>8000:服务器ip:8000</span><span> </span><span>root@服务器ip</span></div></div><div><div><div>2</div></div><div><span>等价于</span></div></div><div><div><div>3</div></div><div><span>ssh</span><span> </span><span>-L</span><span> </span><span>127.0.0.1:8000:服务器ip:8000</span><span> </span><span>root@服务器ip</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-g</span><span> </span><span>-L</span><span> </span><span>8000:服务器ip:8000</span><span> </span><span>root@服务器ip</span></div></div><div><div><div>2</div></div><div><span>等价于</span></div></div><div><div><div>3</div></div><div><span>ssh</span><span> </span><span>-L</span><span> </span><span>0.0.0.0:8000:服务器ip:8000</span><span> </span><span>root@服务器ip</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>转发时要一直保持ssh的连接，也就是不能关闭ssh的命令窗口。也可以添加<code>-qTfNn</code>用于告知ssh连接成功后就转到后台运行。</li>
</ul></section></section><section><h2>远程转发（反向代理）<a href="#远程转发反向代理"><span>#</span></a></h2><p>远程访问就是将本地内网端口的流量通过一台公网设备转发出来
</p><figure><img alt="3.jpg" loading="lazy" width="510" height="192" src="/_astro/162.3.B2I2xPmy_KgKwq.webp" /><figcaption>3.jpg</figcaption></figure>
命令格式：<p></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-g</span><span> </span><span>-R</span><span> [ssh </span><span>server</span><span> </span><span>host:]&lt;SSH</span><span> </span><span>server</span><span> </span><span>port&gt;:&lt;local</span><span> </span><span>host&gt;:&lt;local</span><span> </span><span>port&gt;</span><span> </span><span>&lt;SSH</span><span> </span><span>hostname&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>实例：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-g</span><span> </span><span>-R</span><span> </span><span>8000（指定公网设备的端口）:内网设备ip:8000（内网设备的端口）</span><span> </span><span>root@公网设备ip</span></div></div></code></pre><div><div></div><div></div></div></figure></div><section><h3>注意<a href="#注意-1"><span>#</span></a></h3><ul>
<li>和本地访问一样转发时不能关闭ssh命令窗口。也可以添加<code>-qTfNn</code>用于告知ssh连接成功后就转到后台运行。</li>
<li>转发失败时检查<code>/etc/ssh/sshd_config</code>文件，将<code>AllowTcpForwarding</code>选项设置为<code>yes</code>。</li>
</ul></section></section><section><h2>动态转发(Socks代理)<a href="#动态转发socks代理"><span>#</span></a></h2><p>开启一条Socks隧道。
前面的本地转发和远程转发都需要指定端口进行转发，而动态转发则不需要指定端口就可以转发（不建议使用这个来fq，因为该方法早已被GFW和谐），可以进行内网访问。
</p><figure><img alt="4.jpg" loading="lazy" width="419" height="221" src="/_astro/162.4.Cjparxf__12VkVa.webp" /><figcaption>4.jpg</figcaption></figure>
命令格式：<p></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-D</span><span> </span><span>&lt;local</span><span> </span><span>port&gt;</span><span> </span><span>&lt;SSH</span><span> </span><span>Server&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>实例：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh</span><span> </span><span>-D</span><span> </span><span>8000</span><span>(</span><span>本地指定的端口</span><span>) </span><span>root@进行转发的服务器ip（跳板）</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>ssh执行为后台任务<a href="#ssh执行为后台任务"><span>#</span></a></h2><p><code>ssh -qTfNn</code>用于建立纯端口转发用途的ssh连接，参数具体含义如下：</p><ul>
<li><code>-q</code>: quiet模式，忽视大部分的警告和诊断信息（比如端口转发时的各种连接错误）</li>
<li><code>-T</code>: 禁用tty分配(pseudo-terminal allocation)</li>
<li><code>-f</code>: 登录成功后即转为后台任务执行</li>
<li><code>-N</code>: 不执行远程命令（专门做端口转发）</li>
<li><code>-n</code>: 重定向stdin为/dev/null，用于配合-f后台任务</li>
</ul></section></section>
<section><h1>END<a href="#end"><span>#</span></a></h1></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/160/</id>
      <title type="text">【树莓派】配置usb口电流限制</title>
      <published>2019-05-16T00:00:00.000Z</published>
      <updated>2019-10-24T08:29:45.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/160/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>树莓派usb接口的默认电流只有600mA，而当接入对电流要求较高的设备时会出现问题导致工作不正常。
这里采用的是修改树莓派配置将最大电流提升为1.2A（电源芯片限制）。</p><p><strong>注意</strong></p><ul>
<li>这个方法会使树莓派主板过载，最坏情况会使树莓派主板报废！</li>
<li>如果需要的电流超过默认的600mA的50%以上则建议使用带电源接口的usb hub外接
<figure><img alt="QQ截图20190516224311.jpg" loading="lazy" width="638" height="479" src="/_astro/160.1.D6sfiV2V_Z2ttxU6.webp" /><figcaption>QQ截图20190516224311.jpg</figcaption></figure></li>
<li>本方案不适用树莓派zero版本</li>
</ul></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>本方案实现原理是使电流绕过usb电流保护芯片实现达到更大电流。
实现步骤：
修改 /boot/config.txt，在文件末尾添加：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>max_usb_current</span><span><span>=</span><span>1</span></span></div></div><div><div><div>2</div></div><div><span>current_limit_override</span><span><span>=</span><span>0x5A000020</span></span></div></div><div><div><div>3</div></div><div><span>avoid_warnings</span><span><span>=</span><span>2</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重新启动树莓派即可生效。</p></section>
<section><h1>END<a href="#end"><span>#</span></a></h1></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/158/</id>
      <title type="text">【树莓派】使用BerryBoot安装多系统</title>
      <published>2019-05-13T00:00:00.000Z</published>
      <updated>2019-10-24T08:24:43.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/158/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><blockquote><p>BerryBoot是一款基于树莓派启动的启动管理工具， 它最大的优势是可以在不通过SD卡的前提下在多个系统中选择启动， 你既可以将系统存放在卡上，也可以, 如果你需要更多空间的话，将系统运行在外接的硬盘上并配置BerryBoot只将SD卡作为一个启动器。
可以将它看作是一个引导系统</p></blockquote></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><ol>
<li>
<p>在<a href="https://berryboot.alexgoldcheidt.com/go/berryboot-home" target="_blank">这里</a>下载</p>
</li>
<li>
<p>下载后将其解压并将全部文件放入FAT32格式的空白SD卡，将SD卡插入树莓派，通电开机。</p>
</li>
<li>
<p>当树莓派的灯闪烁几下后会进入BerryBoot系统，在里面进行配置。</p>
</li>
<li>
<p>初次启动后第一个界面可以直接跳过，来到第二个界面选择系统安装位置，可以选择SD卡、usb设备或网络设备。</p>
</li>
<li>
<p>配置完第二个界面后来到第三个界面，在这可以在线下载系统并自动安装。如果要安装已经下载好的系统直接关闭这个界面即可。
提前下载好的系统安装：</p>
<ol>
<li>下载系统，这里推荐<a href="https://berryboot.alexgoldcheidt.com/images/" target="_blank">BerryServer</a>，BerryServer有大量适合树莓派的系统，也可以自己在BerryServer发布自己编译好的系统。</li>
<li>将下载好的系统文件解压至<code>xxxx.img</code>格式的文件。</li>
<li>将系统文件usb设备并将其插入树莓派。</li>
<li>在BerryBoot中鼠标左键长按<code>Add OS</code>选择<code>Install from USB stick</code>，选择系统文件即可。</li>
</ol>
</li>
<li>
<p>每次开机都会进入BerryBoot选择菜单，可以在<code>Edit config</code>的<code>cmdline.txt</code>中更改<code>bootmenutimeout=10</code>的倒计时，如果有其他设备（比如安装在USB设备中）就需要在<code>uEnv.txt</code>中添加<code>bootmenutimeout=10</code>或<code>nobootmenutimeout</code>表示不自动进入系统。如果要跳过BerryBoot可以将系统设为默认（set default），这样可以开机跳过BerryBoot直接进入选定的系统。
若要Openelec支持ssh, 还需要在cmdline.txt 最后添加ssh</p>
</li>
<li>
<p>重启几秒后即可进入选定安装后的系统。</p>
</li>
</ol><section><h3>#无屏幕情况下使用BerryBoot<a href="#无屏幕情况下使用berryboot"><span>#</span></a></h3><p>这里使用VNC进行远程访问，树莓派需要连上网线并与电脑保持在同一个局域网的同一网段。最简单的办法是共享本地连接, 并用一根网线连接树莓派和电脑。</p><ol>
<li>将BerryBoot系统文件中的<code>cmdline.txt</code>文件内容更改为：</li>
</ol><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>smsc95xx.turbo_mode=N elevator=deadline quiet bootmenutimeout=10 vncinstall ipv4=192.168.137.27/255.255.255.0/192.168.137.1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中<code>192.168.137.27</code>为局域网ip地址，<code>192.186.137.1</code>为局域网网段，可以根据自己情况更改，保证电脑能正常连接访问树莓派即可。</p><ol>
<li>树莓派通电并接上网线后，电脑上使用VNC客户端，地址输入<code>树莓派ip:5900</code></li>
</ol></section></section>
<section><h1>END<a href="#end"><span>#</span></a></h1></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/157/</id>
      <title type="text">【Linux】Ubuntu Server安装图形桌面及VNC远程桌面</title>
      <published>2019-05-08T00:00:00.000Z</published>
      <updated>2019-10-24T08:21:55.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/157/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>本篇采用xfce4轻量级图形桌面</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>安装桌面环境与VNC服务器：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>xfce4</span><span> </span><span>xfce4-goodies</span><span> </span><span>vnc4server</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>xdm</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果想新建一个用户：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>useradd</span><span> </span><span>-m</span><span> </span><span>userName</span><span> </span><span>-d</span><span> </span><span>/home/userName</span></div></div><div><div><div>2</div></div><div><span>passwd</span><span> </span><span>userName</span></div></div><div><div><div>3</div></div><div><span>在/etc/sudoers里面将userName添加进去</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>执行完后重启：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>shutdown</span><span> </span><span>now</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重启后执行：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>vnc4server</span></div></div><div><div><div>2</div></div><div><span>输入vnc密码</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>mv</span><span> </span><span>~/.vnc/xstartup</span><span> </span><span>~/.vnc/xstartup.bak</span></div></div><div><div><div>5</div></div><div><span>nano</span><span> </span><span>~/.vnc/xstartup</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>xstartup内容：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/sh</span></div></div><div><div><div>2</div></div><div><span>xrdb</span><span> </span><span>$HOME</span><span>/.Xresources</span></div></div><div><div><div>3</div></div><div><span>unset</span><span> </span><span>SESSION_MANAGER</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>unset</span><span> </span><span>DBUS_SESSION_BUS_ADDRESS</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>[ </span><span>-x</span><span> /etc/vnc/xstartup ] &amp;&amp; </span></span><span>exec</span><span> </span><span>/etc/vnc/xstartup</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>[ </span><span>-r</span><span> </span></span><span>$HOME</span><span>/.Xresources ] &amp;&amp; </span><span>xrdb</span><span> </span><span>$HOME</span><span>/.Xresources</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>vncconfig</span><span> </span><span>-iconic</span><span> &amp;</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>xfce4-session</span><span> &amp; </span><span>startxfce4</span><span> &amp;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>添加vnc服务器文件：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>nano</span><span> </span><span>/etc/init.d/vncserver</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>文件内容：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/bash</span></div></div><div><div><div>2</div></div><div><span>PATH</span><span>=</span><span>"</span><span>$PATH</span><span>:/usr/bin/"</span></div></div><div><div><div>3</div></div><div><span>export</span><span> </span><span>USER</span><span>=</span><span>"user"</span></div></div><div><div><div>4</div></div><div><span>DISPLAY</span><span>=</span><span>"1"</span></div></div><div><div><div>5</div></div><div><span>DEPTH</span><span>=</span><span>"16"</span></div></div><div><div><div>6</div></div><div><span>GEOMETRY</span><span>=</span><span>"1024x768"</span></div></div><div><div><div>7</div></div><div><span>OPTIONS</span><span>=</span><span>"-depth </span><span><span>${</span><span>DEPTH</span><span>}</span></span><span> -geometry </span><span><span>${</span><span>GEOMETRY</span><span>}</span></span><span> :</span><span><span>${</span><span>DISPLAY</span><span>}</span></span><span> -localhost"</span></div></div><div><div><div>8</div></div><div><span>.</span><span> </span><span>/lib/lsb/init-functions</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>授权：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>chmod</span><span> </span><span>+x</span><span> </span><span>~/.vnc/xstartup</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>chmod</span><span> </span><span>+x</span><span> </span><span>/etc/init.d/vncserver</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>开启服务：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>service</span><span> </span><span>vncserver</span><span> </span><span>start</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>打开vnc客户端
地址信息:</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>服务器ip:5901</span></div></div><div><div><div>2</div></div><div><span>或简写</span></div></div><div><div><div>3</div></div><div><span>服务器ip:1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输入密码
连接完成</p><section><h2>END<a href="#end"><span>#</span></a></h2></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/156/</id>
      <title type="text">【Linux】在AWS上配置人头识别环境</title>
      <published>2019-04-25T00:00:00.000Z</published>
      <updated>2019-10-24T08:20:48.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/156/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>这里使用<a href="https://github.com/aditya-vora/FCHD-Fully-Convolutional-Head-Detector" target="_blank">FCHD-Fully-Convolutional-Head-Detector</a>人头识别的开源项目</p><blockquote><p>系统：AWS Ubuntu Server 18.04 LTS(HVM)
类型：p2类型 (我使用的是p2.xlarge)</p></blockquote></section>
<section><h1>0x01 环境安装<a href="#0x01-环境安装"><span>#</span></a></h1><ol>
<li>首先更新系统,更新完建议重启
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>upgrade</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>安装所需要的工具
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>gcc</span><span> </span><span>make</span><span> </span><span>python3-pip</span><span> </span><span>unzip</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>安装CUDA
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>wget</span><span> </span><span>"https://developer.nvidia.com/compute/cuda/10.0/Prod/local_installers/cuda_10.0.130_410.48_linux"</span><span> </span><span>-O</span><span> </span><span>cuda.run</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>bash</span><span> </span><span>cuda.run</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
安装选项使用默认就好</li>
<li>安装所需要的依赖库
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>python3-tk</span><span> </span><span>-y</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>libsm-dev</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>命令行输入
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ldconfig</span><span> </span><span>/usr/local/cuda-10.0/lib64/</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>通过pip安装所需工具
总共需要安装以下工具：
·torch
·torchvision
·cupy-cuda100
·scikit-image
·opencv-python
·torchnet
命令：
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>###使用国内源会下载更快，这里使用清华的源</span></div></div><div><div><div>2</div></div><div><span>yuan</span><span>=</span><span>https://pypi.tuna.tsinghua.edu.cn/simple</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>pip3</span><span> </span><span>install</span><span> </span><span>https://download.pytorch.org/whl/cu100/torch-1.0.1.post2-cp36-cp36m-linux_x86_64.whl</span></div></div><div><div><div>5</div></div><div><span>pip3</span><span> </span><span>install</span><span> </span><span>torchvision</span><span> </span><span>cupy-cuda100</span><span> </span><span>scikit-image</span><span> </span><span>opencv-python</span><span> </span><span>torchnet</span><span> </span><span>-i</span><span> </span><span>$yuan</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ol></section>
<section><h1>0x02 部署<a href="#0x02-部署"><span>#</span></a></h1><ol>
<li>通过S3储存桶下载并解压文件：
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>wget</span><span> </span><span>https://s3.cn-north-1.amazonaws.com.cn/neural-network-model/FCHD-Fully-Convolutional-Head-Detector.zip</span></div></div><div><div><div>2</div></div><div><span>unzip</span><span> </span><span>FCHD-Fully-Convolutional-Head-Detector</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>下载一个视频放入<code>FCHD-Fully-Convolutional-Head-Detector/video</code>中</li>
<li>命令行输入：
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>python3</span><span> </span><span>head_detection_demo.py</span><span>  </span><span>--video_path</span><span> </span><span>video/视频文件名</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
若没有提示cuda错误即成功</li>
</ol></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/155/</id>
      <title type="text">【树莓派】温控风扇（golang)</title>
      <published>2019-04-13T00:00:00.000Z</published>
      <updated>2020-09-06T15:56:03.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/155/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>采用go语言编写，可编译直接运行
使用s8050三极管作为开关
使用14号针脚作为信号开关
2019-11-7 新增后台服务启动</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>package</span><span> </span><span>main</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>import</span><span> (</span></div></div><div><div><div>4</div></div><div><span>  </span><span>"bufio"</span></div></div><div><div><div>5</div></div><div><span>  </span><span>"flag"</span></div></div><div><div><div>6</div></div><div><span>  </span><span>"fmt"</span></div></div><div><div><div>7</div></div><div><span>  </span><span>"github.com/rehtt/gogpio"</span></div></div><div><div><div>8</div></div><div><span>  </span><span>"github.com/kardianos/service"</span></div></div><div><div><div>9</div></div><div><span>  </span><span>"log"</span></div></div><div><div><div>10</div></div><div><span>  </span><span>"os"</span></div></div><div><div><div>11</div></div><div><span>  </span><span>"strconv"</span></div></div><div><div><div>12</div></div><div><span>  </span><span>"time"</span></div></div><div><div><div>13</div></div><div><span>)</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>var</span><span> (</span></div></div><div><div><div>16</div></div><div><span>  </span><span>max</span><span>, </span><span>min</span><span>    </span><span>int</span></div></div><div><div><div>17</div></div><div><span>  </span><span>showTemp</span><span>, </span><span>h</span><span> </span><span>bool</span></div></div><div><div><div>18</div></div><div><span>)</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>func</span><span> </span><span>main</span><span>() {</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>  </span><span>flag</span><span>.</span><span>BoolVar</span><span><span>(</span><span>&amp;</span></span><span>h</span><span>, </span><span>"h"</span><span>, </span><span>false</span><span>, </span><span>"help"</span><span>)</span></div></div><div><div><div>23</div></div><div><span>  </span><span>flag</span><span>.</span><span>IntVar</span><span><span>(</span><span>&amp;</span></span><span>max</span><span>, </span><span>"m"</span><span>, </span><span>55</span><span>, </span><span>"开启风扇温度"</span><span>)</span></div></div><div><div><div>24</div></div><div><span>  </span><span>flag</span><span>.</span><span>IntVar</span><span><span>(</span><span>&amp;</span></span><span>min</span><span>, </span><span>"n"</span><span>, </span><span>50</span><span>, </span><span>"关闭风扇温度"</span><span>)</span></div></div><div><div><div>25</div></div><div><span>  </span><span>flag</span><span>.</span><span>BoolVar</span><span><span>(</span><span>&amp;</span></span><span>showTemp</span><span>, </span><span>"s"</span><span>, </span><span>false</span><span>, </span><span>"查看当前温度"</span><span>)</span></div></div><div><div><div>26</div></div><div><span>  </span><span>flag</span><span>.</span><span>Usage</span><span><span> </span><span>=</span><span> </span></span><span>help</span></div></div><div><div><div>27</div></div><div><span>  </span><span>flag</span><span>.</span><span>Parse</span><span>()</span></div></div><div><div><div>28</div></div><div><span>  </span><span>if</span><span> </span><span>h</span><span> {</span></div></div><div><div><div>29</div></div><div><span>    </span><span>flag</span><span>.</span><span>Usage</span><span>()</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>31</div></div><div><span>    </span><span>if</span><span><span> </span><span>!</span></span><span>showTemp</span><span> {</span></div></div><div><div><div>32</div></div><div><span>      </span><span>//服务</span></div></div><div><div><div>33</div></div><div><span>      </span><span>cfg</span><span><span> </span><span>:=</span><span> </span><span>&amp;</span></span><span>service</span><span>.</span><span>Config</span><span>{</span></div></div><div><div><div>34</div></div><div><span>        </span><span>Name</span><span>:        </span><span>"temp"</span><span>,</span></div></div><div><div><div>35</div></div><div><span>        </span><span>DisplayName</span><span>: </span><span>"RPI CPU Temp"</span><span>,</span></div></div><div><div><div>36</div></div><div><span>        </span><span>Description</span><span>: </span><span>"RPI CPU Temp"</span><span>,</span></div></div><div><div><div>37</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>38</div></div><div><span>      </span><span>prg</span><span><span> </span><span>:=</span><span> </span><span>&amp;</span></span><span>program</span><span>{}</span></div></div><div><div><div>39</div></div><div><span>      </span><span>s</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>service</span><span>.</span><span>New</span><span>(</span><span>prg</span><span>, </span><span>cfg</span><span>)</span></div></div><div><div><div>40</div></div><div><span>      </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>41</div></div><div><span>        </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>42</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>43</div></div><div><span>      </span><span>// logger 用于记录系统日志</span></div></div><div><div><div>44</div></div><div><span>      </span><span>logger</span><span>, </span><span>err</span><span><span> </span><span>:=</span><span> </span></span><span>s</span><span>.</span><span>Logger</span><span>(</span><span>nil</span><span>)</span></div></div><div><div><div>45</div></div><div><span>      </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>46</div></div><div><span>        </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>47</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>48</div></div><div><span>      </span><span>if</span><span> </span><span>len</span><span>(</span><span>os</span><span>.</span><span>Args</span><span><span>) </span><span>==</span><span> </span></span><span>2</span><span> { </span><span>//如果有命令则执行</span></div></div><div><div><div>49</div></div><div><span>        </span><span>err</span><span><span> </span><span>=</span><span> </span></span><span>service</span><span>.</span><span>Control</span><span>(</span><span>s</span><span>, </span><span>os</span><span>.</span><span>Args</span><span>[</span><span>1</span><span>])</span></div></div><div><div><div>50</div></div><div><span>        </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>51</div></div><div><span>          </span><span>log</span><span>.</span><span>Fatal</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>52</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>53</div></div><div><span><span>      </span></span><span>} </span><span>else</span><span> { </span><span>//否则说明是方法启动了</span></div></div><div><div><div>54</div></div><div><span>        </span><span>err</span><span><span> </span><span>=</span><span> </span></span><span>s</span><span>.</span><span>Run</span><span>()</span></div></div><div><div><div>55</div></div><div><span>        </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>56</div></div><div><span>          </span><span>logger</span><span>.</span><span>Error</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>57</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>58</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>59</div></div><div><span>      </span><span>if</span><span> </span><span>err</span><span><span> </span><span>!=</span><span> </span></span><span>nil</span><span> {</span></div></div><div><div><div>60</div></div><div><span>        </span><span>logger</span><span>.</span><span>Error</span><span>(</span><span>err</span><span>)</span></div></div><div><div><div>61</div></div><div><span><span>      </span></span><span>}</span></div></div><div><div><div>62</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>63</div></div><div><span>      </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>"当前温度："</span><span>, </span><span>t</span><span>(), </span><span>"°"</span><span>)</span></div></div><div><div><div>64</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>65</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>66</div></div><div>
</div></div><div><div><div>67</div></div><div><span>}</span></div></div><div><div><div>68</div></div><div>
</div></div><div><div><div>69</div></div><div><span>func</span><span> </span><span>t</span><span>() </span><span>int</span><span> {</span></div></div><div><div><div>70</div></div><div><span>  </span><span>txt</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>os</span><span>.</span><span>Open</span><span>(</span><span>"/sys/class/thermal/thermal_zone0/temp"</span><span>)</span></div></div><div><div><div>71</div></div><div><span>  </span><span>defer</span><span> </span><span>txt</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>72</div></div><div><span>  </span><span>buf</span><span><span> </span><span>:=</span><span> </span></span><span>bufio</span><span>.</span><span>NewReader</span><span>(</span><span>txt</span><span>)</span></div></div><div><div><div>73</div></div><div><span>  </span><span>t</span><span>, </span><span>_</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>buf</span><span>.</span><span>ReadLine</span><span>()</span></div></div><div><div><div>74</div></div><div><span>  </span><span>temp</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>strconv</span><span>.</span><span>Atoi</span><span>(</span><span>string</span><span>(</span><span>t</span><span>))</span></div></div><div><div><div>75</div></div><div><span>  </span><span>temp</span><span><span> </span><span>=</span><span> </span></span><span>temp</span><span><span> </span><span>/</span><span> </span></span><span>1000</span></div></div><div><div><div>76</div></div><div><span>  </span><span>return</span><span> </span><span>temp</span></div></div><div><div><div>77</div></div><div><span>}</span></div></div><div><div><div>78</div></div><div>
</div></div><div><div><div>79</div></div><div><span>func</span><span> </span><span>help</span><span>() {</span></div></div><div><div><div>80</div></div><div><span>  </span><span>fmt</span><span>.</span><span>Fprintln</span><span>(</span><span>os</span><span>.</span><span>Stderr</span><span>, </span><span>`使用：temp [选项] [服务操作]</span></div></div><div><div><div>81</div></div><div><span>选项：`</span><span>)</span></div></div><div><div><div>82</div></div><div><span>  </span><span>flag</span><span>.</span><span>PrintDefaults</span><span>()</span></div></div><div><div><div>83</div></div><div><span>  </span><span>fmt</span><span>.</span><span>Fprintln</span><span>(</span><span>os</span><span>.</span><span>Stderr</span><span>,</span><span>`</span></div></div><div><div><div>84</div></div><div><span>服务操作：</span></div></div><div><div><div>85</div></div><div><span><span>  </span></span><span>install    安装服务（开启服务必做）</span></div></div><div><div><div>86</div></div><div><span><span>  </span></span><span>start    运行服务</span></div></div><div><div><div>87</div></div><div><span><span>  </span></span><span>stop    停止服务</span></div></div><div><div><div>88</div></div><div><span><span>  </span></span><span>uninstall  卸载服务</span></div></div><div><div><div>89</div></div><div>
</div></div><div><div><div>90</div></div><div><span>示例：</span></div></div><div><div><div>91</div></div><div><span><span>  </span></span><span>temp -s      显示温度</span></div></div><div><div><div>92</div></div><div><span><span>  </span></span><span>temp install &amp;&amp; temp start    安装服务并启动</span></div></div><div><div><div>93</div></div><div><span><span>  </span></span><span>temp stop    停止服务</span></div></div><div><div><div>94</div></div><div><span><span>  </span></span><span>temp -m 50  start  带参数启动服务</span></div></div><div><div><div>95</div></div><div><span>启动服务需要root权限`</span><span>)</span></div></div><div><div><div>96</div></div><div><span>}</span></div></div><div><div><div>97</div></div><div>
</div></div><div><div><div>98</div></div><div><span>//服务</span></div></div><div><div><div>99</div></div><div><span>type</span><span> </span><span>program</span><span> </span><span>struct</span><span>{}</span></div></div><div><div><div>100</div></div><div>
</div></div><div><div><div>101</div></div><div><span>func</span><span><span> (</span><span>p </span><span>*</span></span><span>program</span><span>) </span><span>Start</span><span><span>(</span><span>s</span><span> </span></span><span>service</span><span>.</span><span>Service</span><span>) </span><span>error</span><span> {</span></div></div><div><div><div>102</div></div><div><span>  </span><span>log</span><span>.</span><span>Println</span><span>(</span><span>"开始服务"</span><span>)</span></div></div><div><div><div>103</div></div><div><span>  </span><span>go</span><span> </span><span>p</span><span>.</span><span>run</span><span>()</span></div></div><div><div><div>104</div></div><div><span>  </span><span>return</span><span> </span><span>nil</span></div></div><div><div><div>105</div></div><div><span>}</span></div></div><div><div><div>106</div></div><div><span>func</span><span><span> (</span><span>p </span><span>*</span></span><span>program</span><span>) </span><span>Stop</span><span><span>(</span><span>s</span><span> </span></span><span>service</span><span>.</span><span>Service</span><span>) </span><span>error</span><span> {</span></div></div><div><div><div>107</div></div><div><span>  </span><span>log</span><span>.</span><span>Println</span><span>(</span><span>"停止服务"</span><span>)</span></div></div><div><div><div>108</div></div><div><span>  </span><span>return</span><span> </span><span>nil</span></div></div><div><div><div>109</div></div><div><span>}</span></div></div><div><div><div>110</div></div><div><span>func</span><span><span> (</span><span>p </span><span>*</span></span><span>program</span><span>) </span><span>run</span><span>() {</span></div></div><div><div><div>111</div></div><div><span>  </span><span>// 这里放置程序要执行的代码……</span></div></div><div><div><div>112</div></div><div><span>  </span><span>pin</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>gogpio</span><span>.</span><span>Open</span><span>(</span><span>14</span><span>, </span><span>gogpio</span><span>.</span><span>OUT</span><span>)</span></div></div><div><div><div>113</div></div><div><span>  </span><span>for</span><span> ; ; {</span></div></div><div><div><div>114</div></div><div><span>    </span><span>if</span><span> </span><span>t</span><span><span>() </span><span>&gt;=</span><span> </span></span><span>max</span><span> {</span></div></div><div><div><div>115</div></div><div><span>      </span><span>pin</span><span>.</span><span>High</span><span>()</span></div></div><div><div><div>116</div></div><div><span><span>    </span></span><span>} </span><span>else</span><span> </span><span>if</span><span> </span><span>t</span><span><span>() </span><span>&lt;=</span><span> </span></span><span>min</span><span> {</span></div></div><div><div><div>117</div></div><div><span>      </span><span>pin</span><span>.</span><span>Low</span><span>()</span></div></div><div><div><div>118</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>119</div></div><div><span>    </span><span>time</span><span>.</span><span>Sleep</span><span>(</span><span>30</span><span><span> </span><span>*</span><span> </span></span><span>time</span><span>.</span><span>Second</span><span>)</span></div></div><div><div><div>120</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>121</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/154/</id>
      <title type="text">【Golang】Golang在Windows上获取管理员权限</title>
      <published>2019-04-11T00:00:00.000Z</published>
      <updated>2019-10-24T08:06:45.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/154/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>此方法可以双击程序获取权限</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>1.打开命令终端输入：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>go</span><span> </span><span>get</span><span> </span><span>github.com/akavel/rsrc</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>2.在项目根目录创建名为<code>nac.manifest</code>的文件，并填充以下内容：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;?</span><span>xml</span><span> version</span><span>=</span><span>"1.0"</span><span> encoding</span><span>=</span><span>"UTF-8"</span><span> standalone</span><span>=</span><span>"yes"</span><span>?&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>assembly</span><span> </span><span>xmlns</span><span>=</span><span>"urn:schemas-microsoft-com:asm.v1"</span><span> </span><span>manifestVersion</span><span>=</span><span>"1.0"</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>&lt;</span><span>trustInfo</span><span> </span><span>xmlns</span><span>=</span><span>"urn:schemas-microsoft-com:asm.v3"</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>            </span></span><span>&lt;</span><span>security</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span><span>                </span></span><span>&lt;</span><span>requestedPrivileges</span><span>&gt;</span></div></div><div><div><div>6</div></div><div><span><span>                    </span></span><span>&lt;</span><span>requestedExecutionLevel</span><span> </span><span>level</span><span>=</span><span>"requireAdministrator"</span><span>/&gt;</span></div></div><div><div><div>7</div></div><div><span><span>                </span></span><span>&lt;/</span><span>requestedPrivileges</span><span>&gt;</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>&lt;/</span><span>security</span><span>&gt;</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>&lt;/</span><span>trustInfo</span><span>&gt;</span></div></div><div><div><div>10</div></div><div><span>&lt;/</span><span>assembly</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>3.项目根目录下打开命令行输入：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>rsrc</span><span> </span><span>-manifest</span><span> </span><span>nac.manifest</span><span> </span><span>-o</span><span> </span><span>nac.syso</span></div></div><div><div><div>2</div></div><div><span>go</span><span> </span><span>build</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><section><h2>END<a href="#end"><span>#</span></a></h2></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/150/</id>
      <title type="text">【杂项】IDEA/Android Studio 窗口无显示问题</title>
      <published>2019-03-30T00:00:00.000Z</published>
      <updated>2019-10-24T07:49:55.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/150/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>在外接拓展显示器的情况下，如果突然拔掉显示器，就可能出现整个IDEA/Android Studio窗口无法显示的情况</p><p></p><figure><img alt="19-3-30-1.png" loading="lazy" width="1917" height="1073" src="/_astro/150.1.Bm2mU0XN_uuiRS.webp" /><figcaption>19-3-30-1.png</figcaption></figure><p></p></section>
<section><h1>0x01 解决方法<a href="#0x01-解决方法"><span>#</span></a></h1><p>找到最后一次操作的项目中的.idea文件夹下的workspace.xml文件</p><p></p><figure><img alt="19-3-30-2.png" loading="lazy" width="873" height="349" src="/_astro/150.2.CQtY4DRP_Z1CxOht.webp" /><figcaption>19-3-30-2.png</figcaption></figure><p></p><p>打开文件并找到<code>ProjectFrameBounds</code>关键字，将其<code>name="x"</code>的值修改为0即可，然后重启IDEA/Android Studio即可</p><p></p><figure><img alt="19-3-30-3.png" loading="lazy" width="652" height="147" src="/_astro/150.3.DNFx1Si2_Z13MCwX.webp" /><figcaption>19-3-30-3.png</figcaption></figure><p></p></section>
<section><h1>0x03 END<a href="#0x03-end"><span>#</span></a></h1></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/149/</id>
      <title type="text">ffmpeg的简单用法</title>
      <published>2019-01-31T00:00:00.000Z</published>
      <updated>2019-10-24T07:48:04.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/149/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[
<p>转自：https://www.jianshu.com/p/4f399b9dfb43</p>

<h3>转码</h3>

<p>最简单命令如下：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>out.ogv</span><span> </span><span>-vcodec</span><span> </span><span>h264</span><span> </span><span>out.mp4</span></div></div><div><div><div>2</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>out.ogv</span><span> </span><span>-vcodec</span><span> </span><span>mpeg4</span><span> </span><span>out.mp4</span></div></div><div><div><div>3</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>out.ogv</span><span> </span><span>-vcodec</span><span> </span><span>libxvid</span><span> </span><span>out.mp4</span></div></div><div><div><div>4</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>out.mp4</span><span> </span><span>-vcodec</span><span> </span><span>wmv1</span><span> </span><span>out.wmv</span></div></div><div><div><div>5</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>out.mp4</span><span> </span><span>-vcodec</span><span> </span><span>wmv2</span><span> </span><span>out.wmv</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<p>-i 后面是输入文件名。-vcodec 后面是编码格式，h264 最佳，但 Windows 系统默认不安装。如果是要插入 ppt 的视频，选择 wmv1 或 wmv2 基本上万无一失。</p>

<p>附加选项：-r 指定帧率，-s 指定分辨率，-b 指定比特率；于此同时可以对声道进行转码，-acodec 指定音频编码，-ab 指定音频比特率，-ac 指定声道数，例如</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>out.ogv</span><span> </span><span>-s</span><span> </span><span>640x480</span><span> </span><span>-b</span><span> </span><span>500k</span><span> </span><span>-vcodec</span><span> </span><span>h264</span><span> </span><span>-r</span><span> </span><span>29.97</span><span> </span><span>-acodec</span><span> </span><span>libfaac</span><span> </span><span>-ab</span><span> </span><span>48k</span><span> </span><span>-ac</span><span> </span><span>2</span><span> </span><span>out.mp4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<h3>剪切</h3>

<p>用 -ss 和 -t 选项， 从第 30 秒开始，向后截取 10 秒的视频，并保存：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>input.wmv</span><span> </span><span>-ss</span><span> </span><span>00:00:30.0</span><span> </span><span>-c</span><span> </span><span>copy</span><span> </span><span>-t</span><span> </span><span>00:00:10.0</span><span> </span><span>output.wmv</span></div></div><div><div><div>2</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>input.wmv</span><span> </span><span>-ss</span><span> </span><span>30</span><span> </span><span>-c</span><span> </span><span>copy</span><span> </span><span>-t</span><span> </span><span>10</span><span> </span><span>output.wmv</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<p>达成相同效果，也可以用 -ss 和 -to 选项， 从第 30 秒截取到第 40 秒：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>input.wmv</span><span> </span><span>-ss</span><span> </span><span>30</span><span> </span><span>-c</span><span> </span><span>copy</span><span> </span><span>-to</span><span> </span><span>40</span><span> </span><span>output.wmv</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<p>值得注意的是，ffmpeg 为了加速，会使用关键帧技术， 所以有时剪切出来的结果在起止时间上未必准确。 通常来说，把 -ss 选项放在 -i 之前，会使用关键帧技术； 把 -ss 选项放在 -i 之后，则不使用关键帧技术。 如果要使用关键帧技术又要保留时间戳，可以加上 -copyts 选项：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-ss</span><span> </span><span>00:01:00</span><span> </span><span>-i</span><span> </span><span>video.mp4</span><span> </span><span>-to</span><span> </span><span>00:02:00</span><span> </span><span>-c</span><span> </span><span>copy</span><span> </span><span>-copyts</span><span> </span><span>cut.mp4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<h3>合并</h3>

<p>把两个视频文件合并成一个。</p>

<p>简单地使用 concat demuxer，示例：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>cat</span><span> </span><span>mylist.txt</span></div></div><div><div><div>2</div></div><div><span>file</span><span> </span><span>'/path/to/file1'</span></div></div><div><div><div>3</div></div><div><span>file</span><span> </span><span>'/path/to/file2'</span></div></div><div><div><div>4</div></div><div><span>file</span><span> </span><span>'/path/to/file3'</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>$</span><span> </span><span>ffmpeg</span><span> </span><span>-f</span><span> </span><span>concat</span><span> </span><span>-i</span><span> </span><span>mylist.txt</span><span> </span><span>-c</span><span> </span><span>copy</span><span> </span><span>output</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<p>更多时候，由于输入文件的多样性，需要转成中间格式再合成：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>input1.avi</span><span> </span><span>-qscale:v</span><span> </span><span>1</span><span> </span><span>intermediate1.mpg</span></div></div><div><div><div>2</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>input2.avi</span><span> </span><span>-qscale:v</span><span> </span><span>1</span><span> </span><span>intermediate2.mpg</span></div></div><div><div><div>3</div></div><div><span>cat</span><span> </span><span>intermediate1.mpg</span><span> </span><span>intermediate2.mpg</span><span> &gt; </span><span>intermediate_all.mpg</span></div></div><div><div><div>4</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>intermediate_all.mpg</span><span> </span><span>-qscale:v</span><span> </span><span>2</span><span> </span><span>output.avi</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<h3>调整播放速度</h3>

<p>加速四倍：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>TheOrigin.mp4</span><span> </span><span>-vf</span><span>  </span><span>"setpts=0.25*PTS"</span><span> </span><span>UpTheOrigin.mp4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<p>四倍慢速：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>TheOrigin.mp4</span><span> </span><span>-vf</span><span> </span><span>"setpts=4*PTS"</span><span> </span><span>DownTheOrigin.mp4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<h3>帧率设置</h3>

<p>使用-r选项<br />
语法是：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>input</span><span> </span><span>-r</span><span> </span><span>fps</span><span> </span><span>output</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<p>例如：</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>input.avi</span><span> </span><span>-r</span><span> </span><span>30</span><span> </span><span>output.mp4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<h3>使用fps filter</h3>

<p>另一个设置帧率是用fps filter，特别是在filterchains使用时非常有用。<br />
例如：修改输入文件的帧率到25</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-v</span><span> </span><span>clip.mpg</span><span> </span><span>-vf</span><span> </span><span>fps=fps=</span><span>25</span><span> </span><span>clip.webm</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<h3>比特率设置</h3>

<p>比特率也是一个决定音视频总体质量的参数。他决定每个时间单位处理的bit数。<br />
设置比特率：</p>

<p>比特率决定处理1s的编码流需要多少bits，设置用-b选项。区分音视频用-b:a和-b:v<br />
例如：设置整体1.5Mbit每秒</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>file.avi</span><span> </span><span>-b</span><span> </span><span>1.5M</span><span> </span><span>file.mp4</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>input.avi</span><span> </span><span>-b:v</span><span> </span><span>1500K</span><span> </span><span>output.mp4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<h3>CBR设置</h3>

<p>CBR设置一般用作直播流，比如视频会议。为输出设置CBR,有三个参数必须设置为同一个值。<br />
bitrate(-b option), minimal rate(-minrate), maximal rate(-maxrate)。maximal rate需要设置-bufsize选项。例如设置CBR为0.5Mbit/s。</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>in.avi</span><span> </span><span>-b</span><span> </span><span>0.5M</span><span> </span><span>-minrate</span><span> </span><span>0.5M</span><span> </span><span>-maxrate</span><span> </span><span>0.5M</span><span> </span><span>-bufsize</span><span> </span><span>1M</span><span> </span><span>output.mkv</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<h3>设置输出文件的最大size</h3>

<p>用-fs选项。<br />
例如设置输出文件的最大的size为10M</p>

<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ffmpeg</span><span> </span><span>-i</span><span> </span><span>input.avi</span><span> </span><span>-fs</span><span> </span><span>10MB</span><span> </span><span>output.mp4</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<h3>文件大小计算</h3>

<p>文件的大小是是音视频流大小的和。<br />
视频流的大小的方程式是(除以8是由bits到bytes的转换):</p>

<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>video_size = video_bitrate * time_in_seconds / 8;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<p>如果音频是解压缩的，计算公式是：</p>

<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>audio_size = smpaling_rate * bit_depth * channels * time_in_second / 8;</span></div></div></code></pre><div><div></div><div></div></div></figure></div>

<p>例如：计算10分钟的视频， 1500kbits/s 视频比特率和 128kbits/s的音频比特率，用下面的计算方法：</p>

<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>file_size = video_size + audio_size;</span></div></div><div><div><div>2</div></div><div><span>file_size = (video_bitrate + audio_bitrate) * time_in_seconds / 8;</span></div></div><div><div><div>3</div></div><div><span>file_size = (1500 kbits/s + 128kbits/s) * 600s</span></div></div><div><div><div>4</div></div><div><span>file_size = 1628kbits/s * 600s</span></div></div><div><div><div>5</div></div><div><span>file_size = 976800kb = 976800000 b / 8 = 122100000 B / 1024 = 119238.28125KB</span></div></div><div><div><div>6</div></div><div><span>file_size = 119238.28125 KB / 1024 = 116.443634033203125MB = 116.44M</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/147/</id>
      <title type="text">【树莓派】ZERO W上快速安装Open CV</title>
      <published>2019-01-22T00:00:00.000Z</published>
      <updated>2019-10-24T07:45:09.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/147/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>执行命令添加源：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>echo</span><span> </span><span>'deb [trusted=yes] http://dl.bintray.com/yoursunny/PiZero stretch-backports main'</span><span> |</span><span>\</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>tee</span><span>  </span><span>/etc/apt/sources.list.d/bintray-yoursunny-PiZero.list</span></div></div><div><div><div>3</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>Python3:</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>python3-opencv</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>Python2：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>python-opencv</span></div></div></code></pre><div><div></div><div></div></div></figure></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/148/</id>
      <title type="text">【树莓派】延时拍照并上传到服务端</title>
      <published>2019-01-22T00:00:00.000Z</published>
      <updated>2019-10-24T07:46:51.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/148/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>服务端：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># -*- coding: utf-8 -*-</span></div></div><div><div><div>2</div></div><div><span>import</span><span> socket</span></div></div><div><div><div>3</div></div><div><span>import</span><span> os</span></div></div><div><div><div>4</div></div><div><span>import</span><span> time</span></div></div><div><div><div>5</div></div><div><span>#监听ip和端口</span></div></div><div><div><div>6</div></div><div><span><span>IP_Post</span><span> </span><span>=</span><span> (</span></span><span>'0.0.0.0'</span><span>, </span><span>1234</span><span>)</span></div></div><div><div><div>7</div></div><div><span><span>sk </span><span>=</span><span> socket.</span><span>socket</span><span>()</span></span></div></div><div><div><div>8</div></div><div><span><span>sk.</span><span>bind</span><span>(</span><span>IP_Post</span><span>)</span></span></div></div><div><div><div>9</div></div><div><span><span>sk.</span><span>listen</span><span>(</span></span><span>5</span><span>)</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>while</span><span> </span><span>True</span><span>:</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>conn, addr </span><span>=</span><span> sk.</span><span>accept</span><span>()</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>    </span><span># #循环接收文件</span></div></div><div><div><div>15</div></div><div><span>    </span><span># while True:</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>data </span><span>=</span><span> conn.</span><span>recv</span><span>(</span><span>1024</span><span>)</span></div></div><div><div><div>17</div></div><div><span>    </span><span># print(str(data,'utf-8'))</span></div></div><div><div><div>18</div></div><div><span>    </span><span>print</span><span>(data)</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>file_name, file_size </span><span>=</span><span> </span><span>str</span><span>(data, </span><span>'utf-8'</span><span><span>).</span><span>split</span><span>(</span></span><span>'|'</span><span>)</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>    </span><span># path=os.path.join(file_name,".jpg")</span></div></div><div><div><div>22</div></div><div><span><span>    </span></span><span>path </span><span>=</span><span> file_name</span><span>+</span><span>".jpg"</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>file_size </span><span>=</span><span> </span><span>int</span><span>(file_size)</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>has_sent </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>25</div></div><div><span>    </span><span>with</span><span> </span><span>open</span><span>(path, </span><span>'wb'</span><span>) </span><span>as</span><span> fp:</span></div></div><div><div><div>26</div></div><div><span>        </span><span>while</span><span><span> has_sent </span><span>!=</span><span> file_size:</span></span></div></div><div><div><div>27</div></div><div><span><span>            </span></span><span>data </span><span>=</span><span> conn.</span><span>recv</span><span>(</span><span>1024</span><span>)</span></div></div><div><div><div>28</div></div><div><span><span>            </span></span><span>fp.</span><span>write</span><span>(data)</span></div></div><div><div><div>29</div></div><div><span><span>            </span></span><span>has_sent </span><span>+=</span><span> </span><span>len</span><span>(data)</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>conn.</span><span>close</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<p>客户端：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> os</span></div></div><div><div><div>2</div></div><div><span>import</span><span> socket</span></div></div><div><div><div>3</div></div><div><span>import</span><span> cv2</span></div></div><div><div><div>4</div></div><div><span>import</span><span> time</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>def</span><span> </span><span>s</span><span>(</span><span>name</span><span>):</span></div></div><div><div><div>8</div></div><div><span>    </span><span>#服务端ip和端口</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>IP_Post</span><span>=</span><span>(</span><span>'192.168.1.104'</span><span>,</span><span>1234</span><span>)</span></div></div><div><div><div>10</div></div><div><span><span>    </span></span><span>sk</span><span>=</span><span>socket.</span><span>socket</span><span>()</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>sk.</span><span>connect</span><span>(</span><span>IP_Post</span><span>)</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>size</span><span>=</span><span>os.</span><span>stat</span><span>(</span><span>"./1.jpg"</span><span>).st_size</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>data</span><span>=</span><span>name</span><span>+</span><span>"|"</span><span>+</span><span>str</span><span>(size)</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>sk.</span><span>sendall</span><span>(</span><span>bytes</span><span>(data,</span><span>'utf-8'</span><span>))</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>has_sent</span><span>=</span><span>0</span></div></div><div><div><div>17</div></div><div><span>    </span><span>with</span><span> </span><span>open</span><span>(</span><span>"./1.jpg"</span><span>,</span><span>'rb'</span><span>)</span><span>as</span><span> fp:</span></div></div><div><div><div>18</div></div><div><span>        </span><span>while</span><span><span> has_sent </span><span>!=</span><span> size:</span></span></div></div><div><div><div>19</div></div><div><span><span>            </span></span><span>data </span><span>=</span><span> fp.</span><span>read</span><span>(</span><span>1024</span><span>)</span></div></div><div><div><div>20</div></div><div><span><span>            </span></span><span>sk.</span><span>sendall</span><span>(data)</span></div></div><div><div><div>21</div></div><div><span><span>            </span></span><span>has_sent </span><span>+=</span><span> </span><span>len</span><span>(data)</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>sk.</span><span>close</span><span>()</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>while</span><span> </span><span>True</span><span>:</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>cam</span><span>=</span><span>cv2.</span><span>VideoCapture</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>27</div></div><div><span><span>    </span></span><span>ret,c</span><span>=</span><span>cam.</span><span>read</span><span>()</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>cam.</span><span>release</span><span>()</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>cv2.</span><span>imwrite</span><span>(</span><span>"./1.jpg"</span><span>,c)</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>s</span><span>(</span><span>str</span><span>(</span><span>int</span><span><span>(time.</span><span>time</span><span>())))</span></span></div></div><div><div><div>31</div></div><div><span>    </span><span>#延时30秒</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>time.</span><span>sleep</span><span>(</span><span>30</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/146/</id>
      <title type="text">【树莓派】Docker安装脚本</title>
      <published>2019-01-20T00:00:00.000Z</published>
      <updated>2019-10-24T07:43:58.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/146/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/sh</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span></div></div><div><div><div>3</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>-y</span><span> </span><span>apt-transport-https</span><span> </span><span>ca-certificates</span><span> </span><span>curl</span><span> </span><span>gnupg2</span><span> </span><span>lsb-release</span><span> </span><span>software-properties-common</span></div></div><div><div><div>4</div></div><div><span>curl</span><span> </span><span>-fsSL</span><span> </span><span>https://mirrors.ustc.edu.cn/docker-ce/linux/raspbian/gpg</span><span> | </span><span>sudo</span><span> </span><span>apt-key</span><span> </span><span>add</span><span> </span><span>-</span></div></div><div><div><div>5</div></div><div><span>echo</span><span> </span><span>"deb [arch=armhf] https://mirrors.ustc.edu.cn/docker-ce/linux/raspbian $(</span><span>lsb_release</span><span> </span><span>-cs</span><span>) stable"</span><span> |</span><span>sudo</span><span> </span><span>tee</span><span> </span><span>/etc/apt/sources.list.d/docker.list</span></div></div><div><div><div>6</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span></div></div><div><div><div>7</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>-y</span><span> </span><span>docker-ce</span></div></div><div><div><div>8</div></div><div><span>curl</span><span> </span><span>-fsSL</span><span> </span><span>get.docker.com</span><span> </span><span>-o</span><span> </span><span>get-docker.sh</span></div></div><div><div><div>9</div></div><div><span>sudo</span><span> </span><span>sh</span><span> </span><span>get-docker.sh</span><span> </span><span>--mirror</span><span> </span><span>Aliyun</span></div></div><div><div><div>10</div></div><div><span>sudo</span><span> </span><span>systemctl</span><span> </span><span>enable</span><span> </span><span>docker</span></div></div><div><div><div>11</div></div><div><span>sudo</span><span> </span><span>systemctl</span><span> </span><span>start</span><span> </span><span>docker</span></div></div><div><div><div>12</div></div><div><span># sudo groupadd docker</span></div></div><div><div><div>13</div></div><div><span>sudo</span><span> </span><span>usermod</span><span> </span><span>-aG</span><span> </span><span>docker</span><span> </span><span>$USER</span></div></div><div><div><div>14</div></div><div><span>echo</span><span> </span><span>"没有报错情况下退出终端重新登录即可完成"</span></div></div></code></pre><div><div></div><div></div></div></figure></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/145/</id>
      <title type="text">【Linux】WSL+Xming实现gui显示</title>
      <published>2019-01-14T00:00:00.000Z</published>
      <updated>2019-10-24T07:41:43.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/145/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>WSL（Windows Subsystem for Linux）配合Xming实现显示图像界面</p></section>
<section><h1>0x01 安装<a href="#0x01-安装"><span>#</span></a></h1><p>百度谷歌一下<code>Xming</code>下载并安装</p><p>安装过程使用默认就好（一直“下一步”）</p><p>安装好后在开始菜单打开<code>XLaunch</code>，选择你要的显示方式：</p><ul>
<li><code>Multiple windows</code>：为每一个需要显示的Linux应用单独打开一个窗口，类似Windows的窗口（默认选这个就好）</li>
<li><code>Fullscreen</code>：将Linux界面全屏显示</li>
<li><code>One windows</code>：和<code>Multiple windows</code>类似，不过多个应用只会开一个窗口共同显示</li>
<li><code>One windows without titlebar</code>：功能和<code>One windows</code>一样，会窗口隐藏标题栏</li>
<li><code>Display number</code>：设置显示器编号（默认：0）</li>
</ul><p>之后一直下一步即可</p></section>
<section><h1>0x02 使用<a href="#0x02-使用"><span>#</span></a></h1><section><h2>显示WSL的Linux应用界面<a href="#显示wsl的linux应用界面"><span>#</span></a></h2><p>在要显示的应用命令前加<code>DISPLAY=:0</code>，例如：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>DISPLAY=:0</span><span> </span><span>xclock</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p><code>xclock</code>为一个显示时钟的程序</p><p><code>DISPLAY=:0</code>后面的<code>0</code>为之前设置的显示器编号</p></section><section><h2>远程Linux服务器通过WSL的SSH连接显示界面<a href="#远程linux服务器通过wsl的ssh连接显示界面"><span>#</span></a></h2><p>和上面一样，加在连接命令前：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>DISPLAY=localhost:0</span><span> </span><span>ssh</span><span> </span><span>-X</span><span> </span><span>root@192.168.1.100</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>root@192.168.1.100:~#</span><span> </span><span>xclock</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>连接远程服务器就需要加<code>localhost</code>，并且需要在<code>SSH</code>命令中加入<code>-X</code>表示X11转发</p><p>如果有报错就在服务器的<code>/etc/ssh/sshd_config</code>中将下列语句的注释去除（如果没有就在文末添加）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>X11Forwarding</span><span> </span><span>yes</span></div></div><div><div><div>2</div></div><div><span>X11DisplayOffset</span><span> </span><span>10</span></div></div><div><div><div>3</div></div><div><span>X11UseLocalhost</span><span> </span><span>yes</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重启SSH服务：<code>sudo systemctl restart sshd.service</code></p></section></section>
<section><h1>0x03 END<a href="#0x03-end"><span>#</span></a></h1><p>如果客户端不是WSL，而是在Linux系统桌面版的情况下就将客户端的<code>/etc/ssh/ssh_config</code>中将下列语句注释去除（如果没有就在文末添加）：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>ForwardAgent</span><span> </span><span>yes</span></div></div><div><div><div>2</div></div><div><span>ForwardX11</span><span> </span><span>yes</span></div></div><div><div><div>3</div></div><div><span>ForwardX11Trusted</span><span> </span><span>yes</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重启SSH服务：<code>sudo systemctl restart ssh.service</code></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/140/</id>
      <title type="text">【树莓派】在线实时视频流部署</title>
      <published>2019-01-11T00:00:00.000Z</published>
      <updated>2019-10-24T07:39:20.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/140/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>通过树莓派将摄像头推流</p><p>推流使用<a href="https://github.com/jacksonliam/mjpg-streamer" target="_blank">mjpg-streamer</a>组件</p><p>我使用的摄像头为树莓派官方的CSI接口摄像头</p></section>
<section><h1>0x01 安装<a href="#0x01-安装"><span>#</span></a></h1><section><h2>1.挂载摄像头（USB摄像头可跳过）<a href="#1挂载摄像头usb摄像头可跳过"><span>#</span></a></h2><p>将摄像头插在指定的接口上</p><p></p><figure><img alt="1.png" loading="lazy" width="508" height="333" src="/_astro/140.1.Ddn-ORpa_23JaWC.webp" /><figcaption>1.png</figcaption></figure><p></p><p>进入系统执行</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>raspi-config</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>找到Camera选项并打开</p><p></p><figure><img alt="2.png" loading="lazy" width="997" height="228" src="/_astro/140.2.sPdPVGmy_Z1mjXyH.webp" /><figcaption>2.png</figcaption></figure><p></p><p>编辑文件让/dev/video0显示</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>nano</span><span> </span><span>/etc/modules</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>在文件中添加</span></div></div><div><div><div>4</div></div><div><span>snd-bcm2835</span></div></div><div><div><div>5</div></div><div><span>bcm2835-v4l2</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重启树莓派</p></section><section><h2>2.安装mjpg-streamer<a href="#2安装mjpg-streamer"><span>#</span></a></h2><p>执行命令</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>upgrade</span><span> </span><span>-y</span></div></div><div><div><div>3</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>-y</span><span> </span><span>git</span><span> </span><span>cmake</span><span> </span><span>libjpeg62-dev</span><span> </span><span>libjpeg8-dev</span></div></div><div><div><div>4</div></div><div><span>git</span><span> </span><span>clone</span><span> </span><span>https://github.com/jacksonliam/mjpg-streamer.git</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>由于市面上大部分摄像头是YUYV格式输出，所以要修改mjpg-streamer项目的代码文件，让其默认支持此格式的摄像头。</p><p>打开<code>mjpg-streamer-experimental/plugins/input_uvc/input_uvc.c</code>并找到<code>format = V4L2_PIX_FMT_MJPEG</code>将其改为<code>format = V4L2_PIX_FMT_YUYV</code></p><p>编译、部署</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>cd</span><span> </span><span>mjpg-streamer-master/mjpg-streamer-experimental</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>make</span><span> </span><span>clean</span><span> </span><span>all</span></div></div><div><div><div>3</div></div><div><span>sudo</span><span> </span><span>cp</span><span> </span><span>mjpg_streamer</span><span> </span><span>/usr/local/bin</span></div></div><div><div><div>4</div></div><div><span>sudo</span><span> </span><span>cp</span><span> </span><span>output_http.so</span><span> </span><span>input_uvc.so</span><span> </span><span>/usr/local/lib/</span></div></div><div><div><div>5</div></div><div><span>sudo</span><span> </span><span>cp</span><span> </span><span>-R</span><span> </span><span>www</span><span> </span><span>/usr/local/www</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>0x02 启动<a href="#0x02-启动"><span>#</span></a></h1><p>使用命令启动</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>LD_LIBRARY_PATH</span><span>=</span><span>/usr/local/lib</span><span> </span><span>mjpg_streamer</span><span> </span><span>-i</span><span> </span><span>"input_uvc.so -r 640x480 -f 12"</span><span> </span><span>-o</span><span> </span><span>"output_http.so -p 4321 -w /usr/local/www"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中<code>-r 640x480</code>可改为自己摄像头的分辨率</p><p><code>-f 12</code>为帧数</p><p><code>-p 4321</code>为端口号</p><p>更多设置请参考<a href="https://github.com/jacksonliam/mjpg-streamer/blob/master/README.md" target="_blank">README</a></p><p>在同一局域网下在浏览器输入<code>树莓派IP:端口号/?action=stream</code>可观看视频流</p></section>
<section><h1>0x03 END<a href="#0x03-end"><span>#</span></a></h1></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/144/</id>
      <title type="text">【树莓派】树莓派各版本图纸</title>
      <published>2019-01-11T00:00:00.000Z</published>
      <updated>2019-10-24T07:40:10.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/144/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>图纸<a href="#图纸"><span>#</span></a></h1><p>内容转自树莓派基金会官网</p><section><h2>机械图纸<a href="#机械图纸"><span>#</span></a></h2><section><h3>Raspberry Pi 3B+<a href="#raspberry-pi-3b"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/mechanical/rpi_MECH_3bplus.pdf" target="_blank">PDF</a></li>
</ul></section><section><h3>Raspberry Pi 3B<a href="#raspberry-pi-3b-1"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/mechanical/rpi_MECH_3b_1p2.pdf" target="_blank">PDF</a></li>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/mechanical/rpi_MECH_3b_1p2.dxf" target="_blank">DXF</a></li>
</ul></section><section><h3>Raspberry Pi Model B+<a href="#raspberry-pi-model-b"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/mechanical/rpi_MECH_bplus_1p2.pdf" target="_blank">PDF</a></li>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/mechanical/rpi_MECH_bplus_1p2.dxf" target="_blank">DXF</a></li>
</ul></section><section><h3>Raspberry Pi Zero (v1.2)<a href="#raspberry-pi-zero-v12"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/mechanical/rpi_MECH_Zero_1p2.pdf" target="_blank">PDF</a></li>
</ul></section><section><h3>Raspberry Pi PoE HAT<a href="#raspberry-pi-poe-hat"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/mechanical/rpi_MECH_PoEHAT.pdf" target="_blank">PDF</a></li>
</ul></section><section><h3>Raspberry Pi TV HAT<a href="#raspberry-pi-tv-hat"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/mechanical/rpi_MECH_TVHAT_1p0.PNG" target="_blank">PNG</a></li>
</ul></section></section><section><h2>原理图<a href="#原理图"><span>#</span></a></h2><section><h3>Raspberry Pi 3 Model B+<a href="#raspberry-pi-3-model-b"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/schematics/rpi_SCH_3bplus_1p0_reduced.pdf" target="_blank">Revision 1.0</a></li>
</ul></section><section><h3>Raspberry Pi 3 Model B<a href="#raspberry-pi-3-model-b-1"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/schematics/rpi_SCH_3b_1p2_reduced.pdf" target="_blank">Revision 1.2</a></li>
</ul></section><section><h3>Raspberry Pi 2 Model B<a href="#raspberry-pi-2-model-b"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/schematics/rpi_SCH_2b_1p2_reduced.pdf" target="_blank">Revision 1.2</a></li>
</ul></section><section><h3>Raspberry Pi Model B+<a href="#raspberry-pi-model-b-1"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/schematics/rpi_SCH_1bplus_1p2_reduced.pdf" target="_blank">Revision 1.2</a></li>
</ul></section><section><h3>Raspberry Pi Model A+<a href="#raspberry-pi-model-a"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/schematics/rpi_SCH_1aplus_1p1_reduced.pdf" target="_blank">Revision 1.1</a></li>
</ul></section><section><h3>Raspberry Pi Zero<a href="#raspberry-pi-zero"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/schematics/rpi_SCH_Zero_1p3_reduced.pdf" target="_blank">Revision 1.3</a></li>
</ul></section><section><h3>Raspberry Pi Zero W<a href="#raspberry-pi-zero-w"><span>#</span></a></h3><ul>
<li><a href="https://www.raspberrypi.org/documentation/hardware/raspberrypi/schematics/rpi_SCH_ZeroW_1p1_reduced.pdf" target="_blank">Revision 1.1</a></li>
</ul></section></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/137/</id>
      <title type="text">【树莓派】在模拟器中运行树莓派arm系统</title>
      <published>2018-12-29T00:00:00.000Z</published>
      <updated>2019-10-24T07:37:04.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/137/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>我有时候使用golang编译好的程序想在树莓派（arm芯片）测试，但奈何有时候手边没有树莓派或我的远程树莓派掉线了(Ｔ▽Ｔ)，这个时候就需要一个模拟器了。实现这个方法使用的是QEMU模拟器，它是一个全平台模拟器，没有图形界面使用命令启动。</p><p>环境：Windows10 1809</p><p>软件：<a href="http://www.qemu.org/" target="_blank">QEMU</a></p><p>实验镜像：2018-11-13-raspbian-stretch-lite.img</p></section>
<section><h1>0x01 准备<a href="#0x01-准备"><span>#</span></a></h1><ol>
<li>将在树莓派官网下载的镜像解压到.img后缀。</li>
<li>下载编译好的树莓派<a href="https://github.com/dhruvvyas90/qemu-rpi-kernel" target="_blank">内核及相关文件</a>：</li>
</ol><ul>
<li>下载<code>kernel-qemu-x.x.xx</code>文件，我当前使用的是<code>kernel-qemu-4.9.59-stretch</code></li>
<li>下载<code>versatile-pb.dtb</code>文件</li>
</ul></section>
<section><h1>0x02 使用<a href="#0x02-使用"><span>#</span></a></h1><p>命令行执行（如果提示找不到该命令，到QEMU安装目录按住Shift鼠标右键，选择此处打开命令窗口）：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span><span>qemu</span><span>-</span><span>system</span><span>-</span><span>arm </span><span>-</span><span>kernel kernel</span><span>-</span><span>qemu</span><span>-</span><span>x.x.xx文件所在地址 </span><span>-</span><span>cpu arm1176 </span><span>-</span><span>m </span></span><span>256</span><span><span> </span><span>-</span><span>M versatilepb </span><span>-</span><span>dtb versatile</span><span>-</span><span>pb.dtb文件地址 </span><span>-</span><span>no</span><span>-</span><span>reboot </span><span>-</span><span>append </span></span><span>"root=/dev/sda2 panic=1 rootfstype=ext4 rw"</span><span><span> </span><span>-</span><span>net nic </span><span>-</span><span>net user,hostfwd</span><span>=</span><span>tcp::</span></span><span>5022</span><span><span>-</span><span>:</span></span><span>22</span><span><span> </span><span>-</span><span>hda 镜像文件地址</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中<code>-m</code>为运行内存大小</p><p></p><figure><img alt="1.png" loading="lazy" width="1920" height="1034" src="/_astro/137.1.DgZ42cZW_16nfRk.webp" /><figcaption>1.png</figcaption></figure><p></p><p></p><figure><img alt="2.png" loading="lazy" width="692" height="601" src="/_astro/137.2.j-ET7o91_1ttA5a.webp" /><figcaption>2.png</figcaption></figure><p></p></section>
<section><h1>0x03 END<a href="#0x03-end"><span>#</span></a></h1><p>如果想运行其他镜像可以自己编译相关的内核，<a href="https://github.com/dhruvvyas90/qemu-rpi-kernel/tree/master/tools" target="_blank">参考地址</a></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/135/</id>
      <title type="text">【树莓派】搭建FM发射器</title>
      <published>2018-12-25T00:00:00.000Z</published>
      <updated>2019-10-24T07:33:55.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/135/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><div><div><div></div><div>Warning</div></div><div><p>未尽有关部门批准私人架设FM电台是违法的，轻则拘留重则判刑。本教程仅供实验、学习研究，切勿用作实际用途。</p></div></div></section>
<section><h1>0x01 安装<a href="#0x01-安装"><span>#</span></a></h1><p>安装依赖组件</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>libsndfile1-dev</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>检查是否有<code>rpi-mailbox</code>驱动，该驱动在2015年以后的Raspbian自带。</p><p>下载并安装所需程序</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>git</span><span> </span><span>clone</span><span> </span><span>https://github.com/ChristopheJacquet/PiFmRds.git</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>$</span><span> </span><span>cd</span><span> </span><span>PiFmRds/src</span></div></div><div><div><div>4</div></div><div><span>$</span><span> </span><span>make</span><span> </span><span>clean</span></div></div><div><div><div>5</div></div><div><span>$</span><span> </span><span>make</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02 使用<a href="#0x02-使用"><span>#</span></a></h1><p>FM发射信号的发射天线定义在GPIO 4(pin 7)号针脚上，可以在此针脚连接杜邦线增强信号。</p><section><h2>发射信号：<a href="#发射信号"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>./pi_fm_rds</span><span> </span><span>-audio</span><span> </span><span>sound.wav</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>运行pi_fm_rds的一般语法：<a href="#运行pi_fm_rds的一般语法"><span>#</span></a></h2><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pi_fm_rds</span><span> [-freq </span><span>信号频率]</span><span> [-audio </span><span>音频文件]</span><span> [-ppm </span><span>振荡器误差]</span><span> [-pi </span><span>广播代码]</span><span> [-ps </span><span>电台名称]</span><span> [-rt </span><span>传输无线电文本]</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>参数介绍：<a href="#参数介绍"><span>#</span></a></h2><ul>
<li><code>-freq</code>指定载波频率（以MHz为单位）。示例：<code>-freq 107.9</code></li>
<li><code>-audio</code>指定要作为音频播放的音频文件。采样率无关紧要：Pi-FM-RDS将重新采样并对其进行过滤。如果提供立体声文件，Pi-FM-RDS将产生FM立体声信号。示例：<code>-audio sound.wav</code>。支持的格式取决于<code>libsndfile</code>。这包括WAV和Ogg / Vorbis（以及其他），但不包括MP3。指定<code>-</code>作为文件名来读取标准输入上的音频数据（用于将音频传输到Pi-FM-RDS，见下文）。</li>
<li><code>-pi</code>指定RDS广播的PI代码。4个十六进制数字。示例：<code>-pi FFFF</code>。</li>
<li><code>-ps</code>指定RDS广播的电台名称（节目服务名称，PS）。限制：8个字符。示例：<code>-ps RASP-PI</code>。</li>
<li><code>-rt</code>指定要传输的无线电文本（RT）。限制：64个字符。示例：<code>-rt 'Hello, world!'</code>。</li>
<li><code>-ctl</code> 指定一个命名管道（FIFO），用作控制通道，在运行时更改PS和RT（见下文）。</li>
<li><code>-ppm</code> 以百万分率（ppm）表示您的Raspberry Pi振荡器误差，请参见下文。</li>
</ul><p>默认情况下，PS在<code>Pi-FmRds</code>序列号之间来回切换，从<code>00000000</code>开始。PS每秒变化一次。</p></section><section><h2>高级发射音频：<a href="#高级发射音频"><span>#</span></a></h2><p>如果使用参数<code>-audio -</code>，Pi-FM-RDS将读取标准输入的音频数据。这允许您将程序的输出传输到Pi-FM-RDS。例如，这可以用于使用Sox读取MP3文件：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sox</span><span> </span><span>-t</span><span> </span><span>mp3</span><span> </span><span>http://www.linuxvoice.com/episodes/lv_s02e01.mp3</span><span> </span><span>-t</span><span> </span><span>wav</span><span> </span><span>-</span><span>  | </span><span>sudo</span><span> </span><span>./pi_fm_rds</span><span> </span><span>-audio</span><span> </span><span>-</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>或者将声卡的AUX输入传输到Pi-FM-RDS：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>arecord</span><span> </span><span>-fS16_LE</span><span> </span><span>-r</span><span> </span><span>44100</span><span> </span><span>-Dplughw:1,0</span><span> </span><span>-c</span><span> </span><span>2</span><span> </span><span>-</span><span>  | </span><span>sudo</span><span> </span><span>./pi_fm_rds</span><span> </span><span>-audio</span><span> </span><span>-</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>0x03 END<a href="#0x03-end"><span>#</span></a></h1><p>其他问题请查看该<a href="https://github.com/ChristopheJacquet/PiFmRds" target="_blank">项目说明文件</a></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/133/</id>
      <title type="text">【Linux】硬盘休眠</title>
      <published>2018-12-10T00:00:00.000Z</published>
      <updated>2019-10-24T07:30:32.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/133/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<blockquote><p>本文转自：<a href="http://www.mkitby.com/2016/05/15/raspberry-pi-nas-manage-hdd-power/" target="_blank">http://www.mkitby.com/2016/05/15/raspberry-pi-nas-manage-hdd-power/</a></p><p>使用树莓派3b和一块旧式笔记本ide硬盘实验，发现hd-idle可行。</p></blockquote>
<p>为了延长硬盘使用寿命，当硬盘不使用时，需要让硬盘休眠，目前有一些软件可以自动做这事，像 hdparm, hd-idle 和 sdparm，具体用哪个取决于USB to SATA控制器和硬盘本身，其实说白了就是一个一个试，哪个有用就用哪个。当然，这里说的都是机械硬盘，固态硬盘没研究过。</p>
<p>注意：不要让机械硬盘频繁地休眠唤醒，这样会给电机和轴承较大负荷，会加剧硬盘损耗. 一般制造商建议的最小休眠时间是 3-5 分钟。参考（<a href="http://hd-idle.sourceforge.net/%EF%BC%89" target="_blank">http://hd-idle.sourceforge.net/）</a></p>
<p>首先查看硬盘设备名，一般就是/dev/sda,dev/sdb之类的</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>blkid</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>例如输出</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/dev/mmcblk0p1: SEC_TYPE="msdos" LABEL="boot" UUID="15CD-3B79" TYPE="vfat"</span></div></div><div><div><div>2</div></div><div><span>/dev/mmcblk0p2: UUID="13d368bf-6dbf-4751-8ba1-88bed06bef77" TYPE="ext4"</span></div></div><div><div><div>3</div></div><div><span>/dev/sda1: UUID="7e623443-f19a-4564-8e60-e9d2170ac32a" TYPE="ext4"</span></div></div><div><div><div>4</div></div><div><span>/dev/sdb1: LABEL="COLORSPACE" UUID="F8E6-4FDB" TYPE="vfat"</span></div></div><div><div><div>5</div></div><div><span>/dev/sdb2: UUID="3007-F316" TYPE="exfat"</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>硬盘设备名为/dev/sdb,硬盘有两个分区</p>
<section><h1>安装和配置hdparm<a href="#安装和配置hdparm"><span>#</span></a></h1><p>先测试hdparm是否支持。</p><p>安装 hdparm，</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt-get</span><span> </span><span>install</span><span> </span><span>hdparm</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>确保你的硬盘支持hdparm,</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>hdparm</span><span> </span><span>-y</span><span> </span><span>/dev/sdb</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果输出如下结果，就表明支持，</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/dev/sdb:</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>issuing standby command</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果看到类似如下输出，就表明不支持，可以跳到 hd-idle 或者 sdparm，</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/dev/sda:</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>issuing standby command</span></div></div><div><div><div>3</div></div><div><span>SG_IO: bad/missing sense data, sb[]:  70 00 05 00 00 00 00 0a 00 00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>检查硬盘是否支持写缓存功能，</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>hdparm</span><span> </span><span>-I</span><span> </span><span>/dev/sdb</span><span> | </span><span>grep</span><span> </span><span>'Write cache'</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果看到 * (星号)，表示支持，</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>*    Write cache</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果没有看到 * (星号)，表示不支持，</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Write cache</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编辑配置文件，</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>vim</span><span> </span><span>/etc/hdparm.conf</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>spindown_time值乘以 5 得到总的时间（单位秒）. 例如想配置成空闲10分钟就休眠，spindown_time = 10 * 60 / 5 = 120</p><p>在文件结尾加入，</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/dev/sdb {</span></div></div><div><div><div>2</div></div><div><span>write_cache = on</span></div></div><div><div><div>3</div></div><div><span>spindown_time = 120</span></div></div><div><div><div>4</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果不支持写缓存，去掉 write_cache = on。</p><p>重启 hdparm 服务，</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>service</span><span> </span><span>hdparm</span><span> </span><span>restart</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>更多hdparm配置可以参考这(<a href="http://www.linux-magazine.com/Online/Features/Tune-Your-Hard-Disk-with-hdparm" target="_blank">http://www.linux-magazine.com/Online/Features/Tune-Your-Hard-Disk-with-hdparm</a>)</p></section>
<section><h1>安装和配置 hd-idle<a href="#安装和配置-hd-idle"><span>#</span></a></h1><p>如果你的硬盘不支持 hdparm，或者就想试下hd-idle, 可以删除hdparm</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt-get</span><span> </span><span>remove</span><span> </span><span>hdparm</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>hd-idle 使用一个特殊的系统文件来检测磁盘活动, 如果没有这个文件，那么就不能使用hd-idle。输入</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>cat</span><span> </span><span>/proc/diskstats</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>应该会看到如下的输出, 如果提示找不到文件或目录，那就不支持hd-idle。</p><p>8 16 sdb 5604 130363 146538 16780 1814 51838 429152 763380 0 18230 780150
8 17 sdb1 5075 130363 139418 15370 8 0 8 10 0 8680 15370
8 18 sdb2 512 0 6984 1290 1805 51838 429144 763360 0 9770 764650</p><p>hd-idle的自己编译，</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt-get</span><span> </span><span>install</span><span> </span><span>build-essential</span><span> </span><span>fakeroot</span><span> </span><span>debhelper</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>获取源代码，</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>wget</span><span> </span><span>http://sourceforge.net/projects/hd-idle/files/hd-idle-1.05.tgz</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>解压缩进入目录</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>tar</span><span> </span><span>-xvf</span><span> </span><span>hd-idle-1.05.tgz</span><span> &amp;&amp; </span><span>cd</span><span> </span><span>hd-idle</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编译安装，</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>dpkg-buildpackage</span><span> </span><span>-rfakeroot</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>dpkg</span><span> </span><span>-i</span><span> </span><span>../hd-idle_</span><span>*</span><span>.deb</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>继续检查硬盘是否支持hd-idle,</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>hd-idle</span><span> </span><span>-i</span><span> </span><span>0</span><span> </span><span>-a</span><span> </span><span>sda</span><span> </span><span>-i</span><span> </span><span>300</span><span> </span><span>-d</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>你会看到如下输出：</p><p>probing sda: reads: 13418, writes: 594344
probing sdb: reads: 146538, writes: 429152</p><p>按 Ctrl+C 停止 hd-idle</p><p>编辑配置文件，</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>vim</span><span> </span><span>/etc/default/hd-idle</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>修改下面来开启hd-idle</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>START_HD_IDLE</span><span>=</span><span>true</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>调整空闲时间为10分钟 (60 秒 * 10)</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>HD_IDLE_OPTS</span><span>=</span><span>"-i 0 -a sda -i 600"</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重启服务，</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>service</span><span> </span><span>hd-idle</span><span> </span><span>restart</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果hd-idle也不支持，可以试下 sdparm</p></section>
<section><h1>安装和配置 sdparm<a href="#安装和配置-sdparm"><span>#</span></a></h1><p>首先删除 hdparm 和 hd-idle</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt-get</span><span> </span><span>remove</span><span> </span><span>hdparm</span><span> </span><span>-y</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>dpkg</span><span> </span><span>-r</span><span> </span><span>hd-idle</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>安装 sdparm</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt-get</span><span> </span><span>install</span><span> </span><span>sdparm</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>测试sdparm是否支持，停止一切硬盘操作，输入</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sydo</span><span> </span><span>sdparm</span><span> </span><span>--flexible</span><span> </span><span>--command=stop</span><span> </span><span>/dev/sdb</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>应该可以看到如下输出，</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/dev/sdb: SANHO     IUSBPORT          0</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果需要每隔10分钟休眠硬盘，可以用如下crontab命令</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>crontab</span><span> </span><span>-l</span><span> | { </span><span>cat</span><span>; </span><span>echo</span><span> </span><span>"/10 * * * * sdparm --command=stop /dev/sda"</span><span>; } | </span><span>sudo</span><span> </span><span>crontab</span><span> </span><span>-</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>经过以上折腾，终于可以放心了，不用担心硬盘一天24小时不要命的转。</p></section>
<section><h1>参考<a href="#参考"><span>#</span></a></h1><p><a href="http://sg.danny.cz/sg/sdparm.html" target="_blank">http://sg.danny.cz/sg/sdparm.html</a>
<a href="http://www.nslu2-linux.org/wiki/FAQ/SpinDownUSBHarddisks" target="_blank">http://www.nslu2-linux.org/wiki/FAQ/SpinDownUSBHarddisks</a>
<a href="http://hd-idle.sourceforge.net/" target="_blank">http://hd-idle.sourceforge.net/</a></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/130/</id>
      <title type="text">【Tensorflow】卷积神经网络图片风格转化</title>
      <published>2018-12-03T00:00:00.000Z</published>
      <updated>2019-10-24T07:28:44.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/130/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>之前有一款火爆网络的图像风格转化软件 Prisma，它能将一张普通的图片转成各种艺术风格的图像。现在简单来了解一下背后的算法原理及使用Tensorflow实现一下。</p></section>
<section><h1>0x01 原理简述<a href="#0x01-原理简述"><span>#</span></a></h1><p>2016 CVPR 一篇文章：” Image Style Transfer Using Convolutional Neural Networks”（<a href="https://blog.csdn.net/cicibabe/article/details/70885715" target="_blank">文章翻译</a>） 提出了这种算法。</p><p>算法流程图：</p><p></p><figure><img alt="1.png" loading="lazy" width="1534" height="852" src="/_astro/130.1.CmUdlNe6_Z1retKB.webp" /><figcaption>1.png</figcaption></figure><p></p><p>简单地说就是使用一个训练好的卷积神经网络 VGG-19（19层VGG网络包含16个卷积层和5个池化层），而这个网络在<a href="http://www.image-net.org/" target="_blank">ImageNet</a>上已经有训练好了的。</p><p>假如现在有一张<strong>风格图像</strong>和一张<strong>普通图像</strong>，<strong>风格图像</strong>经过VGG-19 的时候在每个卷积层会得到很多 feature maps, 这些feature maps 组成一个<strong>集合 A</strong>，同样的，<strong>普通图像</strong> 通过 VGG-19 的时候也会得到很多 feature maps，这些feature maps 组成一个<strong>集合 B</strong> ，然后生成一张<strong>随机噪声图像</strong> ,同样 <strong>随机噪声图像</strong> 通过VGG-19 的时候也会生成很多feature maps，这些 feature maps 构成<strong>集合 C</strong> ,最终的优化函数是希望调整 <strong>C</strong> 让 <strong>随机噪声图像</strong> 最后既保持<strong>普通图像</strong> 的内容, 又有一定的<strong>风格图像</strong>的风格。</p><p></p><figure><img alt="2.png" loading="lazy" width="909" height="793" src="/_astro/130.2.BhLAP9UL_1N5UO7.webp" /><figcaption>2.png</figcaption></figure><p></p><p>想要了解更多请阅读原文 ” Image Style Transfer Using Convolutional Neural Networks”（<a href="https://blog.csdn.net/cicibabe/article/details/70885715" target="_blank">文章翻译</a>）</p></section>
<section><h1>0x02 实现<a href="#0x02-实现"><span>#</span></a></h1><p>较好的实现项目：</p><ol>
<li><a href="https://github.com/anishathalye/neural-style" target="_blank">neural-style</a> *需要性能较好的计算机。512 x 512分辨率的图片使用不同硬件进行1000次迭代性能对比：
<ol>
<li>GTX 1080                          ~60s</li>
<li>Maxwell Titan X               ~90s</li>
<li>Intel Core i7-5930K         ~1h</li>
</ol>
</li>
<li><a href="https://github.com/Rehtt/fast-neural-style-tensorflow" target="_blank">fast-neural-style-tensorflow</a> *可以使用预训练模型或自己训练模型，使用预训练的模型在性能较低的计算机上也能较好地实现。</li>
</ol><p>这里使用预训练模型。</p><p>Tensorflow安装</p><p>克隆项目：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>git</span><span> </span><span>clone</span><span> </span><span>https://github.com/Rehtt/fast-neural-style-tensorflow.git</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>运行：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>#图像</span></div></div><div><div><div>2</div></div><div><span>python</span><span> </span><span>eval.py</span><span> </span><span>--model_file</span><span> </span><span>&lt;wave.ckpt-done模型的路径&gt;</span><span> </span><span>--image_file</span><span> </span><span>img/test.jpg</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>#视频</span></div></div><div><div><div>5</div></div><div><span>python</span><span> </span><span>video.py</span><span> </span><span>--model_file</span><span> </span><span>&lt;wave.ckpt-done模型的路径&gt;</span><span> </span><span>--video_file</span><span> </span><span>video/test.mp4</span><span> </span><span>--out_video_file</span><span> </span><span>video/video.mp4</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>详情及训练模型请阅读<a href="https://github.com/Rehtt/fast-neural-style-tensorflow/blob/master/README.md" target="_blank">说明</a></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/129/</id>
      <title type="text">【树莓派】树莓派+aria2搭建远程下载器</title>
      <published>2018-11-25T00:00:00.000Z</published>
      <updated>2019-10-24T07:26:23.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/129/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>之前采用的是迅雷+树莓派的方案搭建远程下载机，但是现在迅雷远程下载总是出现问题加上迅雷已经停止维护第三方下载机的程序(╯°Д°)╯︵┻━┻，不过劳动人民的智慧是无穷的(๑＞︶＜)و，在这里采用树莓派+aria2来搭建下载机使用云服务器使用frp内网穿透转发来实现远程控制。</p><p>环境：树莓派3B、Raspbian</p><p>软件：aria2（下载器）、frp（内网穿透）</p></section>
<section><h1>0x01 搭建下载环境<a href="#0x01-搭建下载环境"><span>#</span></a></h1><section><h2>1.aria2安装<a href="#1aria2安装"><span>#</span></a></h2><p>Aria2是一款免费开源跨平台且不限速的多线程下载软件，Aria2的优点是速度快、体积小、资源占用少。</p><p>在树莓派官方系统Raspbian及大多数系统中是支持直接安装的，在其他系统中就有可能需要<a href="https://github.com/aria2/aria2" target="_blank">编译安装</a>。</p><p>这里主要使用直接安装，在终端输入</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>apt</span><span> </span><span>update</span><span> &amp;&amp; </span><span>sudo</span><span> </span><span>apt</span><span> </span><span>upgrade</span><span> </span><span>-y</span></div></div><div><div><div>2</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>aria2</span><span> </span><span>-y</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>2.aria2配置<a href="#2aria2配置"><span>#</span></a></h2><p>先创建配置文件夹和创建相关文件</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>mkdir</span><span> </span><span>~/.config/aria2</span></div></div><div><div><div>2</div></div><div><span>$</span><span> </span><span>touch</span><span> </span><span>~/.config/aria2/aria2.conf</span></div></div><div><div><div>3</div></div><div><span>$</span><span> </span><span>touch</span><span> </span><span>~/.config/aria2/aria2.session</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编写简单配置文件</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>nano</span><span> </span><span>~/.config/aria2/aria2.conf</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>aria2.conf 内容：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#启用RPC远程连接, 默认:false</span></div></div><div><div><div>2</div></div><div><span>enable-rpc</span><span><span>=</span><span>true</span></span></div></div><div><div><div>3</div></div><div><span>#允许所有来源, 默认:false</span></div></div><div><div><div>4</div></div><div><span>rpc-allow-origin-all</span><span><span>=</span><span>true</span></span></div></div><div><div><div>5</div></div><div><span>#允许非外部访问, 默认:false</span></div></div><div><div><div>6</div></div><div><span>rpc-listen-all</span><span><span>=</span><span>true</span></span></div></div><div><div><div>7</div></div><div><span>#RPC监听端口, 端口被占用时可以修改, 默认:6800</span></div></div><div><div><div>8</div></div><div><span>rpc-listen-port</span><span><span>=</span><span>6800</span></span></div></div><div><div><div>9</div></div><div><span>#设置的RPC授权令牌, v1.18.4新增功能, 取代 --rpc-user 和 --rpc-passwd 选项。建议在远程连接下载启用保障安全</span></div></div><div><div><div>10</div></div><div><span>rpc-secret</span><span><span>=</span><span>123456</span></span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>#从会话文件中读取下载任务</span></div></div><div><div><div>13</div></div><div><span>input-file</span><span><span>=</span><span>/etc/aria2/aria2.session</span></span></div></div><div><div><div>14</div></div><div><span>#在Aria2退出时保存`错误/未完成`的下载任务到会话文件</span></div></div><div><div><div>15</div></div><div><span>save-session</span><span><span>=</span><span>/etc/aria2/aria2.session</span></span></div></div><div><div><div>16</div></div><div><span>#定时保存会话, 0为退出时才保存, 需1.16.1以上版本, 默认:0</span></div></div><div><div><div>17</div></div><div><span>save-session-interval</span><span><span>=</span><span>60</span></span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>#下载文件保存地址</span></div></div><div><div><div>20</div></div><div><span>dir</span><span><span>=</span><span>~/downloads</span></span></div></div><div><div><div>21</div></div><div><span>#断点续传</span></div></div><div><div><div>22</div></div><div><span>continue</span><span><span>=</span><span>true</span></span></div></div><div><div><div>23</div></div><div><span>#文件预分配，减少碎片文件，默认：prealloc</span></div></div><div><div><div>24</div></div><div><span>#预分配所需时间: none &lt; falloc ? trunc &lt; prealloc</span></div></div><div><div><div>25</div></div><div><span>#树莓派Raspbian是Linux系统采用EXT3/4文件系统，所以使用trunc</span></div></div><div><div><div>26</div></div><div><span>file-allocation</span><span><span>=</span><span>trunc</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>可以在配置文件中选择添加bt下载服务器，<a href="https://github.com/ngosang/trackerslist" target="_blank">服务器列表</a>：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>bt-tracker</span><span><span>=</span><span>（服务器地址以</span></span><span>","</span><span>分隔）</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果需要添加其他参数请阅读<a href="https://aria2.github.io/manual/en/html/index.html" target="_blank">Aria2官方文档</a>及善于搜索（求人不如求己(～￣▽￣)～ ）</p></section></section>
<section><h1>0x02 配置远程下载及界面<a href="#0x02-配置远程下载及界面"><span>#</span></a></h1><section><h2>1.配置远程下载<a href="#1配置远程下载"><span>#</span></a></h2><p>这里使用frp转发来实现内网穿透（需要有云服务器做中转），如果有公网ip就不需要，公网ip一般只有企业宽带才可能有，或者也可以打电话到宽带运营商开通（可以上网学习一下网友打电话开通的各种骚操作ヽ(￣▽￣)ﾉ）</p><p>使用frp主要转发aria2的rpc端口。</p><p><a href="/posts/33/">参考frp教程</a></p></section><section><h2>2.配置界面<a href="#2配置界面"><span>#</span></a></h2><p>由于aria2是没有图像界面的所以这里使用的是web网页界面<a href="https://github.com/ziahamza/webui-aria2" target="_blank">webui-aria2</a>，可以使用在线的网页需要填入树莓派地址、端口、令牌（可选），也可以将此网页界面下载到本地使用。</p><p>在本地电脑或树莓派或云服务器上下载webui-aria2</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>git</span><span> </span><span>clone</span><span> </span><span>https://github.com/ziahamza/webui-aria2.git</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>进入其中的docs目录修改文件</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>cd</span><span> </span><span>webui-aria2/docs</span></div></div><div><div><div>2</div></div><div><span>$</span><span> </span><span>nano</span><span> </span><span>./app.js</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>点击键盘ctrl+w搜索</span><span>"location.hostname:"</span><span>，修改</span></div></div><div><div><div>5</div></div><div><span>" location.hostname：树莓派所在的ip或网址 "</span></div></div><div><div><div>6</div></div><div><span>" port: aria2的rpc端口 "</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>搜索找到</span><span>" (c = p &amp;&amp; p.auth &amp;&amp; p.auth.token ? p.auth.token : null),"</span><span>，并将这行修改为</span><span>" (c="</span><span>你配置rpc-secret的值</span><span>") "</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>0x03 END<a href="#0x03-end"><span>#</span></a></h1></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/119/</id>
      <title type="text">【免杀】通过修改特征码实现杀毒软件免杀</title>
      <published>2018-10-17T00:00:00.000Z</published>
      <updated>2019-10-24T07:24:54.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/119/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00 前言<a href="#0x00-前言"><span>#</span></a></h1><p>前几天写的一个程序被火绒误报毒了不开森(╬￣皿￣)，不过劳动人民的智慧是无穷的(๑＞︶＜)و，通过修改软件特征码就可以绕过杀毒软件的检测。</p><p>使用工具：myccl（将文件分块找查具体报毒的特征码所在的位置），c32asm（修改文件特征码，用其他的16进制/汇编修改工具也可以）</p></section>
<section><h1>0x01 查找具体特征码<a href="#0x01-查找具体特征码"><span>#</span></a></h1><p>1.打开myccl加载报毒文件，先将文件分块20份</p><p></p><figure><img alt="Lily_Screenshot_1539742852.png" loading="lazy" width="652" height="622" src="/_astro/119.1.tvth5j3d_Z2e7AF3.webp" /><figcaption>Lily_Screenshot_1539742852.png</figcaption></figure><p></p><p>2.点击“生成”，找到分块的目录使用杀毒软件查杀文件</p><p></p><figure><img alt="Lily_Screenshot_1539742992.png" loading="lazy" width="803" height="546" src="/_astro/119.2.B1Y6lmeb_rSoGP.webp" /><figcaption>Lily_Screenshot_1539742992.png</figcaption></figure><p></p><p>3.将报毒的文件删除，回到myccl点击“二次处理”</p><p>4.循环“查杀病毒”&gt;“二次处理”，一直到没报毒为止，这样做是为了缩小特征码范围</p><p>5.随后会定位到特征码范围</p><p></p><figure><img alt="Lily_Screenshot_1539743989.png" loading="lazy" width="652" height="622" src="/_astro/119.3.CkTL4n_-_Z2hsFA1.webp" /><figcaption>Lily_Screenshot_1539743989.png</figcaption></figure><p></p><p>但是特征码物理长度太大，所以还要进一步定位</p><p>6.点击“特征区间”，选中右键“复合定位此处特征”，随后可以看到被重新分块且长度为2
</p><figure><img alt="Lily_Screenshot_1539743135.png" loading="lazy" width="344" height="622" src="/_astro/119.4.fzT_HNSr_Z1x2FOf.webp" /><figcaption>Lily_Screenshot_1539743135.png</figcaption></figure><p></p><p>7.点击“生成”，随后重复第4步，最后找到长度为2的特征码</p><p></p><figure><img alt="Lily_Screenshot_1539744377.png" loading="lazy" width="652" height="622" src="/_astro/119.5.CItD61A7_1dhsQh.webp" /><figcaption>Lily_Screenshot_1539744377.png</figcaption></figure><p></p><p>其中物理地址就是我们要找的特征码</p></section>
<section><h1>0x02 修改特征码<a href="#0x02-修改特征码"><span>#</span></a></h1><p>打开c32asm，以16进制打开文件</p><p>1.右键“跳到”，输入刚刚定位的物理地址</p><p></p><figure><img alt="Lily_Screenshot_1539744661.png" loading="lazy" width="410" height="190" src="/_astro/119.6.CPeWm8r__Z1nDvUr.webp" /><figcaption>Lily_Screenshot_1539744661.png</figcaption></figure><p></p><p>2.右键“对应汇编模式编辑”</p><p></p><figure><img alt="Lily_Screenshot_1539744905.png" loading="lazy" width="147" height="92" src="/_astro/119.7.eDGiMXfO_Z1rNLos.webp" /><figcaption>Lily_Screenshot_1539744905.png</figcaption></figure><p></p><p>3.我这16进制对应的汇编指令是“ADD”（根据自己实际情况而定），将它替换对应的“等价汇编指令”（上百度google一下），“ADD”对应的是“ADC”</p><p>4.右键“汇编”，输入相应的“等价汇编指令”</p><p></p><figure><img alt="Lily_Screenshot_1539744948.png" loading="lazy" width="807" height="275" src="/_astro/119.8.CgMyzARI_2kc7LM.webp" /><figcaption>Lily_Screenshot_1539744948.png</figcaption></figure><p></p><p>5.点击“汇编”，“退出”</p><p>6.保存文件即可</p></section>
<section><h1>0x03 END<a href="#0x03-end"><span>#</span></a></h1><p>用杀毒软件扫描没有报毒就修改成功</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/118/</id>
      <title type="text">【C++】修改注册表管理开机启动项</title>
      <published>2018-10-16T00:00:00.000Z</published>
      <updated>2019-10-24T07:19:10.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/118/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>// 程序开机自动启动</span></div></div><div><div><div>2</div></div><div><span>void</span><span> </span><span>autostart</span><span>()</span></div></div><div><div><div>3</div></div><div><span>{</span></div></div><div><div><div>4</div></div><div><span>    </span><span>HKEY</span><span> </span><span>hKey</span><span>;</span></div></div><div><div><div>5</div></div><div><span>    </span><span>QString</span><span> </span><span>strRegPath</span><span> </span><span>=</span><span> </span><span>"SOFTWARE</span><span>\\</span><span>Microsoft</span><span>\\</span><span>Windows</span><span>\\</span><span>CurrentVersion</span><span>\\</span><span>Run"</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>//1、找到系统的启动项</span></div></div><div><div><div>8</div></div><div><span>    </span><span>if</span><span> (</span><span>RegOpenKeyEx</span><span>(</span><span>HKEY_CURRENT_USER</span><span>, </span><span>strRegPath</span><span>.</span><span>toStdString</span><span>().</span><span>c_str</span><span>(), </span><span>0</span><span>, </span><span>KEY_ALL_ACCESS</span><span>, </span><span>&amp;</span><span>hKey</span><span>) </span><span>==</span><span> </span><span>ERROR_SUCCESS</span><span>)</span><span> ///打开启动项</span></div></div><div><div><div>9</div></div><div><span><span>    </span></span><span>{</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>//2、得到本程序自身的全路径</span></div></div><div><div><div>11</div></div><div><span>        </span><span>TCHAR</span><span> </span><span>strExeFullDir</span><span>[</span><span>MAX_PATH</span><span>];</span></div></div><div><div><div>12</div></div><div><span>        </span><span>GetModuleFileName</span><span>(</span><span>NULL</span><span>, </span><span>strExeFullDir</span><span>, </span><span>MAX_PATH</span><span>);</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>//3、判断注册表项是否已经存在</span></div></div><div><div><div>15</div></div><div><span>        </span><span>TCHAR</span><span> </span><span>strDir</span><span>[</span><span>MAX_PATH</span><span>] </span><span>=</span><span> {};</span></div></div><div><div><div>16</div></div><div><span>        </span><span>DWORD</span><span> </span><span>nLength</span><span> </span><span>=</span><span> </span><span>MAX_PATH</span><span>;</span></div></div><div><div><div>17</div></div><div><span>        </span><span>long</span><span> </span><span>result</span><span> </span><span>=</span><span> </span><span>RegGetValue</span><span>(</span><span>hKey</span><span>, </span><span>nullptr</span><span>, </span><span>"GISRestart"</span><span>, </span><span>RRF_RT_REG_SZ</span><span>, </span><span>0</span><span>, </span><span>strDir</span><span>, </span><span>&amp;</span><span>nLength</span><span>);</span><span> ///"GISRestart"是应用程序名字</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>//4、已经存在</span></div></div><div><div><div>20</div></div><div><span>        </span><span>if</span><span> (</span><span>result</span><span> </span><span>!=</span><span> </span><span>ERROR_SUCCESS</span><span> </span><span>||</span><span> </span><span>_tcscmp</span><span>(</span><span>strExeFullDir</span><span>, </span><span>strDir</span><span>) </span><span>!=</span><span> </span><span>0</span><span>)</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>{</span></div></div><div><div><div>22</div></div><div><span><span>            </span></span><span>//5、添加一个子Key,并设置值，"GISRestart"是应用程序名字（不加后缀.exe）</span></div></div><div><div><div>23</div></div><div><span>            </span><span>RegSetValueEx</span><span>(</span><span>hKey</span><span>, </span><span>"GISRestart"</span><span>, </span><span>0</span><span>, </span><span>REG_SZ</span><span>, (</span><span>LPBYTE</span><span>)</span><span>strExeFullDir</span><span>, (</span><span>lstrlen</span><span>(</span><span>strExeFullDir</span><span>) </span><span>+</span><span> </span><span>1</span><span>)</span><span>*sizeof</span><span>(</span><span>TCHAR</span><span>));</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span><span>            </span></span><span>//6、关闭注册表</span></div></div><div><div><div>26</div></div><div><span>            </span><span>RegCloseKey</span><span>(</span><span>hKey</span><span>);</span></div></div><div><div><div>27</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>29</div></div><div><span>    </span><span>else</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>{</span></div></div><div><div><div>31</div></div><div><span>        </span><span>MessageBox</span><span>(</span><span>NULL</span><span>, </span><span>"设置失败"</span><span>, </span><span>"error"</span><span>, </span><span>0</span><span>);</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>33</div></div><div><span>}</span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span>// 取消开机自动启动</span></div></div><div><div><div>36</div></div><div><span>void</span><span> </span><span>cancelAutoStart</span><span>()</span></div></div><div><div><div>37</div></div><div><span>{</span></div></div><div><div><div>38</div></div><div><span>    </span><span>HKEY</span><span> </span><span>hKey</span><span>;</span></div></div><div><div><div>39</div></div><div><span>    </span><span>const</span><span> </span><span>char*</span><span> </span><span>strRegPath</span><span> </span><span>=</span><span> </span><span>"SOFTWARE</span><span>\\</span><span>Microsoft</span><span>\\</span><span>Windows</span><span>\\</span><span>CurrentVersion</span><span>\\</span><span>Run"</span><span>;</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span><span>    </span></span><span>//1、找到系统的启动项</span></div></div><div><div><div>42</div></div><div><span>    </span><span>if</span><span> (</span><span>RegOpenKeyEx</span><span>(</span><span>HKEY_CURRENT_USER</span><span>, </span><span>strRegPath</span><span>, </span><span>0</span><span>, </span><span>KEY_ALL_ACCESS</span><span>, </span><span>&amp;</span><span>hKey</span><span>) </span><span>==</span><span> </span><span>ERROR_SUCCESS</span><span>)</span></div></div><div><div><div>43</div></div><div><span><span>    </span></span><span>{</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>//2、删除值</span></div></div><div><div><div>45</div></div><div><span>        </span><span>RegDeleteValue</span><span>(</span><span>hKey</span><span>, </span><span>"GISRestart"</span><span>);</span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span><span>        </span></span><span>//3、关闭注册表</span></div></div><div><div><div>48</div></div><div><span>        </span><span>RegCloseKey</span><span>(</span><span>hKey</span><span>);</span></div></div><div><div><div>49</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>50</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/117/</id>
      <title type="text">【人工智能】TensorFlow Windows安装</title>
      <published>2018-10-07T00:00:00.000Z</published>
      <updated>2019-10-24T07:16:38.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/117/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00 TensorFlow环境搭建<a href="#0x00-tensorflow环境搭建"><span>#</span></a></h1><blockquote><p>本教程引用 <a href="https://www.tensorflow.org/install/install_windows" target="_blank">https://www.tensorflow.org/install/install_windows</a></p></blockquote><ul>
<li>仅支持CPU。如果您的系统没有 NVIDIA® GPU，则必须安装此版本。请注意，此版本的 TensorFlow 通常更容易安装（用时通常在 5 或 10 分钟内），所以即使您拥有 NVIDIA GPU，我们也建议先安装此版本。预编译的二进制文件将使用 AVX 指令。</li>
<li>支持GPU。TensorFlow 程序在 GPU 上的运行速度通常要比在 CPU 上快得多。因此，如果您的系统配有满足以下所示先决条件的 NVIDIA® GPU，并且您需要运行性能至关重要的应用，则最终应安装此版本。</li>
</ul><section><h2>GPU版本环境搭建<a href="#gpu版本环境搭建"><span>#</span></a></h2><p><strong>GPU版本要求使用NVIDIA GPU卡，并且CUDA计算能力在3.0及以上</strong>。CUDA 计算能力为3.0或更高的卡需要从源码编译安装TensorFlow 。计算能力为3.5或更高的卡可以使用编译好的二进制文件安装TensorFlow （使用pip安装.whl）。</p><p>当前为TensorFlow-gpu 1.11.0的环境要求，必须按照要求的版本安装，若版本高于或低于要求都有可能出现错误。</p><ul>
<li><a href="https://developer.nvidia.com/cuda-90-download-archive?target_os=Windows&amp;target_arch=x86_64&amp;target_version=10&amp;target_type=exelocal" target="_blank">CUDA Toolkit 9.0</a></li>
<li><a href="https://developer.nvidia.com/rdp/cudnn-archive#a-collapse705-9" target="_blank">cuDNN v7.0</a>  下载完后解压，将内部的三个文件夹复制到CUDA Toolkit 的安装目录下</li>
</ul><p>注意：cuDNN 版本必须完全匹配：如果无法找到 <code>cuDNN64_7.dll</code>，TensorFlow 就不会加载。要使用不同版本的 cuDNN，必须从源代码构建。</p></section></section>
<section><h1>0x01 TensorFlow安装<a href="#0x01-tensorflow安装"><span>#</span></a></h1><section><h2>使用pip安装<a href="#使用pip安装"><span>#</span></a></h2><p>支持的python版本：3.5	3.6</p><p>CPU版本安装：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pip3</span><span> </span><span>install</span><span> </span><span>tensorflow</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>GPU版本安装：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pip3</span><span> </span><span>install</span><span> </span><span>tensorflow-gpu</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>使用Anaconda安装<a href="#使用anaconda安装"><span>#</span></a></h2><ol>
<li>
<p>通过调用以下命令创建名为 <code>tensorflow</code> 的 conda 环境：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>C:&gt; conda create -n tensorflow pip python=3.5</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>通过发出以下命令激活 conda 环境：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>C:&gt; activate tensorflow</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>(tensorflow)C:&gt;  # Your </span><span>prompt</span><span> should </span><span>change</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
<li>
<p>发出相应命令以在 conda 环境中安装 TensorFlow。要安装仅支持 CPU 的 TensorFlow 版本，请输入以下命令：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>(tensorflow)C:&gt; pip install --ignore-installed --upgrade tensorflow</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>要安装 GPU 版本的 TensorFlow，请输入以下命令（在同一行）：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>(tensorflow)C:&gt; pip install --ignore-installed --upgrade tensorflow-gpu</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
</li>
</ol></section><section><h2>验证安装是否成功<a href="#验证安装是否成功"><span>#</span></a></h2><p>进入Python环境</p><p>输入：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>&gt;&gt;&gt;</span><span> </span></span><span>import</span><span> tensorflow </span><span>as</span><span> tf</span></div></div><div><div><div>2</div></div><div><span><span>&gt;&gt;&gt;</span><span> hello </span><span>=</span><span> tf.</span><span>constant</span><span>(</span></span><span>'Hello, TensorFlow!'</span><span>)</span></div></div><div><div><div>3</div></div><div><span><span>&gt;&gt;&gt;</span><span> sess </span><span>=</span><span> tf.</span><span>Session</span><span>()</span></span></div></div><div><div><div>4</div></div><div><span><span>&gt;&gt;&gt;</span><span> </span></span><span>print</span><span><span>(sess.</span><span>run</span><span>(hello))</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>若输出以下内容就说明安装成功：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Hello, TensorFlow!</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果系统输出一条错误消息而不是问候语，请参阅 常见的安装问题</p></section><section><h2>常见的安装问题<a href="#常见的安装问题"><span>#</span></a></h2><p>我们借助 Stack Overflow 来记录 TensorFlow 安装问题及其补救措施。下表包含了 Stack Overflow 上一些常见安装问题解答的链接。如果您遇到了下表中未列出的错误消息或其他安装问题，请在 Stack Overflow 上进行搜索。如果 Stack Overflow 中没有显示相关错误消息，请在 Stack Overflow 上提一个新的问题，并指定 <code>tensorflow</code> 标签。</p>

<table><thead><tr><th>Stack Overflow 链接</th><th>错误消息</th></tr></thead><tbody><tr><td><a href="https://stackoverflow.com/q/41007279" target="_blank">41007279</a></td><td><code> [...\stream_executor\dso_loader.cc] Couldn't open CUDA library nvcuda.dll</code></td></tr><tr><td><a href="https://stackoverflow.com/q/41007279" target="_blank">41007279</a></td><td><code> [...\stream_executor\cuda\cuda_dnn.cc] Unable to load cuDNN DSO</code></td></tr><tr><td><a href="http://stackoverflow.com/q/42006320" target="_blank">42006320</a></td><td><code> ImportError: Traceback (most recent call last): File "...\tensorflow\core\framework\graph_pb2.py", line 6, in  from google.protobuf import descriptor as _descriptor ImportError: cannot import name 'descriptor'</code></td></tr><tr><td><a href="https://stackoverflow.com/q/42011070" target="_blank">42011070</a></td><td><code> No module named "pywrap_tensorflow"</code></td></tr><tr><td><a href="https://stackoverflow.com/q/42217532" target="_blank">42217532</a></td><td><code> OpKernel ('op: "BestSplits" device_type: "CPU"') for unknown op: BestSplits</code></td></tr><tr><td><a href="https://stackoverflow.com/q/43134753" target="_blank">43134753</a></td><td><code> The TensorFlow library wasn't compiled to use SSE instructions</code></td></tr><tr><td><a href="https://stackoverflow.com/q/38896424" target="_blank">38896424</a></td><td><code> Could not find a version that satisfies the requirement tensorflow</code></td></tr></tbody></table></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/116/</id>
      <title type="text">【Python】安装Dlib人脸识别库</title>
      <published>2018-09-30T00:00:00.000Z</published>
      <updated>2019-10-24T07:15:23.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/116/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>安装环境<a href="#安装环境"><span>#</span></a></h2><section><h3>Windows<a href="#windows"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>opencv-python</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>dlib==</span><span>19.8.1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>目前19.8.1及之前的版本支持.whl免编译安装，如果要安装最新版则需要采用编译安装的方式：</p><ol>
<li>确保有安装Visual Studio，因为boost在Windows下需要使用Visual Studio的组件编译安装。</li>
<li>下载boost源文件解压后双击bootstrap.bat，在同目录下会生成b2.exe与bjam.exe两个文件。</li>
<li>命令输入</li>
</ol><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>bjam install --toolset=msvc-10.0 architecture=x86 address-model=</span><span>64</span><span> --build-type=complete --prefix=</span><span>"E:\boost_1_64_0\boost_1_64_0\bin\vc10_x64"</span><span> link=static runtime-link=shared threading=multi debug release</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>进行编译安装</p><p>参数解释：</p><ul>
<li>link=shared    可以生成dll。  （.\bjam.exe link=shared)</li>
<li>
<ul>
<li>
<p>toolset=msvc-14.1 即VS2017    (我用的vs2017)                    </p>
</li>
<li>
<p>toolset=msvc-12.0 即VS2013                   </p>
</li>
<li>
<p>toolset=msvc-10.0 即VS2010                   </p>
</li>
<li>
<p>toolset=msvc-9.0  即VS2008 </p>
</li>
</ul>
</li>
<li>—with-xxxx                             如果你要编 chrono，就用  —with-chrono     </li>
<li>—stagedir=”./vc2017”            自己设定一个输出目录  </li>
<li>address-model=64                 设定32或者64位模式</li>
</ul><ol>
<li>
<p>下载安装CMake</p>
</li>
<li>
<p>编译安装Dlib</p>
</li>
</ol><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pip install dlib</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>Linux<a href="#linux"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>cmake</span><span> </span><span>boost-dev</span></div></div><div><div><div>2</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>opencv-python</span></div></div><div><div><div>3</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>dlib</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h3>Mac<a href="#mac"><span>#</span></a></h3><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>brew</span><span> </span><span>install</span><span> </span><span>cmake</span><span> </span><span>brew</span><span> </span><span>install</span><span> </span><span>boost</span><span> </span><span>brew</span><span> </span><span>install</span><span> </span><span>boost-python</span><span> </span><span>--with-python3</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>opencv-python</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>dlib</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/115/</id>
      <title type="text">【Linux】mysql服务安装</title>
      <published>2018-09-19T00:00:00.000Z</published>
      <updated>2019-10-24T07:13:54.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/115/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00 安装<a href="#0x00-安装"><span>#</span></a></h1><p>终端输入</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>apt</span><span> </span><span>install</span><span> </span><span>-y</span><span> </span><span>mysql-server</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x01 设置root密码<a href="#0x01-设置root密码"><span>#</span></a></h1><p>安装完后root默认是没有密码的，但可以使用系统root权限免密码进入数据库</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>mysql</span><span> </span><span>-u</span><span> </span><span>root</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>进入后</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>use</span><span> mysql;</span></div></div><div><div><div>2</div></div><div><span>update</span><span> user </span><span>set</span><span><span> plugin</span><span>=</span></span><span>'mysql_native_password'</span><span> </span><span>where</span><span><span> user</span><span>=</span></span><span>'root'</span><span>;</span></div></div><div><div><div>3</div></div><div><span>update</span><span> user </span><span>set</span><span> </span><span>password</span><span>=</span><span>password</span><span>(</span><span>'密码'</span><span>) </span><span>where</span><span><span> user</span><span>=</span></span><span>'root'</span><span>;</span></div></div><div><div><div>4</div></div><div><span>flush privileges;</span></div></div><div><div><div>5</div></div><div><span>exit;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>重启数据库</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>service</span><span> </span><span>mysql</span><span> </span><span>restart</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02 开启远程访问<a href="#0x02-开启远程访问"><span>#</span></a></h1><p>修改配置</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>nano</span><span> </span><span>/etc/mysql/mariadb.conf.d/50-server.cnf</span></div></div><div><div><div>2</div></div><div><span>将</span><span> </span><span>bind-address</span><span> </span><span>127.0.0.1</span><span> </span><span>注释掉</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>service</span><span> </span><span>mysql</span><span> </span><span>restart</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>进入数据库设置远程登录操作</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>use</span><span> mysql;</span></div></div><div><div><div>2</div></div><div><span>grant</span><span> all privileges </span><span>on</span><span> *.* </span><span>to</span><span> </span><span>'root'</span><span>@</span><span>'%'</span><span> identified </span><span>by</span><span> </span><span>'root账户密码'</span><span> </span><span>with</span><span> </span><span>grant</span><span> </span><span>option</span><span>;</span></div></div><div><div><div>3</div></div><div><span>flush privileges;</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/113/</id>
      <title type="text">【Golang】所遇问题及解答</title>
      <published>2018-09-13T00:00:00.000Z</published>
      <updated>2019-10-24T07:12:01.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/113/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<ul>
<li>###0x00.Respones.Body只能读一遍</li>
</ul>
<p>因为我采用ioutil.ReadAll读取Respones.Body，所以后来发现再次读取Respones.Body发现是空的。这是因为Body会标记读取位置，ReadAll会读取到末尾，因此第二次就会读不到数据。</p>
<p>解决方法：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>res</span><span>, </span><span>_</span><span><span> </span><span>:=</span><span> </span></span><span>ioutil</span><span>.</span><span>ReadAll</span><span>(</span><span>respones</span><span>.</span><span>Body</span><span>)</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>respones</span><span>.</span><span>Body</span><span>.</span><span>Close</span><span>()</span></div></div><div><div><div>4</div></div><div><span>respones</span><span>.</span><span>Body</span><span><span> </span><span>=</span><span> </span></span><span>ioutil</span><span>.</span><span>NopCloser</span><span>(</span><span>bytes</span><span>.</span><span>NewBuffer</span><span>(</span><span>res</span><span>))</span></div></div></code></pre><div><div></div><div></div></div></figure></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/114/</id>
      <title type="text">【Golang】命令行传递参数</title>
      <published>2018-09-13T00:00:00.000Z</published>
      <updated>2019-10-24T07:12:57.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/114/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00 命令行参数的使用<a href="#0x00-命令行参数的使用"><span>#</span></a></h1><p>Go的命令行参数储存在切片os.Args中</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span> </span><span>i</span><span>,</span><span>s</span><span><span> </span><span>:=</span><span> </span></span><span>range</span><span> </span><span>os</span><span>.</span><span>Args</span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>"Args[</span><span>%d</span><span>]=</span><span>%s</span><span>"</span><span>,</span><span>i</span><span>,</span><span>s</span><span>)</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x01 flag包对命令行参数解析<a href="#0x01-flag包对命令行参数解析"><span>#</span></a></h1><p>flag包</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>flag</span><span>.</span><span>Type</span><span>(</span><span>"Flag Name"</span><span>,</span><span>Default</span><span> </span><span>Value</span><span>,</span><span>"Help Message"</span><span><span>) </span><span>*</span></span><span>Tpye</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>使用实例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span> </span><span>i</span><span><span> </span><span>=</span><span> </span></span><span>flag</span><span>.</span><span>Int</span><span>(</span><span>"i"</span><span> , </span><span>1</span><span> ,</span><span>"number"</span><span>)</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>func</span><span> </span><span>main</span><span>(){</span></div></div><div><div><div>4</div></div><div><span>    </span><span>flag</span><span>.</span><span>Pares</span><span>()</span></div></div><div><div><div>5</div></div><div><span>    </span><span>fmt</span><span>.</span><span>Println</span><span><span>(</span><span>*</span></span><span>n</span><span>)</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>#./main -h</span></div></div><div><div><div>2</div></div><div><span>Usage</span><span> </span><span>of</span><span> </span><span>./main:</span></div></div><div><div><div>3</div></div><div><span>  </span><span>-h</span><span> </span><span>int</span></div></div><div><div><div>4</div></div><div><span>        </span><span>number</span><span> (default </span><span>1</span><span>)</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>#./main -i 1234</span></div></div><div><div><div>7</div></div><div><span>1234</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02 cmd输入<a href="#0x02-cmd输入"><span>#</span></a></h1><p>窗口停留等待输入</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>var</span><span> </span><span>i</span><span> </span><span>string</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>func</span><span> </span><span>main</span><span>(){</span></div></div><div><div><div>4</div></div><div><span>    </span><span>fmt</span><span>.</span><span>Scanln</span><span><span>(</span><span>&amp;</span></span><span>i</span><span>)</span></div></div><div><div><div>5</div></div><div><span>    </span><span>fmt</span><span>.</span><span>Println</span><span>(</span><span>i</span><span>)</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/106/</id>
      <title type="text">【树莓派】使用Python驱动SSD1306 OLED显示</title>
      <published>2018-09-11T00:00:00.000Z</published>
      <updated>2019-10-24T07:08:26.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/106/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>因为之前用的Nokia5110显示有故障，所以在网友的推荐下接触到了SSD1306。</p><blockquote><p>显示模块型号：SSD1306 OLED</p><p>显示范围：单色 128*64点阵</p><p>测试机：树莓派zero w</p><p>测试机系统：<a href="https://www.raspberrypi.org/downloads/raspbian/" target="_blank">Raspbian stretch life</a></p><p>开发语言：Python3</p><p>采用驱动库：<a href="https://github.com/adafruit/Adafruit_Python_SSD1306" target="_blank">Adafruit Python SSD1306</a></p></blockquote></section>
<section><h1>0x01环境准备<a href="#0x01环境准备"><span>#</span></a></h1><section><h2>1.树莓派开启I2C接口<a href="#1树莓派开启i2c接口"><span>#</span></a></h2><p>终端输入</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>raspi-config</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>选择<code>Interfacing Options</code>，开启<code>I2C</code>接口</p><p></p><figure><img alt="Lily_Screenshot_1536654250.png" loading="lazy" width="1097" height="600" src="/_astro/106.1.TrPJ2mhp_Z2pF8jp.webp" /><figcaption>Lily_Screenshot_1536654250.png</figcaption></figure><p></p><p></p><figure><img alt="Lily_Screenshot_1536654260.png" loading="lazy" width="1097" height="600" src="/_astro/106.2.CTE51Z9q_Zm3KLY.webp" /><figcaption>Lily_Screenshot_1536654260.png</figcaption></figure><p></p><p></p><figure><img alt="Lily_Screenshot_1536654272.png" loading="lazy" width="1108" height="600" src="/_astro/106.3.BQoO3mSO_Z1U1fz8.webp" /><figcaption>Lily_Screenshot_1536654272.png</figcaption></figure><p></p><section><h3>更改显示速率（可选，不推荐，会占用大量GPIO资源）<a href="#更改显示速率可选不推荐会占用大量gpio资源"><span>#</span></a></h3><p>为了更好的显示性能，例如显示动画时如对帧率有要求，可以通过修改下面的参数将 I2C 频率从默认的 100KHz 或 400KHz 提升到 1MHz。</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>nano</span><span> </span><span>/boot/config.txt</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在文件末添加一行：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>dtparam</span><span>=</span><span>i2c_baudrate</span><span><span>=</span><span>1000000</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section><section><h2>2.接线<a href="#2接线"><span>#</span></a></h2><p>模块共4针脚，接线为</p><blockquote><p>VCC		1</p><p>GND	    6</p><p>SCL		5</p><p>SDA		3</p></blockquote><p></p><figure><img alt="Lily_Screenshot_1536654018.png" loading="lazy" width="405" height="161" src="/_astro/106.4.Bo59nvj9_ZLFSVV.webp" /><figcaption>Lily_Screenshot_1536654018.png</figcaption></figure><p></p></section><section><h2>3.驱动<a href="#3驱动"><span>#</span></a></h2><p>GPIO驱动：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>Adafruit_GPIO</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>SSD1306采用的驱动是<a href="https://github.com/adafruit/Adafruit_Python_SSD1306" target="_blank">Adafruit Python SSD1306</a>，用pip安装即可。</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>python</span><span> </span><span>-m</span><span> </span><span>pip</span><span> </span><span>install</span><span> </span><span>--upgrade</span><span> </span><span>pip</span><span> </span><span>setuptools</span><span> </span><span>wheel</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>pip</span><span> </span><span>install</span><span> </span><span>Adafruit-SSD1306</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>或者采用python文件安装：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>python</span><span> </span><span>-m</span><span> </span><span>pip</span><span> </span><span>install</span><span> </span><span>--upgrade</span><span> </span><span>pip</span><span> </span><span>setuptools</span><span> </span><span>wheel</span></div></div><div><div><div>2</div></div><div><span>git</span><span> </span><span>clone</span><span> </span><span>https://github.com/adafruit/Adafruit_Python_SSD1306.git</span></div></div><div><div><div>3</div></div><div><span>cd</span><span> </span><span>Adafruit_Python_SSD1306</span></div></div><div><div><div>4</div></div><div><span>sudo</span><span> </span><span>python</span><span> </span><span>setup.py</span><span> </span><span>install</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section></section>
<section><h1>0x03使用<a href="#0x03使用"><span>#</span></a></h1><p>采用python文件安装的可以在<code>Adafruit_Python_SSD1306</code>文件夹中看见<code>examples</code>实例文件夹。</p><p>首先是导入驱动的库：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span><span> Adafruit_GPIO.</span><span>SPI</span><span> </span></span><span>as</span><span><span> </span><span>SPI</span></span></div></div><div><div><div>2</div></div><div><span>import</span><span> Adafruit_SSD1306</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>针脚配置：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># Raspberry Pi pin configuration:</span></div></div><div><div><div>2</div></div><div><span><span>RST</span><span> </span><span>=</span><span> </span></span><span>24</span></div></div><div><div><div>3</div></div><div><span># Note the following are only used with SPI:</span></div></div><div><div><div>4</div></div><div><span><span>DC</span><span> </span><span>=</span><span> </span></span><span>23</span></div></div><div><div><div>5</div></div><div><span><span>SPI_PORT</span><span> </span><span>=</span><span> </span></span><span>0</span></div></div><div><div><div>6</div></div><div><span><span>SPI_DEVICE</span><span> </span><span>=</span><span> </span></span><span>0</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>显示配置：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#分辨率选择一个即可</span></div></div><div><div><div>2</div></div><div><span># 128x32</span></div></div><div><div><div>3</div></div><div><span><span>disp </span><span>=</span><span> Adafruit_SSD1306.</span><span>SSD1306_128_32</span><span>(</span></span><span>rst</span><span><span>=</span><span>RST</span><span>)</span></span></div></div><div><div><div>4</div></div><div><span># 128x64</span></div></div><div><div><div>5</div></div><div><span><span>disp </span><span>=</span><span> Adafruit_SSD1306.</span><span>SSD1306_128_64</span><span>(</span></span><span>rst</span><span><span>=</span><span>RST</span><span>)</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span># 初始化库</span></div></div><div><div><div>9</div></div><div><span><span>disp.</span><span>begin</span><span>()</span></span></div></div><div><div><div>10</div></div><div><span># 获取屏幕大小</span></div></div><div><div><div>11</div></div><div><span><span>width </span><span>=</span><span> disp.width</span></span></div></div><div><div><div>12</div></div><div><span><span>height </span><span>=</span><span> disp.height</span></span></div></div><div><div><div>13</div></div><div><span># 清除屏幕内容</span></div></div><div><div><div>14</div></div><div><span><span>disp.</span><span>clear</span><span>()</span></span></div></div><div><div><div>15</div></div><div><span><span>disp.</span><span>display</span><span>()</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><section><h2>1.显示内容<a href="#1显示内容"><span>#</span></a></h2><p>屏幕显示内容是先建立一张与屏幕相等的空白画布，将要显示的内容添加到其中，最后再显示出来：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 创建空白画布</span></div></div><div><div><div>2</div></div><div><span># 颜色为1 bit</span></div></div><div><div><div>3</div></div><div><span><span>width </span><span>=</span><span> disp.width</span></span></div></div><div><div><div>4</div></div><div><span><span>height </span><span>=</span><span> disp.height</span></span></div></div><div><div><div>5</div></div><div><span><span>image </span><span>=</span><span> Image.</span><span>new</span><span>(</span></span><span>'1'</span><span>, (width, height))</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span># 画布绘制对象</span></div></div><div><div><div>8</div></div><div><span><span>draw </span><span>=</span><span> ImageDraw.</span><span>Draw</span><span>(image)</span></span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span># 绘制一个黑色内容清除画布内容</span></div></div><div><div><div>11</div></div><div><span><span>draw.</span><span>rectangle</span><span>((</span></span><span>0</span><span>,</span><span>0</span><span>,width,height), </span><span>outline</span><span>=</span><span>0</span><span>, </span><span>fill</span><span>=</span><span>0</span><span>)</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 绘制内容</span></div></div><div><div><div>14</div></div><div><span># 定义一些常亮控制图形大小</span></div></div><div><div><div>15</div></div><div><span><span>padding </span><span>=</span><span> </span></span><span>2</span></div></div><div><div><div>16</div></div><div><span><span>shape_width </span><span>=</span><span> </span></span><span>20</span></div></div><div><div><div>17</div></div><div><span><span>top </span><span>=</span><span> padding</span></span></div></div><div><div><div>18</div></div><div><span><span>bottom </span><span>=</span><span> height</span><span>-</span><span>padding</span></span></div></div><div><div><div>19</div></div><div><span># 从左向右移动，跟踪绘制形状的当前位置</span></div></div><div><div><div>20</div></div><div><span><span>x </span><span>=</span><span> padding</span></span></div></div><div><div><div>21</div></div><div><span># 绘制椭圆</span></div></div><div><div><div>22</div></div><div><span><span>draw.</span><span>ellipse</span><span>((x, top , x</span><span>+</span><span>shape_width, bottom), </span></span><span>outline</span><span>=</span><span>255</span><span>, </span><span>fill</span><span>=</span><span>0</span><span>)</span></div></div><div><div><div>23</div></div><div><span><span>x </span><span>+=</span><span> shape_width</span><span>+</span><span>padding</span></span></div></div><div><div><div>24</div></div><div><span># 绘制矩形</span></div></div><div><div><div>25</div></div><div><span><span>draw.</span><span>rectangle</span><span>((x, top, x</span><span>+</span><span>shape_width, bottom), </span></span><span>outline</span><span>=</span><span>255</span><span>, </span><span>fill</span><span>=</span><span>0</span><span>)</span></div></div><div><div><div>26</div></div><div><span><span>x </span><span>+=</span><span> shape_width</span><span>+</span><span>padding</span></span></div></div><div><div><div>27</div></div><div><span># 绘制三角</span></div></div><div><div><div>28</div></div><div><span><span>draw.</span><span>polygon</span><span>([(x, bottom), (x</span><span>+</span><span>shape_width</span><span>/</span></span><span>2</span><span><span>, top), (x</span><span>+</span><span>shape_width, bottom)], </span></span><span>outline</span><span>=</span><span>255</span><span>, </span><span>fill</span><span>=</span><span>0</span><span>)</span></div></div><div><div><div>29</div></div><div><span><span>x </span><span>+=</span><span> shape_width</span><span>+</span><span>padding</span></span></div></div><div><div><div>30</div></div><div><span># 绘制X</span></div></div><div><div><div>31</div></div><div><span><span>draw.</span><span>line</span><span>((x, bottom, x</span><span>+</span><span>shape_width, top), </span></span><span>fill</span><span>=</span><span>255</span><span>)</span></div></div><div><div><div>32</div></div><div><span><span>draw.</span><span>line</span><span>((x, top, x</span><span>+</span><span>shape_width, bottom), </span></span><span>fill</span><span>=</span><span>255</span><span>)</span></div></div><div><div><div>33</div></div><div><span><span>x </span><span>+=</span><span> shape_width</span><span>+</span><span>padding</span></span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span># 加载默认字体</span></div></div><div><div><div>36</div></div><div><span><span>font </span><span>=</span><span> ImageFont.</span><span>load_default</span><span>()</span></span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span># 或者使用其他.ttf格式的字体，字体文件要与执行文件在同一目录</span></div></div><div><div><div>39</div></div><div><span>#font = ImageFont.truetype('Minecraftia.ttf', 8)</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span># 加两行文字</span></div></div><div><div><div>42</div></div><div><span><span>draw.</span><span>text</span><span>((x, top),    </span></span><span>'Hello'</span><span>,  </span><span>font</span><span><span>=</span><span>font, </span></span><span>fill</span><span>=</span><span>255</span><span>)</span></div></div><div><div><div>43</div></div><div><span><span>draw.</span><span>text</span><span>((x, top</span><span>+</span></span><span>20</span><span>), </span><span>'World!'</span><span>, </span><span>font</span><span><span>=</span><span>font, </span></span><span>fill</span><span>=</span><span>255</span><span>)</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span># 显示</span></div></div><div><div><div>46</div></div><div><span><span>disp.</span><span>image</span><span>(image)</span></span></div></div><div><div><div>47</div></div><div><span><span>disp.</span><span>display</span><span>()</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p></p><figure><img alt="617739217782034705.jpg" loading="lazy" width="467" height="463" src="/_astro/106.5.C9-v2xB6_X25Dr.webp" /><figcaption>617739217782034705.jpg</figcaption></figure><p></p></section><section><h2>2.显示图片<a href="#2显示图片"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># 根据OLED高度加载图片，图片要转换成1 bit颜色</span></div></div><div><div><div>2</div></div><div><span>if</span><span><span> disp.height </span><span>==</span><span> </span></span><span>64</span><span>:</span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>image </span><span>=</span><span> Image.</span><span>open</span><span>(</span><span>'image_64.png'</span><span><span>).</span><span>convert</span><span>(</span></span><span>'1'</span><span>)</span></div></div><div><div><div>4</div></div><div><span>else</span><span>:</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>image </span><span>=</span><span> Image.</span><span>open</span><span>(</span><span>'image_32.png'</span><span><span>).</span><span>convert</span><span>(</span></span><span>'1'</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p></p><figure><img alt="46229923031718465.jpg" loading="lazy" width="529" height="486" src="/_astro/106.6.CQkfP909_RFo1g.webp" /><figcaption>46229923031718465.jpg</figcaption></figure><p></p><p><em>PS&lt;可以把喜欢的图片改成不超过128&gt;*64，再在Photoshop里先把模式改成灰度，然后调对比度和亮度，在不影响视觉的前提下尽可能对比度大。然后再改模式为“位图”，方法选“扩散仿色”，然后另存为PNG，选项为交错，就可以让OLED显示了。</em></p><p><strong>END</strong></p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/103/</id>
      <title type="text">ArchLinux使用中文输入法</title>
      <published>2018-08-29T00:00:00.000Z</published>
      <updated>2019-10-24T06:57:28.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/103/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>0x00</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pacman</span><span> </span><span>-S</span><span> </span><span>fcitx</span><span> </span><span>fcitx-im</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>安装完后编辑<code>~/.xprofile</code>文件，添加代码：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>#fcitx</span></div></div><div><div><div>2</div></div><div><span>export</span><span> </span><span>GTK_IM_MODULE</span><span>=</span><span>fcitx</span></div></div><div><div><div>3</div></div><div><span>export</span><span> </span><span>QT_IM_MODULE</span><span>=</span><span>fcitx</span></div></div><div><div><div>4</div></div><div><span>export</span><span> </span><span>XMODIFIERS</span><span>=</span><span>"@im=fcitx"</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>重启或注销即可</p>
<p>0x01
安装搜狗输入法（先要导入国内arch论坛源）</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pacman</span><span> </span><span>-S</span><span> </span><span>fcitx-sogoupinyin</span></div></div></code></pre><div><div></div><div></div></div></figure></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/201/</id>
      <title type="text">收藏</title>
      <published>2018-08-26T00:00:00.000Z</published>
      <updated>2020-02-21T07:16:15.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/201/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>0x01 强大的在线工具<a href="#0x01-强大的在线工具"><span>#</span></a></h2><p><a href="https://miku.tools/" target="_blank">MikuTools - 在线工具集合</a></p><p><a href="https://www.gaoding.com/koutu" target="_blank">在线抠图 - 抠图</a></p><p><a href="https://www.processon.com" target="_blank">Processon - 在线作图 流程图、思维导图、原型图、UML、网络拓扑图、组织结构图等</a></p><p><a href="https://uzer.me/" target="_blank">UZER - 随时使用各种应用</a></p><p><a href="onsole.amazonaws.cn/console/home?region=cn-north-1">二次元头像生成器 - 生成二次元头像</a>&gt;&gt;&gt;<a href="https://github.com/makegirlsmoe/makegirlsmoe_web" target="_blank">GitHub</a></p><p><a href="https://github.com/wb14123/seq2seq-couplet" target="_blank">seq2seq-couplet - 深度学习对对联</a></p><p><a href="http://ping.pe/" target="_blank">ping.pe - 在线测试服务器延迟和丢包</a></p></section>
<section><h2>0x02 生活需要点趣味<a href="#0x02-生活需要点趣味"><span>#</span></a></h2><p><a href="https://yikm.net/" target="_blank">小霸王，其乐无穷 - 在线小霸王游戏</a></p><p><a href="https://likexia.gitee.io/game/index.html" target="_blank">GitHub Game - 在线小游戏</a></p><p><a href="https://aidn.jp/mikutap/" target="_blank">Mikutap - 解压</a></p><p><a href="https://github.com/WarpPrism/AutoPiano" target="_blank">AutoPiano - 在线钢琴</a></p><p><a href="https://github.com/xtyxtyx/sorry" target="_blank">sorry - gif表情包</a></p><p><a href="https://useum.org/" target="_blank">useum - 博物馆艺术品高清扫描图</a></p></section>
<section><h2>0x03 学习也是门艺术<a href="#0x03-学习也是门艺术"><span>#</span></a></h2><p><a href="http://www.duolingo.cn/?user_invite=BDHTZTB5CWWKSRTPQLFZHB2CK4" target="_blank">多邻国 - 多国语言学习</a></p><p><a href="https://github.com/houshanren/hangzhou_house_knowledge" target="_blank">hangzhou_house_knowledge - 买房参考</a></p><section><h3>数据科学<a href="#数据科学"><span>#</span></a></h3><p><a href="https://github.com/FavioVazquez/ds-cheatsheets" target="_blank">数据科学相关速查表 - 内容包含 Python、R、大数据、机器学习、深度学习等分类</a></p><p><a href="https://github.com/abhat222/Data-Science--Cheat-Sheet" target="_blank">Data Science Cheatsheets - 数据科学相关资料</a></p></section><section><h3>人工智能<a href="#人工智能"><span>#</span></a></h3><p><a href="https://github.com/apachecn/AiLearning" target="_blank">AiLearning - AI学习路线</a></p></section><section><h3>算法<a href="#算法"><span>#</span></a></h3><p><a href="https://leetcode-cn.com/" target="_blank">Leetcode(中国) - 算法题库</a></p><p><a href="https://visualgo.net/zh" target="_blank">Visualgo - 数据结构和算法动态可视化</a></p><p><a href="https://algorithm-visualizer.org/" target="_blank">Algorithm Visualizer - 算法可视化</a></p></section><section><h3>基础学习<a href="#基础学习"><span>#</span></a></h3><p><a href="https://github.com/ityouknow/spring-boot-examples" target="_blank">Spring Boot 学习示例 - Spring Boot 学习</a></p><p><a href="https://github.com/guolindev/booksource" target="_blank">《第一行代码》代码资源 - Android</a></p><p><a href="https://github.com/enbandari/Kotlin-Tutorials" target="_blank">Kotlin-Tutorials - Kotlin学习视频</a></p><p><a href="https://docs.hacknode.org/gopl-zh/index.html" target="_blank">Go语言圣经 - Golang学习宝典</a></p><p><a href="https://github.com/tiimgreen/github-cheat-sheet" target="_blank">github-cheat-sheet - GitHub 秘籍</a>&gt;&gt;&gt;<a href="https://github.com/tiimgreen/github-cheat-sheet/blob/master/README.zh-cn.md" target="_blank">翻译</a></p><p><a href="https://docker_practice.gitee.io/" target="_blank">Docker — 从入门到实践 - Docker学习</a></p><p><a href="http://cn.linux.vbird.org/" target="_blank">鸟哥的linux私房菜 - Linux学习</a></p><p><a href="https://cherrot.com/tech/2017/01/08/ssh-tunneling-practice.html" target="_blank">SSH隧道：内网穿透实战 - SSH内网穿透</a></p></section><section><h3>安全<a href="#安全"><span>#</span></a></h3><p><a href="https://github.com/ring04h/papers" target="_blank">Papers - 安全大神的安全峰会文件</a></p><p><a href="https://github.com/Hack-with-Github/Awesome-Hacking" target="_blank">Awesome Hacking - 黑客技术清单</a></p><p><a href="https://www.freebuf.com/" target="_blank">Freebuf</a></p><p><a href="https://www.sec-wiki.com/" target="_blank">sec-wiki</a></p><p><a href="https://www.pediy.com/" target="_blank">看雪</a></p></section><section><h3>趣味<a href="#趣味"><span>#</span></a></h3><p><a href="https://github.com/alex/what-happens-when" target="_blank">What happens when… - 从计算机底层讲起打开一个网页的全过程</a>&gt;&gt;&gt;<a href="https://github.com/skyline75489/what-happens-when-zh_CN" target="_blank">翻译</a></p><p><a href="https://github.com/ruby-china/How-To-Ask-Questions-The-Smart-Way" target="_blank">How To Ask Questions The Smart Way - 提问的智慧，学习如何提问</a></p><p><a href="https://github.com/maebert/themostdangerouswritingapp" target="_blank">themostdangerouswritingapp - 写作，超过5秒没输入就删档</a></p></section></section>
<section><h2>0x03 好的工具让你事半功倍<a href="#0x03-好的工具让你事半功倍"><span>#</span></a></h2><section><h3>树莓派<a href="#树莓派"><span>#</span></a></h3><p><a href="https://github.com/WOA-Project/WOA-Deployer-Rpi" target="_blank">WOA Deployer for Raspberry Pi 3 - 树莓派3上运行win10</a></p><p><a href="https://github.com/ChristopheJacquet/PiFmRds" target="_blank">Pi-FM-RDS - 通过树莓派发送FM广播</a></p><p><a href="https://berryboot.alexgoldcheidt.com/go/berryboot-home" target="_blank">BerryBoot - 树莓派多系统引导</a></p><p><a href="https://mlapp.cn/369.html" target="_blank">OpenWrt（第三方编译，插件多，符合“国情”） - 树莓派路由器</a></p><p><a href="https://github.com/coolsnowwolf/lede" target="_blank">OpenWrt/LEDE编译项目</a></p></section><section><h3>网络<a href="#网络"><span>#</span></a></h3><p><a href="https://github.com/ashnkumar/sketch-code" target="_blank">SketchCode - 手绘图自动生成 html</a></p><p><a href="https://github.com/jpillora/cloud-torrent" target="_blank">Cloud Torrent - Golang开发的BT磁力下载神器</a></p><p><a href="https://github.com/jacksonliam/mjpg-streamer" target="_blank">mjpg-streamer - 网络摄像头</a></p><p><a href="https://github.com/littlecodersh/ItChat" target="_blank">itchat - Python实现微信</a></p><p><a href="https://github.com/SpiderClub/haipproxy" target="_blank">高可用IP代理池 - 为大型爬虫项目提供高可用低延迟的高匿IP代理池</a></p><p><a href="https://github.com/soimort/you-get" target="_blank">you-get - 下载视频</a></p><p><a href="https://github.com/ytdl-org/youtube-dl" target="_blank">youtube-dl - 下载视频</a></p><p><a href="https://github.com/MrS0m30n3/youtube-dl-gui" target="_blank">youtube-dl-gui - youtube-dl图形界面版</a></p><p><a href="https://github.com/fatedier/frp" target="_blank">frp - 内网穿透</a></p><p><a href="https://github.com/hwdsl2/setup-ipsec-vpn" target="_blank">IPsec VPN Server Auto Setup Scripts - vpn服务器架设</a></p></section><section><h3>Hack<a href="#hack"><span>#</span></a></h3><p><a href="https://github.com/wifiphisher/wifiphisher" target="_blank">wifiphisher - wifi钓鱼</a></p><p><a href="https://github.com/samdenty/Wi-PWN" target="_blank">Wi-PWN - 在ESP8266上进行wifi攻击</a></p><p><a href="https://github.com/mame82/P4wnP1" target="_blank">P4wnP1 - 使用树莓派进行渗透攻击</a></p><p><a href="https://github.com/cSploit/android" target="_blank">cSploit - Android网络渗透</a></p><p><a href="https://github.com/epinna/weevely3" target="_blank">weevely3 - PHP后门</a></p><p><a href="https://github.com/oblique/create_ap" target="_blank">create_ap - linux Wifi热点</a></p><p><a href="https://github.com/gentilkiwi/mimikatz" target="_blank">mimikatz - 套取windows密码</a></p></section><section><h3>其他<a href="#其他"><span>#</span></a></h3><p><a href="https://github.com/faressoft/terminalizer" target="_blank">Terminalizer - 录制终端生成GIF或视频</a></p><p><a href="https://github.com/octref/polacode" target="_blank">Polacode - 生成代码截图，VScode插件</a></p><p><a href="https://github.com/tzutalin/labelImg" target="_blank">LabelImg - 图片标注</a></p><p><a href="https://github.com/idevelop/ascii-camera" target="_blank">ASCII Camera - ASCII相机</a></p><p><a href="https://github.com/balena-io/etcher" target="_blank">etcher - 系统烧录工具</a></p><p><a href="https://ephtracy.github.io/" target="_blank">ephtracy - 快速3D建模</a></p></section></section>
<section><h2>0x04 优质资源让人欲罢不能<a href="#0x04-优质资源让人欲罢不能"><span>#</span></a></h2><section><h3>深度学习<a href="#深度学习"><span>#</span></a></h3><p><a href="https://github.com/aditya-vora/FCHD-Fully-Convolutional-Head-Detector/blob/master/head_detection_demo.py" target="_blank">FCHD-Fully-Convolutional-Head-Detector - 基于torch的高精度人头识别</a></p><p><a href="https://github.com/anishathalye/neural-style" target="_blank">neural-style - 基于tensorflow的图片风格化（推荐）</a></p><p><a href="https://github.com/jcjohnson/neural-style" target="_blank">neural-style - 基于torch的图片风格化</a></p><p><a href="https://github.com/hzy46/fast-neural-style-tensorflow" target="_blank">fast-neural-style-tensorflow - 基于tensorflow的图片风格化</a></p><p><a href="https://github.com/nagadomi/waifu2x" target="_blank">waifu2x - 放大图片</a></p><p><a href="https://github.com/lltcggie/waifu2x-caffe" target="_blank">waifu2x-caffe - waifu2x caffe版</a></p><p><a href="https://github.com/microsoft/Terminal" target="_blank">Windows Terminal - windows终端</a></p><p><a href="https://grisk.itch.io/dain-app" target="_blank">DAIN-APP - AI插帧（低帧视频转高帧）</a></p><p><a href="https://videoai.topazlabs.com/beta" target="_blank">Topaz Gigapixel AI for Video - AI提高视频分辨率</a></p></section><section><h3>库<a href="#库"><span>#</span></a></h3><section><h4>#Android<a href="#android"><span>#</span></a></h4><p><a href="https://github.com/sunfusheng/GlideImageView" target="_blank">GlideImageView - 基于Glide V4.9.0封装的图片加载库，可以监听加载图片时的进度#Android</a></p><p><a href="https://github.com/hongyangAndroid/Highlight" target="_blank">Highlight - 一个用于app指向性功能高亮的库#Android</a></p><p><a href="https://github.com/dinuscxj/LoadingDrawable" target="_blank">LoadingDrawable - 加载动画#Android</a></p><p><a href="https://github.com/dmytrodanylyk/android-process-button" target="_blank">android-process-button - 按钮库#Android</a></p><p><a href="https://github.com/hongyangAndroid/Android-ProgressBarWidthNumber" target="_blank">Android-ProgressBarWidthNumber - 滚动条#Android</a></p></section><section><h4>JS<a href="#js"><span>#</span></a></h4><p><a href="https://github.com/benhowdle89/grade" target="_blank">Grade.js - 从图片中提取两种主色，并生成互补渐变背景</a></p><p><a href="https://github.com/bramblex/jsjs" target="_blank">jsjs - 简易的 JavaScript 元循环解释器</a></p></section><section><h4>树莓派<a href="#树莓派-1"><span>#</span></a></h4><p><a href="https://berryboot.alexgoldcheidt.com/images/" target="_blank">BerryServer - 大量适用于树莓派BerryBoot的系统</a></p><p><a href="https://github.com/dhruvvyas90/qemu-rpi-kernel" target="_blank">qemu-rpi-kernel - 树莓派的QEMU模拟器内核</a></p><p><a href="http://blog.pifan.org/index.php/knowledge-base/pi64-info/" target="_blank">Debian Pi Aarch64 - 树莓派64位系统</a></p><ul>
<li>|-&gt;<a href="https://pan.baidu.com/s/1bN6lpVtGHijE1E2LjkV4wQ" target="_blank">1.0</a></li>
<li>|-&gt;<a href="https://pan.baidu.com/s/1czBi6isWh0qavXC72nT5fw" target="_blank">2.0</a></li>
</ul></section><section><h4>其他<a href="#其他-1"><span>#</span></a></h4><p><a href="https://github.com/googlehosts/hosts" target="_blank">Google Host - host</a></p><p><a href="https://github.com/iiinsomnia/yiigo" target="_blank">yiigo - 简单易用的轻量级 Golang 辅助库</a></p><p><a href="https://github.com/gpakosz/.tmux" target="_blank">.tmux - Tmux设置</a></p><p><a href="https://github.com/toddmotto/public-apis" target="_blank">Public APIs - 汇集了公开的API</a></p><p><a href="https://github.com/plotly/dash" target="_blank">Dash - 纯Python构建的Web框架，无js脚本</a></p><p><a href="https://blog.rehtt.com/article/%E7%BB%85%E5%A3%AB/" target="_blank">绅士</a></p></section></section><section><h3>资源<a href="#资源"><span>#</span></a></h3><p><a href="http://pianyuan.la/" target="_blank">片源网 - 影视资源</a></p><p><a href="http://www.aigei.com/" target="_blank">爱给网 - 汇集免费素材</a></p><p><a href="http://www.fonts.net.cn/" target="_blank">字体天下 - 免费的商用字体</a></p><p><a href="https://www.hezibuluo.com/" target="_blank">盒子部落 - 软件资源网站</a></p><p><a href="http://www.dayanzai.me/" target="_blank">大眼仔 - 软件资源网站</a></p><p><a href="https://saier.me/" target="_blank">月夜七境 - 提供优质汉化软件</a></p><blockquote><p>2019-11-24更新1条
2019-11-18更新1条
2019-11-8 更新1条
2019-11-2 更新3条
2019-8-26 更新5条网站
2019-5-26 更新
2020-2-21 更新</p></blockquote></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/105/</id>
      <title type="text">linux触摸板手势</title>
      <published>2018-08-21T00:00:00.000Z</published>
      <updated>2019-10-24T07:00:29.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/105/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>这里使用的是<code>libinput-gestures</code>，依赖xdotool（模拟鼠标/键盘输入)</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>pacman</span><span> </span><span>-S</span><span> </span><span>libinput-gestures</span><span> </span><span>xdotool</span></div></div><div><div><div>2</div></div><div><span>sudo</span><span> </span><span>pacman</span><span> </span><span>-S</span><span> </span><span>libinput</span><span> </span><span>xf86-input-libinput</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>配置libinput文件（文件名字视情况而定，我的是40-libinput.conf）</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>cp</span><span> </span><span>/usr/share/X11/xorg.conf.d/40-libinput.conf</span><span> </span><span>/etc/X11/xorg.conf.d/40-libinput.conf</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>下面是文件中touchpad部分的配置：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Section "InputClass"</span></div></div><div><div><div>2</div></div><div><span><span>        </span></span><span>Identifier "touchpad"</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>MatchIsTouchpad "on"</span></div></div><div><div><div>4</div></div><div><span><span>        </span></span><span>MatchDevicePath "/dev/input/event*"</span></div></div><div><div><div>5</div></div><div><span><span>        </span></span><span>Driver "libinput"</span></div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>Option "Tapping" "on"</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>Option "ButtonMapping" "1 3 0 4 5 6 7"</span></div></div><div><div><div>8</div></div><div><span><span>        </span></span><span>Option "TappingButtonMap" "lmr"</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>Option "DisableWhileTyping" "on"</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>Option "TappingDrag" "on"</span></div></div><div><div><div>11</div></div><div><span>EndSection</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>详细参数和解释见<a href="https://www.mankier.com/4/libinput#Configuration_Details" target="_blank">libinput man page: based on X.Org input dirver</a>，解释下几个重要的配置参数：</p><p>Option “Tapping” “on”：手指点击touchpad发送鼠标点击事件
Option “TappingButtonMap” “lmr”：1个手指点击对应<code>鼠标左键</code>，2个手指点击对应<code>鼠标中键</code>，3个鼠标点击对应<code>鼠标右键</code>。
Option “ButtonMapping” “1 3 0 4 5 6 7″，按钮映射，详情见<a href="https://www.mankier.com/4/libinput#Button_Mapping" target="_blank">libinput#Button_Mapping</a>，这里笔者关闭了3指对应的左键。
Option “DisableWhileTyping” “on”：打字时不检测touchpad事件，防止用户不小心触碰touchpad引起不必要的影响。
Option “TappingDrag” “on”：开启点击拖拽。</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>添加当前用户到用户组</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>gpasswd</span><span> </span><span>-a</span><span> </span><span>$USER</span><span> </span><span>input</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>复制文件</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>cp</span><span> </span><span>/etc/libinput-gestures.conf</span><span> </span><span>~/.config/</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>编辑<code>~/.config/libinput-gestures</code>文件修改所需操作</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>gesture swipe left 4 xdotool key super+Left</span></div></div><div><div><div>2</div></div><div><span># 4指左划: 切换到左侧工作区</span></div></div><div><div><div>3</div></div><div><span>gesture swipe right 4 xdotool key super+Right</span></div></div><div><div><div>4</div></div><div><span># 4指右划: 切换到右侧工作区</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>gesture swipe left 3 xdotool key alt+Left</span></div></div><div><div><div>7</div></div><div><span># 3指左划: 浏览器后退</span></div></div><div><div><div>8</div></div><div><span>gesture swipe right 3 xdotool key alt+Right</span></div></div><div><div><div>9</div></div><div><span># 3指右划: 浏览器前进</span></div></div><div><div><div>10</div></div><div><span>gesture swipe up 3 xdotool key F5</span></div></div><div><div><div>11</div></div><div><span># 3指上划: 刷新当前页面</span></div></div><div><div><div>12</div></div><div><span>gesture swipe down 3 xdotool key ctrl+w</span></div></div><div><div><div>13</div></div><div><span># 3指下划: 关闭当前页面</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>gesture pinch in 2 xdotool key ctrl+minus</span></div></div><div><div><div>16</div></div><div><span># 2指捏: 缩小</span></div></div><div><div><div>17</div></div><div><span>gesture pinch out 2 xdotool key ctrl+plus</span></div></div><div><div><div>18</div></div><div><span># 2指张: 放大</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>启动</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>libinput-gestures-setup</span><span> </span><span>start</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>END</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/101/</id>
      <title type="text">【vim】代码自动补全插件（YouCompleteMe）安装</title>
      <published>2018-08-13T00:00:00.000Z</published>
      <updated>2019-10-24T06:55:31.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/101/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<h1>0x00什么是YouCompleteMe</h1>
<p><a href="https://github.com/Valloric/YouCompleteMe">YouCompleteMe</a>&lt;一个随键而全的&gt;、支持模糊搜索的、高速补全的插件。YCM 由 google 公司搜索项目组的软件工程师 Strahinja Val Markovic 所开发,YCM 后端调用 libclang(以获取AST,当然还有其他语言的语义分析库)、前端由 C++ 开发(以提升补全效 率)、外层由 python 封装(以成为 vim 插件),它可能是我见过安装最复杂的 vim 插件了。</p>
<h1>0x01安装</h1>
<p>这里采用<a href="/posts/100/">Vundle</a>插件管理器安装</p>
<h3>1.安装必要工具</h3>
<p><code>sudo apt install build-essential cmake</code></p>
<p><code>sudo apt install python-dev python3-dev</code></p>
<h3>2.配置vundle插件安装</h3>
<p>打开编辑<code>/usr/share/vim/vimrc</code>文件，在其中添加<code>Bundle ‘Valloric/YouCompleteMe’</code></p>
<p>退出文件并进入vim输入<code></code>等待进度完成</p>
<h3>3.安装YouCompleteMe</h3>
<p>进入<code>~/.vim/bundle/YouCompleteMe</code>文件夹</p>
<p><code>./install.py —clang-completer</code></p>
<p>等待编译安装完即可</p>
<p>其他语言支持</p>
<ul>
 	<li>C#：<code>./install.py --cs-completer</code></li>
 	<li>Go：<code>./install.py --go-completer</code></li>
 	<li>JavaScript 和 TypeScript：<code>nmp install -gtypescript</code></li>
 	<li>Rust：<code>./install.py --rust-completer</code></li>
 	<li>Java：<code>./install.py --java-completer</code></li>
</ul>
如要安装所以支持可以使用<code>--all</code>参数：<code>./install.py --all</code>
<h1>0x02配置自动补全</h1>
<p>打开<code>.vimrc</code>文件，添加配置：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>" 自动补全配置</span></div></div><div><div><div>2</div></div><div><span>set</span><span> </span><span>completeopt</span><span>=longest,menu  </span><span>"让Vim的补全菜单行为与一般IDE一致(参考VimTip1228)</span></div></div><div><div><div>3</div></div><div><span>autocmd</span><span> </span><span>InsertLeave</span><span> * </span><span>if</span><span> </span><span>pumvisible</span><span>() == </span><span>0</span><span>|pclose|</span><span>endif </span><span> </span><span>"离开插入模式后自动关闭预览窗口</span></div></div><div><div><div>4</div></div><div><span>inoremap</span><span> &lt;</span><span>expr</span><span>&gt; &lt;</span><span>cr</span><span>&gt;       </span><span>pumvisible</span><span>() ? </span><span>"\&lt;c-y&gt;"</span><span> : </span><span>"\&lt;cr&gt;"</span><span>  </span><span>"回车即选中当前项</span></div></div><div><div><div>5</div></div><div><span>"上下左右键的行为 会显示其他信息</span></div></div><div><div><div>6</div></div><div><span>inoremap</span><span> &lt;</span><span>expr</span><span>&gt; &lt;</span><span>down</span><span>&gt;     </span><span>pumvisible</span><span>() ? </span><span>"\&lt;c-n&gt;"</span><span> : </span><span>"\&lt;down&gt;"</span></div></div><div><div><div>7</div></div><div><span>inoremap</span><span> &lt;</span><span>expr</span><span>&gt; &lt;</span><span>up</span><span>&gt;       </span><span>pumvisible</span><span>() ? </span><span>"\&lt;c-p&gt;"</span><span> : </span><span>"\&lt;up&gt;"</span></div></div><div><div><div>8</div></div><div><span>inoremap</span><span> &lt;</span><span>expr</span><span>&gt; &lt;page</span><span>down</span><span>&gt; </span><span>pumvisible</span><span>() ? </span><span>"\&lt;pagedown&gt;\&lt;c-p&gt;\&lt;c-n&gt;"</span><span> : </span><span>"\&lt;pagedown&gt;"</span></div></div><div><div><div>9</div></div><div><span>inoremap</span><span> &lt;</span><span>expr</span><span>&gt; &lt;page</span><span>up</span><span>&gt;   </span><span>pumvisible</span><span>() ? </span><span>"\&lt;pageup&gt;\&lt;c-p&gt;\&lt;c-n&gt;"</span><span> : </span><span>"\&lt;pageup&gt;"</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>"youcompleteme  默认tab  s-tab 和自动补全冲突</span></div></div><div><div><div>12</div></div><div><span>"let g:ycm_key_list_select_completion=['&lt;c-n&gt;']</span></div></div><div><div><div>13</div></div><div><span>let</span><span> </span><span>g:ycm_key_list_select_completion</span><span> = [</span><span>'&lt;down&gt;'</span><span>]</span></div></div><div><div><div>14</div></div><div><span>"let g:ycm_key_list_previous_completion=['&lt;c-p&gt;']</span></div></div><div><div><div>15</div></div><div><span>let</span><span> </span><span>g:ycm_key_list_previous_completion</span><span> = [</span><span>'&lt;up&gt;'</span><span>]</span></div></div><div><div><div>16</div></div><div><span>let</span><span> </span><span>g:ycm_confirm_extra_conf</span><span>=</span><span>0</span><span> </span><span>"关闭加载.ycm_extra_conf.py提示</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>let</span><span> </span><span>g:ycm_collect_identifiers_from_tags_files</span><span>=</span><span>1</span><span>  " 开启 YCM 基于标签引擎</span></div></div><div><div><div>19</div></div><div><span>let</span><span> </span><span>g:ycm_min_num_of_chars_for_completion</span><span>=</span><span>2</span><span>  " 从第2个键入字符就开始罗列匹配项</span></div></div><div><div><div>20</div></div><div><span>let</span><span> </span><span>g:ycm_cache_omnifunc</span><span>=</span><span>0</span><span>  " 禁止缓存匹配项,每次都重新生成匹配项</span></div></div><div><div><div>21</div></div><div><span>let</span><span> </span><span>g:ycm_seed_identifiers_with_syntax</span><span>=</span><span>1</span><span>  " 语法关键字补全</span></div></div><div><div><div>22</div></div><div><span>nnoremap</span><span> &lt;</span><span>f5</span><span>&gt; :YcmForceCompileAndDiagnostics&lt;</span><span>cr</span><span>&gt;  </span><span>"force recomile with syntastic</span></div></div><div><div><div>23</div></div><div><span>"nnoremap &lt;leader&gt;lo :lopen&lt;cr&gt;  "open locationlist</span></div></div><div><div><div>24</div></div><div><span>"nnoremap &lt;leader&gt;lc :lclose&lt;cr&gt;  "close locationlist</span></div></div><div><div><div>25</div></div><div><span>inoremap</span><span> &lt;</span><span>leader</span><span>&gt;&lt;</span><span>leader</span><span>&gt; &lt;</span><span>c-x</span><span>&gt;&lt;</span><span>c-o</span><span>&gt;</span></div></div><div><div><div>26</div></div><div><span>"在注释输入中也能补全</span></div></div><div><div><div>27</div></div><div><span>let</span><span> </span><span>g:ycm_complete_in_comments</span><span> = </span><span>1</span></div></div><div><div><div>28</div></div><div><span>"在字符串输入中也能补全</span></div></div><div><div><div>29</div></div><div><span>let</span><span> </span><span>g:ycm_complete_in_strings</span><span> = </span><span>1</span></div></div><div><div><div>30</div></div><div><span>"注释和字符串中的文字也会被收入补全</span></div></div><div><div><div>31</div></div><div><span>let</span><span> </span><span>g:ycm_collect_identifiers_from_comments_and_strings</span><span> = </span><span>0</span></div></div><div><div><div>32</div></div><div>
</div></div><div><div><div>33</div></div><div><span>nnoremap</span><span> &lt;</span><span>leader</span><span>&gt;jd :YcmCompleter GoToDefinitionElseDeclaration&lt;</span><span>cr</span><span>&gt;</span><span> " 跳转到定义处</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<h1>0x03后记</h1>
<p>简单安装教程已完成，如需详情请访问作者<a href="https://github.com/Valloric/YouCompleteMe">GitHub</a></p>
<h1>END</h1>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/100/</id>
      <title type="text">【vim】自动插件管理器（Vundle）安装</title>
      <published>2018-08-12T00:00:00.000Z</published>
      <updated>2019-10-24T06:55:57.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/100/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<h1>0x00什么是Vundle</h1>
<p><a href="https://github.com/VundleVim/Vundle.vim" target="_blank">Vundle</a>意即Vim Bundle，是一个vim插件管理器。Vundle能让你很简单地实现插件的安装、升级、搜索或者清除。它还能管理你的运行环境并且在标签方面提供帮助。在本教程中我们将展示如何安装和使用Vundle。</p>
<h2>0x01安装Vundle</h2>
<p>这里使用git命令来下载文件，没有安装git的请自行安装</p>
<p><code>$ git clone <a href="https://github.com/VundleVim/Vundle.vim.git" target="_blank">https://github.com/VundleVim/Vundle.vim.git</a> ~/.vim/bundle/Vundle.vim</code></p>
<p> </p>
<p>编辑<code>.vimrc</code>文件，建议将原文件备份并另建一个新文件。</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>set</span><span> </span><span>nocompatible</span><span>              " 必需。</span></div></div><div><div><div>2</div></div><div><span>filetype</span><span> off</span><span>                  " 必须。</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>" 在这里设置你的运行时环境的路径。</span></div></div><div><div><div>5</div></div><div><span>set</span><span> </span><span>rtp</span><span>+=~</span><span>/.vim/</span><span>bundle/Vundle.vim</span></div></div><div><div><div>6</div></div><div><span>" 初始化vundle</span></div></div><div><div><div>7</div></div><div><span>call</span><span> </span><span>vundle#begin</span><span>()</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>" 这一行应该永远放在开头。</span></div></div><div><div><div>10</div></div><div><span>Plugin</span><span> </span><span>'gmarik/Vundle.vim'</span></div></div><div><div><div>11</div></div><div><span>" 这个示范来自https://github.com/gmarik/Vundle.vim README</span></div></div><div><div><div>12</div></div><div><span>Plugin</span><span> </span><span>'tpope/vim-fugitive'</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>" 取自http://vim-scripts.org/vim/scripts.html的插件</span></div></div><div><div><div>15</div></div><div><span>Plugin</span><span> </span><span>'L9'</span></div></div><div><div><div>16</div></div><div><span>"　该Git插件没有放在GitHub上。</span></div></div><div><div><div>17</div></div><div><span>Plugin</span><span> </span><span>'git://git.wincent.com/command-t.git'</span></div></div><div><div><div>18</div></div><div>
</div></div><div><div><div>19</div></div><div><span>"本地计算机上的Git仓库路径　（例如，当你在开发你自己的插件时）</span></div></div><div><div><div>20</div></div><div><span>Plugin</span><span> </span><span>'file:///home/gmarik/path/to/plugin'</span></div></div><div><div><div>21</div></div><div><span>" vim脚本sparkup存放在这个名叫vim的仓库下的一个子目录中。</span></div></div><div><div><div>22</div></div><div><span>" 将这个路径正确地设置为runtimepath。</span></div></div><div><div><div>23</div></div><div><span>Plugin</span><span> </span><span>'rstacruz/sparkup'</span><span>, {</span><span>'rtp'</span><span>: </span><span>'vim/'</span><span>}</span></div></div><div><div><div>24</div></div><div><span>"　避免与L9发生名字上的冲突</span></div></div><div><div><div>25</div></div><div><span>Plugin</span><span> </span><span>'user/L9'</span><span>, {</span><span>'name'</span><span>: </span><span>'newL9'</span><span>}</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>"所有的插件都应该在这一行之前。</span></div></div><div><div><div>28</div></div><div><span>call</span><span> </span><span>vundle#end</span><span>()</span><span>            " 必需。</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<p>上文解释：</p>
<ol>
 	<li>要从github安装插件：<code>Plugin 'user/plugin'</code></li>
 	<li>要从特定网址安装：<code>Plugin 'plugin_name'</code></li>
 	<li>要从一个git库安装：<code>Plugin 'git://url.git'</code></li>
 	<li>从本地安装：<code>Plugin 'file:///path'</code></li>
</ol>
你同样可以定制其它东西，例如你的插件的运行时路径，当你自己在编写一个插件时，或者你只是想从其它目录——而不是~/.vim——中加载插件时，这样做就非常有用。
<code>Plugin 'rstacruz/sparkup', {'rtp' :'another_vim_path/'}</code>
如果你有同名的插件，你可以重命名你的插件，这样它们就不会发生冲突了。
<code>Plugin 'user/plugin', {'name': 'newPlugin'}</code>
<h1>0x02Vundle相关命令</h1>
<p>进入vim</p>
<h3>1.安装新插件</h3>
<p>输入<code></code>安装配置文件中的插件</p>
<p>输入<code> &lt;插件名&gt;</code>通过插件名安装指定插件</p>
<h3>2.清除插件</h3>
<p>删除配置文件中插件再运行<code></code>来删除</p>
<h3>3.查看插件列表</h3>
<p><code></code></p>
<h1>END</h1>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/99/</id>
      <title type="text">树莓派通过USB方式与计算机连接（Win10）</title>
      <published>2018-07-25T00:00:00.000Z</published>
      <updated>2019-10-24T06:51:36.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/99/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>刷入树莓派官方系统raspbian</p></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>打开boot文件夹，找到 config.txt文件并在最后添加<code>dtoverlay=dwc2</code></p><p>找到<code>cmdline.txt</code>文件，找到 rootwait并在后面添加<code>modules-load=dwc2,g_ether</code></p></section>
<section><h1>0x03<a href="#0x03"><span>#</span></a></h1><p>树莓派通过usb连接电脑，过一会儿电脑会提示有新的设备。（第一次可能会识别为COM设备，在设备管理器<a href="http:///src/RPI_Driver_OTG.zip" target="_blank">更新驱动</a>即可）</p></section>
<section><h1>0x04<a href="#0x04"><span>#</span></a></h1><p>打开ssh连接工具，输入地址<code>raspberrypi.local</code>即可（若提示找不到地址就安装Bonjour（基于mDNS，它允许你的电脑自动识别 USB/以太网设备， iTunes 与 Adobe CS 包含该软件，也可独立安装），最新版windows 10（我的是1809）已经内置mDNS功能不需要额外安装）</p></section>
<section><h1>0x05（可选）<a href="#0x05可选"><span>#</span></a></h1><p>更改hostname</p><p>修改<code>/etc/hosts</code>与<code>/etc/hostname</code>中的raspberry即可</p><p>连接地址就变为更改后的<code>hostname.local</code></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/95/</id>
      <title type="text">【python】查看Linux实时网速</title>
      <published>2018-07-15T00:00:00.000Z</published>
      <updated>2019-10-24T06:34:18.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/95/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> time</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>speed_down</span><span>=</span><span>[]</span></span></div></div><div><div><div>4</div></div><div><span><span>speed_up</span><span>=</span><span>[]</span></span></div></div><div><div><div>5</div></div><div><span><span>speed_name</span><span>=</span><span>[]</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span><span>speed_up_1</span><span>=</span><span>[]</span></span></div></div><div><div><div>8</div></div><div><span><span>speed_down_1</span><span>=</span><span>[]</span></span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>while</span><span> </span><span>True</span><span>:</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>i</span><span>=</span><span>open</span><span>(</span><span>'/proc/net/dev'</span><span>,</span><span>'r'</span><span><span>).</span><span>readlines</span><span>()</span></span></div></div><div><div><div>12</div></div><div><span>    </span><span>for</span><span> p </span><span>in</span><span> i:</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>p</span><span>=</span><span>p.</span><span>split</span><span>( )</span></div></div><div><div><div>14</div></div><div><span>        </span><span>if</span><span> p[</span><span>1</span><span><span>].</span><span>isdigit</span><span>() </span></span><span>and</span><span> p[</span><span>1</span><span><span>]</span><span>!=</span></span><span>'0'</span><span>:</span></div></div><div><div><div>15</div></div><div><span><span>            </span></span><span>index</span><span>=</span><span>0</span></div></div><div><div><div>16</div></div><div><span>            </span><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>len</span><span>(speed_name)):</span></div></div><div><div><div>17</div></div><div><span>                </span><span>if</span><span> p[</span><span>0</span><span><span>]</span><span>==</span><span>speed_name[i]:</span></span></div></div><div><div><div>18</div></div><div><span><span>                    </span></span><span>index</span><span>=</span><span>i</span></div></div><div><div><div>19</div></div><div><span>                    </span><span>break</span></div></div><div><div><div>20</div></div><div><span>            </span><span>if</span><span> p[</span><span>0</span><span>] </span><span>in</span><span> speed_name:</span></div></div><div><div><div>21</div></div><div><span>                </span><span>pass</span></div></div><div><div><div>22</div></div><div><span>            </span><span>else</span><span>:</span></div></div><div><div><div>23</div></div><div><span><span>                </span></span><span>speed_name.</span><span>append</span><span>(p[</span><span>0</span><span>])</span></div></div><div><div><div>24</div></div><div><span><span>                </span></span><span>speed_down_1.</span><span>append</span><span>(p[</span><span>1</span><span>])</span></div></div><div><div><div>25</div></div><div><span><span>                </span></span><span>speed_up_1.</span><span>append</span><span>(p[</span><span>9</span><span>])</span></div></div><div><div><div>26</div></div><div><span><span>                </span></span><span>speed_down.</span><span>append</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>27</div></div><div><span><span>                </span></span><span>speed_up.</span><span>append</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>28</div></div><div><span>                </span><span>break</span></div></div><div><div><div>29</div></div><div><span><span>            </span></span><span>speed_down[index]</span><span>=</span><span>(</span><span>float</span><span>)((</span><span>int</span><span>)(p[</span><span>1</span><span><span>])</span><span>-</span><span>(</span></span><span>int</span><span><span>)(speed_down_1[index]))</span><span>/</span></span><span>1000</span></div></div><div><div><div>30</div></div><div><span><span>            </span></span><span>speed_up[index]</span><span>=</span><span>(</span><span>float</span><span>)((</span><span>int</span><span>)(p[</span><span>9</span><span><span>])</span><span>-</span><span>(</span></span><span>int</span><span><span>)(speed_up_1[index]))</span><span>/</span></span><span>1000</span></div></div><div><div><div>31</div></div><div><span><span>            </span></span><span>speed_down_1[index]</span><span>=</span><span>p[</span><span>1</span><span>]</span></div></div><div><div><div>32</div></div><div><span><span>            </span></span><span>speed_up_1[index]</span><span>=</span><span>p[</span><span>9</span><span>]</span></div></div><div><div><div>33</div></div><div><span>    </span><span>for</span><span> i </span><span>in</span><span> </span><span>range</span><span>(</span><span>len</span><span>(speed_name)):</span></div></div><div><div><div>34</div></div><div><span>        </span><span>print</span><span>(</span><span>"网卡："</span><span><span>+</span><span>speed_name[i])</span></span></div></div><div><div><div>35</div></div><div><span>        </span><span>print</span><span>(</span><span>"上行："</span><span><span>+</span><span>speed_up[i])</span></span></div></div><div><div><div>36</div></div><div><span>        </span><span>print</span><span>(</span><span>"下行："</span><span><span>+</span><span>speed_down[i])</span></span></div></div><div><div><div>37</div></div><div><span><span>    </span></span><span>time.</span><span>sleep</span><span>(</span><span>1</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/96/</id>
      <title type="text">【树莓派】使用温度湿度传感器DHT系列</title>
      <published>2018-07-15T00:00:00.000Z</published>
      <updated>2019-10-24T06:51:52.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/96/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div></div><div>Note</div></div><div><p>2019-10-24更新</p></div></div>
<p>新版本的raspbian内核包括一些传感器,在<code>/boot/overlays/README</code>里有相关说明,以DHT11为例:
在<code>/boot/config</code>最后一行添加</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>dtoverlay</span><span><span>=</span><span>dht11,</span></span><span>gpiopin</span><span><span>=</span><span>4</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>重启.
<code>gpiopin</code>为读取数据的引脚,可自行更改,引脚号码为BCM编码.
读取数据直接读取<code>/dev/dht11</code>即可</p>
<hr />
<div><div><div></div><div>Warning</div></div><div><p>2018-7-15</p></div></div>
<p>驱动：<a href="https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code" target="_blank">https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code</a></p>
<p>具体：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>git</span><span> </span><span>clone</span><span> </span><span>https://github.com/adafruit/Adafruit_Python_DHT.git</span></div></div><div><div><div>2</div></div><div><span>cd</span><span> </span><span>Adafruit_Python_DHT</span></div></div><div><div><div>3</div></div><div><span>sudo</span><span> </span><span>python3</span><span> </span><span>setup.py</span><span> </span><span>install</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>使用：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> Adafruit_DHT</span></div></div><div><div><div>2</div></div><div><span><span>sensor </span><span>=</span><span> Adafruit_DHT.</span><span>DHT11</span><span>     </span></span><span>#DHT22型号的传感器就填Adafruit_DHT.DHT22</span></div></div><div><div><div>3</div></div><div><span><span>humidity, temperature </span><span>=</span><span> Adafruit_DHT.</span><span>read_retry</span><span>(sensor, </span></span><span>26</span><span>)    </span><span>#26 是 GPIO 的引脚编号</span></div></div><div><div><div>4</div></div><div><span>print</span><span> (humidity)</span></div></div><div><div><div>5</div></div><div><span>print</span><span> (temperature)</span></div></div></code></pre><div><div></div><div></div></div></figure></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/98/</id>
      <title type="text">LCD显示系统信息脚本</title>
      <published>2018-07-15T00:00:00.000Z</published>
      <updated>2019-10-24T06:48:28.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/98/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>包括,系统运行时间,网卡名称,上下行网速</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span><span> </span><span>PCD8544</span><span> </span></span><span>import</span><span><span> </span><span>PCD8544</span><span> </span></span><span>as</span><span> lcd</span></div></div><div><div><div>2</div></div><div><span>import</span><span> time</span></div></div><div><div><div>3</div></div><div><span>import</span><span> os</span></div></div><div><div><div>4</div></div><div><span>import</span><span> threading</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>cpu_info</span><span>=</span></span><span>""</span></div></div><div><div><div>7</div></div><div><span><span>time_info</span><span>=</span></span><span>""</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span><span>speed_down</span><span>=</span><span>[]</span></span></div></div><div><div><div>10</div></div><div><span><span>speed_up</span><span>=</span><span>[]</span></span></div></div><div><div><div>11</div></div><div><span><span>speed_name</span><span>=</span><span>[]</span></span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span># 显示cpu温度</span></div></div><div><div><div>14</div></div><div><span>def</span><span> </span><span>cpu_t</span><span>():</span></div></div><div><div><div>15</div></div><div><span>    </span><span>global</span><span> cpu_info</span></div></div><div><div><div>16</div></div><div><span>    </span><span>while</span><span>(</span><span>True</span><span>):</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>info</span><span>=</span><span>open</span><span>(</span><span>'/sys/class/thermal/thermal_zone0/temp'</span><span>,</span><span>'r'</span><span><span>).</span><span>read</span><span>()</span></span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>info</span><span>=</span><span>(</span><span>int</span><span><span>)(info)</span><span>/</span></span><span>1000</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>info</span><span>=</span><span>(</span><span>str</span><span><span>)(info)</span><span>+</span></span><span>'C'</span></div></div><div><div><div>20</div></div><div><span><span>        </span></span><span>cpu_info</span><span>=</span><span>info</span></div></div><div><div><div>21</div></div><div><span><span>        </span></span><span>time.</span><span>sleep</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span># 显示开机运行时间</span></div></div><div><div><div>24</div></div><div><span>def</span><span> </span><span>time_local</span><span>():</span></div></div><div><div><div>25</div></div><div><span>    </span><span>global</span><span> time_info</span></div></div><div><div><div>26</div></div><div><span>    </span><span>while</span><span>(</span><span>True</span><span>):</span></div></div><div><div><div>27</div></div><div><span><span>        </span></span><span>info</span><span>=</span><span>os.</span><span>popen</span><span>(</span><span>'cat /proc/uptime| awk -F. </span><span>\'</span><span>{run_days=$1 / 86400;run_hour=($1 % 86400)/3600;run_minute=($1 % 3600)/60;run_second=$1 % 60;printf(</span><span>\"</span><span>%d</span><span>D </span><span>%d</span><span>:</span><span>%d</span><span>:</span><span>%d</span><span>\"</span><span>,run_days,run_hour,run_minute,run_second)}</span><span>\'</span><span>'</span><span>)</span></div></div><div><div><div>28</div></div><div><span><span>        </span></span><span>info</span><span>=</span><span>info.</span><span>read</span><span>()</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>time_info</span><span>=</span><span>info</span></div></div><div><div><div>30</div></div><div><span><span>        </span></span><span>time.</span><span>sleep</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>31</div></div><div>
</div></div><div><div><div>32</div></div><div><span># 显示网卡速度</span></div></div><div><div><div>33</div></div><div><span>def</span><span> </span><span>net_speed</span><span>():</span></div></div><div><div><div>34</div></div><div><span>    </span><span>global</span><span> speed_name</span></div></div><div><div><div>35</div></div><div><span>    </span><span>global</span><span> speed_down</span></div></div><div><div><div>36</div></div><div><span>    </span><span>global</span><span> speed_up</span></div></div><div><div><div>37</div></div><div>
</div></div><div><div><div>38</div></div><div><span><span>    </span></span><span>speed_down_1</span><span>=</span><span>{}</span></div></div><div><div><div>39</div></div><div><span><span>    </span></span><span>speed_up_1</span><span>=</span><span>{}</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span><span>    </span></span><span>speed_net_time</span><span>=</span><span>{}       </span><span>#记录各网卡有网速的时间</span></div></div><div><div><div>42</div></div><div>
</div></div><div><div><div>43</div></div><div><span>    </span><span>while</span><span> </span><span>True</span><span>:</span></div></div><div><div><div>44</div></div><div><span><span>        </span></span><span>info</span><span>=</span><span>open</span><span>(</span><span>'/proc/net/dev'</span><span>,</span><span>'r'</span><span><span>).</span><span>readlines</span><span>()</span></span></div></div><div><div><div>45</div></div><div><span>        </span><span>for</span><span> p </span><span>in</span><span> info:</span></div></div><div><div><div>46</div></div><div><span><span>            </span></span><span>p</span><span>=</span><span>p.</span><span>split</span><span>( )</span></div></div><div><div><div>47</div></div><div><span>            </span><span>if</span><span> p[</span><span>1</span><span><span>].</span><span>isdigit</span><span>() </span></span><span>and</span><span> p[</span><span>1</span><span><span>] </span><span>!=</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>48</div></div><div><span><span>                </span></span><span>index </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>49</div></div><div><span>                </span><span>if</span><span> p[</span><span>0</span><span>] </span><span>in</span><span> speed_name:</span></div></div><div><div><div>50</div></div><div><span><span>                    </span></span><span>index </span><span>=</span><span> speed_name.</span><span>index</span><span>(p[</span><span>0</span><span>])</span></div></div><div><div><div>51</div></div><div>
</div></div><div><div><div>52</div></div><div><span>                    </span><span>#若10秒后网速仍然为0就取消显示该网卡速度</span></div></div><div><div><div>53</div></div><div><span>                    </span><span>if</span><span> (</span><span>int</span><span><span>)(time.</span><span>time</span><span>()) </span><span>-</span><span> speed_net_time.</span><span>get</span><span>(p[</span></span><span>0</span><span>],</span><span>0</span><span><span>) </span><span>&gt;</span><span> </span></span><span>10</span><span> </span><span>and</span><span><span> speed_down_1.</span><span>get</span><span>(p[</span></span><span>0</span><span><span>]) </span><span>==</span><span> p[</span></span><span>1</span><span>] </span><span>and</span><span><span> speed_up_1.</span><span>get</span><span>(p[</span></span><span>0</span><span><span>]) </span><span>==</span><span> p[</span></span><span>9</span><span>]:</span></div></div><div><div><div>54</div></div><div><span>                        </span><span>del</span><span> speed_name[index]</span></div></div><div><div><div>55</div></div><div><span>                        </span><span>del</span><span> speed_down[index]</span></div></div><div><div><div>56</div></div><div><span>                        </span><span>del</span><span> speed_up[index]</span></div></div><div><div><div>57</div></div><div><span><span>                        </span></span><span>speed_net_time[p[</span><span>0</span><span><span>]] </span><span>=</span><span> (</span></span><span>int</span><span><span>)(time.</span><span>time</span><span>())</span></span></div></div><div><div><div>58</div></div><div><span>                    </span><span>else</span><span>:</span></div></div><div><div><div>59</div></div><div><span><span>                        </span></span><span>speed_down[index]</span><span>=</span><span>(</span><span>float</span><span>)((</span><span>int</span><span>)(p[</span><span>1</span><span><span>])</span><span>-</span><span>(</span></span><span>int</span><span><span>)(speed_down_1.</span><span>get</span><span>(p[</span></span><span>0</span><span><span>])))</span><span>/</span></span><span>1000</span></div></div><div><div><div>60</div></div><div><span><span>                        </span></span><span>speed_up[index]</span><span>=</span><span>(</span><span>float</span><span>)((</span><span>int</span><span>)(p[</span><span>9</span><span><span>])</span><span>-</span><span>(</span></span><span>int</span><span><span>)(speed_up_1.</span><span>get</span><span>(p[</span></span><span>0</span><span><span>])))</span><span>/</span></span><span>1000</span></div></div><div><div><div>61</div></div><div><span>                        </span><span>if</span><span><span> speed_down[index] </span><span>!=</span><span> </span></span><span>0</span><span> </span><span>and</span><span><span> speed_up[index] </span><span>!=</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>62</div></div><div><span><span>                            </span></span><span>speed_net_time[p[</span><span>0</span><span><span>]] </span><span>=</span><span> (</span></span><span>int</span><span><span>)(time.</span><span>time</span><span>())</span></span></div></div><div><div><div>63</div></div><div><span><span>                    </span></span><span>speed_down_1[p[</span><span>0</span><span><span>]]</span><span>=</span><span>p[</span></span><span>1</span><span>]</span></div></div><div><div><div>64</div></div><div><span><span>                    </span></span><span>speed_up_1[p[</span><span>0</span><span><span>]]</span><span>=</span><span>p[</span></span><span>9</span><span>]</span></div></div><div><div><div>65</div></div><div><span>                </span><span>else</span><span>:</span></div></div><div><div><div>66</div></div><div><span>                    </span><span>if</span><span><span> speed_down_1.</span><span>get</span><span>(p[</span></span><span>0</span><span>],</span><span>0</span><span><span>) </span><span>!=</span><span> p[</span></span><span>1</span><span>] </span><span>and</span><span><span> speed_up_1.</span><span>get</span><span>(p[</span></span><span>0</span><span>],</span><span>0</span><span><span>) </span><span>!=</span><span> p[</span></span><span>9</span><span>]:</span></div></div><div><div><div>67</div></div><div><span><span>                        </span></span><span>speed_name.</span><span>append</span><span>(p[</span><span>0</span><span>])</span></div></div><div><div><div>68</div></div><div><span><span>                        </span></span><span>speed_down.</span><span>append</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>69</div></div><div><span><span>                        </span></span><span>speed_up.</span><span>append</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>70</div></div><div><span><span>                        </span></span><span>speed_down_1[p[</span><span>0</span><span><span>]] </span><span>=</span><span> p[</span></span><span>1</span><span>]</span></div></div><div><div><div>71</div></div><div><span><span>                        </span></span><span>speed_up_1[p[</span><span>0</span><span><span>]] </span><span>=</span><span> p[</span></span><span>9</span><span>]</span></div></div><div><div><div>72</div></div><div><span>                    </span><span>continue</span></div></div><div><div><div>73</div></div><div><span><span>        </span></span><span>time.</span><span>sleep</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>74</div></div><div>
</div></div><div><div><div>75</div></div><div>
</div></div><div><div><div>76</div></div><div>
</div></div><div><div><div>77</div></div><div><span>def</span><span> </span><span>main</span><span>():</span></div></div><div><div><div>78</div></div><div><span><span>    </span></span><span>a </span><span>=</span><span> </span><span>lcd</span><span>(</span><span>dc</span><span>=</span><span>13</span><span>, </span><span>rst</span><span>=</span><span>5</span><span>, </span><span>sclk</span><span>=</span><span>26</span><span>, </span><span>din</span><span>=</span><span>19</span><span>, </span><span>cs</span><span>=</span><span>6</span><span>, </span><span>vcc</span><span>=</span><span>20</span><span>, </span><span>bl</span><span>=</span><span>21</span><span>, </span><span>bk</span><span>=</span><span>0</span><span>)</span></div></div><div><div><div>79</div></div><div><span><span>    </span></span><span>a.</span><span>begin</span><span>(</span><span>contrast</span><span>=</span><span>60</span><span>)        </span><span>#屏幕对比度</span></div></div><div><div><div>80</div></div><div>
</div></div><div><div><div>81</div></div><div><span>    </span><span>#各任务使用多线程运行</span></div></div><div><div><div>82</div></div><div><span><span>    </span></span><span>tmp</span><span>=</span><span>threading.</span><span>Thread</span><span>(</span><span>target</span><span><span>=</span><span>time_local)</span></span></div></div><div><div><div>83</div></div><div><span><span>    </span></span><span>tmp.</span><span>setDaemon</span><span>(</span><span>True</span><span>)</span></div></div><div><div><div>84</div></div><div><span><span>    </span></span><span>tmp.</span><span>start</span><span>()</span></div></div><div><div><div>85</div></div><div><span><span>    </span></span><span>tmp</span><span>=</span><span>threading.</span><span>Thread</span><span>(</span><span>target</span><span><span>=</span><span>cpu_t)</span></span></div></div><div><div><div>86</div></div><div><span><span>    </span></span><span>tmp.</span><span>setDaemon</span><span>(</span><span>True</span><span>)</span></div></div><div><div><div>87</div></div><div><span><span>    </span></span><span>tmp.</span><span>start</span><span>()</span></div></div><div><div><div>88</div></div><div><span><span>    </span></span><span>tmp</span><span>=</span><span>threading.</span><span>Thread</span><span>(</span><span>target</span><span><span>=</span><span>net_speed)</span></span></div></div><div><div><div>89</div></div><div><span><span>    </span></span><span>tmp.</span><span>setDaemon</span><span>(</span><span>True</span><span>)</span></div></div><div><div><div>90</div></div><div><span><span>    </span></span><span>tmp.</span><span>start</span><span>()</span></div></div><div><div><div>91</div></div><div>
</div></div><div><div><div>92</div></div><div><span><span>    </span></span><span>t1</span><span>=</span><span>(</span><span>int</span><span><span>)(time.</span><span>time</span><span>())</span></span></div></div><div><div><div>93</div></div><div><span><span>    </span></span><span>index</span><span>=</span><span>0</span></div></div><div><div><div>94</div></div><div><span>    </span><span>while</span><span>(</span><span>True</span><span>):</span></div></div><div><div><div>95</div></div><div><span>        </span><span>try</span><span>:</span></div></div><div><div><div>96</div></div><div><span><span>            </span></span><span>t2</span><span>=</span><span>(</span><span>int</span><span><span>)(time.</span><span>time</span><span>())</span></span></div></div><div><div><div>97</div></div><div><span><span>            </span></span><span>a.</span><span>clear</span><span>()</span></div></div><div><div><div>98</div></div><div><span><span>            </span></span><span>a.</span><span>draw_str</span><span>(</span><span>0</span><span>,</span><span>'CPU: '</span><span><span>+</span><span>cpu_info)</span></span></div></div><div><div><div>99</div></div><div><span><span>            </span></span><span>a.</span><span>draw_str</span><span>(</span><span>1</span><span>,time_info)</span></div></div><div><div><div>100</div></div><div><span>            </span><span>try</span><span>:</span></div></div><div><div><div>101</div></div><div><span>                </span><span># 网卡显示，10秒切换网卡信息</span></div></div><div><div><div>102</div></div><div><span>                </span><span>if</span><span><span> t2</span><span>-</span><span>t1</span><span>&gt;</span></span><span>10</span><span>:</span></div></div><div><div><div>103</div></div><div><span><span>                    </span></span><span>t1</span><span>=</span><span>t2</span></div></div><div><div><div>104</div></div><div><span>                    </span><span>if</span><span><span> index </span><span>&lt;</span><span> </span></span><span>len</span><span><span>(speed_name)</span><span>-</span></span><span>1</span><span>:</span></div></div><div><div><div>105</div></div><div><span><span>                        </span></span><span>index</span><span>=</span><span>index</span><span>+</span><span>1</span></div></div><div><div><div>106</div></div><div><span>                    </span><span>else</span><span>:</span></div></div><div><div><div>107</div></div><div><span><span>                        </span></span><span>index</span><span>=</span><span>0</span></div></div><div><div><div>108</div></div><div><span><span>                </span></span><span>a.</span><span>draw_str</span><span>(</span><span>2</span><span><span>,speed_name[index]</span><span>+</span></span><span>" ("</span><span><span>+</span><span>(</span></span><span>str</span><span><span>)(index</span><span>+</span></span><span>1</span><span><span>)</span><span>+</span></span><span>"/"</span><span><span>+</span><span>(</span></span><span>str</span><span>)(</span><span>len</span><span><span>(speed_name))</span><span>+</span></span><span>")"</span><span>)</span></div></div><div><div><div>109</div></div><div><span><span>                </span></span><span>a.</span><span>draw_str</span><span>(</span><span>3</span><span>,</span><span>"D: "</span><span><span>+</span><span>(</span></span><span>str</span><span><span>)(speed_down[index])</span><span>+</span></span><span>"k/s"</span><span>)</span></div></div><div><div><div>110</div></div><div><span><span>                </span></span><span>a.</span><span>draw_str</span><span>(</span><span>4</span><span>,</span><span>"U: "</span><span><span>+</span><span>(</span></span><span>str</span><span><span>)(speed_up[index])</span><span>+</span></span><span>"k/s"</span><span>)</span></div></div><div><div><div>111</div></div><div><span>            </span><span>except</span><span> </span><span>Exception</span><span> </span><span>as</span><span> e:</span></div></div><div><div><div>112</div></div><div><span>                </span><span>pass</span></div></div><div><div><div>113</div></div><div><span><span>            </span></span><span>a.</span><span>display</span><span>()</span></div></div><div><div><div>114</div></div><div><span><span>            </span></span><span>time.</span><span>sleep</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>115</div></div><div><span>        </span><span>except</span><span> </span><span>KeyboardInterrupt</span><span>:</span></div></div><div><div><div>116</div></div><div><span><span>            </span></span><span>a.</span><span>quit</span><span>()</span></div></div><div><div><div>117</div></div><div><span>            </span><span>exit</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>118</div></div><div>
</div></div><div><div><div>119</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>'__main__'</span><span>:</span></div></div><div><div><div>120</div></div><div><span><span>    </span></span><span>main</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/94/</id>
      <title type="text">【树莓派】使用Nokia5110显示信息</title>
      <published>2018-07-14T00:00:00.000Z</published>
      <updated>2019-10-24T06:33:00.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/94/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>接线：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>dc 13</span></div></div><div><div><div>2</div></div><div><span>rst 5</span></div></div><div><div><div>3</div></div><div><span>sclk 26</span></div></div><div><div><div>4</div></div><div><span>din 19</span></div></div><div><div><div>5</div></div><div><span>cs 6</span></div></div><div><div><div>6</div></div><div><span>bl 21</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>需要的python库<code>Adafruit_GPIO</code></p>
<p>屏幕显示驱动：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span># coding:utf-8</span></div></div><div><div><div>2</div></div><div><span>import</span><span> time</span></div></div><div><div><div>3</div></div><div><span>import</span><span> Adafruit_GPIO </span><span>as</span><span><span> </span><span>GPIO</span></span></div></div><div><div><div>4</div></div><div><span>import</span><span><span> Adafruit_GPIO.</span><span>SPI</span><span> </span></span><span>as</span><span><span> </span><span>SPI</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>LCDWIDTH</span><span> </span><span>=</span><span> </span></span><span>84</span></div></div><div><div><div>7</div></div><div><span><span>LCDHEIGHT</span><span> </span><span>=</span><span> </span></span><span>48</span></div></div><div><div><div>8</div></div><div><span><span>ROWPIXELS</span><span> </span><span>=</span><span> </span><span>LCDHEIGHT</span><span>//</span></span><span>6</span></div></div><div><div><div>9</div></div><div><span><span>PCD8544_POWERDOWN</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>04</span></div></div><div><div><div>10</div></div><div><span><span>PCD8544_ENTRYMODE</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>02</span></div></div><div><div><div>11</div></div><div><span><span>PCD8544_EXTENDEDINSTRUCTION</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>01</span></div></div><div><div><div>12</div></div><div><span><span>PCD8544_DISPLAYBLANK</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>0</span></div></div><div><div><div>13</div></div><div><span><span>PCD8544_DISPLAYNORMAL</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>4</span></div></div><div><div><div>14</div></div><div><span><span>PCD8544_DISPLAYALLON</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>1</span></div></div><div><div><div>15</div></div><div><span><span>PCD8544_DISPLAYINVERTED</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>5</span></div></div><div><div><div>16</div></div><div><span><span>PCD8544_FUNCTIONSET</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>20</span></div></div><div><div><div>17</div></div><div><span><span>PCD8544_DISPLAYCONTROL</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>08</span></div></div><div><div><div>18</div></div><div><span><span>PCD8544_SETYADDR</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>40</span></div></div><div><div><div>19</div></div><div><span><span>PCD8544_SETXADDR</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>80</span></div></div><div><div><div>20</div></div><div><span><span>PCD8544_SETTEMP</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>04</span></div></div><div><div><div>21</div></div><div><span><span>PCD8544_SETBIAS</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>10</span></div></div><div><div><div>22</div></div><div><span><span>PCD8544_SETVOP</span><span> </span><span>=</span><span> </span></span><span>0x</span><span>80</span></div></div><div><div><div>23</div></div><div><span><span>FONT</span><span> </span><span>=</span><span> {</span></span></div></div><div><div><div>24</div></div><div><span>  </span><span>' '</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>25</div></div><div><span>  </span><span>'!'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>5f</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>26</div></div><div><span>  </span><span>'"'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>07</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>07</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>27</div></div><div><span>  </span><span>'#'</span><span>: [</span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>14</span><span>],</span></div></div><div><div><div>28</div></div><div><span>  </span><span>'$'</span><span>: [</span><span>0x</span><span>24</span><span>, </span><span>0x</span><span>2a</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>2a</span><span>, </span><span>0x</span><span>12</span><span>],</span></div></div><div><div><div>29</div></div><div><span>  </span><span>'%'</span><span>: [</span><span>0x</span><span>23</span><span>, </span><span>0x</span><span>13</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>64</span><span>, </span><span>0x</span><span>62</span><span>],</span></div></div><div><div><div>30</div></div><div><span>  </span><span>'&amp;'</span><span>: [</span><span>0x</span><span>36</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>55</span><span>, </span><span>0x</span><span>22</span><span>, </span><span>0x</span><span>50</span><span>],</span></div></div><div><div><div>31</div></div><div><span>  </span><span>"'"</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>05</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>32</div></div><div><span>  </span><span>'('</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>1c</span><span>, </span><span>0x</span><span>22</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>33</div></div><div><span>  </span><span>')'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>22</span><span>, </span><span>0x</span><span>1c</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>34</div></div><div><span>  </span><span>'*'</span><span>: [</span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>3e</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>14</span><span>],</span></div></div><div><div><div>35</div></div><div><span>  </span><span>'+'</span><span>: [</span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>3e</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>08</span><span>],</span></div></div><div><div><div>36</div></div><div><span>  </span><span>','</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>50</span><span>, </span><span>0x</span><span>30</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>37</div></div><div><span>  </span><span>'-'</span><span>: [</span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>08</span><span>],</span></div></div><div><div><div>38</div></div><div><span>  </span><span>'.'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>60</span><span>, </span><span>0x</span><span>60</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>39</div></div><div><span>  </span><span>'/'</span><span>: [</span><span>0x</span><span>20</span><span>, </span><span>0x</span><span>10</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>02</span><span>],</span></div></div><div><div><div>40</div></div><div><span>  </span><span>'0'</span><span>: [</span><span>0x</span><span>3e</span><span>, </span><span>0x</span><span>51</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>45</span><span>, </span><span>0x</span><span>3e</span><span>],</span></div></div><div><div><div>41</div></div><div><span>  </span><span>'1'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>42</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>42</div></div><div><span>  </span><span>'2'</span><span>: [</span><span>0x</span><span>42</span><span>, </span><span>0x</span><span>61</span><span>, </span><span>0x</span><span>51</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>46</span><span>],</span></div></div><div><div><div>43</div></div><div><span>  </span><span>'3'</span><span>: [</span><span>0x</span><span>21</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>45</span><span>, </span><span>0x</span><span>4b</span><span>, </span><span>0x</span><span>31</span><span>],</span></div></div><div><div><div>44</div></div><div><span>  </span><span>'4'</span><span>: [</span><span>0x</span><span>18</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>12</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>10</span><span>],</span></div></div><div><div><div>45</div></div><div><span>  </span><span>'5'</span><span>: [</span><span>0x</span><span>27</span><span>, </span><span>0x</span><span>45</span><span>, </span><span>0x</span><span>45</span><span>, </span><span>0x</span><span>45</span><span>, </span><span>0x</span><span>39</span><span>],</span></div></div><div><div><div>46</div></div><div><span>  </span><span>'6'</span><span>: [</span><span>0x</span><span>3c</span><span>, </span><span>0x</span><span>4a</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>30</span><span>],</span></div></div><div><div><div>47</div></div><div><span>  </span><span>'7'</span><span>: [</span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>71</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>05</span><span>, </span><span>0x</span><span>03</span><span>],</span></div></div><div><div><div>48</div></div><div><span>  </span><span>'8'</span><span>: [</span><span>0x</span><span>36</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>36</span><span>],</span></div></div><div><div><div>49</div></div><div><span>  </span><span>'9'</span><span>: [</span><span>0x</span><span>06</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>29</span><span>, </span><span>0x</span><span>1e</span><span>],</span></div></div><div><div><div>50</div></div><div><span>  </span><span>':'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>36</span><span>, </span><span>0x</span><span>36</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>51</div></div><div><span>  </span><span>';'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>56</span><span>, </span><span>0x</span><span>36</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>52</div></div><div><span>  </span><span>'&lt;'</span><span>: [</span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>22</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>00</span><span>], </span><span>'='</span><span>: [</span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>14</span><span>], </span><span>'&gt;'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>22</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>08</span><span>],</span></div></div><div><div><div>53</div></div><div><span>  </span><span>'?'</span><span>: [</span><span>0x</span><span>02</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>51</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>06</span><span>],</span></div></div><div><div><div>54</div></div><div><span>  </span><span>'@'</span><span>: [</span><span>0x</span><span>32</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>79</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>3e</span><span>],</span></div></div><div><div><div>55</div></div><div><span>  </span><span>'A'</span><span>: [</span><span>0x</span><span>7e</span><span>, </span><span>0x</span><span>11</span><span>, </span><span>0x</span><span>11</span><span>, </span><span>0x</span><span>11</span><span>, </span><span>0x</span><span>7e</span><span>],</span></div></div><div><div><div>56</div></div><div><span>  </span><span>'B'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>36</span><span>],</span></div></div><div><div><div>57</div></div><div><span>  </span><span>'C'</span><span>: [</span><span>0x</span><span>3e</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>22</span><span>],</span></div></div><div><div><div>58</div></div><div><span>  </span><span>'D'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>22</span><span>, </span><span>0x</span><span>1c</span><span>],</span></div></div><div><div><div>59</div></div><div><span>  </span><span>'E'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>41</span><span>],</span></div></div><div><div><div>60</div></div><div><span>  </span><span>'F'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>01</span><span>],</span></div></div><div><div><div>61</div></div><div><span>  </span><span>'G'</span><span>: [</span><span>0x</span><span>3e</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>7a</span><span>],</span></div></div><div><div><div>62</div></div><div><span>  </span><span>'H'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>7f</span><span>],</span></div></div><div><div><div>63</div></div><div><span>  </span><span>'I'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>64</div></div><div><span>  </span><span>'J'</span><span>: [</span><span>0x</span><span>20</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>3f</span><span>, </span><span>0x</span><span>01</span><span>],</span></div></div><div><div><div>65</div></div><div><span>  </span><span>'K'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>22</span><span>, </span><span>0x</span><span>41</span><span>],</span></div></div><div><div><div>66</div></div><div><span>  </span><span>'L'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>],</span></div></div><div><div><div>67</div></div><div><span>  </span><span>'M'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>02</span><span>, </span><span>0x</span><span>0c</span><span>, </span><span>0x</span><span>02</span><span>, </span><span>0x</span><span>7f</span><span>],</span></div></div><div><div><div>68</div></div><div><span>  </span><span>'N'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>10</span><span>, </span><span>0x</span><span>7f</span><span>],</span></div></div><div><div><div>69</div></div><div><span>  </span><span>'O'</span><span>: [</span><span>0x</span><span>3e</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>3e</span><span>],</span></div></div><div><div><div>70</div></div><div><span>  </span><span>'P'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>06</span><span>],</span></div></div><div><div><div>71</div></div><div><span>  </span><span>'Q'</span><span>: [</span><span>0x</span><span>3e</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>51</span><span>, </span><span>0x</span><span>21</span><span>, </span><span>0x</span><span>5e</span><span>],</span></div></div><div><div><div>72</div></div><div><span>  </span><span>'R'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>19</span><span>, </span><span>0x</span><span>29</span><span>, </span><span>0x</span><span>46</span><span>],</span></div></div><div><div><div>73</div></div><div><span>  </span><span>'S'</span><span>: [</span><span>0x</span><span>46</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>31</span><span>],</span></div></div><div><div><div>74</div></div><div><span>  </span><span>'T'</span><span>: [</span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>],</span></div></div><div><div><div>75</div></div><div><span>  </span><span>'U'</span><span>: [</span><span>0x</span><span>3f</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>3f</span><span>],</span></div></div><div><div><div>76</div></div><div><span>  </span><span>'V'</span><span>: [</span><span>0x</span><span>1f</span><span>, </span><span>0x</span><span>20</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>20</span><span>, </span><span>0x</span><span>1f</span><span>],</span></div></div><div><div><div>77</div></div><div><span>  </span><span>'W'</span><span>: [</span><span>0x</span><span>3f</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>38</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>3f</span><span>],</span></div></div><div><div><div>78</div></div><div><span>  </span><span>'X'</span><span>: [</span><span>0x</span><span>63</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>63</span><span>],</span></div></div><div><div><div>79</div></div><div><span>  </span><span>'Y'</span><span>: [</span><span>0x</span><span>07</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>70</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>07</span><span>],</span></div></div><div><div><div>80</div></div><div><span>  </span><span>'Z'</span><span>: [</span><span>0x</span><span>61</span><span>, </span><span>0x</span><span>51</span><span>, </span><span>0x</span><span>49</span><span>, </span><span>0x</span><span>45</span><span>, </span><span>0x</span><span>43</span><span>],</span></div></div><div><div><div>81</div></div><div><span>  </span><span>'['</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>82</div></div><div><span>  </span><span>'</span><span>\\</span><span>'</span><span>: [</span><span>0x</span><span>02</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>10</span><span>, </span><span>0x</span><span>20</span><span>],</span></div></div><div><div><div>83</div></div><div><span>  </span><span>']'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>84</div></div><div><span>  </span><span>'^'</span><span>: [</span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>02</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>02</span><span>, </span><span>0x</span><span>04</span><span>],</span></div></div><div><div><div>85</div></div><div><span>  </span><span>'_'</span><span>: [</span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>],</span></div></div><div><div><div>86</div></div><div><span>  </span><span>'`'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>02</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>87</div></div><div><span>  </span><span>'a'</span><span>: [</span><span>0x</span><span>20</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>78</span><span>],</span></div></div><div><div><div>88</div></div><div><span>  </span><span>'b'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>48</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>38</span><span>],</span></div></div><div><div><div>89</div></div><div><span>  </span><span>'c'</span><span>: [</span><span>0x</span><span>38</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>20</span><span>],</span></div></div><div><div><div>90</div></div><div><span>  </span><span>'d'</span><span>: [</span><span>0x</span><span>38</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>48</span><span>, </span><span>0x</span><span>7f</span><span>],</span></div></div><div><div><div>91</div></div><div><span>  </span><span>'e'</span><span>: [</span><span>0x</span><span>38</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>18</span><span>],</span></div></div><div><div><div>92</div></div><div><span>  </span><span>'f'</span><span>: [</span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>7e</span><span>, </span><span>0x</span><span>09</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>02</span><span>],</span></div></div><div><div><div>93</div></div><div><span>  </span><span>'g'</span><span>: [</span><span>0x</span><span>0c</span><span>, </span><span>0x</span><span>52</span><span>, </span><span>0x</span><span>52</span><span>, </span><span>0x</span><span>52</span><span>, </span><span>0x</span><span>3e</span><span>],</span></div></div><div><div><div>94</div></div><div><span>  </span><span>'h'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>78</span><span>],</span></div></div><div><div><div>95</div></div><div><span>  </span><span>'i'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>7d</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>96</div></div><div><span>  </span><span>'j'</span><span>: [</span><span>0x</span><span>20</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>3d</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>97</div></div><div><span>  </span><span>'k'</span><span>: [</span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>10</span><span>, </span><span>0x</span><span>28</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>98</div></div><div><span>  </span><span>'l'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>99</div></div><div><span>  </span><span>'m'</span><span>: [</span><span>0x</span><span>7c</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>18</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>78</span><span>],</span></div></div><div><div><div>100</div></div><div><span>  </span><span>'n'</span><span>: [</span><span>0x</span><span>7c</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>78</span><span>],</span></div></div><div><div><div>101</div></div><div><span>  </span><span>'o'</span><span>: [</span><span>0x</span><span>38</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>38</span><span>],</span></div></div><div><div><div>102</div></div><div><span>  </span><span>'p'</span><span>: [</span><span>0x</span><span>7c</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>08</span><span>],</span></div></div><div><div><div>103</div></div><div><span>  </span><span>'q'</span><span>: [</span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>14</span><span>, </span><span>0x</span><span>18</span><span>, </span><span>0x</span><span>7c</span><span>],</span></div></div><div><div><div>104</div></div><div><span>  </span><span>'r'</span><span>: [</span><span>0x</span><span>7c</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>08</span><span>],</span></div></div><div><div><div>105</div></div><div><span>  </span><span>'s'</span><span>: [</span><span>0x</span><span>48</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>20</span><span>],</span></div></div><div><div><div>106</div></div><div><span>  </span><span>'t'</span><span>: [</span><span>0x</span><span>04</span><span>, </span><span>0x</span><span>3f</span><span>, </span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>20</span><span>],</span></div></div><div><div><div>107</div></div><div><span>  </span><span>'u'</span><span>: [</span><span>0x</span><span>3c</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>20</span><span>, </span><span>0x</span><span>7c</span><span>],</span></div></div><div><div><div>108</div></div><div><span>  </span><span>'v'</span><span>: [</span><span>0x</span><span>1c</span><span>, </span><span>0x</span><span>20</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>20</span><span>, </span><span>0x</span><span>1c</span><span>],</span></div></div><div><div><div>109</div></div><div><span>  </span><span>'w'</span><span>: [</span><span>0x</span><span>3c</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>30</span><span>, </span><span>0x</span><span>40</span><span>, </span><span>0x</span><span>3c</span><span>],</span></div></div><div><div><div>110</div></div><div><span>  </span><span>'x'</span><span>: [</span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>28</span><span>, </span><span>0x</span><span>10</span><span>, </span><span>0x</span><span>28</span><span>, </span><span>0x</span><span>44</span><span>],</span></div></div><div><div><div>111</div></div><div><span>  </span><span>'y'</span><span>: [</span><span>0x</span><span>0c</span><span>, </span><span>0x</span><span>50</span><span>, </span><span>0x</span><span>50</span><span>, </span><span>0x</span><span>50</span><span>, </span><span>0x</span><span>3c</span><span>],</span></div></div><div><div><div>112</div></div><div><span>  </span><span>'z'</span><span>: [</span><span>0x</span><span>44</span><span>, </span><span>0x</span><span>64</span><span>, </span><span>0x</span><span>54</span><span>, </span><span>0x</span><span>4c</span><span>, </span><span>0x</span><span>44</span><span>],</span></div></div><div><div><div>113</div></div><div><span>  </span><span>'{'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>36</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>114</div></div><div><span>  </span><span>'|'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>7f</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>115</div></div><div><span>  </span><span>'}'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>41</span><span>, </span><span>0x</span><span>36</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>00</span><span>],</span></div></div><div><div><div>116</div></div><div><span>  </span><span>'~'</span><span>: [</span><span>0x</span><span>10</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>08</span><span>, </span><span>0x</span><span>10</span><span>, </span><span>0x</span><span>08</span><span>],</span></div></div><div><div><div>117</div></div><div><span>  </span><span>'</span><span>\x7f</span><span>'</span><span>: [</span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>7e</span><span>, </span><span>0x</span><span>42</span><span>, </span><span>0x</span><span>42</span><span>, </span><span>0x</span><span>7e</span><span>],</span></div></div><div><div><div>118</div></div><div><span>}</span></div></div><div><div><div>119</div></div><div><span><span>X </span><span>=</span><span> </span></span><span>13</span></div></div><div><div><div>120</div></div><div><span><span>Y </span><span>=</span><span> </span></span><span>5</span></div></div><div><div><div>121</div></div><div>
</div></div><div><div><div>122</div></div><div><span>class</span><span><span> </span><span>PCD8544</span><span>(</span></span><span>object</span><span>)</span><span>:</span></div></div><div><div><div>123</div></div><div><span>    </span><span>"""Nokia 5110/3310 PCD8544-based LCD display."""</span></div></div><div><div><div>124</div></div><div>
</div></div><div><div><div>125</div></div><div><span>    </span><span>def</span><span> </span><span>__init__</span><span>(</span><span>self</span><span>,</span><span>bk</span><span>,</span><span><span> </span><span>dc</span></span><span>,</span><span><span> </span><span>rst</span></span><span>,</span><span><span> </span><span>sclk</span></span><span>=</span><span>None</span><span>,</span><span><span> </span><span>din</span></span><span>=</span><span>None</span><span>,</span><span><span> </span><span>cs</span></span><span>=</span><span>None</span><span>,</span><span><span> </span><span>gpio</span></span><span>=</span><span>None</span><span>,</span><span><span> </span><span>spi</span></span><span>=</span><span>None</span><span>,</span><span><span> </span><span>vcc</span></span><span>=</span><span>None</span><span>,</span><span><span> </span><span>bl</span></span><span>=</span><span>None</span><span>):</span></div></div><div><div><div>126</div></div><div><span>        </span><span>self</span><span><span>._sclk </span><span>=</span><span> sclk</span></span></div></div><div><div><div>127</div></div><div><span>        </span><span>self</span><span><span>._din </span><span>=</span><span> din</span></span></div></div><div><div><div>128</div></div><div><span>        </span><span>self</span><span><span>._dc </span><span>=</span><span> dc</span></span></div></div><div><div><div>129</div></div><div><span>        </span><span>self</span><span><span>._cs </span><span>=</span><span> cs</span></span></div></div><div><div><div>130</div></div><div><span>        </span><span>self</span><span><span>._rst </span><span>=</span><span> rst</span></span></div></div><div><div><div>131</div></div><div><span>        </span><span>self</span><span><span>._gpio </span><span>=</span><span> gpio</span></span></div></div><div><div><div>132</div></div><div><span>        </span><span>self</span><span><span>._spi </span><span>=</span><span> spi</span></span></div></div><div><div><div>133</div></div><div><span>        </span><span>self</span><span><span>._buffer </span><span>=</span><span> [</span></span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>C0</span><span>, </span><span>0x</span><span>E0</span><span>, </span><span>0x</span><span>F0</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>FE</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>E0</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F0</span><span>, </span><span>0x</span><span>F0</span><span>, </span><span>0x</span><span>E0</span><span>, </span><span>0x</span><span>E0</span><span>, </span><span>0x</span><span>C0</span><span>, </span><span>0x</span><span>80</span><span>, </span><span>0x</span><span>C0</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>7F</span><span>, </span><span>0x</span><span>3F</span><span>, </span><span>0x</span><span>7F</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>0F</span><span>, </span><span>0x</span><span>1F</span><span>, </span><span>0x</span><span>3F</span><span>, </span><span>0x</span><span>7F</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>E7</span><span>, </span><span>0x</span><span>C7</span><span>, </span><span>0x</span><span>C7</span><span>, </span><span>0x</span><span>87</span><span>, </span><span>0x</span><span>8F</span><span>, </span><span>0x</span><span>9F</span><span>, </span><span>0x</span><span>9F</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>C1</span><span>, </span><span>0x</span><span>C0</span><span>, </span><span>0x</span><span>E0</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>FE</span><span>, </span><span>0x</span><span>FE</span><span>, </span><span>0x</span><span>FE</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F0</span><span>, </span><span>0x</span><span>E0</span><span>, </span><span>0x</span><span>C0</span><span>, </span><span>0x</span><span>C0</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>80</span><span>, </span><span>0x</span><span>C0</span><span>, </span><span>0x</span><span>E0</span><span>, </span><span>0x</span><span>F1</span><span>, </span><span>0x</span><span>FB</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>7F</span><span>, </span><span>0x</span><span>1F</span><span>, </span><span>0x</span><span>0F</span><span>, </span><span>0x</span><span>0F</span><span>, </span><span>0x</span><span>87</span><span>, </span><span>0x</span><span>E7</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>1F</span><span>, </span><span>0x</span><span>1F</span><span>, </span><span>0x</span><span>3F</span><span>, </span><span>0x</span><span>F9</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>F8</span><span>, </span><span>0x</span><span>FD</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>7F</span><span>, </span><span>0x</span><span>3F</span><span>, </span><span>0x</span><span>0F</span><span>, </span><span>0x</span><span>07</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>F0</span><span>, </span><span>0x</span><span>FE</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FE</span><span>, </span><span>0x</span><span>7E</span><span>, </span><span>0x</span><span>3F</span><span>, </span><span>0x</span><span>3F</span><span>, </span><span>0x</span><span>0F</span><span>, </span><span>0x</span><span>1F</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>F0</span><span>, </span><span>0x</span><span>E0</span><span>, </span><span>0x</span><span>F1</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FC</span><span>, </span><span>0x</span><span>F0</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>01</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>0F</span><span>, </span><span>0x</span><span>1F</span><span>, </span><span>0x</span><span>3F</span><span>, </span><span>0x</span><span>7F</span><span>, </span><span>0x</span><span>7F</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>FF</span><span>, </span><span>0x</span><span>7F</span><span>, </span><span>0x</span><span>7F</span><span>, </span><span>0x</span><span>1F</span><span>, </span><span>0x</span><span>03</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span>, </span><span>0x</span><span>00</span><span> ]</span></div></div><div><div><div>134</div></div><div><span>        </span><span>if</span><span> </span><span>self</span><span>._gpio </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>135</div></div><div><span>            </span><span>self</span><span><span>._gpio </span><span>=</span><span> </span><span>GPIO</span><span>.</span><span>get_platform_gpio</span><span>()</span></span></div></div><div><div><div>136</div></div><div><span>            </span><span>self</span><span><span>._gpio.</span><span>setup</span><span>(vcc, </span><span>GPIO</span><span>.</span><span>OUT</span><span>)</span></span></div></div><div><div><div>137</div></div><div><span>            </span><span>self</span><span><span>._gpio.</span><span>setup</span><span>(bl, </span><span>GPIO</span><span>.</span><span>OUT</span><span>)</span></span></div></div><div><div><div>138</div></div><div><span>            </span><span>self</span><span><span>._gpio.</span><span>output</span><span>(vcc, </span></span><span>1</span><span>)</span></div></div><div><div><div>139</div></div><div><span>            </span><span>if</span><span><span> bk </span><span>==</span></span><span>0</span><span>:</span></div></div><div><div><div>140</div></div><div><span>                </span><span>self</span><span><span>._gpio.</span><span>output</span><span>(bl, </span></span><span>0</span><span>)</span></div></div><div><div><div>141</div></div><div><span>            </span><span>else</span><span>:</span></div></div><div><div><div>142</div></div><div><span>                </span><span>self</span><span><span>._gpio.</span><span>output</span><span>(bl, </span></span><span>1</span><span>)</span></div></div><div><div><div>143</div></div><div><span>        </span><span>if</span><span> </span><span>self</span><span>._rst </span><span>is</span><span> </span><span>not</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>144</div></div><div><span>            </span><span>self</span><span><span>._gpio.</span><span>setup</span><span>(</span></span><span>self</span><span><span>._rst, </span><span>GPIO</span><span>.</span><span>OUT</span><span>)</span></span></div></div><div><div><div>145</div></div><div><span>        </span><span># Default to bit bang SPI.</span></div></div><div><div><div>146</div></div><div><span>        </span><span>if</span><span> </span><span>self</span><span>._spi </span><span>is</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>147</div></div><div><span>            </span><span>self</span><span><span>._spi </span><span>=</span><span> </span><span>SPI</span><span>.</span><span>BitBang</span><span>(</span></span><span>self</span><span>._gpio, </span><span>self</span><span>._sclk, </span><span>self</span><span>._din, </span><span>None</span><span>, </span><span>self</span><span>._cs)</span></div></div><div><div><div>148</div></div><div><span>        </span><span># Set pin outputs.</span></div></div><div><div><div>149</div></div><div><span>        </span><span>self</span><span><span>._gpio.</span><span>setup</span><span>(</span></span><span>self</span><span><span>._dc, </span><span>GPIO</span><span>.</span><span>OUT</span><span>)</span></span></div></div><div><div><div>150</div></div><div><span>        </span><span># Initialize buffer to Adafruit logo.</span></div></div><div><div><div>151</div></div><div>
</div></div><div><div><div>152</div></div><div><span>    </span><span>def</span><span> </span><span>command</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>c</span></span><span>):</span></div></div><div><div><div>153</div></div><div><span>        </span><span>"""Send command byte to display."""</span></div></div><div><div><div>154</div></div><div><span>        </span><span># DC pin low signals command byte.</span></div></div><div><div><div>155</div></div><div><span>        </span><span>self</span><span><span>._gpio.</span><span>set_low</span><span>(</span></span><span>self</span><span>._dc)</span></div></div><div><div><div>156</div></div><div><span>        </span><span>self</span><span><span>._spi.</span><span>write</span><span>([c])</span></span></div></div><div><div><div>157</div></div><div>
</div></div><div><div><div>158</div></div><div><span>    </span><span>def</span><span> </span><span>extended_command</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>c</span></span><span>):</span></div></div><div><div><div>159</div></div><div><span>        </span><span>"""Send a command in extended mode"""</span></div></div><div><div><div>160</div></div><div><span>        </span><span># Set extended command mode</span></div></div><div><div><div>161</div></div><div><span>        </span><span>self</span><span><span>.</span><span>command</span><span>(</span><span>PCD8544_FUNCTIONSET</span><span> </span><span>|</span><span> </span><span>PCD8544_EXTENDEDINSTRUCTION</span><span>)</span></span></div></div><div><div><div>162</div></div><div><span>        </span><span>self</span><span><span>.</span><span>command</span><span>(c)</span></span></div></div><div><div><div>163</div></div><div><span>        </span><span># Set normal display mode.</span></div></div><div><div><div>164</div></div><div><span>        </span><span>self</span><span><span>.</span><span>command</span><span>(</span><span>PCD8544_FUNCTIONSET</span><span>)</span></span></div></div><div><div><div>165</div></div><div><span>        </span><span>self</span><span><span>.</span><span>command</span><span>(</span><span>PCD8544_DISPLAYCONTROL</span><span> </span><span>|</span><span> </span><span>PCD8544_DISPLAYNORMAL</span><span>)</span></span></div></div><div><div><div>166</div></div><div>
</div></div><div><div><div>167</div></div><div><span>    </span><span>def</span><span> </span><span>begin</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>contrast</span></span><span>=</span><span>40</span><span>,</span><span><span> </span><span>bias</span></span><span>=</span><span>4</span><span>):</span></div></div><div><div><div>168</div></div><div><span>        </span><span>"""Initialize display."""</span></div></div><div><div><div>169</div></div><div><span>        </span><span>self</span><span><span>.</span><span>reset</span><span>()</span></span></div></div><div><div><div>170</div></div><div><span>        </span><span># Set LCD bias.</span></div></div><div><div><div>171</div></div><div><span>        </span><span>self</span><span><span>.</span><span>set_bias</span><span>(bias)</span></span></div></div><div><div><div>172</div></div><div><span>        </span><span>self</span><span><span>.</span><span>set_contrast</span><span>(contrast)</span></span></div></div><div><div><div>173</div></div><div>
</div></div><div><div><div>174</div></div><div><span>    </span><span>def</span><span> </span><span>reset</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>175</div></div><div><span>        </span><span>"""Reset the display"""</span></div></div><div><div><div>176</div></div><div><span>        </span><span>if</span><span> </span><span>self</span><span>._rst </span><span>is</span><span> </span><span>not</span><span> </span><span>None</span><span>:</span></div></div><div><div><div>177</div></div><div><span>            </span><span># Toggle RST low to reset.</span></div></div><div><div><div>178</div></div><div><span>            </span><span>self</span><span><span>._gpio.</span><span>set_low</span><span>(</span></span><span>self</span><span>._rst)</span></div></div><div><div><div>179</div></div><div><span><span>            </span></span><span>time.</span><span>sleep</span><span>(</span><span>0.1</span><span>)</span></div></div><div><div><div>180</div></div><div><span>            </span><span>self</span><span><span>._gpio.</span><span>set_high</span><span>(</span></span><span>self</span><span>._rst)</span></div></div><div><div><div>181</div></div><div>
</div></div><div><div><div>182</div></div><div><span>    </span><span>def</span><span> </span><span>display</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>183</div></div><div><span>        </span><span>"""Write display buffer to physical display."""</span></div></div><div><div><div>184</div></div><div><span>        </span><span># </span><span>TODO</span><span>: Consider support for partial updates like Arduino library.</span></div></div><div><div><div>185</div></div><div><span>        </span><span># Reset to position zero.</span></div></div><div><div><div>186</div></div><div><span>        </span><span>self</span><span><span>.</span><span>command</span><span>(</span><span>PCD8544_SETYADDR</span><span>)</span></span></div></div><div><div><div>187</div></div><div><span>        </span><span>self</span><span><span>.</span><span>command</span><span>(</span><span>PCD8544_SETXADDR</span><span>)</span></span></div></div><div><div><div>188</div></div><div><span>        </span><span># Write the buffer.</span></div></div><div><div><div>189</div></div><div><span>        </span><span>self</span><span><span>._gpio.</span><span>set_high</span><span>(</span></span><span>self</span><span>._dc)</span></div></div><div><div><div>190</div></div><div><span>        </span><span>self</span><span><span>._spi.</span><span>write</span><span>(</span></span><span>self</span><span>._buffer)</span></div></div><div><div><div>191</div></div><div>
</div></div><div><div><div>192</div></div><div><span>    </span><span>def</span><span> </span><span>clear</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>193</div></div><div><span>        </span><span>"""Clear contents of image buffer."""</span></div></div><div><div><div>194</div></div><div><span>        </span><span>self</span><span><span>._buffer </span><span>=</span><span> [</span></span><span>0</span><span><span>] </span><span>*</span><span> (</span><span>LCDWIDTH</span><span> </span><span>*</span><span> </span><span>LCDHEIGHT</span><span> </span><span>//</span><span> </span></span><span>8</span><span>)</span></div></div><div><div><div>195</div></div><div>
</div></div><div><div><div>196</div></div><div><span>    </span><span>def</span><span> </span><span>set_contrast</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>contrast</span></span><span>):</span></div></div><div><div><div>197</div></div><div><span>        </span><span>"""Set contrast to specified value (should be 0-127)."""</span></div></div><div><div><div>198</div></div><div><span><span>        </span></span><span>contrast </span><span>=</span><span> </span><span>max</span><span>(</span><span>0</span><span>, </span><span>min</span><span>(contrast, </span><span>0x</span><span>7f</span><span>)) </span><span># Clamp to values 0-0x7f</span></div></div><div><div><div>199</div></div><div><span>        </span><span>self</span><span><span>.</span><span>extended_command</span><span>(</span><span>PCD8544_SETVOP</span><span> </span><span>|</span><span> contrast)</span></span></div></div><div><div><div>200</div></div><div>
</div></div><div><div><div>201</div></div><div><span>    </span><span>def</span><span> </span><span>set_bias</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>bias</span></span><span>):</span></div></div><div><div><div>202</div></div><div><span>        </span><span>"""Set bias"""</span></div></div><div><div><div>203</div></div><div><span>        </span><span>self</span><span><span>.</span><span>extended_command</span><span>(</span><span>PCD8544_SETBIAS</span><span> </span><span>|</span><span> bias)</span></span></div></div><div><div><div>204</div></div><div>
</div></div><div><div><div>205</div></div><div><span>    </span><span>def</span><span> </span><span>draw_str</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>y</span></span><span>,</span><span><span> </span><span>s</span></span><span>):</span></div></div><div><div><div>206</div></div><div><span>        </span><span>"""修改显示数据，y 为第几行，s 为要显示的数据"""</span></div></div><div><div><div>207</div></div><div><span>        </span><span>if</span><span><span> (y </span><span>&gt;=</span><span> Y ) </span></span><span>or</span><span><span> (y </span><span>&lt;</span><span> </span></span><span>0</span><span>):</span></div></div><div><div><div>208</div></div><div><span>            </span><span>return</span><span> </span><span>False</span></div></div><div><div><div>209</div></div><div><span><span>        </span></span><span>x </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>210</div></div><div><span>        </span><span>for</span><span> c </span><span>in</span><span> s[</span><span>0</span><span>:</span><span>14</span><span>]:</span></div></div><div><div><div>211</div></div><div><span>            </span><span>try</span><span>:</span></div></div><div><div><div>212</div></div><div><span>                </span><span>self</span><span><span>._buffer[y</span><span>*</span></span><span>84</span><span><span>+</span><span>x</span><span>*</span></span><span>6</span><span><span>: y</span><span>*</span></span><span>84</span><span><span>+</span><span>x</span><span>*</span></span><span>6</span><span><span> </span><span>+</span><span> </span></span><span>6</span><span><span>] </span><span>=</span><span> </span><span>FONT</span><span>[c] </span><span>+</span><span> [</span></span><span>0</span><span>]</span></div></div><div><div><div>213</div></div><div><span>            </span><span>except</span><span> </span><span>KeyError</span><span>:</span></div></div><div><div><div>214</div></div><div><span>                </span><span>pass</span></div></div><div><div><div>215</div></div><div><span><span>            </span></span><span>x </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>216</div></div><div>
</div></div><div><div><div>217</div></div><div><span>    </span><span>def</span><span> </span><span>draw_char</span><span>(</span><span>self</span><span>,</span><span><span> </span><span>x</span></span><span>,</span><span><span> </span><span>y</span></span><span>):</span></div></div><div><div><div>218</div></div><div><span>        </span><span>pass</span></div></div><div><div><div>219</div></div><div>
</div></div><div><div><div>220</div></div><div><span>    </span><span>def</span><span> </span><span>quit</span><span>(</span><span>self</span><span>):</span></div></div><div><div><div>221</div></div><div><span>        </span><span>self</span><span><span>._gpio.</span><span>cleanup</span><span>()</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<p>使用方法：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>from</span><span><span> </span><span>PCD8544</span><span> </span></span><span>import</span><span><span> </span><span>PCD8544</span><span> </span></span><span>as</span><span> lcd</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span><span>a </span><span>=</span><span> </span><span>lcd</span><span>(</span></span><span>dc</span><span>=</span><span>13</span><span>, </span><span>rst</span><span>=</span><span>5</span><span>, </span><span>sclk</span><span>=</span><span>26</span><span>, </span><span>din</span><span>=</span><span>19</span><span>, </span><span>cs</span><span>=</span><span>6</span><span>, </span><span>vcc</span><span>=</span><span>20</span><span>, </span><span>bl</span><span>=</span><span>21</span><span>, </span><span>bk</span><span>=</span><span>1</span><span><span>)       </span><span>//</span><span>bk为0时关闭背景灯</span></span></div></div><div><div><div>4</div></div><div><span><span>a.</span><span>begin</span><span>(</span></span><span>contrast</span><span>=</span><span>60</span><span>)</span></div></div><div><div><div>5</div></div><div><span><span>a.</span><span>draw_str</span><span>(</span></span><span>0</span><span>,</span><span>"hello"</span><span>)</span></div></div><div><div><div>6</div></div><div><span><span>a.</span><span>draw_str</span><span>(</span></span><span>1</span><span>,</span><span>"hi"</span><span><span>)                </span><span>//</span><span>最多5行</span></span></div></div><div><div><div>7</div></div><div><span><span>a.</span><span>display</span><span>()                       </span><span>//</span><span>显示</span></span></div></div><div><div><div>8</div></div><div><span><span>a.</span><span>clear</span><span>()                         每次显示新的前要清除旧的</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/91/</id>
      <title type="text">OkHttp封装</title>
      <published>2018-06-21T00:00:00.000Z</published>
      <updated>2019-10-24T04:20:13.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/91/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/**</span></div></div><div><div><div>2</div></div><div><span><span> </span></span><span>* Okhttp封装</span></div></div><div><div><div>3</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>4</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>OkhttpNet</span><span> </span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>    </span><span>private</span><span> </span><span>static</span><span> </span><span>OkHttpClient</span><span> client </span><span><span>=</span><span> </span></span><span>null</span><span>;</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>    </span><span>private</span><span> </span><span>OkhttpNet</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>OkHttpClient</span><span> </span><span>getInstance</span><span><span>()</span><span> </span><span>{</span></span></div></div><div><div><div>11</div></div><div><span>        </span><span>if</span><span><span> (client </span><span>==</span><span> </span></span><span>null</span><span>) {</span></div></div><div><div><div>12</div></div><div><span>            </span><span>synchronized</span><span> (</span><span>OkhttpNet</span><span>.</span><span>class</span><span>) {</span></div></div><div><div><div>13</div></div><div><span>                </span><span>if</span><span><span> (client </span><span>==</span><span> </span></span><span>null</span><span>)</span></div></div><div><div><div>14</div></div><div><span><span>                    </span></span><span>client </span><span>=</span><span> </span><span>new</span><span> </span><span>OkHttpClient</span><span>();</span></div></div><div><div><div>15</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>17</div></div><div><span>        </span><span>return</span><span> client;</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>/**</span></div></div><div><div><div>21</div></div><div><span><span>     </span></span><span>* Get请求</span></div></div><div><div><div>22</div></div><div><span><span>     </span></span><span>*</span></div></div><div><div><div>23</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>url</span></div></div><div><div><div>24</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>callback</span></div></div><div><div><div>25</div></div><div><span><span>     </span></span><span>*/</span></div></div><div><div><div>26</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>doGet</span><span>(</span><span>String</span><span><span> </span><span>url</span><span>, </span></span><span>Callback</span><span><span> </span><span>callback</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>27</div></div><div><span>        </span><span>Request</span><span><span> </span><span>request</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> Request.</span><span>Builder</span><span>()</span></div></div><div><div><div>28</div></div><div><span><span>                </span></span><span>.</span><span>url</span><span>(url)</span></div></div><div><div><div>29</div></div><div><span><span>                </span></span><span>.</span><span>build</span><span>();</span></div></div><div><div><div>30</div></div><div><span>        </span><span>Call</span><span><span> </span><span>call</span><span> </span></span><span><span>=</span><span> </span></span><span>getInstance</span><span>().</span><span>newCall</span><span>(request);</span></div></div><div><div><div>31</div></div><div><span>        </span><span>call</span><span>.</span><span>enqueue</span><span>(callback);</span></div></div><div><div><div>32</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>/**</span></div></div><div><div><div>35</div></div><div><span><span>     </span></span><span>* Post请求发送键值对数据</span></div></div><div><div><div>36</div></div><div><span><span>     </span></span><span>*</span></div></div><div><div><div>37</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>url</span></div></div><div><div><div>38</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>mapParams</span></div></div><div><div><div>39</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>callback</span></div></div><div><div><div>40</div></div><div><span><span>     </span></span><span>*/</span></div></div><div><div><div>41</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>doPost</span><span>(</span><span>String</span><span><span> </span><span>url</span><span>, </span></span><span>Map</span><span><span> </span><span>mapParams</span><span>, </span></span><span>Callback</span><span><span> </span><span>callback</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>42</div></div><div><span>        </span><span>FormBody</span><span>.</span><span>Builder</span><span><span> </span><span>builder</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> FormBody.</span><span>Builder</span><span>();</span></div></div><div><div><div>43</div></div><div><span>        </span><span>for</span><span> (</span><span>String</span><span><span> </span><span>key</span><span> </span></span><span>:</span><span> </span><span>mapParams</span><span>.</span><span>keySet</span><span>()) {</span></div></div><div><div><div>44</div></div><div><span>            </span><span>builder</span><span>.</span><span>add</span><span>(key, </span><span>mapParams</span><span>.</span><span>get</span><span>(key));</span></div></div><div><div><div>45</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>46</div></div><div><span>        </span><span>Request</span><span><span> </span><span>request</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> Request.</span><span>Builder</span><span>()</span></div></div><div><div><div>47</div></div><div><span><span>                </span></span><span>.</span><span>url</span><span>(url)</span></div></div><div><div><div>48</div></div><div><span><span>                </span></span><span>.</span><span>post</span><span>(</span><span>builder</span><span>.</span><span>build</span><span>())</span></div></div><div><div><div>49</div></div><div><span><span>                </span></span><span>.</span><span>build</span><span>();</span></div></div><div><div><div>50</div></div><div><span>        </span><span>Call</span><span><span> </span><span>call</span><span> </span></span><span><span>=</span><span> </span></span><span>getInstance</span><span>().</span><span>newCall</span><span>(request);</span></div></div><div><div><div>51</div></div><div><span>        </span><span>call</span><span>.</span><span>enqueue</span><span>(callback);</span></div></div><div><div><div>52</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>53</div></div><div>
</div></div><div><div><div>54</div></div><div>
</div></div><div><div><div>55</div></div><div><span><span>    </span></span><span>/**</span></div></div><div><div><div>56</div></div><div><span><span>     </span></span><span>* Post请求发送JSON数据</span></div></div><div><div><div>57</div></div><div><span><span>     </span></span><span>*</span></div></div><div><div><div>58</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>url</span></div></div><div><div><div>59</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>jsonParams</span></div></div><div><div><div>60</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>callback</span></div></div><div><div><div>61</div></div><div><span><span>     </span></span><span>*/</span></div></div><div><div><div>62</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>doPost</span><span>(</span><span>String</span><span><span> </span><span>url</span><span>, </span></span><span>String</span><span><span> </span><span>jsonParams</span><span>, </span></span><span>Callback</span><span><span> </span><span>callback</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>63</div></div><div><span>        </span><span>RequestBody</span><span><span> </span><span>body</span><span> </span></span><span><span>=</span><span> </span></span><span>RequestBody</span><span>.</span><span>create</span><span>(</span><span>MediaType</span><span>.</span><span>parse</span><span>(</span><span>"application/json; charset=utf-8"</span><span>)</span></div></div><div><div><div>64</div></div><div><span><span>                </span></span><span>, jsonParams);</span></div></div><div><div><div>65</div></div><div><span>        </span><span>Request</span><span><span> </span><span>request</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> Request.</span><span>Builder</span><span>()</span></div></div><div><div><div>66</div></div><div><span><span>                </span></span><span>.</span><span>url</span><span>(url)</span></div></div><div><div><div>67</div></div><div><span><span>                </span></span><span>.</span><span>post</span><span>(body)</span></div></div><div><div><div>68</div></div><div><span><span>                </span></span><span>.</span><span>build</span><span>();</span></div></div><div><div><div>69</div></div><div><span>        </span><span>Call</span><span><span> </span><span>call</span><span> </span></span><span><span>=</span><span> </span></span><span>getInstance</span><span>().</span><span>newCall</span><span>(request);</span></div></div><div><div><div>70</div></div><div><span>        </span><span>call</span><span>.</span><span>enqueue</span><span>(callback);</span></div></div><div><div><div>71</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>72</div></div><div>
</div></div><div><div><div>73</div></div><div>
</div></div><div><div><div>74</div></div><div><span><span>    </span></span><span>/**</span></div></div><div><div><div>75</div></div><div><span><span>     </span></span><span>* 上传文件</span></div></div><div><div><div>76</div></div><div><span><span>     </span></span><span>*</span></div></div><div><div><div>77</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>url</span></div></div><div><div><div>78</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>callback</span></div></div><div><div><div>79</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>map</span><span>           上传文件，map值：file///文件路径</span></div></div><div><div><div>80</div></div><div><span><span>     </span></span><span>*/</span></div></div><div><div><div>81</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>doFile</span><span>(</span><span>String</span><span><span> </span><span>url</span><span>, </span></span><span>Map</span><span><span> </span><span>map</span><span>, </span></span><span>Callback</span><span><span> </span><span>callback</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>82</div></div><div>
</div></div><div><div><div>83</div></div><div><span>        </span><span>//创建文件参数</span></div></div><div><div><div>84</div></div><div><span>        </span><span>MultipartBody</span><span>.</span><span>Builder</span><span><span> </span><span>builder</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> MultipartBody.</span><span>Builder</span><span>()</span></div></div><div><div><div>85</div></div><div><span><span>                </span></span><span>.</span><span>setType</span><span>(</span><span>MultipartBody</span><span>.</span><span>FORM</span><span>);</span></div></div><div><div><div>86</div></div><div><span>        </span><span>if</span><span><span> (map </span><span>!=</span><span> </span></span><span>null</span><span>) {</span></div></div><div><div><div>87</div></div><div><span>            </span><span>for</span><span> (</span><span>String</span><span><span> </span><span>key</span><span> </span></span><span>:</span><span> </span><span>map</span><span>.</span><span>keySet</span><span>()) {</span></div></div><div><div><div>88</div></div><div>
</div></div><div><div><div>89</div></div><div><span>                </span><span>Pattern</span><span><span> </span><span>pattern</span><span> </span></span><span><span>=</span><span> </span></span><span>Pattern</span><span>.</span><span>compile</span><span>(</span><span>"^file///"</span><span>);</span></div></div><div><div><div>90</div></div><div><span>                    </span><span>Matcher</span><span><span> </span><span>matcher</span><span> </span></span><span><span>=</span><span> </span></span><span>pattern</span><span>.</span><span>matcher</span><span>(</span><span>map</span><span>.</span><span>get</span><span>(key));</span></div></div><div><div><div>91</div></div><div><span>                    </span><span>//判断是否是要上传文件</span></div></div><div><div><div>92</div></div><div><span>                    </span><span>if</span><span> (</span><span>matcher</span><span>.</span><span>find</span><span>()) {</span></div></div><div><div><div>93</div></div><div><span>                        </span><span>String</span><span><span>[] </span><span>path</span><span> </span></span><span><span>=</span><span> </span></span><span>map</span><span>.</span><span>get</span><span>(key).</span><span>split</span><span>(</span><span>"file///"</span><span>);</span></div></div><div><div><div>94</div></div><div><span>                        </span><span>String</span><span><span> </span><span>filePath</span><span> </span></span><span><span>=</span><span> path[</span></span><span>1</span><span>];</span></div></div><div><div><div>95</div></div><div><span>                        </span><span>String</span><span><span>[] </span><span>fileName</span><span> </span></span><span><span>=</span><span> </span></span><span>filePath</span><span>.</span><span>split</span><span>(</span><span>"/"</span><span>);</span></div></div><div><div><div>96</div></div><div><span>                        </span><span>//判断文件类型</span></div></div><div><div><div>97</div></div><div><span>                        </span><span>MediaType</span><span><span> </span><span>MEDIA_TYPE</span><span> </span></span><span><span>=</span><span> </span></span><span>MediaType</span><span>.</span><span>parse</span><span>(</span><span>judgeType</span><span>(filePath));</span></div></div><div><div><div>98</div></div><div><span>                        </span><span>builder</span><span>.</span><span>addFormDataPart</span><span>(key, fileName[</span><span>fileName</span><span>.</span><span>length</span><span><span> </span><span>-</span><span> </span></span><span>1</span><span>],</span></div></div><div><div><div>99</div></div><div><span>                                </span><span>RequestBody</span><span>.</span><span>create</span><span>(MEDIA_TYPE, </span><span>new</span><span> </span><span>File</span><span>(filePath)));</span></div></div><div><div><div>100</div></div><div><span><span>                </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>101</div></div><div><span>                    </span><span>builder</span><span>.</span><span>addFormDataPart</span><span>(key, </span><span>map</span><span>.</span><span>get</span><span>(key));</span></div></div><div><div><div>102</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>103</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>104</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>105</div></div><div>
</div></div><div><div><div>106</div></div><div><span>        </span><span>//发出请求参数</span></div></div><div><div><div>107</div></div><div><span>        </span><span>Request</span><span><span> </span><span>request</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> Request.</span><span>Builder</span><span>()</span></div></div><div><div><div>108</div></div><div><span>//                .header("Authorization", "Client-ID " + "9199fdef135c122")</span></div></div><div><div><div>109</div></div><div><span><span>                </span></span><span>.</span><span>url</span><span>(url)</span></div></div><div><div><div>110</div></div><div><span><span>                </span></span><span>.</span><span>post</span><span>(</span><span>builder</span><span>.</span><span>build</span><span>())</span></div></div><div><div><div>111</div></div><div><span><span>                </span></span><span>.</span><span>build</span><span>();</span></div></div><div><div><div>112</div></div><div><span>        </span><span>Call</span><span><span> </span><span>call</span><span> </span></span><span><span>=</span><span> </span></span><span>getInstance</span><span>().</span><span>newCall</span><span>(request);</span></div></div><div><div><div>113</div></div><div><span>        </span><span>call</span><span>.</span><span>enqueue</span><span>(callback);</span></div></div><div><div><div>114</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>115</div></div><div>
</div></div><div><div><div>116</div></div><div><span><span>    </span></span><span>/**</span></div></div><div><div><div>117</div></div><div><span><span>     </span></span><span>* 根据文件路径判断MediaType</span></div></div><div><div><div>118</div></div><div><span><span>     </span></span><span>*</span></div></div><div><div><div>119</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>path</span></div></div><div><div><div>120</div></div><div><span><span>     </span></span><span>* </span><span>@return</span></div></div><div><div><div>121</div></div><div><span><span>     </span></span><span>*/</span></div></div><div><div><div>122</div></div><div><span>    </span><span>private</span><span> </span><span>static</span><span> </span><span>String</span><span> </span><span>judgeType</span><span>(</span><span>String</span><span><span> </span><span>path</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>123</div></div><div><span>        </span><span>FileNameMap</span><span><span> </span><span>fileNameMap</span><span> </span></span><span><span>=</span><span> </span></span><span>URLConnection</span><span>.</span><span>getFileNameMap</span><span>();</span></div></div><div><div><div>124</div></div><div><span>        </span><span>String</span><span><span> </span><span>contentTypeFor</span><span> </span></span><span><span>=</span><span> </span></span><span>fileNameMap</span><span>.</span><span>getContentTypeFor</span><span>(path);</span></div></div><div><div><div>125</div></div><div><span>        </span><span>if</span><span><span> (contentTypeFor </span><span>==</span><span> </span></span><span>null</span><span>) {</span></div></div><div><div><div>126</div></div><div><span><span>            </span></span><span>contentTypeFor </span><span>=</span><span> </span><span>"application/octet-stream"</span><span>;</span></div></div><div><div><div>127</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>128</div></div><div><span>        </span><span>return</span><span> contentTypeFor;</span></div></div><div><div><div>129</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>130</div></div><div>
</div></div><div><div><div>131</div></div><div>
</div></div><div><div><div>132</div></div><div><span><span>    </span></span><span>/**</span></div></div><div><div><div>133</div></div><div><span><span>     </span></span><span>* 下载文件</span></div></div><div><div><div>134</div></div><div><span><span>     </span></span><span>*</span></div></div><div><div><div>135</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>url</span></div></div><div><div><div>136</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>fileDir</span></div></div><div><div><div>137</div></div><div><span><span>     </span></span><span>* </span><span>@param</span><span> </span><span>fileName</span></div></div><div><div><div>138</div></div><div><span><span>     </span></span><span>*/</span></div></div><div><div><div>139</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>void</span><span> </span><span>downFile</span><span>(</span><span>String</span><span><span> </span><span>url</span><span>, </span></span><span>final</span><span> </span><span>String</span><span><span> </span><span>fileDir</span><span>, </span></span><span>final</span><span> </span><span>String</span><span><span> </span><span>fileName</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>140</div></div><div><span>        </span><span>Request</span><span><span> </span><span>request</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> Request.</span><span>Builder</span><span>()</span></div></div><div><div><div>141</div></div><div><span><span>                </span></span><span>.</span><span>url</span><span>(url)</span></div></div><div><div><div>142</div></div><div><span><span>                </span></span><span>.</span><span>build</span><span>();</span></div></div><div><div><div>143</div></div><div><span>        </span><span>Call</span><span><span> </span><span>call</span><span> </span></span><span><span>=</span><span> </span></span><span>getInstance</span><span>().</span><span>newCall</span><span>(request);</span></div></div><div><div><div>144</div></div><div><span>        </span><span>call</span><span>.</span><span>enqueue</span><span>(</span><span>new</span><span> </span><span>Callback</span><span>() {</span></div></div><div><div><div>145</div></div><div><span><span>            </span></span><span>@</span><span>Override</span></div></div><div><div><div>146</div></div><div><span>            </span><span>public</span><span> </span><span>void</span><span> </span><span>onFailure</span><span>(</span><span>Call</span><span><span> </span><span>call</span><span>, </span></span><span>IOException</span><span><span> </span><span>e</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>147</div></div><div>
</div></div><div><div><div>148</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>149</div></div><div>
</div></div><div><div><div>150</div></div><div><span><span>            </span></span><span>@</span><span>Override</span></div></div><div><div><div>151</div></div><div><span>            </span><span>public</span><span> </span><span>void</span><span> </span><span>onResponse</span><span>(</span><span>Call</span><span><span> </span><span>call</span><span>, </span></span><span>Response</span><span><span> </span><span>response</span><span>)</span><span> </span></span><span>throws</span><span> </span><span>IOException</span><span><span> </span><span>{</span></span></div></div><div><div><div>152</div></div><div><span>                </span><span>InputStream</span><span><span> </span><span>is</span><span> </span></span><span><span>=</span><span> </span></span><span>null</span><span>;</span></div></div><div><div><div>153</div></div><div><span>                </span><span>byte</span><span><span>[] </span><span>buf</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>byte</span><span>[</span><span>2048</span><span>];</span></div></div><div><div><div>154</div></div><div><span>                </span><span>int</span><span><span> </span><span>len</span><span> </span></span><span><span>=</span><span> </span></span><span>0</span><span>;</span></div></div><div><div><div>155</div></div><div><span>                </span><span>FileOutputStream</span><span><span> </span><span>fos</span><span> </span></span><span><span>=</span><span> </span></span><span>null</span><span>;</span></div></div><div><div><div>156</div></div><div><span>                </span><span>try</span><span> {</span></div></div><div><div><div>157</div></div><div><span><span>                    </span></span><span>is </span><span>=</span><span> </span><span>response</span><span>.</span><span>body</span><span>().</span><span>byteStream</span><span>();</span></div></div><div><div><div>158</div></div><div><span>                    </span><span>File</span><span><span> </span><span>file</span><span> </span></span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>File</span><span>(fileDir, fileName);</span></div></div><div><div><div>159</div></div><div><span><span>                    </span></span><span>fos </span><span>=</span><span> </span><span>new</span><span> </span><span>FileOutputStream</span><span>(file);</span></div></div><div><div><div>160</div></div><div><span>                    </span><span>while</span><span><span> ((len </span><span>=</span><span> </span></span><span>is</span><span>.</span><span>read</span><span><span>(buf)) </span><span>!=</span><span> </span><span>-</span></span><span>1</span><span>) {</span></div></div><div><div><div>161</div></div><div><span>                        </span><span>fos</span><span>.</span><span>write</span><span>(buf, </span><span>0</span><span>, len);</span></div></div><div><div><div>162</div></div><div><span><span>                    </span></span><span>}</span></div></div><div><div><div>163</div></div><div><span>                    </span><span>fos</span><span>.</span><span>flush</span><span>();</span></div></div><div><div><div>164</div></div><div><span><span>                </span></span><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>165</div></div><div><span>                    </span><span>e</span><span>.</span><span>printStackTrace</span><span>();</span></div></div><div><div><div>166</div></div><div><span><span>                </span></span><span>} </span><span>finally</span><span> {</span></div></div><div><div><div>167</div></div><div><span>                    </span><span>if</span><span><span> (is </span><span>!=</span><span> </span></span><span>null</span><span>) </span><span>is</span><span>.</span><span>close</span><span>();</span></div></div><div><div><div>168</div></div><div><span>                    </span><span>if</span><span><span> (fos </span><span>!=</span><span> </span></span><span>null</span><span>) </span><span>fos</span><span>.</span><span>close</span><span>();</span></div></div><div><div><div>169</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>170</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>171</div></div><div><span>            </span><span>//获取进度条</span></div></div><div><div><div>172</div></div><div><span>//            @Override</span></div></div><div><div><div>173</div></div><div><span>//            public void onResponse(Call call, Response response) throws IOException {</span></div></div><div><div><div>174</div></div><div><span>//                InputStream is = null;</span></div></div><div><div><div>175</div></div><div><span>//                byte[] buf = new byte[2048];</span></div></div><div><div><div>176</div></div><div><span>//                int len = 0;</span></div></div><div><div><div>177</div></div><div><span>//                FileOutputStream fos = null;</span></div></div><div><div><div>178</div></div><div><span>//                try {</span></div></div><div><div><div>179</div></div><div><span>//                    is = response.body().byteStream();</span></div></div><div><div><div>180</div></div><div><span>//                    File file = new File(fileDir, fileName);</span></div></div><div><div><div>181</div></div><div><span>//                    fos = new FileOutputStream(file);</span></div></div><div><div><div>182</div></div><div><span>//                    //---增加的代码---</span></div></div><div><div><div>183</div></div><div><span>//                    //计算进度</span></div></div><div><div><div>184</div></div><div><span>//                    long totalSize = response.body().contentLength();</span></div></div><div><div><div>185</div></div><div><span>//                    long sum = 0;</span></div></div><div><div><div>186</div></div><div><span>//                    while ((len = is.read(buf)) != -1) {</span></div></div><div><div><div>187</div></div><div><span>//                        sum += len;</span></div></div><div><div><div>188</div></div><div><span>//                        //progress就是进度值</span></div></div><div><div><div>189</div></div><div><span>//                        int progress = (int) (sum * 1.0f/totalSize * 100);</span></div></div><div><div><div>190</div></div><div><span>//                        //---增加的代码---</span></div></div><div><div><div>191</div></div><div><span>//                        fos.write(buf, 0, len);</span></div></div><div><div><div>192</div></div><div><span>//                    }</span></div></div><div><div><div>193</div></div><div><span>//                    fos.flush();</span></div></div><div><div><div>194</div></div><div><span>//                } catch (IOException e) {</span></div></div><div><div><div>195</div></div><div><span>//                    e.printStackTrace();</span></div></div><div><div><div>196</div></div><div><span>//                } finally {</span></div></div><div><div><div>197</div></div><div><span>//                    if (is != null) is.close();</span></div></div><div><div><div>198</div></div><div><span>//                    if (fos != null) fos.close();</span></div></div><div><div><div>199</div></div><div><span>//                }</span></div></div><div><div><div>200</div></div><div><span>//            }</span></div></div><div><div><div>201</div></div><div><span><span>        </span></span><span>});</span></div></div><div><div><div>202</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>203</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/92/</id>
      <title type="text">Android Dialog回传</title>
      <published>2018-06-21T00:00:00.000Z</published>
      <updated>2019-10-24T06:28:31.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/92/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>MyDialog</span><span>.</span><span>java</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>//定义一个接口</span></div></div><div><div><div>4</div></div><div><span>public</span><span> </span><span>interface</span><span><span> </span><span>chuang</span></span><span>{</span></div></div><div><div><div>5</div></div><div><span>        </span><span>public</span><span> </span><span>void</span><span> </span><span>chuang</span><span>(</span><span>String</span><span><span> </span><span>string</span><span>);</span></span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>chuang chuang</span><span>;</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>public</span><span> </span><span>MyDialog</span><span><span>(</span><span>@</span></span><span>NonNull</span><span> </span><span>Context</span><span><span> context</span><span>,</span><span>chuang chuang) {</span></span></div></div><div><div><div>10</div></div><div><span>    </span><span>super</span><span><span>(context)</span><span>;</span></span></div></div><div><div><div>11</div></div><div><span>    </span><span>this</span><span>.</span><span>chuang</span><span><span>=</span><span>chuang</span><span>;</span></span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>public</span><span> </span><span>void</span><span> </span><span>test</span><span>(){</span></div></div><div><div><div>15</div></div><div><span>    </span><span>chuang</span><span>.</span><span>chuang</span><span>(</span><span>"asd"</span><span>);</span></div></div><div><div><div>16</div></div><div><span><span> </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>MainActivity</span><span>.</span><span>java</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>...</span></div></div><div><div><div>4</div></div><div><span>new</span><span> </span><span>MyDialog</span><span>(</span><span>this</span><span><span>,</span><span> </span></span><span>new</span><span><span> MyDialog</span><span>.</span></span><span>chuang</span><span><span>()</span><span> {</span></span></div></div><div><div><div>5</div></div><div><span><span>            </span></span><span>@</span><span>Override</span></div></div><div><div><div>6</div></div><div><span>            </span><span>public</span><span> </span><span>void</span><span> </span><span>chuang</span><span>(</span><span>String</span><span> string) {</span></div></div><div><div><div>7</div></div><div><span>                </span><span>Log</span><span>.</span><span>i</span><span>(</span><span>"chuang"</span><span>,string);</span></div></div><div><div><div>8</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>9</div></div><div><span><span>        </span></span><span>})</span><span>.</span><span>show</span><span>();</span></div></div><div><div><div>10</div></div><div><span>...</span></div></div></code></pre><div><div></div><div></div></div></figure></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/93/</id>
      <title type="text">Linux下对设备进行压力测试</title>
      <published>2018-06-21T00:00:00.000Z</published>
      <updated>2019-10-24T06:30:06.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/93/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<h1>0x00</h1>
<p>使用sysbench进行测试</p>
<p>安装：<code>apt install sysbench</code></p>
<h1>0x01一般语法</h1>
<p><code>prepare</code>&lt;用于文件io和数据库oltp测试的数据准备阶段&gt;。</p>
<p><code>run</code>&lt;性能测试阶段&gt;</p>
<p><code>cleanup</code>&lt;移除测试过程中产生的数据&gt;</p>
<p><code>help</code>&lt;显示帮助信息&gt;，获取—test帮助可以使用—test=name —help</p>
<h3>主要参数</h3>
<p><code>—num-threads</code></p>
<p><code>—max-requests</code></p>
<p><code>—test</code></p>
<p>以下几个参数也经常会使用：</p>
<p><code>—max-time</code> 最大的测试时长</p>
<p><code>—debug</code>(开启debug可以显示更详细的每个线程的执行情况)</p>
<h1>0x02测试</h1>
<h3>cpu测试</h3>
<p>对CPU的性能测试通常有：1. 通过算质数；2计算圆周率等；sysbench使用的就是通过质数相加的测试。对CPU测试直接运行run即可</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=10000</span><span> </span><span>--debug=on</span><span> </span><span>--test=cpu</span><span> </span><span>--cpu-max-prime=20000</span><span> </span><span>run</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>上面的测试是：12个线程执行1万条请求，每个请求执行质数相加到20000</p>
<h3>线程测试</h3>
<p>测试线程调度的性能，用于高负载下的线程性能测试。</p>
<p><code>—thread-yields=N</code>      每个请求执行“lock/yield/unlock”循环的次数，默认1000</p>
<p><code>—thread-locks=N</code>       每个线程的互斥锁，默认8个</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=10000</span><span>  </span><span>--test=threads</span><span> </span><span>--thread-yields=100</span><span> </span><span>--thread-locks=2</span><span> </span><span>run</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<h3>内存测试</h3>
<p>内存分配测试，主要是针对不同的块大小进行内存的连续读写或者随机读写测试。</p>
<h5><strong>1.8k顺序分配</strong></h5>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=10000</span><span> </span><span>--test=memory</span><span> </span><span>--memory-block-size=8K</span><span> </span><span>--memory-total-size=100G</span><span> </span><span>--memory-access-mode=seq</span><span> </span><span>run</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<h5><strong>2.8k随机分配</strong></h5>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=10000</span><span> </span><span>--test=memory</span><span> </span><span>--memory-block-size=8K</span><span> </span><span>--memory-total-size=100G</span><span> </span><span>--memory-access-mode=rnd</span><span> </span><span>run</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<h5><strong>3.16K顺序分配</strong></h5>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=10000</span><span> </span><span>--test=memory</span><span> </span><span>--memory-block-size=16K</span><span> </span><span>--memory-total-size=100G</span><span> </span><span>--memory-access-mode=seq</span><span> </span><span>run</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<h5><strong>4.16K随机分配</strong></h5>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=10000</span><span> </span><span>--test=memory</span><span> </span><span>--memory-block-size=16K</span><span> </span><span>--memory-total-size=100G</span><span> </span><span>--memory-access-mode=rnd</span><span> </span><span>run</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p><span>总结：对于分配同样大小的内存，块月大分配的速率越快，随机分配比顺序分配的速度要快</span></p>
<h3>文件IO测试</h3>
<p>文件IO的测试主要用于测试IO的负载性能。主要的测试选项为—file-test-mode。还有几个可以关注的参数包括—file-block-size、—file-io-mode、—file-fsync-freq 、—file-rw-ratio</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>--file-num=N                   创建测试文件的数量,默认128个</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>--file-block-size=N          block size大小,默认16K</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>--file-total-size=SIZE       所有文件的总大小，默认2G</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>--file-test-mode=STRING      测试类型 {seqwr(顺序写), seqrewr(顺序读写), seqrd(顺序读), rndrd(随机读), rndwr(随机写), rndrw(随机读写)}</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>--file-io-mode=STRING         I/O模式,需要系统支持默认sync[sync(同步IO),async(异步IO),mmap()]</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>--file-async-backlog=N        每个线程的异步操作队列数，默认128个，需要--file-io-mode=async;</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>--file-extra-flags=STRING     additional flags to use on opening files {sync,dsync,direct} []</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>--file-fsync-freq=N           当请求数达到多少时执行fsync()刷新,默认100,0代表过程中不执行fsync()</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>--file-fsync-all=[on|off]     执行每一个写操作后执行fsync()刷新操作,默认关闭off</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>--file-fsync-end=[on|off]     测试结束执行fsync()操作,默认开启on</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>--file-fsync-mode=STRING      同步刷新方法,默认fsync {fsync, fdatasync}</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>--file-merged-requests=N      合并指定数量的IO请求,0代表不合并,默认0</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>--file-rw-ratio=N            读写比例，默认1.5/1</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=10000</span><span>  </span><span>--test=fileio</span><span> </span><span>--file-total-size=3G</span><span> </span><span>--file-test-mode=rndrw</span><span> </span><span>prepare</span></div></div><div><div><div>2</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=10000</span><span>  </span><span>--test=fileio</span><span> </span><span>--file-total-size=3G</span><span> </span><span>--file-test-mode=rndrw</span><span> </span><span>run</span></div></div><div><div><div>3</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=10000</span><span>  </span><span>--test=fileio</span><span> </span><span>--file-total-size=3G</span><span> </span><span>--file-test-mode=rndrw</span><span> </span><span>clean</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>注意：如果要对比两台服务器的io性能，需要跑相同的线程。</p>
<h3>互斥锁测试</h3>
<p>互斥锁测试模拟所有线程在同一时刻并发运行</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span>  </span><span>--num-threads=12</span><span>  </span><span>--test=mutex</span><span> </span><span>--mutex-num=1024</span><span> </span><span>--mutex-locks=10000</span><span> </span><span>--mutex-loops=10000</span><span> </span><span>run</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<h3>oltp测试</h3>
<p>oltp是针对数据库的基准测试，例如每次对数据库进行优化后执行基准测试来测试不同的配置的tps。</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>--oltp-test-mode=STRING                    测试类型：simple(简单select测试),complex(事务测试),nontrx(非事务测试),sp(存储过程) ；默认complex</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>--oltp-reconnect-mode=STRING             连接类型：session(每个线程到测试结束不重新连接),transaction(执行每个事务重新连接),query(每一个查询重新连接),random(随机)；默认 [session]</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>--oltp-sp-name=STRING                    指定执行测试的存储过程名</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>--oltp-read-only=[on|off]                仅执行select测试，默认关闭</span></div></div><div><div><div>5</div></div><div><span><span>  </span></span><span>--oltp-avoid-deadlocks=[on|off]          更新过程中忽略死锁，默认[off]</span></div></div><div><div><div>6</div></div><div><span><span>  </span></span><span>--oltp-skip-trx=[on|off]                 语句以bigin/commit开始结尾，默认[off]</span></div></div><div><div><div>7</div></div><div><span><span>  </span></span><span>--oltp-range-size=N                      范围查询的范围大小，默认 [100]，例如begin 100 and 200</span></div></div><div><div><div>8</div></div><div><span><span>  </span></span><span>--oltp-point-selects=N                   单个事务中select查询的数量，默认 [10]</span></div></div><div><div><div>9</div></div><div><span><span>  </span></span><span>--oltp-use-in-statement=N                每个查询中主键查找(in 10个值)的数量，默认 [0]</span></div></div><div><div><div>10</div></div><div><span><span>  </span></span><span>--oltp-simple-ranges=N                   单个事务中执行范围查询的数量(SELECT c  FROM sbtest WHERE id BETWEEN  N AND  M)，默认[1]</span></div></div><div><div><div>11</div></div><div><span><span>  </span></span><span>--oltp-sum-ranges=N                      单个事务中执行范围sum查询的数量，默认 [1]</span></div></div><div><div><div>12</div></div><div><span><span>  </span></span><span>--oltp-order-ranges=N                    单个事务中执行范围order by查询的数量，默认[1]</span></div></div><div><div><div>13</div></div><div><span><span>  </span></span><span>--oltp-distinct-ranges=N                 单个事务中执行范围distinct查询的数量，默认[1]</span></div></div><div><div><div>14</div></div><div><span><span>  </span></span><span>--oltp-index-updates=N                   单个事务中执行索引更新的操作的数量，默认[1]</span></div></div><div><div><div>15</div></div><div><span><span>  </span></span><span>--oltp-non-index-updates=N               单个事务中执行非索引更新操作的数量，默认[1]</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>--oltp-nontrx-mode=STRING                指定单独非事务测试类型进行测试，默认select {select, update_key, update_nokey, insert, delete} [select]</span></div></div><div><div><div>17</div></div><div><span><span>  </span></span><span>--oltp-auto-inc=[on|off]                 id列默认自增，默认[on]</span></div></div><div><div><div>18</div></div><div><span><span>  </span></span><span>--oltp-connect-delay=N                   指定每一次重新连接延时的时长，默认1秒 [10000]</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>--oltp-user-delay-min=N                  minimum time in microseconds to sleep after each request [0]</span></div></div><div><div><div>20</div></div><div><span><span>  </span></span><span>--oltp-user-delay-max=N                  maximum time in microseconds to sleep after each request [0]</span></div></div><div><div><div>21</div></div><div><span><span>  </span></span><span>--oltp-table-name=STRING                 指定测试的表名，默认[sbtest]</span></div></div><div><div><div>22</div></div><div><span><span>  </span></span><span>--oltp-table-size=N                      指定表的记录大小，默认[10000]</span></div></div><div><div><div>23</div></div><div><span><span>  </span></span><span>--oltp-dist-type=STRING                  随机数分布状态。uniform(均匀分布)、gauss(高斯分布)、special(特殊分布)，默认 [special]</span></div></div><div><div><div>24</div></div><div><span><span>  </span></span><span>--oltp-dist-iter=N                       number of iterations used for numbers generation [12]</span></div></div><div><div><div>25</div></div><div><span><span>  </span></span><span>--oltp-dist-pct=N                        启用百分比特殊分布，默认 [1]</span></div></div><div><div><div>26</div></div><div><span><span>  </span></span><span>--oltp-dist-res=N                        special 百分比[75]</span></div></div><div><div><div>27</div></div><div><span><span>  </span></span><span>--oltp-point-select-mysql-handler=[on|off] Use MySQL HANDLER for point select [off]</span></div></div><div><div><div>28</div></div><div><span><span>  </span></span><span>--oltp-point-select-all-cols=[on|off]    select查询测试时select所有列，默认[off]</span></div></div><div><div><div>29</div></div><div><span><span>  </span></span><span>--oltp-secondary=[on|off]                索引不是主键索引而是二级索引，默认[off]</span></div></div><div><div><div>30</div></div><div><span><span>  </span></span><span>--oltp-num-partitions=N                  指定表分区的数量，默认 [0]</span></div></div><div><div><div>31</div></div><div><span><span>  </span></span><span>--oltp-num-tables=N                      指定测试表的数量，默认[1]</span></div></div><div><div><div>32</div></div><div><span>General database options:</span></div></div><div><div><div>33</div></div><div><span><span>  </span></span><span>--db-driver=STRING  指定测试数据库类型，默认mysql</span></div></div><div><div><div>34</div></div><div><span><span>  </span></span><span>--db-ps-mode=STRING prepared statements usage mode {auto, disable} [auto]</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>mysql options:</span></div></div><div><div><div>37</div></div><div><span><span>  </span></span><span>--mysql-host=[LIST,...]       MySQL server host [localhost]</span></div></div><div><div><div>38</div></div><div><span><span>  </span></span><span>--mysql-port=N                MySQL server port [3306]</span></div></div><div><div><div>39</div></div><div><span><span>  </span></span><span>--mysql-socket=STRING         MySQL socket</span></div></div><div><div><div>40</div></div><div><span><span>  </span></span><span>--mysql-user=STRING           MySQL user [sbtest]</span></div></div><div><div><div>41</div></div><div><span><span>  </span></span><span>--mysql-password=STRING       MySQL password []</span></div></div><div><div><div>42</div></div><div><span><span>  </span></span><span>--mysql-db=STRING             MySQL database name [sbtest]</span></div></div><div><div><div>43</div></div><div><span><span>  </span></span><span>--mysql-table-engine=STRING   storage engine to use for the test table {myisam,innodb,bdb,heap,ndbcluster,federated} [innodb]</span></div></div><div><div><div>44</div></div><div><span><span>  </span></span><span>--mysql-engine-trx=STRING     whether storage engine used is transactional or not {yes,no,auto} [auto]</span></div></div><div><div><div>45</div></div><div><span><span>  </span></span><span>--mysql-ssl=[on|off]          use SSL connections, if available in the client library [off]</span></div></div><div><div><div>46</div></div><div><span><span>  </span></span><span>--myisam-max-rows=N           max-rows parameter for MyISAM tables [1000000]</span></div></div><div><div><div>47</div></div><div><span><span>  </span></span><span>--mysql-create-options=STRING additional options passed to CREATE TABLE []</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<p><strong>oltp</strong><strong>测试主要会有以下相关参数的测试,,</strong><strong>其它相关参数默认即可，有需求也可以自定义：</strong></p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>--mysql-engine-trx=STRING     指定不同的存储引擎测试。</span></div></div><div><div><div>2</div></div><div><span>--oltp-test-mode=STRING       测试类型：simple(简单select测试),complex(事务测试),nontrx(非事务测试),sp(存储过程) ；默认complex</span></div></div><div><div><div>3</div></div><div><span>--oltp-sp-name=STRING         指定存储过程进行语句测试</span></div></div><div><div><div>4</div></div><div><span>--oltp-table-size=N           指定表的记录大小，默认[10000]</span></div></div><div><div><div>5</div></div><div><span>--oltp-num-tables=N           指定测试表的数量，默认[1]</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>需要先创建好测试数据库sbtest。</p>
<p>1.事务测试，测试12个线程执行1万条请求，10个表，每个表大小100W</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=100000</span><span>  </span><span>--test=oltp</span><span> </span><span>--mysql-user=root</span><span> </span><span>--mysql-password=root</span><span> </span><span>--oltp-test-mode=complex</span><span> </span><span>--mysql-db=sbtest</span><span> </span><span>--oltp-table-size=1000000</span><span> </span><span>--oltp-num-tables=10</span><span> </span><span>prepare</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=100000</span><span>  </span><span>--test=oltp</span><span> </span><span>--mysql-user=root</span><span> </span><span>--mysql-password=root</span><span> </span><span>--oltp-test-mode=complex</span><span> </span><span>--mysql-db=sbtest</span><span> </span><span>--oltp-table-size=1000000</span><span> </span><span>--oltp-num-tables=10</span><span> </span><span>run</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>./sysbench</span><span> </span><span>--num-threads=12</span><span> </span><span>--max-requests=100000</span><span>  </span><span>--test=oltp</span><span> </span><span>--mysql-user=root</span><span> </span><span>--mysql-password=root</span><span> </span><span>--oltp-test-mode=complex</span><span> </span><span>--mysql-db=sbtest</span><span> </span><span>--oltp-table-size=1000000</span><span> </span><span>--oltp-num-tables=10</span><span> </span><span>cleanup</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p> </p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/89/</id>
      <title type="text">【Linux】测试硬盘读写速度</title>
      <published>2018-06-19T00:00:00.000Z</published>
      <updated>2019-10-24T04:16:07.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/89/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<h1>0x00</h1>
测试速度采用的是<code>dd</code>命令，<code>dd</code>命令用于复制文件并对原文件的内容进行转换和格式化处理。
<p>统计消耗时间采用的是<code>time</code>，若无安装可采用apt、yum安装。</p>
<h1>0x01测速纯写速度</h1>
<code>time dd if=/dev/zero of=/var/test bs=8k count=100000</code>
<ul>
 	<li><code>if</code>为源文件</li>
 	<li><code>of</code>为写入文件</li>
 	<li><code>bs</code>为每次写入块的字节数</li>
 	<li><code>count</code>为写入块的数量</li>
 	<li><code>/dev/zero</code>为Unix中一个特殊字符设备，读取时可以提供<strong>无限</strong>的<strong>空字符</strong>（NULL, ASCII NUL, 0x00）</li>
</ul>
![](./images/89.1.avif)
<h1>0x02测试纯读速度</h1>
在上一步的基础上测试读的速度
<p><code>time dd if=/var/test of=/dev/null bs=8k</code></p>
<ul>
 	<li><code>/dev/null</code>为Unix中“空设备”，它丢弃一切写入其中的数据（但报告写入操作成功），读取它则会立即得到一个EOF。可以将它理解为文件“黑洞”。</li>
</ul>
![](./images/89.2.avif)
<h1>0x03测试读写速度</h1>
在纯写的基础上测试
<p><code>time dd if=/var/test of=/var/test2 bs=8k</code></p>
<div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/90/</id>
      <title type="text">【Linux】常用命令</title>
      <published>2018-06-19T00:00:00.000Z</published>
      <updated>2019-10-24T04:18:25.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/90/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<h4>备份磁盘并压缩</h4>
<code>dd if=/dev/hdb | gzip &gt; /root/image.gz</code>
<h4>压缩恢复磁盘</h4>
<code>gzip -dc /root/image.gz | dd of=/dev/hdb</code>
<h4>备份磁盘开始的512个字节大小的MBR信息到指定文件</h4>
<code>dd if=/dev/hda of=/root/image count=1 bs=512</code>
<h4>销毁磁盘数据</h4>
<code>dd if=/dev/urandom of=/dev/hda</code>
<ul>
 	<li>/dev/random设备会封锁，直到系统产生的随机字符流已经充分够用，所以耗用时间较长</li>
 	<li>/dev/urandom设备不会封锁，数据的随机程度不高，但是一般情况已经够用</li>
</ul>
<h4>测试读写速度</h4>
[/posts/89/](/posts/89/)
<h4>确定硬盘的最佳块大小</h4>
<code>dd if=/dev/zero bs=1024 count=1000000 of=/root/1Gb.file</code>
<p><code>dd if=/dev/zero bs=2048 count=500000 of=/root/1Gb.file</code></p>
<p><code>dd if=/dev/zero bs=4096 count=250000 of=/root/1Gb.file</code></p>
<p><code>dd if=/dev/zero bs=8192 count=125000 of=/root/1Gb.file</code></p>
<p>通过比较以上命令输出中所显示的命令执行时间,即可确定系统最佳的块大小。</p>
<h4>修复硬盘</h4>
<code>dd if=/dev/sda of=/dev/sda</code>
<p>当硬盘较长时间(比如1,2年)放置不使用后,磁盘上会产生magnetic fluxpoint。当磁头读到这些区域时会遇到困难,并可能导致I/O错误。当这种情况影响到硬盘的第一个扇区时,可能导致硬盘报废。上边的命令有可能使这些数据起死回生。且这个过程是安全,高效的。</p>
<h4>磁盘操作（分区、挂载、格式化）</h4>
[/posts/83/](/posts/83/)
<div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/80/</id>
      <title type="text">Android 6.0(API 23)及以上动态申请权限</title>
      <published>2018-06-13T00:00:00.000Z</published>
      <updated>2019-10-24T04:07:09.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/80/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<h1>0x00 权限组</h1>
<table>
<thead>
<tr>
<th>所属权限组</th>
<th>权限</th>
</tr>
</thead>
<tbody>
<tr>
<td>日历</td>
<td>READ_CALENDAR</td>
</tr>
<tr>
<td>日历</td>
<td>WRITE_CALENDAR</td>
</tr>
<tr>
<td>相机</td>
<td>CAMERA</td>
</tr>
<tr>
<td>联系人</td>
<td>READ_CONTACTS</td>
</tr>
<tr>
<td>联系人</td>
<td>WRITE_CONTACTS</td>
</tr>
<tr>
<td>联系人</td>
<td>GET_ACCOUNTS</td>
</tr>
<tr>
<td>位置</td>
<td>ACCESS_FINE_LOCATION</td>
</tr>
<tr>
<td>位置</td>
<td>ACCESS_COARSE_LOCATION</td>
</tr>
<tr>
<td>麦克风</td>
<td>RECORD_AUDIO</td>
</tr>
<tr>
<td>电话</td>
<td>READ_PHONE_STATE</td>
</tr>
<tr>
<td>电话</td>
<td>CALL_PHONE</td>
</tr>
<tr>
<td>电话</td>
<td>READ_CALL_LOG</td>
</tr>
<tr>
<td>电话</td>
<td>WRITE_CALL_LOG</td>
</tr>
<tr>
<td>电话</td>
<td>ADD_VOICEMAIL</td>
</tr>
<tr>
<td>电话</td>
<td>USE_SIP</td>
</tr>
<tr>
<td>电话</td>
<td>PROCESS_OUTGOING_CALLS</td>
</tr>
<tr>
<td>传感器</td>
<td>BODY_SENSORS</td>
</tr>
<tr>
<td>短信</td>
<td>SEND_SMS</td>
</tr>
<tr>
<td>短信</td>
<td>RECEIVE_SMS</td>
</tr>
<tr>
<td>短信</td>
<td>READ_SMS</td>
</tr>
<tr>
<td>短信</td>
<td>RECEIVE_WAP_PUSH</td>
</tr>
<tr>
<td>短信</td>
<td>RECEIVE_MMS</td>
</tr>
<tr>
<td>存储</td>
<td>READ_EXTERNAL_STORAGE</td>
</tr>
<tr>
<td>存储</td>
<td>WRITE_EXTERNAL_STORAGE</td>
</tr>
</tbody>
</table>
来自谷歌API,<a href="https://developer.android.com/guide/topics/permissions/requesting.html#normal-dangerous" target="_blank">点击此处跳转</a>
<strong>注意：如果应用程序请求在AndroidManifest中列出的危险权限，并且应用程序已经在同一权限组中具有另一个危险权限，系统会立即授予权限，而不会与用户进行任何交互,。例如，如果一个应用程序先前已经请求并被授予READ_CONTACTS权限，然后它请求WRITE_CONTACTS(同属于联系人一组)，系统会立即授予该权限，不会再弹出权限授予询问的对话框。</strong>
<h1>0x01 动态申请权限方法</h1>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>void</span><span> </span><span>requestPower</span><span>() {</span></div></div><div><div><div>2</div></div><div><span>    </span><span>//判断是否已经赋予权限</span></div></div><div><div><div>3</div></div><div><span>        </span><span>if</span><span> (</span><span>ContextCompat</span><span>.</span><span>checkSelfPermission</span><span>(</span><span>this</span><span>,</span></div></div><div><div><div>4</div></div><div><span>                </span><span>Manifest</span><span>.</span><span>permission</span><span>.上表权限字符)</span></div></div><div><div><div>5</div></div><div><span><span>                </span></span><span>!=</span><span> </span><span>PackageManager</span><span>.</span><span>PERMISSION_GRANTED</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>           </span><span>//如果应用之前请求过此权限但用户拒绝了请求，此方法将返回 true。</span></div></div><div><div><div>7</div></div><div><span>            </span><span>if</span><span> (</span><span>ActivityCompat</span><span>.</span><span>shouldShowRequestPermissionRationale</span><span>(</span><span>this</span><span>,</span></div></div><div><div><div>8</div></div><div><span>                    </span><span>Manifest</span><span>.</span><span>permission</span><span><span>.上表权限字符)</span><span>) {</span></span><span>//这里可以写个对话框之类的项向用户解释为什么要申请权限，并在对话框的确认键后续再次申请权限</span></div></div><div><div><div>9</div></div><div><span><span>            </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>10</div></div><div><span>            </span><span>//申请权限，字符串数组内是一个或多个要申请的权限，1是申请权限结果的返回参数，在onRequestPermissionsResult可以得知申请结果</span></div></div><div><div><div>11</div></div><div><span>                </span><span>ActivityCompat</span><span>.</span><span>requestPermissions</span><span>(</span><span>this</span><span>,</span></div></div><div><div><div>12</div></div><div><span>                        </span><span>new</span><span> </span><span>String</span><span>[]{</span><span>Manifest</span><span>.</span><span>permission</span><span>.上表权限字符,}, </span><span>1</span><span>);</span></div></div><div><div><div>13</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<p>注意，因为判断语句，其实实际上当用户拒绝一次权限申请后，再次调用方法，不会再出现申请权限对话框。而如果不把权限写在数组里，而是每条权限放在一个多个以下方法里一起调用，实际上，每次一起调用这多个方法，实际只申请这些方法的一条权限。</p>
<h1>0x02 判断权限申请结果</h1>
<p>判断权限申请结果的方法（在权限申请对话框消失后执行）</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@</span><span>Override</span></div></div><div><div><div>2</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>onRequestPermissionsResult</span><span>(</span><span>int</span><span><span> requestCode</span><span>,</span><span> </span></span><span>String</span><span><span>[] permissions</span><span>,</span><span> </span></span><span>int</span><span>[] grantResults) {</span></div></div><div><div><div>3</div></div><div><span>        </span><span>super</span><span>.</span><span>onRequestPermissionsResult</span><span>(requestCode, permissions, grantResults);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>        </span><span>if</span><span><span> (requestCode </span><span>==</span><span> </span></span><span>1</span><span>) {</span></div></div><div><div><div>6</div></div><div><span>            </span><span>for</span><span> (</span><span>int</span><span> i </span><span><span>=</span><span> </span></span><span>0</span><span><span>;</span><span> i </span><span>&lt;</span><span> </span></span><span>permissions</span><span>.</span><span>length</span><span><span>;</span><span> i</span><span>++</span><span>) {</span></span></div></div><div><div><div>7</div></div><div><span>                </span><span>if</span><span><span> (grantResults[i] </span><span>==</span><span> PERMISSION_GRANTED) {</span></span></div></div><div><div><div>8</div></div><div><span>                    </span><span>Toast</span><span>.</span><span>makeText</span><span>(</span><span>this</span><span>, </span><span>""</span><span><span> </span><span>+</span><span> </span></span><span>"权限"</span><span><span> </span><span>+</span><span> permissions[i] </span><span>+</span><span> </span></span><span>"申请成功"</span><span>, </span><span>Toast</span><span>.</span><span>LENGTH_SHORT</span><span>).</span><span>show</span><span>();</span></div></div><div><div><div>9</div></div><div><span><span>                </span></span><span>} </span><span>else</span><span> {</span></div></div><div><div><div>10</div></div><div><span>                    </span><span>Toast</span><span>.</span><span>makeText</span><span>(</span><span>this</span><span>, </span><span>""</span><span><span> </span><span>+</span><span> </span></span><span>"权限"</span><span><span> </span><span>+</span><span> permissions[i] </span><span>+</span><span> </span></span><span>"申请失败"</span><span>, </span><span>Toast</span><span>.</span><span>LENGTH_SHORT</span><span>).</span><span>show</span><span>();</span></div></div><div><div><div>11</div></div><div><span><span>                </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span><span>            </span></span><span>}</span></div></div><div><div><div>13</div></div><div><span><span>        </span></span><span>}</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>当系统要求用户授予权限时，用户可以选择指示系统不再要求提供该权限。这种情况下，无论应用在什么时候使用 requestPermissions() 再次要求该权限，系统都会立即拒绝此请求。</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/83/</id>
      <title type="text">Linux硬盘操作</title>
      <published>2018-06-13T00:00:00.000Z</published>
      <updated>2019-10-24T04:10:51.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/83/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<h3>0x01 查看磁盘设备</h3>
<p><code># df</code>
<img alt="" loading="lazy" width="641" height="225" src="/_astro/83.1.BGIfJy0D_13wu7F.webp" /></p>
<h3>0x02 查看磁盘信息</h3>
<p><code>#  fdisk -l</code>
<img alt="" loading="lazy" width="557" height="474" src="/_astro/83.2.B4wYQX-C_Z15aMSF.webp" /></p>
<h3>0x03 磁盘分区命令</h3>
<table>
<tbody>
<tr>
<td>fdisk可以用m命令来看fdisk命令的内部命令；</td>
</tr>
<tr>
<td>a：命令指定启动分区；</td>
</tr>
<tr>
<td>d：命令删除一个存在的分区；</td>
</tr>
<tr>
<td>l：命令显示分区ID号的列表；</td>
</tr>
<tr>
<td>m：查看fdisk命令帮助；</td>
</tr>
<tr>
<td>n：命令创建一个新分区；</td>
</tr>
<tr>
<td>p：命令显示分区列表；</td>
</tr>
<tr>
<td>t：命令修改分区的类型ID号；</td>
</tr>
<tr>
<td>w：命令是将对分区表的修改存盘让它发生作用。</td>
</tr>
</tbody>
</table>
<code># fdisk /dev/sda</code>进入磁盘
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Command (m for help):n</span></div></div><div><div><div>2</div></div><div><span>Command action</span></div></div><div><div><div>3</div></div><div><span><span>　　   </span></span><span>e    extended                  //输入e为创建扩展分区</span></div></div><div><div><div>4</div></div><div><span><span>　　   </span></span><span>p    primary partition (1-4)      //输入p为创建逻辑分区</span></div></div><div><div><div>5</div></div><div><span>p</span></div></div><div><div><div>6</div></div><div><span>Partion number(1-4)：1      //在这里输入l，就进入划分逻辑分区阶段了；</span></div></div><div><div><div>7</div></div><div><span>First cylinder (51-125, default 51):   //注：这个就是分区的Start 值；这里最好直接按回车，如果您输入了一个非默认的数字，会造成空间浪费；</span></div></div><div><div><div>8</div></div><div><span>Using default value 51</span></div></div><div><div><div>9</div></div><div><span>Last cylinder or +size or +sizeM or +sizeK (51-125, default 125): +200M 注：这个是定义分区大小的，+200M 就是大小为200M ；当然您也可以根据p提示的单位cylinder的大小来算，然后来指定 End的数值。回头看看是怎么算的；还是用+200M这个办法来添加，这样能直观一点。如果您想添加一个10G左右大小的分区，请输入 +10000M ；</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span>Command (m for help): w                     //最后输入w回车保存。</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<h3>0x04 格式化分区</h3>
<p><code>mkfs.ext3 /dev/sda6       # 把该设备格式化成ext3文件系统</code>
<code>mke2fs -j /dev/sda6       # 把该设备格式化成ext3文件系统</code>
<code>mkfs.reiserfs /dev/sda6   # 格式化成reiserfs文件系统</code>
<code>mkfs.vfat /dev/sda6       # 格式化成fat32文件系统</code>
<code>mkfs.msdos /dev/sda6      # 格式化成fat16文件系统,msdos就是fat16</code>
<code>mkdosfs /dev/sda6         # 格式化成msdos文件系统</code></p>
<h3>0x05 挂载分区</h3>
<p><code># mount /dev/sda /mnt</code>将/dev/sda挂载到/mnt（umount卸载）</p>
<p><code># mount —bind /home /mnt</code>将/home内容挂载到/mnt（mount —move卸载）</p>
<p><b>参数说明：</b></p>
<ul>
 	<li>-V：显示程序版本</li>
 	<li>-h：显示辅助讯息</li>
 	<li>-v：显示较讯息，通常和 -f 用来除错。</li>
 	<li>-a：将 /etc/fstab 中定义的所有档案系统挂上。</li>
 	<li>-F：这个命令通常和 -a 一起使用，它会为每一个 mount 的动作产生一个行程负责执行。在系统需要挂上大量 NFS 档案系统时可以加快挂上的动作。</li>
 	<li>-f：通常用在除错的用途。它会使 mount 并不执行实际挂上的动作，而是模拟整个挂上的过程。通常会和 -v 一起使用。</li>
 	<li>-n：一般而言，mount 在挂上后会在 /etc/mtab 中写入一笔资料。但在系统中没有可写入档案系统存在的情况下可以用这个选项取消这个动作。</li>
 	<li>-s-r：等于 -o ro</li>
 	<li>-w：等于 -o rw</li>
 	<li>-L：将含有特定标签的硬盘分割挂上。</li>
 	<li>-U：将档案分割序号为 的档案系统挂下。-L 和 -U 必须在/proc/partition 这种档案存在时才有意义。</li>
 	<li>-t：指定档案系统的型态，通常不必指定。mount 会自动选择正确的型态。</li>
 	<li>-o async：打开非同步模式，所有的档案读写动作都会用非同步模式执行。</li>
 	<li>-o sync：在同步模式下执行。</li>
 	<li>-o atime、-o noatime：当 atime 打开时，系统会在每次读取档案时更新档案的『上一次调用时间』。当我们使用 flash 档案系统时可能会选项把这个选项关闭以减少写入的次数。</li>
 	<li>-o auto、-o noauto：打开/关闭自动挂上模式。</li>
 	<li>-o defaults:使用预设的选项 rw, suid, dev, exec, auto, nouser, and async.</li>
 	<li>-o dev、-o nodev-o exec、-o noexec允许执行档被执行。</li>
 	<li>-o suid、-o nosuid：</li>
 	<li>允许执行档在 root 权限下执行。</li>
 	<li>-o user、-o nouser：使用者可以执行 mount/umount 的动作。</li>
 	<li>-o remount：将一个已经挂下的档案系统重新用不同的方式挂上。例如原先是唯读的系统，现在用可读写的模式重新挂上。</li>
 	<li>-o ro：用唯读模式挂上。</li>
 	<li>-o rw：用可读写模式挂上。</li>
 	<li>-o loop=：使用 loop 模式用来将一个档案当成硬盘分割挂上系统。</li>
</ul>
<h5>实例</h5>
<p>将 /dev/hda1 挂在 /mnt 之下。</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>mount</span><span> </span><span>/dev/hda1</span><span> </span><span>/mnt</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>将 /dev/hda1 用唯读模式挂在 /mnt 之下。</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>mount</span><span> </span><span>-o</span><span> </span><span>ro</span><span> </span><span>/dev/hda1</span><span> </span><span>/mnt</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>将 /tmp/image.iso 这个光碟的 image 档使用 loop 模式挂在 /mnt/cdrom之下。用这种方法可以将一般网络上可以找到的 Linux 光 碟 ISO 档在不烧录成光碟的情况下检视其内容。</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>mount</span><span> </span><span>-o</span><span> </span><span>loop</span><span> </span><span>/tmp/image.iso</span><span> </span><span>/mnt/cdrom</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<h4>NTFS格式磁盘挂载</h4>
<p>这里采用简单的方式，安装ntfs-3g来实现挂载</p>
<p><code># apt install ntfs-3g</code></p>
<p>挂载：</p>
<p><code># mount -t ntfs-3g /dev/sda1 /mnt</code></p>
<h4>开机自动挂载</h4>
<p>编辑<code>/etc/fstab</code></p>
<p>插入格式：
<code>&lt;实际分区&gt; &lt;挂载点&gt; &lt;分区类型&gt; &lt;挂载参数&gt; &lt;dump备份设置&gt; &lt;fsck磁盘检查设置&gt;</code></p>
<p>分区类型
Linux可以使用ext2、ext3等类型，此字段须与分区格式化时使用的类型相同。也可以使用 auto 这一特殊的语法，使系统自动侦测目标分区的分区类型。auto通常用于可移动设备的挂载。</p>
<p>挂载参数</p>
<ul>
 	<li>auto: 系统自动挂载，fstab默认就是这个选项</li>
 	<li>defaults: rw, suid, dev, exec, auto, nouser, and async.</li>
 	<li>noauto 开机不自动挂载</li>
 	<li>nouser 只有超级用户可以挂载</li>
 	<li>ro 按只读权限挂载</li>
 	<li>rw 按可读可写权限挂载</li>
 	<li>user 任何用户都可以挂载
请注意光驱和软驱只有在装有介质时才可以进行挂载，因此它是noauto</li>
</ul>
dump备份设置
当其值设置为1时，将允许dump备份程序备份；设置为0时，忽略备份操作
<p>fsck磁盘检查设置
其值是一个顺序。当其值为0时，永远不检查；而 / 根目录分区永远都为1。其它分区从2开始，数字越小越先检查，如果两个分区的数字相同，则同时检查</p>
<h5>
实例</h5>
<p><code>/dev/sda1 /mnt ntfs-3g defaults 0 0</code></p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/84/</id>
      <title type="text">服务脚本</title>
      <published>2018-06-13T00:00:00.000Z</published>
      <updated>2019-10-24T04:12:35.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/84/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> commands</span></div></div><div><div><div>2</div></div><div><span>import</span><span> sys</span></div></div><div><div><div>3</div></div><div><span>import</span><span> os</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>Error </span><span>=</span><span> </span></span><span>"</span><span>\033</span><span>[1;31;40m"</span></div></div><div><div><div>6</div></div><div><span><span>Through </span><span>=</span><span> </span></span><span>"</span><span>\033</span><span>[1;32;40m"</span></div></div><div><div><div>7</div></div><div><span><span>Tail </span><span>=</span><span> </span></span><span>"</span><span>\033</span><span>[0m"</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>def</span><span> </span><span>fen</span><span>(</span><span>x</span><span>):</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>status, result </span><span>=</span><span> commands.</span><span>getstatusoutput</span><span>(</span></div></div><div><div><div>12</div></div><div><span>        </span><span>'ps aux|grep fen.py|grep -v grep'</span><span>)</span></div></div><div><div><div>13</div></div><div><span>    </span><span>if</span><span><span> status </span><span>==</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>14</div></div><div><span>        </span><span>if</span><span><span> x </span><span>==</span><span> </span></span><span>"k"</span><span>:</span></div></div><div><div><div>15</div></div><div><span>            </span><span>return</span><span> </span><span>1</span></div></div><div><div><div>16</div></div><div><span>        </span><span>return</span><span><span> Through </span><span>+</span><span> </span></span><span>"运行中"</span><span><span> </span><span>+</span><span> Tail</span></span></div></div><div><div><div>17</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>18</div></div><div><span>        </span><span>if</span><span><span> x</span><span>==</span><span> </span></span><span>"g"</span><span>:</span></div></div><div><div><div>19</div></div><div><span>            </span><span>return</span><span> </span><span>1</span></div></div><div><div><div>20</div></div><div><span>        </span><span>return</span><span><span> Error </span><span>+</span><span> </span></span><span>"未运行"</span><span><span> </span><span>+</span><span> Tail</span></span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div>
</div></div><div><div><div>23</div></div><div><span>def</span><span> </span><span>xunlei</span><span>(</span><span>x</span><span>):</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>status, result </span><span>=</span><span> commands.</span><span>getstatusoutput</span><span>(</span></div></div><div><div><div>25</div></div><div><span>        </span><span>'ps aux|grep xunlei|grep -v grep'</span><span>)</span></div></div><div><div><div>26</div></div><div><span>    </span><span>if</span><span><span> status </span><span>==</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>27</div></div><div><span>        </span><span>if</span><span><span> x </span><span>==</span><span> </span></span><span>"k"</span><span>:</span></div></div><div><div><div>28</div></div><div><span>            </span><span>return</span><span> </span><span>1</span></div></div><div><div><div>29</div></div><div><span>        </span><span>return</span><span><span> Through </span><span>+</span><span> </span></span><span>"运行中"</span><span><span> </span><span>+</span><span> Tail</span></span></div></div><div><div><div>30</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>31</div></div><div><span>        </span><span>if</span><span><span> x</span><span>==</span><span> </span></span><span>"g"</span><span>:</span></div></div><div><div><div>32</div></div><div><span>            </span><span>return</span><span> </span><span>1</span></div></div><div><div><div>33</div></div><div><span>        </span><span>return</span><span><span> Error </span><span>+</span><span> </span></span><span>"未运行"</span><span><span> </span><span>+</span><span> Tail</span></span></div></div><div><div><div>34</div></div><div>
</div></div><div><div><div>35</div></div><div><span>def</span><span> </span><span>frp</span><span>(</span><span>x</span><span>):</span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>status, result </span><span>=</span><span> commands.</span><span>getstatusoutput</span><span>(</span></div></div><div><div><div>37</div></div><div><span>        </span><span>'ps aux|grep frp|grep -v grep'</span><span>)</span></div></div><div><div><div>38</div></div><div><span>    </span><span>if</span><span><span> status </span><span>==</span><span> </span></span><span>0</span><span>:</span></div></div><div><div><div>39</div></div><div><span>        </span><span>if</span><span><span> x </span><span>==</span><span> </span></span><span>"k"</span><span>:</span></div></div><div><div><div>40</div></div><div><span>            </span><span>return</span><span> </span><span>1</span></div></div><div><div><div>41</div></div><div><span>        </span><span>return</span><span><span> Through </span><span>+</span><span> </span></span><span>"运行中"</span><span><span> </span><span>+</span><span> Tail</span></span></div></div><div><div><div>42</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>43</div></div><div><span>        </span><span>if</span><span><span> x</span><span>==</span><span> </span></span><span>"g"</span><span>:</span></div></div><div><div><div>44</div></div><div><span>            </span><span>return</span><span> </span><span>1</span></div></div><div><div><div>45</div></div><div><span>        </span><span>return</span><span><span> Error </span><span>+</span><span> </span></span><span>"未运行"</span><span><span> </span><span>+</span><span> Tail</span></span></div></div><div><div><div>46</div></div><div>
</div></div><div><div><div>47</div></div><div><span>def</span><span> </span><span>state</span><span>():</span></div></div><div><div><div>48</div></div><div><span><span>    </span></span><span>f </span><span>=</span><span> </span><span>open</span><span>(</span><span>"/etc/startup-script/state.txt"</span><span>)</span></div></div><div><div><div>49</div></div><div><span>    </span><span>for</span><span> line </span><span>in</span><span> f:</span></div></div><div><div><div>50</div></div><div><span><span>        </span></span><span>line </span><span>=</span><span> line.</span><span>strip</span><span>(</span><span>'</span><span>\n</span><span>'</span><span>)</span></div></div><div><div><div>51</div></div><div><span><span>        </span></span><span>v </span><span>=</span><span> line.</span><span>split</span><span>(</span><span>':'</span><span>)</span></div></div><div><div><div>52</div></div><div><span>        </span><span>if</span><span> v[</span><span>0</span><span><span>] </span><span>==</span><span> </span></span><span>"fen_state"</span><span>:</span></div></div><div><div><div>53</div></div><div><span>            </span><span>return</span><span><span> </span><span>fen_state</span><span>(v[</span></span><span>1</span><span>])</span></div></div><div><div><div>54</div></div><div><span>    </span><span>return</span><span><span> Error </span><span>+</span><span> </span></span><span>"Error"</span><span><span> </span><span>+</span><span> Tail</span></span></div></div><div><div><div>55</div></div><div>
</div></div><div><div><div>56</div></div><div>
</div></div><div><div><div>57</div></div><div><span>def</span><span> </span><span>fen_state</span><span>(</span><span>stat</span><span>):</span></div></div><div><div><div>58</div></div><div><span>    </span><span>if</span><span><span> stat </span><span>==</span><span> </span></span><span>"1"</span><span>:</span></div></div><div><div><div>59</div></div><div><span>        </span><span>return</span><span> </span><span>"风扇开启中</span><span>\n</span><span>"</span></div></div><div><div><div>60</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>61</div></div><div><span>        </span><span>return</span><span> </span><span>"风扇已关闭</span><span>\n</span><span>"</span></div></div><div><div><div>62</div></div><div>
</div></div><div><div><div>63</div></div><div><span>def</span><span> </span><span>help</span><span>():</span></div></div><div><div><div>64</div></div><div><span>    </span><span>print</span><span>(</span><span>"  _____      _     _   _   "</span><span>)</span></div></div><div><div><div>65</div></div><div><span>    </span><span>print</span><span>(</span><span>" |  __ \    | |   | | | |  "</span><span>)</span></div></div><div><div><div>66</div></div><div><span>    </span><span>print</span><span>(</span><span>" | |__) |___| |__ | |_| |_ "</span><span>)</span></div></div><div><div><div>67</div></div><div><span>    </span><span>print</span><span>(</span><span>" |  _  // _ \ '_ \| __| __|"</span><span>)</span></div></div><div><div><div>68</div></div><div><span>    </span><span>print</span><span>(</span><span>" | | \ \  __/ | | | |_| |_ "</span><span>)</span></div></div><div><div><div>69</div></div><div><span>    </span><span>print</span><span>(</span><span>" |_|  \_\___|_| |_|\__|\__|"</span><span>)</span></div></div><div><div><div>70</div></div><div><span>    </span><span>print</span></div></div><div><div><div>71</div></div><div><span>    </span><span>print</span><span>(</span><span>"-h | help    显示帮助"</span><span>)</span></div></div><div><div><div>72</div></div><div><span>    </span><span>print</span><span>(</span><span>"-f           开启温控风扇"</span><span>)</span></div></div><div><div><div>73</div></div><div><span>    </span><span>print</span><span>(</span><span>"-df          关闭温控风扇"</span><span>)</span></div></div><div><div><div>74</div></div><div><span>    </span><span>print</span><span>(</span><span>"-x           开启迅雷远程下载"</span><span>)</span></div></div><div><div><div>75</div></div><div><span>    </span><span>print</span><span>(</span><span>"-dx          关闭迅雷远程下载"</span><span>)</span></div></div><div><div><div>76</div></div><div><span>    </span><span>print</span><span>(</span><span>"-frp         开启frpc"</span><span>)</span></div></div><div><div><div>77</div></div><div><span>    </span><span>print</span><span>(</span><span>"-dfrp        关闭frpc"</span><span>)</span></div></div><div><div><div>78</div></div><div><span>    </span><span>print</span><span>(</span><span>"-ls          显示服务状态"</span><span>)</span></div></div><div><div><div>79</div></div><div>
</div></div><div><div><div>80</div></div><div><span>def</span><span> </span><span>show</span><span>():</span></div></div><div><div><div>81</div></div><div><span>    </span><span>print</span><span>(</span><span>"cpu温控风扇："</span><span><span> </span><span>+</span><span> </span><span>fen</span><span>(</span></span><span>0</span><span>))</span></div></div><div><div><div>82</div></div><div><span>    </span><span>print</span><span>(</span><span>"迅雷远程下载："</span><span><span> </span><span>+</span><span> </span><span>xunlei</span><span>(</span></span><span>0</span><span>))</span></div></div><div><div><div>83</div></div><div><span>    </span><span>print</span><span>(</span><span>"frp:"</span><span><span>+</span><span>frp</span><span>(</span></span><span>0</span><span>))</span></div></div><div><div><div>84</div></div><div><span>    </span><span>print</span></div></div><div><div><div>85</div></div><div><span>    </span><span>print</span><span>(</span><span>"状态："</span><span><span> </span><span>+</span><span> </span><span>state</span><span>())</span></span></div></div><div><div><div>86</div></div><div>
</div></div><div><div><div>87</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>'__main__'</span><span>:</span></div></div><div><div><div>88</div></div><div><span><span>    </span></span><span>arg</span><span>=</span><span>sys.argv</span></div></div><div><div><div>89</div></div><div><span><span>    </span></span><span>k</span><span>=</span><span>"k"</span></div></div><div><div><div>90</div></div><div><span><span>    </span></span><span>g</span><span>=</span><span>"g"</span></div></div><div><div><div>91</div></div><div><span>    </span><span>try</span><span>:</span></div></div><div><div><div>92</div></div><div><span>        </span><span>if</span><span> arg[</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>"help"</span><span> </span><span>and</span><span> arg[</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>"-h"</span><span>:</span></div></div><div><div><div>93</div></div><div><span>            </span><span>help</span><span>()</span></div></div><div><div><div>94</div></div><div><span>        </span><span>elif</span><span> arg[</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>"-f"</span><span>:</span></div></div><div><div><div>95</div></div><div><span>            </span><span>if</span><span><span> </span><span>fen</span><span>(k) </span><span>==</span><span> </span></span><span>1</span><span>:</span></div></div><div><div><div>96</div></div><div><span><span>                </span></span><span>os.</span><span>system</span><span>(</span><span>'sudo python /etc/startup-script/fen.py &amp;'</span><span>)</span></div></div><div><div><div>97</div></div><div><span>                </span><span>print</span><span>(</span><span>"开启成功"</span><span>)</span></div></div><div><div><div>98</div></div><div><span>            </span><span>else</span><span>:</span></div></div><div><div><div>99</div></div><div><span>                </span><span>print</span><span>(</span><span>"温控风扇已在运行状态"</span><span>)</span></div></div><div><div><div>100</div></div><div><span>        </span><span>elif</span><span> arg[</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>"-df"</span><span>:</span></div></div><div><div><div>101</div></div><div><span>            </span><span>if</span><span><span> </span><span>fen</span><span>(g) </span><span>==</span></span><span>1</span><span>:</span></div></div><div><div><div>102</div></div><div><span><span>                </span></span><span>os.</span><span>system</span><span>(</span><span>'sudo killall python /etc/startup-script/fen.py'</span><span>)</span></div></div><div><div><div>103</div></div><div><span>                </span><span>print</span><span>(</span><span>"关闭成功"</span><span>)</span></div></div><div><div><div>104</div></div><div><span>            </span><span>else</span><span>:</span></div></div><div><div><div>105</div></div><div><span>                </span><span>print</span><span>(</span><span>"温控风扇未运行"</span><span>)</span></div></div><div><div><div>106</div></div><div><span>        </span><span>elif</span><span> arg[</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>"-x"</span><span>:</span></div></div><div><div><div>107</div></div><div><span>            </span><span>if</span><span><span> </span><span>fen</span><span>(k) </span><span>==</span><span> </span></span><span>1</span><span>:</span></div></div><div><div><div>108</div></div><div><span><span>                </span></span><span>os.</span><span>system</span><span>(</span><span>'sudo python /etc/startup-script/xunlei/setup.py'</span><span>)</span></div></div><div><div><div>109</div></div><div><span>                </span><span>print</span><span>(</span><span>"开启成功"</span><span>)</span></div></div><div><div><div>110</div></div><div><span>            </span><span>else</span><span>:</span></div></div><div><div><div>111</div></div><div><span>                </span><span>print</span><span>(</span><span>"迅雷远程下载已在运行状态"</span><span>)</span></div></div><div><div><div>112</div></div><div><span>        </span><span>elif</span><span> arg[</span><span>1</span><span><span>] </span><span>==</span><span> </span></span><span>"-dx"</span><span>:</span></div></div><div><div><div>113</div></div><div><span>            </span><span>if</span><span><span> </span><span>fen</span><span>(g) </span><span>==</span></span><span>1</span><span>:</span></div></div><div><div><div>114</div></div><div><span><span>                </span></span><span>os.</span><span>system</span><span>(</span><span>'sudo /etc/startup-script/xunlei/portal -s'</span><span>)</span></div></div><div><div><div>115</div></div><div><span>                </span><span>print</span><span>(</span><span>"关闭成功"</span><span>)</span></div></div><div><div><div>116</div></div><div><span>            </span><span>else</span><span>:</span></div></div><div><div><div>117</div></div><div><span>                </span><span>print</span><span>(</span><span>"迅雷远程下载未运行"</span><span>)</span></div></div><div><div><div>118</div></div><div><span>        </span><span>elif</span><span> arg[</span><span>1</span><span><span>]</span><span>==</span></span><span>"-frp"</span><span>:</span></div></div><div><div><div>119</div></div><div><span>            </span><span>if</span><span><span> </span><span>frp</span><span>(k) </span><span>==</span></span><span>1</span><span>:</span></div></div><div><div><div>120</div></div><div><span><span>                </span></span><span>os.</span><span>system</span><span>(</span><span>'sudo screen -dmS frp /etc/startup-script/frp_0.20.0_linux_arm/frpc -c /etc/startup-script/frp_0.20.0_linux_arm/frpc.ini'</span><span>)</span></div></div><div><div><div>121</div></div><div><span>                </span><span>print</span><span>(</span><span>"开启成功"</span><span>)</span></div></div><div><div><div>122</div></div><div><span>            </span><span>else</span><span>:</span></div></div><div><div><div>123</div></div><div><span>                </span><span>print</span><span>(</span><span>"frp已在运行状态"</span><span>)</span></div></div><div><div><div>124</div></div><div><span>        </span><span>elif</span><span> arg[</span><span>1</span><span><span>]</span><span>==</span></span><span>"-dfrp"</span><span>:</span></div></div><div><div><div>125</div></div><div><span>            </span><span>if</span><span><span> </span><span>frp</span><span>(g)</span><span>==</span></span><span>1</span><span>:</span></div></div><div><div><div>126</div></div><div><span><span>                </span></span><span>os.</span><span>system</span><span>(</span><span>'sudo screen -d frp'</span><span>)</span></div></div><div><div><div>127</div></div><div><span>                </span><span>print</span><span>(</span><span>"关闭成功"</span><span>)</span></div></div><div><div><div>128</div></div><div><span>            </span><span>else</span><span>:</span></div></div><div><div><div>129</div></div><div><span>                </span><span>print</span><span>(</span><span>"frp未运行"</span><span>)</span></div></div><div><div><div>130</div></div><div><span>        </span><span>elif</span><span> arg[</span><span>1</span><span><span>] </span><span>==</span></span><span>"-ls"</span><span>:</span></div></div><div><div><div>131</div></div><div><span><span>            </span></span><span>show</span><span>()</span></div></div><div><div><div>132</div></div><div><span>        </span><span>else</span><span>:</span></div></div><div><div><div>133</div></div><div><span>            </span><span>help</span><span>()</span></div></div><div><div><div>134</div></div><div><span>    </span><span>except</span><span>:</span></div></div><div><div><div>135</div></div><div><span>        </span><span>help</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/79/</id>
      <title type="text">面向对象六大原则</title>
      <published>2018-05-24T00:00:00.000Z</published>
      <updated>2019-10-24T04:04:55.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/79/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x01 单一职责原则-优化代码的第一步<a href="#0x01-单一职责原则-优化代码的第一步"><span>#</span></a></h1><p>单一职责原则英文名称为Single Responsilbility Principle，缩写为SRP</p><p>定义：就一个类而言，应该仅有一个引起它变化的原因。</p><p>简单来说，一个类中应该是一组相关性很高的函数、数据的封装。</p><p>两个完全不一样的功能就不能放在一个类中。</p></section>
<section><h1>0x02 闭源原则-让程序更稳定、更灵活<a href="#0x02-闭源原则-让程序更稳定更灵活"><span>#</span></a></h1><p>开闭原则的英文是Open Close Principle，缩写为OCP，它是java中最基础的设计原则，它指导我们如何建立一个稳定、灵活的系统。</p><p>定义：软件中的对象（类、模块、函数等）应该对于扩展是开放的，但是，对于修改是封闭的。</p><p>在软件生命周期内，因为变化、升级和维护等原因需要对软件原有代码进行修改时，可能将错误引入原本已经经过测试的旧代码中，破坏原有系统。因此，当软件需要变化时，我们应该尽量通过扩展的方式来实现变化，而不是通过修改已有的代码来实现。当然，在显示开发中，只通过继承的方式来实现升级、扩展原有系统只是一个理想化的愿景，因此，在实际开发中，修改原有代码、扩展代码往往是同时存在的。</p><p>程序一旦开发完成，原有的类只因修改代码错误而被修改，新的或更改的特性应该建立新的类来实现，新建的类可以通过继承的方式来重写原有类的代码。</p></section>
<section><h1>0x03 里氏替换原则-构建扩展性更好的系统<a href="#0x03-里氏替换原则-构建扩展性更好的系统"><span>#</span></a></h1></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/68/</id>
      <title type="text">用AndroidStudio编写.so</title>
      <published>2018-05-07T00:00:00.000Z</published>
      <updated>2019-10-24T04:03:03.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/68/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>Android开发中，我们经常会用到.so文件。原因有很多，比如部分方法不想暴露，如加密规则。比如部分秘钥需要存储，哪怕最简单的一个String我们使用.so调用获取这个String，也比直接明文写在代码中要来的安全。
<a href="/posts/72/">NDK开发环境搭建</a></p>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>首先新建一个java文件
</p><figure><img alt="QQ截图20180507165536-1024x190.png" loading="lazy" width="1024" height="190" src="/_astro/68.1.pDBTFZlL_ZCcnNk.webp" /><figcaption>QQ截图20180507165536-1024x190.png</figcaption></figure>
代码：<p></p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>public</span><span> </span><span>class</span><span><span> </span><span>myJNT</span><span> </span></span><span>{</span></div></div><div><div><div>2</div></div><div><span>    </span><span>static</span><span> {</span></div></div><div><div><div>3</div></div><div><span>        </span><span>System</span><span>.</span><span>loadLibrary</span><span>(</span><span>"JniTest"</span><span>);</span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>5</div></div><div><span>    </span><span>public</span><span> </span><span>static</span><span> </span><span>native</span><span> </span><span>String</span><span> </span><span>Hello</span><span>();</span></div></div><div><div><div>6</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>使用javah工具生成.h文件
</p><figure><img alt="QQ截图20180507170454.png" loading="lazy" width="542" height="772" src="/_astro/68.2.BPZH2Bpy_15759P.webp" /><figcaption>QQ截图20180507170454.png</figcaption></figure><p></p></section>
<section><h1>0x03<a href="#0x03"><span>#</span></a></h1><p>将生成好的.h文件改为.c文件，并修改其中内容</p><p>生成的.h文件：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* DO NOT EDIT THIS FILE - it is machine generated */</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;jni.h&gt;</span></div></div><div><div><div>3</div></div><div><span>/* Header for class com_rehtt_test_ndk_myJNT */</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>#ifndef</span><span> </span><span>_Included_com_rehtt_test_ndk_myJNT</span></div></div><div><div><div>6</div></div><div><span>#define</span><span> </span><span>_Included_com_rehtt_test_ndk_myJNT</span></div></div><div><div><div>7</div></div><div><span>#ifdef</span><span> </span><span>__cplusplus</span></div></div><div><div><div>8</div></div><div><span>extern</span><span> </span><span>"C"</span><span> {</span></div></div><div><div><div>9</div></div><div><span>#endif</span></div></div><div><div><div>10</div></div><div><span>/*</span></div></div><div><div><div>11</div></div><div><span><span> </span></span><span>* Class:     com_rehtt_test_ndk_myJNT</span></div></div><div><div><div>12</div></div><div><span><span> </span></span><span>* Method:    Hello</span></div></div><div><div><div>13</div></div><div><span><span> </span></span><span>* Signature: ()Ljava/lang/String;</span></div></div><div><div><div>14</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>15</div></div><div><span>JNIEXPORT jstring JNICALL Java_com_rehtt_test_ndk_myJNT_Hello</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>(JNIEnv </span><span>*</span><span>, jclass);</span></div></div><div><div><div>17</div></div><div>
</div></div><div><div><div>18</div></div><div><span>#ifdef</span><span> </span><span>__cplusplus</span></div></div><div><div><div>19</div></div><div><span>}</span></div></div><div><div><div>20</div></div><div><span>#endif</span></div></div><div><div><div>21</div></div><div><span>#endif</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>修改后的.c文件：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/* DO NOT EDIT THIS FILE - it is machine generated */</span></div></div><div><div><div>2</div></div><div><span>#include</span><span> </span><span>&lt;jni.h&gt;</span></div></div><div><div><div>3</div></div><div><span>/* Header for class com_rehtt_test_ndk_myJNT */</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>#ifndef</span><span> </span><span>_Included_com_rehtt_test_ndk_myJNT</span></div></div><div><div><div>6</div></div><div><span>#define</span><span> </span><span>_Included_com_rehtt_test_ndk_myJNT</span></div></div><div><div><div>7</div></div><div><span>#ifdef</span><span> </span><span>__cplusplus</span></div></div><div><div><div>8</div></div><div><span>extern</span><span> </span><span>"C"</span><span> {</span></div></div><div><div><div>9</div></div><div><span>#endif</span></div></div><div><div><div>10</div></div><div><span>/*</span></div></div><div><div><div>11</div></div><div><span><span> </span></span><span>* Class:     com_rehtt_test_ndk_myJNT</span></div></div><div><div><div>12</div></div><div><span><span> </span></span><span>* Method:    Hello</span></div></div><div><div><div>13</div></div><div><span><span> </span></span><span>* Signature: ()Ljava/lang/String;</span></div></div><div><div><div>14</div></div><div><span><span> </span></span><span>*/</span></div></div><div><div><div>15</div></div><div><span>JNIEXPORT jstring JNICALL Java_com_rehtt_test_ndk_myJNT_Hello</span></div></div><div><div><div>16</div></div><div><span><span>  </span></span><span>(JNIEnv </span><span>*</span><span>env, jclass jobj){</span></div></div><div><div><div>17</div></div><div><span>  </span><span>//返回字符串</span></div></div><div><div><div>18</div></div><div><span>  </span><span>return</span><span> (</span><span>*</span><span>env)-&gt;</span><span>NewStringUTF</span><span>(env,</span><span>"emmmmmm"</span><span>);</span></div></div><div><div><div>19</div></div><div><span><span>  </span></span><span>}</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span>#ifdef</span><span> </span><span>__cplusplus</span></div></div><div><div><div>22</div></div><div><span>}</span></div></div><div><div><div>23</div></div><div><span>#endif</span></div></div><div><div><div>24</div></div><div><span>#endif</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>
<section><h1>0x04<a href="#0x04"><span>#</span></a></h1><p>打开moduled的build.gradle文件，在defaultConfig下添加代码：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>ndk {</span></div></div><div><div><div>2</div></div><div><span>moduleName </span><span>"JniTest"</span><span>    </span><span>//编译出来so的名字</span></div></div><div><div><div>3</div></div><div><span>ldLibs </span><span>"log"</span><span>, </span><span>"z"</span><span>, </span><span>"m"</span></div></div><div><div><div>4</div></div><div><span>abiFilters </span><span>"armeabi"</span><span>, </span><span>"armeabi-v7a"</span><span>, </span><span>"x86"</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p></p><figure><img alt="QQ截图20180507171708-1024x554.png" loading="lazy" width="1024" height="554" src="/_astro/68.3.B23jQbBw_Z1c02tJ.webp" /><figcaption>QQ截图20180507171708-1024x554.png</figcaption></figure><p></p><p>在gradle.properties里面加上:
<code>android.useDeprecatedNdk=true</code>
可能会报错，根据报错提示信息进行相应修改即可。</p></section>
<section><h1>0x05<a href="#0x05"><span>#</span></a></h1><p>Rebuild Project就可以生成so库，在<code>app\build\intermediates\ndk\debug\lib</code>路径下。
如果出现了<code>...\ndk-bundle\ndk-build.cmd'' finished with non-zero exit value 2</code>报错就将<code>app\build\intermediates\ndk\debug\lib</code>下的Android.mk复制到<code>src\main\jni</code>下，并使用<code>ndk -build</code>手动生成so文件。</p></section>
<section><h1>0x06<a href="#0x06"><span>#</span></a></h1><p>myJNT.Hello()即可调用so中的字符串</p><p>END</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/72/</id>
      <title type="text">AndroidStudio NDK开发环境搭建</title>
      <published>2018-05-07T00:00:00.000Z</published>
      <updated>2019-10-24T04:01:51.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/72/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>NDK即Native Development Kit,NDK允许开发者使用类似C / C++之类的原生代码语言执行部分程序。
为何要用到NDK?
概括来说主要分为以下几种情况：</p><ol>
<li>代码的保护，由于apk的java层代码很容易被反编译，而C/C++库被反编译的难度较大。</li>
<li>在NDK中调用第三方C/C++库，因为大部分的开源库都是用C/C++代码编写的。</li>
<li>便于移植，用C/C++写的库可以方便在其他的嵌入式平台上再次使用。</li>
</ol></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>打开AndroidStudio的settings，找到Android SDK一栏点击SDK Tools，找到NDK选项并勾选。
</p><figure><img alt="QQ截图20180507174001-1024x684.png" loading="lazy" width="1024" height="684" src="/_astro/72.1.CT2avWqr_cVhFm.webp" /><figcaption>QQ截图20180507174001-1024x684.png</figcaption></figure><p></p></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>在settings中找到<code>External Tools</code>添加<code>javah -jni</code>和<code>ndk -build</code>
javah -jni
</p><figure><img alt="QQ截图20180507174824.png" loading="lazy" width="684" height="463" src="/_astro/72.2.DCH8pXeY_ZcW3Ks.webp" /><figcaption>QQ截图20180507174824.png</figcaption></figure><p></p><p><code>$JDKPath$\bin\javah.exe -classpath . -jni -d "$ModuleFileDir$\src\main\jni" $FileClass$ $ModuleFileDir$\src\main\java</code></p><p>ndk -build
</p><figure><img alt="QQ截图20180507175123.png" loading="lazy" width="684" height="463" src="/_astro/72.3.BHrhy2wu_u24U8.webp" /><figcaption>QQ截图20180507175123.png</figcaption></figure><p></p><p><code>C:\Users\用户名\.android\Android_SDK\ndk-bundle\ndk-build.cmd</code> ndk工具所在的路径
<code>$ModuleFileDir$\src\main\</code></p></section>
<section><h1>END<a href="#end"><span>#</span></a></h1></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/64/</id>
      <title type="text">计算机网络-根据掩码和ip计算网段起始ip和最终ip</title>
      <published>2018-04-23T00:00:00.000Z</published>
      <updated>2019-10-24T03:44:43.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/64/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>一个B类ip<br />ip：10.254.68.136<br />掩码：255.255.224.0</p>
<p></p>
<table>
<tbody>
<tr>
<th><span>网络位</span></th>
<th><span>主机位</span></th>
</tr>
</tbody>
</table>
<p> <br />掩码二进制：</p>
<table>
<tbody>
<tr>
<th><span>1111 1111</span></th>
<th><span>1111 1111</span></th>
<th><span>111</span><span>0 0000</span></th>
<th><span>0000 0000</span></th>
</tr>
</tbody>
</table>
<p>掩码中0为主机位，1为网络位</p>
<p> <br />ip二进制：</p>
<table>
<tbody>
<tr>
<th><span>0000 1010</span></th>
<th><span>1111 1110</span></th>
<th><span>010</span><span>0 0100</span></th>
<th><span>1000 1000</span></th>
</tr>
</tbody>
</table>
<p> <br />网段网络位不动，主机位从0到1，所以该网段起始ip为：</p>
<table>
<tbody>
<tr>
<th>10</th>
<th>254</th>
<th>64</th>
<th>0</th>
</tr>
<tr>
<th><span>0000 1010</span></th>
<th><span>1111 1110</span></th>
<th><span>010</span><span>0 0000</span></th>
<th><span>0000 0000</span></th>
</tr>
</tbody>
</table>
<p>最终ip为：</p>
<table>
<tbody>
<tr>
<th>10</th>
<th>254</th>
<th>95</th>
<th>255</th>
</tr>
<tr>
<th><span>0000 1010</span></th>
<th><span>1111 1110</span></th>
<th><span>010</span><span>1 1111</span></th>
<th><span>1111 1111</span></th>
</tr>
</tbody>
</table>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/63/</id>
      <title type="text">Python中sys.arg[]的用法</title>
      <published>2018-04-12T00:00:00.000Z</published>
      <updated>2019-10-24T03:23:44.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/63/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>引入库：<code>import sys</code>
文件名：<code>test.py</code></p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>a</span><span>=</span><span>sys.arg[</span></span><span>0</span><span>]</span></div></div><div><div><div>2</div></div><div><span>print</span><span>(a)</span></div></div><div><div><div>3</div></div><div><span>结果输出：test.py</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span><span>a</span><span>=</span><span>sys.arg[</span></span><span>1</span><span>]</span></div></div><div><div><div>6</div></div><div><span><span>b</span><span>=</span><span>sys.arg[</span></span><span>2</span><span>]</span></div></div><div><div><div>7</div></div><div><span>print</span><span><span>(a</span><span>+</span></span><span>" "</span><span><span>+</span><span>b)</span></span></div></div><div><div><div>8</div></div><div><span><span>运行</span><span>&gt;</span><span>test.py </span></span><span>1</span><span> </span><span>2</span></div></div><div><div><div>9</div></div><div><span>结果输出：</span><span>1</span><span> </span><span>2</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>a</span><span>=</span><span>sys.arg[</span></span><span>1</span><span>:]</span></div></div><div><div><div>12</div></div><div><span>print</span><span>(a)</span></div></div><div><div><div>13</div></div><div><span><span>运行</span><span>&gt;</span><span>test.py </span></span><span>1</span><span> </span><span>2</span><span> </span><span>3</span></div></div><div><div><div>14</div></div><div><span>结果输出：[</span><span>'1'</span><span>,</span><span>'2'</span><span>,</span><span>'3'</span><span>]</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>a</span><span>=</span><span>sys.arg[</span></span><span>2</span><span>:]:</span></div></div><div><div><div>17</div></div><div><span>print</span><span>(a)</span></div></div><div><div><div>18</div></div><div><span><span>运行</span><span>&gt;</span><span>test.py </span></span><span>1</span><span> </span><span>2</span><span> </span><span>3</span></div></div><div><div><div>19</div></div><div><span>结果输出：[</span><span>'2'</span><span>,</span><span>'3'</span><span>]</span></div></div><div><div><div>20</div></div><div>
</div></div><div><div><div>21</div></div><div><span><span>a</span><span>=</span><span>sys.arg[</span></span><span>0</span><span>:]</span></div></div><div><div><div>22</div></div><div><span>print</span><span>(a)</span></div></div><div><div><div>23</div></div><div><span><span>运行</span><span>&gt;</span><span>test.py </span></span><span>1</span><span> </span><span>2</span><span> </span><span>3</span></div></div><div><div><div>24</div></div><div><span>结果输出：[</span><span>'test.py'</span><span>,</span><span>'1'</span><span>,</span><span>'2'</span><span>,</span><span>'3'</span><span>]</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/61/</id>
      <title type="text">P4wnP1通过USB连接电脑网络(windowns)</title>
      <published>2018-04-07T00:00:00.000Z</published>
      <updated>2019-10-24T04:00:28.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/61/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>插入电脑后在“网络连接”中会出现P4wnP1网卡<code>以太网 Remote NDIS Compatibl...</code></p><p>打开目前连接网络的网卡设置，选择“共享”勾选“连接共享”，选择P4wnP1的接口<code>以太网</code>
选择P4wnP1的网卡，配置静态ip,更改ip和子网掩码：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>ip:         172.16.0.2</span></div></div><div><div><div>2</div></div><div><span>子网掩码:    255.255.255.252</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x01 win8-10额外配置(ping 172.16.0.2不通)可忽略<a href="#0x01-win8-10额外配置ping-1721602不通可忽略"><span>#</span></a></h1><p>以<strong>管理员身份</strong>运行power shell，将网卡改为私有</p><p>输入<code>Get-NetConnectionProfile</code>，复制P4wnP1网卡的名字</p><p>输入<code>Set-NetConnectionProfile -Name "你的P4wnP1网卡名字" -NetworkCategory Private</code>
</p><figure><img alt="微信截图_20180407132535.png" loading="lazy" width="982" height="448" src="/_astro/61.1.DI03Bv-X_1ln6IJ.webp" /><figcaption>微信截图_20180407132535.png</figcaption></figure><p></p></section>
<section><h1>0x02设置路由访问外网<a href="#0x02设置路由访问外网"><span>#</span></a></h1><p>ssh连接P4wnP1后输入<code>sudo route add -net default gw 172.16.0.2</code></p><p>切换到root添加dns，输入<code>echo nameserver 114.114.114.114 &gt; /etc/resolv.conf</code></p><p>Done</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/60/</id>
      <title type="text">ARP攻击（断网攻击）</title>
      <published>2018-04-01T00:00:00.000Z</published>
      <updated>2019-10-24T04:01:22.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/60/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div></div><div>Note</div></div><div><p>所谓ARP攻击，就是伪造IP和MAC地址进行的攻击或者欺骗，ARP攻击和ARP欺骗应该是两个概念，ARP攻击所产生的效果就是使目标主机（当然这里默认的是局域网，倘若你处在外网，涉及到内网渗透，以后在具体说内网渗透）断网，这种行为从某种意义上来说是，是损人不利己的，因为攻击者并没有得到什么好处，只是让对方不能上网，但是如果在ARP攻击的基础上，通过嗅探对方的流量，非法获取一些隐私信息，那就大大不同了。</p></div></div>
<p>ARP欺骗：<a href="/posts/21/">传送</a></p>
<section><h1>0x00环境及工具<a href="#0x00环境及工具"><span>#</span></a></h1><p>环境：Kali linux环境</p><p>工具：Dsniff、fping</p><p>Dsniff是一个基于unix系统网络嗅探工具集，这里所用的是arpspoof命令。</p><p>fping可以说是ping的增强版,可以在ping时间按照从1毫秒到5秒的频率调整时间并且在每次应答成功(超时)的时间发出语音提示,还可以同时ping多台主机，在这里的作用是寻找局域网中的设备ip地址。</p></section>
<section><h1>0x01寻找目标<a href="#0x01寻找目标"><span>#</span></a></h1><p>使用fping寻找地址：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>fping</span><span> </span><span>-a</span><span> </span><span>-g</span><span> </span><span>192.168.199.0/24</span><span> 2&gt;</span><span>/dev/null</span></div></div><div><div><div>2</div></div><div><span>也可以用：</span></div></div><div><div><div>3</div></div><div><span>$</span><span> </span><span>fping</span><span> </span><span>-a</span><span> </span><span>-g</span><span> </span><span>192.168.199.1</span><span> </span><span>192.168.199.254</span><span> 2&gt;</span><span>/dev/null</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p></p><figure><img alt="微信截图_20180401163933.png" loading="lazy" width="579" height="164" src="/_astro/60.1.CLsE6IZp_Zg5PMi.webp" /><figcaption>微信截图_20180401163933.png</figcaption></figure>
这里选用192.168.199.180作为目标<p></p></section>
<section><h1>0x02攻击<a href="#0x02攻击"><span>#</span></a></h1><p>arpspoof语法：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>arpspoof [-i interface] [-c own|host|both] [-t target] [-r] host</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>攻击：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>arpspoof</span><span> </span><span>-i</span><span> </span><span>wlan0</span><span> </span><span>-t</span><span> </span><span>192.168.199.180</span><span> </span><span>192.168.199.1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p></p><figure><img alt="微信截图_20180401164416.png" loading="lazy" width="946" height="107" src="/_astro/60.2.BscmZ0Zx_Z1zJD3d.webp" /><figcaption>微信截图_20180401164416.png</figcaption></figure>
这时会发现目标上不了网了，攻击目标也达到了。<p></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/57/</id>
      <title type="text">树莓派配置wifi连接</title>
      <published>2018-03-31T00:00:00.000Z</published>
      <updated>2019-10-24T03:00:37.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/57/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>在树莓派官方系统可以更快捷配置wifi和ssh：<a href="/posts/27/">传送</a></p><p>在非官方系统下使用命令配置wifi连接。</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>树莓派默认wifi接口为wlan0，如果不确定可以输入命令查看：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>iwconfig</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>首先保证接口的服务是运行的：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>ip</span><span> </span><span>link</span><span> </span><span>set</span><span> </span><span>wlan0</span><span> </span><span>up</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>扫描网络：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>iw</span><span> </span><span>dev</span><span> </span><span>wlan0</span><span> </span><span>scan</span><span> | </span><span>less</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>如果连接没有加密的网络：</li>
</ul><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>iw</span><span> </span><span>dev</span><span> </span><span>wlan0</span><span> </span><span>connect</span><span> [网络 </span><span>SSID]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>`如果连接WEP加密的网络：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>iw</span><span> </span><span>dev</span><span> </span><span>wlan0</span><span> </span><span>connect</span><span> [网络 </span><span>SSID]</span></div></div></code></pre><div><div></div><div></div></div></figure></div><ul>
<li>如果连接WPA\WPA2加密的网络则需要使用wpasupplicant 来连接，修改或创建<code>/etc/wpasupplicant/wpa_supplicant.conf</code> 文件写入：</li>
</ul><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>country</span><span><span>=</span><span>CN</span></span></div></div><div><div><div>2</div></div><div><span>ctrl_interface</span><span>=</span><span>DIR</span><span><span>=</span><span>/var/run/wpa_supplicant </span></span><span>GROUP</span><span><span>=</span><span>netdev</span></span></div></div><div><div><div>3</div></div><div><span>update_config</span><span><span>=</span><span>1</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>network</span><span><span>=</span><span>{</span></span></div></div><div><div><div>6</div></div><div><span>ssid</span><span>=</span><span>"WiFi-A"</span></div></div><div><div><div>7</div></div><div><span>psk</span><span>=</span><span>"12345678"</span><span>                  </span><span>#psk可以填加密后的值，加密：终端输入 wpa_passphrase WiFi-A 12345678</span></div></div><div><div><div>8</div></div><div><span>priority</span><span><span>=</span><span>1                       </span></span><span>#连接优先级，数字越大优先级越高（不可以是负数）</span></div></div><div><div><div>9</div></div><div><span>scan_ssid:=1                 </span><span>#连接隐藏WiFi时需要指定该值为1</span></div></div><div><div><div>10</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>写好了后输入命令启动：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>wpa_supplicant</span><span> </span><span>-i</span><span> </span><span>wlan0</span><span> </span><span>-c</span><span> </span><span>/etc/wpa_supplicant/wpa_supplicant.conf</span><span> &amp;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>输入命令自动获取ip：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>dhcpcd</span><span> </span><span>wlan0</span></div></div><div><div><div>2</div></div><div><span>或</span></div></div><div><div><div>3</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>dhclient</span><span> </span><span>wlan0</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x03<a href="#0x03"><span>#</span></a></h1><p>输入命令查看wlan0是否在配置中：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>cat</span><span> </span><span>/etc/network/interfaces</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果没有就输入:</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>nano</span><span> </span><span>/etc/network/interfaces</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>文本中追加写入：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>auto wlan0</span></div></div><div><div><div>2</div></div><div><span>iface wlan0 inet dhcp</span></div></div><div><div><div>3</div></div><div><span>wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>配置完后就可开机自动连接wifi</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/56/</id>
      <title type="text">Arduino入门hello world</title>
      <published>2018-03-29T00:00:00.000Z</published>
      <updated>2019-10-24T02:55:32.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/56/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div></div><div>Note</div></div><div><p>Arduino是一款单片机开发板，是个很好上手的入门级开发板，适合于用于开发电子产品原型，开发语言采用Ｃ，其特点是简单、方便、软件库多、模块配件多。</p></div></div>
<section><h1>0x00初识Arduino<a href="#0x00初识arduino"><span>#</span></a></h1><p>工欲善其事，必先利其器。首先是需要一块Arduino开发版，我使用的是Arduino uno r3，淘宝售价在25元左右。</p><p></p><figure><img alt="微信图片_20180328230444-1024x768.jpg" loading="lazy" width="1024" height="768" src="/_astro/56.1.C9MyepjH_Z24girx.webp" /><figcaption>微信图片_20180328230444-1024x768.jpg</figcaption></figure><p></p><p>这块板子使用的是atmega328p的芯片，闪存容量32K（其中0.5K用作引导程序），EEPROM容量1K，时钟速度16MHz，I/O针脚电流为20mA，3.3V针脚电流为50mA。</p><p>针脚中A为模拟引入脚，D为数字IO脚，RET是复位脚，RX，TX分别是串行通信收发脚，GND为电源零线，5V、3.3V为正电引出脚（向外供电），VIN为电源输入脚（向板子供电，工作电压为5V，正常电压为7-12V，极限电压为6-20V）。</p></section>
<section><h1>0x01安装软件<a href="#0x01安装软件"><span>#</span></a></h1><p>Arduino IDE 是 Arduino的集成开发环境，用于单片机软件编程、下载、测试等。</p><p>到官网下载Arduino IDE即可。</p><p>连接电脑后Windowns系统电脑需要安装驱动（Mac os与Liunx可以不用安装驱动），需要安装的驱动根据板子的usb转串口芯片有关，我的是CH340G，下载相关驱动安装即可。</p><p></p><figure><img alt="微信图片_20180328233548.jpg" loading="lazy" width="610" height="777" src="/_astro/56.2.CbGwYMZf_1Nm1mC.webp" /><figcaption>微信图片_20180328233548.jpg</figcaption></figure><p></p><p>安装好后会在电脑设备管理器中的端口出现一个新的端口</p><p></p><figure><img alt="微信截图_20180328234119.png" loading="lazy" width="502" height="437" src="/_astro/56.3.DlIc7rbN_2psIUP.webp" /><figcaption>微信截图_20180328234119.png</figcaption></figure><p></p><p>如果没安装好（或与芯片型号不匹配）会显示一个“未知设备”。</p><p>Arduino IDE安装目录下有一个drivers目录，包含了Arduino官方版本的驱动程序。可以选中未知设备，更新驱动程序，将搜索目录指向Arduino IDE安装目录下有一个drivers目录试试。</p></section>
<section><h1>0x02配置<a href="#0x02配置"><span>#</span></a></h1><p>板子连接电脑后启动Arduino IDE，点击“工具”-&gt;“开发版”选择对应型号的板子，点击“工具”-&gt;“端口”选择对应的端口。</p><p></p><figure><img alt="1.jpg" loading="lazy" width="672" height="481" src="/_astro/56.4.BNbQBVDa_ZeTV5h.webp" /><figcaption>1.jpg</figcaption></figure><p></p><p></p><figure><img alt="2.jpg" loading="lazy" width="452" height="332" src="/_astro/26.2.DhFyUji__1O1thr.webp" /><figcaption>2.jpg</figcaption></figure><p></p></section>
<section><h1>0x03编写第一个程序<a href="#0x03编写第一个程序"><span>#</span></a></h1><p>Arduino IDE会自动给新项目添加setup()和loop()函数，Arduino程序不需要写main()因为会自动生成main函数，但是必须要setup()和loop()。</p><p>setup()是设置函数，主要写初始化相关的代码，板子启动后只会调用一次etup()函数。</p><p>loop()是循环函数，在setup()执行完后会执行loop()，loop()执行完后将会再次执行loop()函数。</p><p>用c语言理解：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>main</span><span>()</span></div></div><div><div><div>2</div></div><div><span>{</span></div></div><div><div><div>3</div></div><div><span>    </span><span>setup</span><span>();</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>    </span><span>while</span><span>(</span><span>1</span><span>){</span></div></div><div><div><div>6</div></div><div><span>        </span><span>loop</span><span>();</span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>写入下列代码：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>void</span><span> </span><span>setup</span><span>(){</span></div></div><div><div><div>2</div></div><div><span>    </span><span>Serial</span><span>.</span><span>begin</span><span>(</span><span>9600</span><span>);</span><span>  //初始化串口，波特率为9600</span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>void</span><span> </span><span>loop</span><span>(){</span></div></div><div><div><div>6</div></div><div><span>    </span><span>Serial</span><span>.</span><span>println</span><span>(</span><span>"hello world"</span><span>);</span><span>  //向串口打印字符串</span></div></div><div><div><div>7</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在Arduino IDE左上角有两个按钮，分别为编译和上传。</p><p></p><figure><img alt="微信截图_20180329000820.jpg" loading="lazy" width="100" height="72" src="/_astro/56.6.DiqFXWOt_1eDtsv.webp" /><figcaption>微信截图_20180329000820.jpg</figcaption></figure><p></p><p>程序写好后先编译后上传，如果编译出错下方会有提示。</p><p>当程序上传完毕后将立即运行。</p><p>点击“工具”-&gt;“串口监视器”选择正确的波特率就可以看见运行结果。</p><p></p><figure><img alt="微信截图_20180329001410.jpg" loading="lazy" width="722" height="411" src="/_astro/56.7.YnuhoFJ5_Z2Vtxs.webp" /><figcaption>微信截图_20180329001410.jpg</figcaption></figure><p></p><p>到这来你的第一个Arduino程序开发、运行起来了。</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/47/</id>
      <title type="text">理解Linux硬链接与软链接</title>
      <published>2018-03-26T00:00:00.000Z</published>
      <updated>2019-10-24T02:44:09.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/47/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<blockquote><p>内容转自：<a href="https://www.ibm.com/developerworks/cn/linux/l-cn-hardandsymb-links/index.html" target="_blank">https://www.ibm.com/developerworks/cn/linux/l-cn-hardandsymb-links/index.html</a></p></blockquote>
<section><h1>0x00文件概念<a href="#0x00文件概念"><span>#</span></a></h1><p>现代操作系统为解决信息能独立于进程之外被长期存储引入了文件，文件作为进程创   建信息的逻辑单元可被多个进程并发使用。在 UNIX 系统中，操作系统为磁盘上的文本与图像、鼠标与键盘等输入设备及网络交互等 I/O 操作设计了一组通用 API，使他们被处理时均可统一使用字节流方式。换言之，UNIX 系统中除进程之外的一切皆是文件，而 Linux 保持了这一特性。为了便于文件的管理，Linux 还引入了目录（有时亦被称为文件夹）这一概念。目录使文件可被分类管理，且目录的引入使 Linux 的文件系统形成一个层级结构的目录树。下图所示的是普通 Linux 系统的顶层目录结构，其中 /dev 是存放了设备相关文件的目录。
</p><figure><img alt="tree.png" loading="lazy" width="558" height="433" src="/_astro/47.1.B3Mbgc9k_2mS2tq.webp" /><figcaption>tree.png</figcaption></figure><p></p><p>Linux 与其他类 UNIX 系统一样并不区分文件与目录：目录是记录了其他文件名的文件。使用命令 mkdir 创建目录时，若期望创建的目录的名称与现有的文件名（或目录名）重复，则会创建失败。</p><p>Linux 将设备当做文件进行处理，下图展示了如何打开设备文件 /dev/input/event5 并读取文件内容。文件 event5 表示一种输入设备，其可能是鼠标或键盘等。查看文件 /proc/bus/input/devices 可知 event5 对应设备的类型。设备文件 /dev/input/event5 使用 read() 以字符流的方式被读取。结构体 input_event 被定义在内核头文件 linux/input.h 中。
</p><figure><img alt="1-1.png" loading="lazy" width="528" height="166" src="/_astro/47.2.CSV2CJTd_ZswCTI.webp" /><figcaption>1-1.png</figcaption></figure><p></p></section>
<section><h1>0x01硬链接与软链接的联系与区别<a href="#0x01硬链接与软链接的联系与区别"><span>#</span></a></h1><p>我们知道文件都有文件名与数据，这在 Linux 上被分成两个部分：用户数据 (user data) 与元数据 (metadata)。用户数据，即文件数据块 (data block)，数据块是记录文件真实内容的地方；而元数据则是文件的附加属性，如文件大小、创建时间、所有者等信息。在 Linux 中，元数据中的 inode 号（inode 是文件元数据的一部分但其并不包含文件名，inode 号即索引节点号）才是文件的唯一标识而非文件名。文件名仅是为了方便人们的记忆和使用，系统或程序通过 inode 号寻找正确的文件数据块。下图展示了程序通过文件名获取文件内容的过程。
</p><figure><img alt="微信截图_20180326100721.png" loading="lazy" width="399" height="145" src="/_astro/47.3.Cx4L5Kqo_2jPFBm.webp" /><figcaption>微信截图_20180326100721.png</figcaption></figure><p></p><p>在 Linux 系统中查看 inode 号可使用命令 stat 或 ls -i（若是 AIX 系统，则使用命令 istat）。假设一个文件名为a，inode号为2485677，对其使用命令 mv 移动并重命名文件 ，其结果不影响文件的用户数据及 inode 号，文件移动前后 inode 号均为：2485677。</p><p>为解决文件的共享使用，Linux 系统引入了两种链接：硬链接 (hard link) 与软链接（又称符号链接，即 soft link 或 symbolic link）。链接为 Linux 系统解决了文件的共享使用，还带来了隐藏文件路径、增加权限安全及节省存储等好处。若一个 inode 号对应多个文件名，则称这些文件为硬链接。换言之，硬链接就是同一个文件使用了多个别名硬链接可由命令 link 或 ln 创建。
</p><figure><img alt="微信截图_20180326101044.png" loading="lazy" width="275" height="59" src="/_astro/47.4.CMD3soG5_1ehlbj.webp" /><figcaption>微信截图_20180326101044.png</figcaption></figure><p></p><p>由于硬链接是有着相同 inode 号仅文件名不同的文件，因此硬链接存在以下几点特性：</p><ul>
<li>文件有相同的 inode 及 data block；</li>
<li>只能对已存在的文件进行创建；</li>
<li>不能交叉文件系统进行硬链接的创建；</li>
<li>不能对目录进行创建，只可对文件创建；</li>
<li>删除一个硬链接文件并不影响其他有相同 inode 号的文件。</li>
</ul><p>inode 是随着文件的存在而存在，因此只有当文件存在时才可创建硬链接，即当 inode 存在且链接计数器（link count）不为 0 时。inode 号仅在各文件系统下是唯一的，当 Linux 挂载多个文件系统后将出现 inode 号重复的现象，因此硬链接创建时不可跨文件系统。设备文件目录 /dev 使用的文件系统是 devtmpfs，而 /root（与根目录 / 一致）使用的是磁盘文件系统 ext4。</p><p>值得一提的是，Linux 系统存在 inode 号被用完但磁盘空间还有剩余的情况。</p><p>硬链接不能对目录创建是受限于文件系统的设计现（下图）。 Linux 文件系统中的目录均隐藏了两个个特殊的目录：当前目录（.）与父目录（..）。查看这两个特殊目录的 inode 号可知其实这两目录就是两个硬链接（注意目录 /mnt/lost+found/ 的 inode 号）。若系统允许对目录创建硬链接，则会产生目录环。
</p><figure><img alt="微信截图_20180326101548.png" loading="lazy" width="849" height="325" src="/_astro/47.5.1piqoMOL_LqoyQ.webp" /><figcaption>微信截图_20180326101548.png</figcaption></figure><p></p><p>软链接与硬链接不同，若文件用户数据块中存放的内容是另一文件的路径名的指向，则该文件就是软连接。软链接就是一个普通文件，只是数据块内容有点特殊。软链接有着自己的 inode 号以及用户数据块。因此软链接的创建与使用没有类似硬链接的诸多限制：</p><ul>
<li>软链接有自己的文件属性及权限等；</li>
<li>可对不存在的文件或目录创建软链接；</li>
<li>软链接可交叉文件系统；</li>
<li>软链接可对文件或目录创建；</li>
<li>创建软链接时，链接计数 i_nlink 不会增加；</li>
<li>删除软链接并不影响被指向的文件，但若被指向的原文件被删除，则相关软连接被称为死链接（即 dangling link，若被指向路径文件被重新创建，死链接可恢复为正常的软链接）。</li>
</ul><p></p><figure><img alt="微信截图_20180326101728.png" loading="lazy" width="329" height="258" src="/_astro/47.6.BbF8_R_2_282YoS.webp" /><figcaption>微信截图_20180326101728.png</figcaption></figure><p></p><p></p><figure><img alt="微信截图_20180326101955.png" loading="lazy" width="816" height="676" src="/_astro/47.7.DCEKlV0V_2otfY2.webp" /><figcaption>微信截图_20180326101955.png</figcaption></figure><p></p><p>当然软链接的用户数据也可以是另一个软链接的路径，其解析过程是递归的。但需注意：软链接创建时原文件的路径指向使用绝对路径较好。使用相对路径创建的软链接被移动后该软链接文件将成为一个死链接（如下所示的软链接 a 使用了相对路径，因此不宜被移动），因为链接数据块中记录的亦是相对路径指向。
</p><figure><img alt="微信截图_20180326102051.png" loading="lazy" width="819" height="148" src="/_astro/47.8.uVJKysgX_ZQoIRi.webp" /><figcaption>微信截图_20180326102051.png</figcaption></figure><p></p></section>
<section><h1>0x02链接相关命令<a href="#0x02链接相关命令"><span>#</span></a></h1><ul>
<li>在 Linux 中查看当前系统已挂着的文件系统类型，除上述使用的命令 df，还可使用命令 mount 或查看文件 /proc/mounts。</li>
<li>命令 ls 或 stat 可帮助我们区分软链接与其他文件并查看文件 inode 号，但较好的方式还是使用 find 命令，其不仅可查找某文件的软链接，还可以用于查找相同 inode 的所有硬链接。</li>
<li>系统根据磁盘的大小默认设定了 inode 的值，如若必要，可在格式文件系统前对该值进行修改。如键入命令 mkfs -t ext4 -I 512/dev/sda4，将使磁盘设备 /dev/sda4 格式成 inode 大小是 512 字节的 ext4 文件系统。</li>
</ul></section>
<section><h1>0x03Linux VFS<a href="#0x03linux-vfs"><span>#</span></a></h1><p>Linux 有着极其丰富的文件系统，大体上可分如下几类：</p><ul>
<li>网络文件系统，如 nfs、cifs 等；</li>
<li>磁盘文件系统，如 ext4、ext3 等；</li>
<li>特殊文件系统，如 proc、sysfs、ramfs、tmpfs 等。
实现以上这些文件系统并在 Linux 下共存的基础就是 Linux VFS（Virtual File System 又称 Virtual Filesystem Switch），即虚拟文件系统。VFS 作为一个通用的文件系统，抽象了文件系统的四个基本概念：文件、目录项 (dentry)、索引节点 (inode) 及挂载点，其在内核中为用户空间层的文件系统提供了相关的接口（下图所示 VFS 在 Linux 系统的架构）。VFS 实现了 open()、read() 等系统调并使得 cp 等用户空间程序可跨文件系统。VFS 真正实现了上述内容中：在 Linux 中除进程之外一切皆是文件。
<figure><img alt="微信截图_20180326102645.png" loading="lazy" width="405" height="268" src="/_astro/47.9.TohdDlve_20M56y.webp" /><figcaption>微信截图_20180326102645.png</figcaption></figure></li>
</ul><p>Linux VFS 存在四个基本对象：超级块对象 (superblock object)、索引节点对象 (inode object)、目录项对象 (dentry object) 及文件对象 (file object)。超级块对象代表一个已安装的文件系统；索引节点对象代表一个文件；目录项对象代表一个目录项，如设备文件 event5 在路径 /dev/input/event5 中，其存在四个目录项对象：/ 、dev/ 、input/ 及 event5。文件对象代表由进程打开的文件。这四个对象与进程及磁盘文件间的关系如图 4. 所示，其中 d_inode 即为硬链接。为文件路径的快速解析，Linux VFS 设计了目录项缓存（Directory Entry Cache，即 dcache）。
</p><figure><img alt="微信截图_20180326102733.png" loading="lazy" width="462" height="170" src="/_astro/47.10.BZqWdTY8_Z18smcT.webp" /><figcaption>微信截图_20180326102733.png</figcaption></figure><p></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/48/</id>
      <title type="text">mount命令</title>
      <published>2018-03-26T00:00:00.000Z</published>
      <updated>2019-10-24T02:46:18.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/48/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>mount命令用于加载文件系统到指定的加载点。此命令的最常用于挂载cdrom，使我们可以访问cdrom中的数据，因为你将光盘插入cdrom中，Linux并不会自动挂载，必须使用Linux mount命令来手动完成挂载。</p>
<section><h1>语法<a href="#语法"><span>#</span></a></h1><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>mount(选项)(参数)</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>选项<a href="#选项"><span>#</span></a></h1><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>-V：显示程序版本；</span></div></div><div><div><div>2</div></div><div><span>-l：显示已加载的文件系统列表；</span></div></div><div><div><div>3</div></div><div><span>-h：显示帮助信息并退出；</span></div></div><div><div><div>4</div></div><div><span>-v：冗长模式，输出指令执行的详细信息；</span></div></div><div><div><div>5</div></div><div><span>-n：加载没有写入文件“/etc/mtab”中的文件系统；</span></div></div><div><div><div>6</div></div><div><span>-r：将文件系统加载为只读模式；</span></div></div><div><div><div>7</div></div><div><span>-a：加载文件“/etc/fstab”中描述的所有文件系统。</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>参数<a href="#参数"><span>#</span></a></h1><ul>
<li>设备文件名：指定要加载的文件系统对应的设备名；</li>
<li>加载点：指定加载点目录。</li>
</ul></section>
<section><h1>实例<a href="#实例"><span>#</span></a></h1><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>mount -t auto /dev/cdrom /mnt/cdrom</span></div></div><div><div><div>2</div></div><div><span>mount: mount point /mnt/cdrom does not exist           /mnt/cdrom目录不存在，需要先创建。</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>cd /mnt</span></div></div><div><div><div>5</div></div><div><span>-bash: cd: /mnt: No such file or directory</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>mkdir -p /mnt/cdrom    创建/mnt/cdrom目录</span></div></div><div><div><div>8</div></div><div><span>ls</span></div></div><div><div><div>9</div></div><div><span>bin   dev  home    lib         media  mnt  proc  sbin     srv  tmp  var</span></div></div><div><div><div>10</div></div><div><span>boot  etc  initrd  lost+found  misc   opt  root  selinux  sys  usr</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>mount -t auto /dev/cdrom /mnt/cdrom     挂载cdrom</span></div></div><div><div><div>13</div></div><div><span>mount: block device /dev/cdrom is write-protected, mounting read-only     挂载成功</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>ll /mnt/cdrom    查看cdrom里面内容</span></div></div><div><div><div>16</div></div><div><span>total 859</span></div></div><div><div><div>17</div></div><div><span>dr-xr-xr-x  4 root root   2048 Sep  4  2005 CentOS</span></div></div><div><div><div>18</div></div><div><span>-r--r--r--  2 root root   8859 Mar 19  2005 centosdocs-man.css</span></div></div><div><div><div>19</div></div><div><span>-r--r--r--  9 root root  18009 Mar  1  2005 GPL</span></div></div><div><div><div>20</div></div><div><span>dr-xr-xr-x  2 root root 241664 May  7 02:32 headers</span></div></div><div><div><div>21</div></div><div><span>dr-xr-xr-x  4 root root   2048 May  7 02:23 images</span></div></div><div><div><div>22</div></div><div><span>dr-xr-xr-x  2 root root   4096 May  7 02:23 isolinux</span></div></div><div><div><div>23</div></div><div><span>dr-xr-xr-x  2 root root  18432 May  2 18:50 NOTES</span></div></div><div><div><div>24</div></div><div><span>-r--r--r--  2 root root   5443 May  7 01:49 RELEASE-NOTES-en.html</span></div></div><div><div><div>25</div></div><div><span>dr-xr-xr-x  2 root root   2048 May  7 02:34 repodata</span></div></div><div><div><div>26</div></div><div><span>-r--r--r--  9 root root   1795 Mar  1  2005 rpm-GPG-KEY</span></div></div><div><div><div>27</div></div><div><span>-r--r--r--  2 root root   1795 Mar  1  2005 RPM-GPG-KEY-centos4</span></div></div><div><div><div>28</div></div><div><span>-r--r--r--  1 root root 571730 May  7 01:39 yumgroups.xml</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/36/</id>
      <title type="text">AppCompatActivity的标题栏上加上返回按钮</title>
      <published>2018-03-25T00:00:00.000Z</published>
      <updated>2019-10-24T02:34:21.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/36/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>一般情况下新创建的Activity默认没有添加返回按钮，目前基于android6.0版本sdk并通过android studio创建的空Activity默认都是继承自AppCompatActivity。</p><p></p><figure><img alt="微信截图_20180325171241.png" loading="lazy" width="939" height="722" src="/_astro/36.1.BwG6b1bS_ZIbaK.webp" /><figcaption>微信截图_20180325171241.png</figcaption></figure><p></p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>此时如果需要给AppCompatActivity的标题栏上加上返回按钮，可以在Activity的onCreate中加入如下代码：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>android</span><span>.</span><span>support</span><span>.</span><span>v7</span><span>.</span><span>app</span><span>.</span><span>ActionBar</span><span> actionBar </span><span><span>=</span><span> </span></span><span>getSupportActionBar</span><span><span>()</span><span>;</span></span></div></div><div><div><div>2</div></div><div><span>if</span><span><span>(actionBar </span><span>!=</span><span> </span></span><span>null</span><span>){</span></div></div><div><div><div>3</div></div><div><span>    </span><span>actionBar</span><span>.</span><span>setHomeButtonEnabled</span><span>(</span><span>true</span><span>);</span></div></div><div><div><div>4</div></div><div><span>    </span><span>actionBar</span><span>.</span><span>setDisplayHomeAsUpEnabled</span><span>(</span><span>true</span><span>);</span></div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在onOptionsItemSelected中加入如下代码：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>@</span><span>Override</span></div></div><div><div><div>2</div></div><div><span>public</span><span> </span><span>boolean</span><span> </span><span>onOptionsItemSelected</span><span>(</span><span>MenuItem</span><span> item) {</span></div></div><div><div><div>3</div></div><div><span>    </span><span>if</span><span>(</span><span>item</span><span>.</span><span>getItemId</span><span><span>()</span><span>==</span></span><span>android</span><span>.</span><span>R</span><span>.</span><span>id</span><span>.</span><span>home</span><span>){</span></div></div><div><div><div>4</div></div><div><span>        </span><span>this</span><span>.</span><span>finish</span><span>();</span></div></div><div><div><div>5</div></div><div><span>        </span><span>return</span><span> </span><span>true</span><span>;</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span>    </span><span>return</span><span> </span><span>super</span><span>.</span><span>onOptionsItemSelected</span><span>(item);</span></div></div><div><div><div>8</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/33/</id>
      <title type="text">frp内网穿透</title>
      <published>2018-03-21T00:00:00.000Z</published>
      <updated>2019-10-24T02:30:53.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/33/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>frp是一款使用go语言开发开源的内网穿透反向代理应用，通过一台拥有公网ip的服务器来转发没有公网ip服务器的端口实现反向代理，支持 tcp, udp, http, https 协议。</p><p></p><figure><img alt="1-2.png" loading="lazy" width="494" height="421" src="/_astro/33.1.xbTJJJfz_BG9vF.webp" /><figcaption>1-2.png</figcaption></figure><p></p><p></p><figure><img alt="architecture.png" loading="lazy" width="532" height="456" src="/_astro/33.2.D0D-1fCw_J08tF.webp" /><figcaption>architecture.png</figcaption></figure><p></p></section>
<section><h1>0x01 下载及配置<a href="#0x01-下载及配置"><span>#</span></a></h1><section><h2>1.下载<a href="#1下载"><span>#</span></a></h2><p>应用作者已经编译好各平台的应用，只需找到相应平台的版本即可。</p><p>例如树莓派的cpu平台是arm的，所以选择下载linux_arm</p><p>常见设备版本：</p><p><code>linux_amd64</code> linux 64位版</p><p><code>linux_386</code> linux 32位版</p><p><code>windows_amd64</code> windows 64位版</p><p><code>windows_386</code> windows 32位版</p><p><code>darwin_amd64</code> mac系统版</p><p><a href="https://github.com/fatedier/frp/releases" target="_blank">下载地址</a></p><p>2.配置
简单配置：
公网ip端使用frps和frps.ini</p><div><figure><figcaption><span>frps.ini</span></figcaption><pre><code><div><div><div>1</div></div><div><span>#必填</span></div></div><div><div><div>2</div></div><div><span>[common]</span></div></div><div><div><div>3</div></div><div><span>#连接端口，自义定不要端口冲突就好</span></div></div><div><div><div>4</div></div><div><span>bind_port</span><span><span>=</span><span>7000</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>内网端使用frpc和frpc.ini</p><div><div><div><figure><figcaption><span>frpc.ini</span><span>展开</span><span>收起</span></figcaption><pre><code><div><div><div>1</div></div><div><span>#必填</span></div></div><div><div><div>2</div></div><div><span>[common]</span></div></div><div><div><div>3</div></div><div><span>#公网ip机器的ip或网址</span></div></div><div><div><div>4</div></div><div><span>server_addr</span><span><span>=</span><span>x.x.x.x</span></span></div></div><div><div><div>5</div></div><div><span>#公网ip机器的连接端口，必须和公网机器一致</span></div></div><div><div><div>6</div></div><div><span>server_port</span><span><span>=</span><span>7000</span></span></div></div><div><div><div>7</div></div><div>
</div></div><div><div><div>8</div></div><div><span>#名字自义定</span></div></div><div><div><div>9</div></div><div><span>[test]</span></div></div><div><div><div>10</div></div><div><span>#协议类型</span></div></div><div><div><div>11</div></div><div><span>type</span><span><span>=</span><span>tcp</span></span></div></div><div><div><div>12</div></div><div><span>#要转发的本地ip</span></div></div><div><div><div>13</div></div><div><span>local_ip</span><span><span>=</span><span>127.0.0.1</span></span></div></div><div><div><div>14</div></div><div><span>#要转发的本地端口</span></div></div><div><div><div>15</div></div><div><span>local_port</span><span><span>=</span><span>1234</span></span></div></div><div><div><div>16</div></div><div><span>#公网机器转发端口，自义定不要与公网机器端口冲突就好</span></div></div><div><div><div>17</div></div><div><span>remote_port</span><span><span>=</span><span>6000</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>启动：
公网机器：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>./frps</span><span> </span><span>-c</span><span> </span><span>./frps.ini</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>内网机器：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>./frpc</span><span> </span><span>-c</span><span> </span><span>./frpc.ini</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>0x02 END
其他详情请查阅官方配置说明</p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/34/</id>
      <title type="text">Java、android彻底关闭应用方法</title>
      <published>2018-03-21T00:00:00.000Z</published>
      <updated>2019-10-24T02:31:51.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/34/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>android应用中new出很多线程在关闭应用时发现不能彻底退出。只用<code>finish()</code>方法，有时候不能彻底退出。</p>
<p>彻底退出用：<code>System.exit(0);</code></p>
<p>System.exit(0)是将你的整个虚拟机里的内容都停掉了 。内存都释放了！也就是说连JVM都关闭了，内存里根本不可能还有什么东西</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/30/</id>
      <title type="text">Android: runOnUiThread</title>
      <published>2018-03-14T00:00:00.000Z</published>
      <updated>2019-10-24T02:22:39.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/30/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>在Fragment中使用getActivity().runOnUiThread()更新Ui可能会遇到报错：</p>
<blockquote><p>java.lang.NullPointerException: Attempt to invoke virtual method ‘void android.support.v4.app.FragmentActivity.runOnUiThread(java.lang.Runnable)’ on a null object reference
at com.rehtt.app.Fragment.MainFragment$3.onFailure(MainFragment.java&lt;103&gt;)</p></blockquote>
<p>这是因为getActivity()为null所致。</p>
<p>解决方法：</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>if</span><span> (</span><span>getActivity</span><span><span>() </span><span>!=</span></span><span>null</span><span> ){</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>   </span><span>getActivity</span><span><span>()</span><span>.</span></span><span>runOnUiThread</span><span>(......);</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/29/</id>
      <title type="text">SSH免密码登录</title>
      <published>2018-03-06T00:00:00.000Z</published>
      <updated>2019-10-24T02:22:14.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/29/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00 前言<a href="#0x00-前言"><span>#</span></a></h1><p>实现ssh服务器免密码登录</p></section>
<section><h1>0x01 生成密钥<a href="#0x01-生成密钥"><span>#</span></a></h1><p>命令行:</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh-keygen</span><span> </span><span>-t</span><span> </span><span>rsa</span><span> </span><span>#使用rsa加密</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在当前用户根目录下<code>~/.ssh/</code>会生成两个文件:<code>id_rsa</code>(密钥文件),<code>id_rsa.pub</code>(公钥文件)</p></section>
<section><h1>0x02 发送公钥到服务器<a href="#0x02-发送公钥到服务器"><span>#</span></a></h1><p>1.使用ssh自带工具发送</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>ssh-copy-id</span><span> </span><span>-i</span><span> </span><span>~/.ssh/id_rsa.pub</span><span> </span><span>&lt;UserName&gt;@&lt;ServerIP&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>2.使用scp发送</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>scp</span><span> </span><span>-p</span><span> </span><span>~/.ssh/id_rsa.pub</span><span> </span><span>&lt;UserName&gt;@&lt;ServerIp&gt;:~/.ssh/authorized_keys</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x03 常见问题<a href="#0x03-常见问题"><span>#</span></a></h1><p>如果提示权限不够,修改权限即可</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>chmod</span><span> </span><span>755</span><span> </span><span>~/.ssh/</span></div></div><div><div><div>2</div></div><div><span>chmod</span><span> </span><span>600</span><span> </span><span>~/.ssh/id_rsa</span><span> </span><span>~/.ssh/id_rsa.pub</span></div></div><div><div><div>3</div></div><div><span>chmod</span><span> </span><span>644</span><span> </span><span>~/.ssh/known_hosts</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/26/</id>
      <title type="text">NodeMcu安装wifi killer</title>
      <published>2018-03-05T00:00:00.000Z</published>
      <updated>2019-10-23T13:05:27.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/26/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>所需下载：nodemcu firmware programmer（一键刷入工具），CH340G驱动（usb转串口驱动，我的板子是CH340G根据自己的情况下载并安装），wifi kllier固件（适用esp8266芯片）</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>插入板子并安装驱动，打开nodemcu firmware programmer，选择固件文件地址，选择端口，刷入
</p><figure><img alt="1.png" loading="lazy" width="715" height="416" src="/_astro/26.1.D35fsY2R_1AgRLV.webp" /><figcaption>1.png</figcaption></figure><p></p><p></p><figure><img alt="2.jpg" loading="lazy" width="452" height="332" src="/_astro/26.2.DhFyUji__1O1thr.webp" /><figcaption>2.jpg</figcaption></figure><p></p></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>进度条走完了后，左下角出现绿色的√即刷入成功</p><p>将板子拔出电源再插入电源即可开机（插入电源时板子的esp8266芯片的灯会闪一下），手机或电脑搜索名为：pwned的wifi，密码为：deauther</p><p>浏览器打开192.168.4.1进入主界面</p><p>ps.如果更改密码后忘记密码需要进行Flash清除</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/27/</id>
      <title type="text">树莓派安装Raspbian</title>
      <published>2018-03-05T00:00:00.000Z</published>
      <updated>2019-10-23T13:09:43.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/27/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>Raspbian是一个单纯的Arm版的Linux系统，基于Debian</p><p>下载文件：Raspbian（分为桌面版与无桌面版，根据所需选择），镜像写入工具（推荐Etcher）</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>将内存卡插入读卡器再插入电脑，打开<a href="https://etcher.io" target="_blank">Etcher</a>，选择镜像文件地址和要烧录的驱动器，进行烧录</p></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><section><h2>1.登录<a href="#1登录"><span>#</span></a></h2><p>raspbain默认账户是 ，密码是raspberry</p><p>登录后可运行<code>sudo passwd pi</code>来更改密码。</p></section><section><h2>2.开启Root账户<a href="#2开启root账户"><span>#</span></a></h2><p>运行<code>sudo passwd root</code>设置root密码</p><p>因为raspbain默认的root账户是锁定的，所以需运行<code>sudo passwd --unlock root</code></p></section><section><h2>3.SSH<a href="#3ssh"><span>#</span></a></h2><blockquote><p>2016-11-25 官方发布的 Raspbian 系统镜像，系统默认禁用了 SSH 服务。</p></blockquote><p>官方方案：</p><blockquote><p>SSH disabled by default; can be enabled by creating a file with name “ssh” in boot partiti.</p></blockquote><p>因此只需在/boot目录下新建一个ssh目录即可解决。</p><p>4.WiFi 网络配置</p><p>用户可以在未启动树莓派的状态下单独修改 /boot/wpa_supplicant.conf 文件配置 WiFi 的 SSID 和密码，这样树莓派启动后会自行读取<code>wpa_supplicant.conf</code>配置文件连接 WiFi 设备。</p><p>操作方法简单：将刷好 Raspbian 系统的 SD 卡用电脑读取。在 boot 分区，也就是树莓派的 <code>/boot</code> 目录下新建 <code>wpa_supplicant.conf</code> 文件，按照下面的参考格式填入内容并保存 <code>wpa_supplicant.conf</code> 文件。</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>country</span><span><span>=</span><span>CN</span></span></div></div><div><div><div>2</div></div><div><span>ctrl_interface</span><span>=</span><span>DIR</span><span><span>=</span><span>/var/run/wpa_supplicant </span></span><span>GROUP</span><span><span>=</span><span>netdev</span></span></div></div><div><div><div>3</div></div><div><span>update_config</span><span><span>=</span><span>1</span></span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>network</span><span><span>=</span><span>{</span></span></div></div><div><div><div>6</div></div><div><span>ssid</span><span>=</span><span>"WiFi-A"</span></div></div><div><div><div>7</div></div><div><span>psk</span><span>=</span><span>"12345678"</span></div></div><div><div><div>8</div></div><div><span>key_mgmt</span><span><span>=</span><span>WPA-PSK</span></span></div></div><div><div><div>9</div></div><div><span>priority</span><span><span>=</span><span>1</span></span></div></div><div><div><div>10</div></div><div><span>}</span></div></div><div><div><div>11</div></div><div>
</div></div><div><div><div>12</div></div><div><span>network</span><span><span>=</span><span>{</span></span></div></div><div><div><div>13</div></div><div><span>ssid</span><span>=</span><span>"WiFi-B"</span></div></div><div><div><div>14</div></div><div><span>psk</span><span>=</span><span>"12345678"</span></div></div><div><div><div>15</div></div><div><span>key_mgmt</span><span><span>=</span><span>WPA-PSK</span></span></div></div><div><div><div>16</div></div><div><span>priority</span><span><span>=</span><span>2</span></span></div></div><div><div><div>17</div></div><div><span>scan_ssid</span><span><span>=</span><span>1</span></span></div></div><div><div><div>18</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>说明以及不同安全性的 WiFi 配置示例：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#ssid:网络的ssid</span></div></div><div><div><div>2</div></div><div><span>#psk:密码</span></div></div><div><div><div>3</div></div><div><span>#priority:连接优先级，数字越大优先级越高（不可以是负数）</span></div></div><div><div><div>4</div></div><div><span>#scan_ssid:连接隐藏WiFi时需要指定该值为1</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>如果你的 WiFi 没有密码</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>network</span><span><span>=</span><span>{</span></span></div></div><div><div><div>2</div></div><div><span>ssid</span><span>=</span><span>"你的无线网络名称（ssid）"</span></div></div><div><div><div>3</div></div><div><span>key_mgmt</span><span><span>=</span><span>NONE</span></span></div></div><div><div><div>4</div></div><div><span>}</span></div></div><div><div><div>5</div></div><div><span>如果你的 WiFi 使用WEP加密</span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>network</span><span><span>=</span><span>{</span></span></div></div><div><div><div>8</div></div><div><span>ssid</span><span>=</span><span>"你的无线网络名称（ssid）"</span></div></div><div><div><div>9</div></div><div><span>key_mgmt</span><span><span>=</span><span>NONE</span></span></div></div><div><div><div>10</div></div><div><span>wep_key0</span><span>=</span><span>"你的wifi密码"</span></div></div><div><div><div>11</div></div><div><span>}</span></div></div><div><div><div>12</div></div><div><span>如果你的 WiFi 使用WPA/WPA2加密</span></div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>network</span><span><span>=</span><span>{</span></span></div></div><div><div><div>15</div></div><div><span>ssid</span><span>=</span><span>"你的无线网络名称（ssid）"</span></div></div><div><div><div>16</div></div><div><span>key_mgmt</span><span><span>=</span><span>WPA-PSK</span></span></div></div><div><div><div>17</div></div><div><span>psk</span><span>=</span><span>"你的wifi密码"</span></div></div><div><div><div>18</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>如果你不清楚 WiFi 的加密模式，可以在安卓手机上用 root explorer 打开 /data/misc/wifi/wpa/wpa_supplicant.conf，查看 WiFi 的信息。</p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/28/</id>
      <title type="text">树莓派zero w安装P4wnP1</title>
      <published>2018-03-05T00:00:00.000Z</published>
      <updated>2019-10-24T01:53:40.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/28/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>P4wnP1是一个高度可定制的usb攻击平台，可在zero和zero w上运行（zero w上功能100%兼容）。</p><div><div><div></div><div>Caution</div></div><div><p>本教程仅用于学习交流</p></div></div><p><a href="http://p4wnp1.readthedocs.io/en/latest/" target="_blank">P4wnP1帮助文档</a></p><p><a href="https://github.com/mame82/P4wnP1" target="_blank">P4wnP1作者GitHub</a></p><p><a href="/posts/61/">P4wnP1通过usb连接网络</a></p><p>0x01
1 首先下载并刷入树莓派官方系统<a href="https://www.raspberrypi.org/downloads/raspbian/" target="_blank">raspbain</a>，<a href="/posts/27/">安装教程</a>，建议更改密码以免被别人反（bao）黑（ju）。</p><p>2  安装git，下载安装P4wnP1</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt-get</span><span> </span><span>-y</span><span> </span><span>install</span><span> </span><span>git</span></div></div><div><div><div>2</div></div><div><span>cd</span><span> </span><span>/home/pi</span></div></div><div><div><div>3</div></div><div><span>git</span><span> </span><span>clone</span><span> </span><span>--recursive</span><span> </span><span>https://github.com/mame82/P4wnP1</span></div></div><div><div><div>4</div></div><div><span>cd</span><span> </span><span>P4wnP1</span></div></div><div><div><div>5</div></div><div><span>./install.sh</span></div></div><div><div><div>6</div></div><div><span>sudo</span><span> </span><span>reboot</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>搜索名为<code>P4wnP1</code>的wifi</p><p>密码为<code>MaMe82-P4wnP1</code></p><p>ssh连接<code>pi@127.16.0.1</code></p></section>
<section><h1>0x03<a href="#0x03"><span>#</span></a></h1><p>配置P4wnP1</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>nano</span><span> </span><span>setup.cfg</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p></p><figure><img alt="界面" loading="lazy" width="690" height="1227" src="/_astro/28.1.Hyt48vSv_Z2ae7et.webp" /><figcaption>界面</figcaption></figure><p></p><p>（图片转自：<a href="http://image.3001.net/images/20171003/15069622944860.png!small%EF%BC%89" target="_blank">http://image.3001.net/images/20171003/15069622944860.png!small）</a></p><p>这个配置文件的话可以修改wifi的名字还有密码</p><p>还有键盘语言之类的底部有payload选择</p><p>刚开始的时候 <code>playload=network_only.txt</code>前面加上<code>#</code></p><p>每次只能执行一个payload</p><p>然后选择执行的payload即可(去掉注释即可执行payload)</p><p>比如选择<code>hid_backdoor</code>的话就去去掉<code>#PAYLOAD=hid_backdoor_remote.txt</code></p><p>前面的<code>#</code></p><p>如下图:
</p><figure><img alt="请输入图片描述" loading="lazy" width="690" height="1227" src="/_astro/28.2.BWnKyZlz_JwgH6.webp" /><figcaption>请输入图片描述</figcaption></figure>
（图片转自：<a href="http://image.3001.net/images/20171003/15069623442312.png!small%EF%BC%89" target="_blank">http://image.3001.net/images/20171003/15069623442312.png!small）</a><p></p><p>米特尼克在defcon上那个解锁win10锁屏界面这个程序也是可以给你实现的，那个就是 <code>PAYLOAD=Win10_LockPicker.txt</code></p><p>hash密码文件存储在<code>P4wnP1/responder/logs/</code>文件夹里</p><p>其他更多功能可以输入<code>help</code>查看</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/22/</id>
      <title type="text">ESP8266清除Flash数据</title>
      <published>2018-03-04T00:00:00.000Z</published>
      <updated>2019-10-23T12:41:57.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/22/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x00<a href="#0x00"><span>#</span></a></h1><p>一键刷入固件工具只能向8266写入固件程序，无法对flash进行擦除操作，因而可能会由于某些原因造成烧录的固件运行不正常。</p><p>这里使用的是esptool.py，在python2.7环境下运行，python3.0可能会出错。</p></section>
<section><h1>0x01<a href="#0x01"><span>#</span></a></h1><p>使用pip自动安装esptool</p><p>命令：pip install esptool</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>pip</span><span> </span><span>install</span><span> </span><span>pyserial</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>0x02<a href="#0x02"><span>#</span></a></h1><p>注意下面命令中的串口需要根据实际串口设定，如果擦除的速度过快（不到1S），很可能没有完全擦除，这是可以再擦除一次。擦除时和刷固件一样，需要保持按住Flash按键然后再按下并释放RESET按键，然后在进行擦除。</p><p>在Linux下：<code>esptool.py --port /dev/ttyUSB0 erase_flash</code>
在Windows下：<code>c:\Python27\Scripts\esptool.py --port /COM9 erase_flash</code></p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/21/</id>
      <title type="text">中间人攻击-简单窃听</title>
      <published>2018-02-26T00:00:00.000Z</published>
      <updated>2019-10-23T12:39:57.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/21/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x01前提<a href="#0x01前提"><span>#</span></a></h1><p>攻击者与目标要位于同一路由网络下</p><p>使用工具：kali linux（ettercap+wireshark+dsniff）</p></section>
<section><h1>（本教程仅用于学术交流）<a href="#本教程仅用于学术交流"><span>#</span></a></h1></section>
<section><h1>0x02过程<a href="#0x02过程"><span>#</span></a></h1><p>终端输入<code>echo 1 &gt; /proc/sys/net/ipv4/ip_forward</code>开启转发保证目标能正常上网</p><section><h2>一。开启嗅探<a href="#一开启嗅探"><span>#</span></a></h2><p>终端输入<code>ettercap -G</code>打开<code>ettercap</code>界面，选择<code>Sniff</code> –&gt; <code>Unified sniffing</code> –&gt; 选择你对应的网卡 –&gt; <code>Hosts</code> –&gt; <code>Scan for hosts</code> –&gt; <code>Hosts list</code> –&gt; 将目标ip添加到<code>Target 1</code>，将路由器ip添加到<code>Target 2</code> –&gt; <code>Mitm</code> –&gt; <code>APR poisoning</code> –&gt; <code>Sniff remote connections</code> –&gt; <code>Start</code> –&gt; <code>Start sniffing</code></p></section><section><h2>二。监听数据<a href="#二监听数据"><span>#</span></a></h2><p>终端输入<code>driftnet -i eth0</code>（我嗅探使用的网卡是eth0，具体情况具体填写），弹出一个窗口会显示目标正在浏览的图片。</p><p>终端输入<code>urlsnarf -i eth0</code> 监听目标浏览过的网页日志。</p><p>打开wireshark进行抓包。</p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/19/</id>
      <title type="text">new一个对象的引用在循环里与循环外的区别</title>
      <published>2018-02-14T00:00:00.000Z</published>
      <updated>2019-10-23T12:34:00.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/19/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>for</span><span>(</span><span>int</span><span> i</span><span>=</span><span>0</span><span><span>;</span><span>i</span><span>&lt;</span></span><span>100</span><span><span>;</span><span>i</span><span>++</span><span>){</span></span></div></div><div><div><div>2</div></div><div><span>Object</span><span> obj </span><span><span>=</span><span> </span></span><span>new</span><span> </span><span>Object</span><span><span>()</span><span>;</span></span></div></div><div><div><div>3</div></div><div><span>}</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>Object</span><span> obj</span><span>;</span></div></div><div><div><div>7</div></div><div><span>for</span><span>(</span><span>int</span><span> i</span><span>=</span><span>0</span><span><span>;</span><span>i</span><span>&lt;</span></span><span>100</span><span><span>;</span><span>i</span><span>++</span><span>){</span></span></div></div><div><div><div>8</div></div><div><span><span>obj  </span><span>=</span><span> </span></span><span>new</span><span> </span><span>Object</span><span><span>()</span><span>;</span></span></div></div><div><div><div>9</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>以上分别为在循环里与循环外new对象。</p>
<p>在循环里就相当于为100个引用了100个对象分配内存，直到内存不足会被GC释放。</p>
<p>在循环外使用1个引用分别100次调用了100个对象所以当后一个对象init后，前一个对象已经是“无引用状态”，会很快的被GC自动回收(在你的循环还未结束时，可能已经进行了多次GC回收，这点很重要)。</p>
<p>也就是说第二种方法能更好的管理内存。</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/20/</id>
      <title type="text">Android自带抽屉布局及NavigationView的使用</title>
      <published>2018-02-14T00:00:00.000Z</published>
      <updated>2019-10-23T12:36:51.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/20/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<blockquote><p>转自：<a href="https://segmentfault.com/a/1190000004151222" target="_blank">https://segmentfault.com/a/1190000004151222</a></p></blockquote>
<p>获取<code>NavigationView</code>的中的控件出现空指针异常
我们在<code>Navigation Drawer Activity</code>中获取控件，第一反应就是直接在<code>onCreateView</code>里调用<code>findViewById</code>,例如我想获取上图中的<code>TextView</code>，假如id为<code>tv_user</code></p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>TextView</span><span> tv </span><span><span>=</span><span> (TextView)</span></span><span>findViewById</span><span>(</span><span>R</span><span>.</span><span>id</span><span>.</span><span>tv_user</span><span><span>)</span><span>;</span></span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>然后给tv改下字</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>tv</span><span>.</span><span>setText</span><span>(</span><span>"Hello world"</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>这时候就会报错说tv为空指针。问题引起其实非常简单，是因为在activity刚创建的时候，Dawer其实是没有打开的，所以布局没有初始化，自然也不能找到其中的空间。一般这种情况我们为了获取这类未初始布局里的空间会使用inflate方法，这里其实处理是类似的，后面会提到。</p>
<p>我们首先了解一下NavigationView的使用，新建一个抽屉活动后，我们可以看到主界面的布局文件是这样的</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span><span>    </span></span><span>&lt;?</span><span>xml</span><span> version</span><span>=</span><span>"1.0"</span><span> encoding</span><span>=</span><span>"utf-8"</span><span>?&gt;</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>&lt;</span><span>android.support.v4.widget.DrawerLayout</span><span> </span><span>xmlns:android</span><span>=</span><span>"http://schemas.android.com/apk/res/android"</span></div></div><div><div><div>3</div></div><div><span>        </span><span>xmlns:app</span><span>=</span><span>"http://schemas.android.com/apk/res-auto"</span></div></div><div><div><div>4</div></div><div><span>        </span><span>xmlns:tools</span><span>=</span><span>"http://schemas.android.com/tools"</span></div></div><div><div><div>5</div></div><div><span>        </span><span>android:id</span><span>=</span><span>"@+id/drawer_layout"</span></div></div><div><div><div>6</div></div><div><span>        </span><span>android:layout_width</span><span>=</span><span>"match_parent"</span></div></div><div><div><div>7</div></div><div><span>        </span><span>android:layout_height</span><span>=</span><span>"match_parent"</span></div></div><div><div><div>8</div></div><div><span>        </span><span>android:fitsSystemWindows</span><span>=</span><span>"true"</span></div></div><div><div><div>9</div></div><div><span>        </span><span>tools:openDrawer</span><span>=</span><span>"start"</span><span>&gt;</span></div></div><div><div><div>10</div></div><div>
</div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>&lt;</span><span>include</span></div></div><div><div><div>12</div></div><div><span>            </span><span>layout</span><span>=</span><span>"@layout/app_bar_main"</span></div></div><div><div><div>13</div></div><div><span>            </span><span>android:layout_width</span><span>=</span><span>"match_parent"</span></div></div><div><div><div>14</div></div><div><span>            </span><span>android:layout_height</span><span>=</span><span>"match_parent"</span><span> /&gt;</span></div></div><div><div><div>15</div></div><div>
</div></div><div><div><div>16</div></div><div><span><span>        </span></span><span>&lt;</span><span>android.support.design.widget.NavigationView</span></div></div><div><div><div>17</div></div><div><span>            </span><span>android:id</span><span>=</span><span>"@+id/nav_view"</span></div></div><div><div><div>18</div></div><div><span>            </span><span>android:layout_width</span><span>=</span><span>"wrap_content"</span></div></div><div><div><div>19</div></div><div><span>            </span><span>android:layout_height</span><span>=</span><span>"match_parent"</span></div></div><div><div><div>20</div></div><div><span>            </span><span>android:layout_gravity</span><span>=</span><span>"start"</span></div></div><div><div><div>21</div></div><div><span>            </span><span>android:fitsSystemWindows</span><span>=</span><span>"true"</span></div></div><div><div><div>22</div></div><div><span>            </span><span>app:headerLayout</span><span>=</span><span>"@layout/nav_header_main"</span></div></div><div><div><div>23</div></div><div><span>            </span><span>app:menu</span><span>=</span><span>"@menu/activity_main_drawer"</span><span> /&gt;</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span><span>    </span></span><span>&lt;/</span><span>android.support.v4.widget.DrawerLayout</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<p>其实这里的NavigationView就是左边抽屉拉出来后的布局了~可以看到它有两个属性app:headerLayout和app</p><menu></menu>
其实这两个属性后面就分别是上图中蓝色背景部分的抽屉头和下面的菜单。要对其编辑也很简单，进入ID对应的布局修改即可。<p></p>
<p>操作1：
前面提到的获取不到控件的方法，可以在onCreate方法中这样来获取</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>    </span><span>View</span><span> headerLayout </span><span><span>=</span><span> </span></span><span>navigationView</span><span>.</span><span>inflateHeaderView</span><span>(</span><span>R</span><span>.</span><span>layout</span><span>.</span><span>nav_header_main</span><span>);</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>tv_nav_user </span><span>=</span><span> (TextView)</span><span>headerLayout</span><span>.</span><span>findViewById</span><span>(</span><span>R</span><span>.</span><span>id</span><span>.</span><span>tv_nav_username</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>通过查看谷歌官方开发文档我们还可以发现几个方法
<code>http://developer.android.com/reference/android/support/design/widget/NavigationView.html</code></p>
<p>这时会发现有两个头，解决方法也很简单，就是在layout文件中去掉</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>app:headerLayout="@layout/nav_header_main"</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>然后就可以获取到里面的控件愉快玩耍了~</p>
<p>补充：
其实如果不用上面的方法的话也是可以直接获取到header的，可以调用</p>
<div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>View</span><span> headerView </span><span><span>=</span><span> </span></span><span>navigationView</span><span>.</span><span>getHeaderView</span><span>(</span><span>0</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>来获得头部布局</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/18/</id>
      <title type="text">Weevely 介绍</title>
      <published>2018-02-02T00:00:00.000Z</published>
      <updated>2019-10-23T12:32:00.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/18/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>0x0前言</p>
<blockquote><p>Weevely is a stealth PHP web shell that simulate telnet-like connection. It is an essential tool for web application post exploitation, and can be used as stealth backdoor or as a web shell to manage legit web accounts, even free hosted ones.</p></blockquote>
<p>Weevely是一个用python写的一个作用于php的web shell工具，可以很好帮助开发者进行开发，但是它又是一个很好的php后门程序。</p>
<p>（仅用于安全学习教学之用，禁止非法用途）</p>
<p>项目地址：<code>https://github.com/epinna/Weevely</code></p>
<p>环境：python&gt;= 2.7.10</p>
<p>linux环境安装：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># Make sure that the python package manager and yaml libraries are installed</span></div></div><div><div><div>2</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>apt-get</span><span> </span><span>install</span><span> </span><span>g++</span><span> </span><span>python-pip</span><span> </span><span>libyaml-dev</span><span> </span><span>python-dev</span><span> </span><span>libncurses5-dev</span></div></div><div><div><div>3</div></div><div><span># Install requirements from within the weevely3/ folder</span></div></div><div><div><div>4</div></div><div><span>$</span><span> </span><span>cd</span><span> </span><span>weevely3/</span></div></div><div><div><div>5</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>pip</span><span> </span><span>install</span><span> </span><span>-r</span><span> </span><span>requirements.txt</span><span> </span><span>--upgrade</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>OS X环境安装：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>port</span><span> </span><span>install</span><span> </span><span>python27</span><span> </span><span>py27-pip</span></div></div><div><div><div>2</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>port</span><span> </span><span>select</span><span> </span><span>--set</span><span> </span><span>pip</span><span> </span><span>pip27</span></div></div><div><div><div>3</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>port</span><span> </span><span>select</span><span> </span><span>--set</span><span> </span><span>python</span><span> </span><span>python27</span></div></div><div><div><div>4</div></div><div><span># Ideally, at this point you should install editline library (http://thrysoee.dk/editline/)</span></div></div><div><div><div>5</div></div><div><span># to have a working line completion in terminal. See issue #7 for more info.</span></div></div><div><div><div>6</div></div><div><span># Install requirements from within the weevely3/ folder</span></div></div><div><div><div>7</div></div><div><span>$</span><span> </span><span>cd</span><span> </span><span>weevely3/</span></div></div><div><div><div>8</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>pip</span><span> </span><span>install</span><span> </span><span>-r</span><span> </span><span>requirements.txt</span><span> </span><span>--upgrade</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>Windows环境安装：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># Enter in a folder which allows to </span><span>call</span><span> pip.exe usually C:\Python27\Scripts\ with no </span><span>%PATH%</span><span> </span><span>set</span><span> and</span></div></div><div><div><div>2</div></div><div><span># install the following requirements</span></div></div><div><div><div>3</div></div><div><span>&gt; pip install prettytable Mako PyYAML python-dateutil pyreadline PySocks --upgrade</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<section><h1>0x1生成后门文件<a href="#0x1生成后门文件"><span>#</span></a></h1><p>可以生成三种文件后门：</p><ul>
<li>
<p>php（生成php后门文件）</p>
</li>
<li>
<p>img（将后门代码插入到图片中，并修改.htaccess，该后门需要服务器开启.htaccess）</p>
</li>
<li>
<p>htaccess（将后门代码插入到.htaccess，同样需要开启.htaccess支持）</p>
</li>
</ul><p>使用：</p><p>格式：<code>weevely generate &lt;password&gt; &lt;path&gt;</code></p><p>例子：<code>weevely generate mypassword ~/test.php</code>（生成了一名为“test.php”密码为“mypassword”的php后门。最好在文件名前加路径，不然可能生成的文件在weevely的根目录下）</p><p><code>weevely generate mypassword ~/test.jpg</code>（生成了一名为“test.php”密码为“mypassword”的图片后门）</p></section>
<section><h1>0x2连接<a href="#0x2连接"><span>#</span></a></h1><p>格式：<code>weevely &lt;URL&gt; &lt;password&gt; [cmd]</code></p><p>例子：<code>weevely http://127.0.0.1/test.php mypassword</code>（连接了php后门。连接img或htaccess后门需要开启服务器对htaccess的支持）</p></section>
<section><h1>0x3操作<a href="#0x3操作"><span>#</span></a></h1><p>连接成功后即可对服务器进行相应操作。</p><p><code>－audit.userfiles</code>          枚举用户目录下的具有权限的文件（可加载用户字典），默认情况下字典很小（注意：该模块目前只支持linux，windows不支持）</p><p><code>－audit.systemfiles [logs|root|home|…]</code>                    枚举各种系统目录并寻找可读写的目录，模块仅默认搜索部分linux下的常见目录，logs、root、home等等（注意：该模块也仅支持linux，windows不支持）</p><p><code>－audit.phpconf</code>                查看php配置信息</p><p><code>－audit.etcpasswd [-real]</code>          查看/etc/passwd文件（特殊说明：很多命令的-vector参数是用以指定php执行命令函数的，当默认函数不可用是，使用该参数来尝试指定其他命令执行函数来获取信息），同时也可使用-real参数来过滤出真实用户</p><p><code>－audit.mapwebfiles</code>                从制定url开始爬取目标站点结构，可用-depth参数来指定爬取深度</p><p><code>－shell.sh/shell.php</code>                利用接口执行命令，和虚拟终端类似</p><p><code>－system.info</code>                     在weevely里比较由用的一个模块，可以获取到系统的基本信息</p><p><code>－backdoor.reverstcp host port [-vector]</code>           反弹一个tcp shell到目标端口（同样也可指定向量：选择反弹shell的形式，nc，perl，ruby等）</p><p><code>－backdoor.tcp -port &lt;listen_port&gt; -no-connect [-vector]</code>            在本地打开一个端口，等待连接（查看了该模块的源码，使用时必须带上-no-connect才能监听成功，负责他会在本地形成一个tcp环路）</p><p><code>－net.ifaces</code>            查看网络ip地址</p><p><code>－file.upload lpath rpath</code>               上传本地文件到目标站点指定路径</p><p><code>－file.rm filename [-recursive] [-vector]</code>                 删除指定文件，可开启安全确认模式</p><p><code>－file.check</code>            用以检查目标站点下文件的状态（md5值，大小，权限等）</p><p><code>－file.download rpath lpath [-vector]</code>                将目标站点上的文件下载到本地（可用于批量会话操作）</p><p><code>－file.edit filename</code>                对指定文件进行编辑</p><p><code>－file.read filename</code>             读取指定文件内容</p><p><code>－file.ls path</code>               列觉指定路径的文件信息</p><p><code>－file.upload2web</code>           将本地文件上传至目标站点文件夹（可自动枚举到一个可写目录将其写入）</p><p><code>－file.webdownload &lt;webfile_path&gt; filename</code>            从其他服务器上下载文件到目标站点</p><p><code>－file.touch rpath</code>               创建一个新文件</p><p><code>－bruteforce.sql</code>                  爆破指定数据库用户名密码</p><p><code>－bruteforce.sqlusers</code>        爆破所有数据库用户密码</p><p><code>－sql.dump</code>           脱裤，你懂的 ^_^</p><p><code>－sql.console</code>        sql交互式终端</p><p><code>－net.scan</code>              端口扫描</p><p><code>－find.perms</code>          搜索具有读、写、执行权限的文件，好像比较给力</p><p><code>－find.suidsgid</code>       搜索linux具有suid或者sgid标记的文件</p><p><code>－find.name</code>            查找某文件或者文件夹</p></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/17/</id>
      <title type="text">延时拍照</title>
      <published>2018-01-05T00:00:00.000Z</published>
      <updated>2019-10-23T12:24:10.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/17/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>import</span><span> os</span></div></div><div><div><div>2</div></div><div><span>import</span><span> time</span></div></div><div><div><div>3</div></div><div>
</div></div><div><div><div>4</div></div><div><span>def</span><span> </span><span>main</span><span>():</span></div></div><div><div><div>5</div></div><div><span><span>    </span></span><span>i </span><span>=</span><span> </span><span>0</span></div></div><div><div><div>6</div></div><div><span>    </span><span>while</span><span><span> i </span><span>&lt;</span><span> </span></span><span>1000</span><span>:</span></div></div><div><div><div>7</div></div><div><span><span>        </span></span><span>res </span><span>=</span><span> </span><span>"raspistill -t 1 -o img/"</span><span>+</span><span>str</span><span><span>(i)</span><span>+</span></span><span>".jpg"</span></div></div><div><div><div>8</div></div><div><span>        </span><span># os.system(res)</span></div></div><div><div><div>9</div></div><div><span>        </span><span>print</span><span>(res)</span></div></div><div><div><div>10</div></div><div><span><span>        </span></span><span>i </span><span>+=</span><span> </span><span>1</span></div></div><div><div><div>11</div></div><div><span><span>        </span></span><span>time.</span><span>sleep</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div>
</div></div><div><div><div>14</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>'__main__'</span><span>:</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>main</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/16/</id>
      <title type="text">Python项目打包成exe文件</title>
      <published>2017-12-18T00:00:00.000Z</published>
      <updated>2019-10-23T12:22:14.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/16/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<blockquote><p>[转]<a href="https://note.youdao.com/share/?id=4ed1687d752255b2f44b34bab3c719a8&amp;type=note#/" target="_blank">https://note.youdao.com/share/?id=4ed1687d752255b2f44b34bab3c719a8&amp;type=note#/</a></p></blockquote>
<p>CMD下输入:<code>py -m pip install pyinstaller</code>，安装pyinstaller。</p>
<p>在要制作的exe文件目录输入<code>pyinstaller -F -w *.py</code>，就可以制作出exe。生成的文件放在同目录dist下。
<code>-F</code>（注意大写）是所有库文件打包成一个exe
<code>-w</code>是不出黑色控制台窗口。
不加-F参数生成一堆文件，但运行快。压缩后比单个exe文件还小一点点。
加-F参数生成一个exe文件，运行起来慢。
按照第一步的方法，将pyinstaller加入pycharm的external tool，我加了两个，一个生成单独exe文件，一个生成运行带库的程序目录。</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/15/</id>
      <title type="text">frp开机启动与自动检查运行脚本(Python)</title>
      <published>2017-12-08T00:00:00.000Z</published>
      <updated>2019-10-23T12:19:36.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/15/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/python</span></div></div><div><div><div>2</div></div><div><span>import</span><span> os</span></div></div><div><div><div>3</div></div><div><span>import</span><span> time</span></div></div><div><div><div>4</div></div><div><span>import</span><span> commands</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>##开启frp</span></div></div><div><div><div>7</div></div><div><span>def</span><span> </span><span>start</span><span>():</span></div></div><div><div><div>8</div></div><div><span><span>    </span></span><span>os.</span><span>system</span><span>(</span><span>'/home/pi/frp/frpc -c /home/pi/frp/frpc.ini &gt; /dev/null 2&gt;&amp;1 &amp;'</span><span>)</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>##检查是否运行frp</span></div></div><div><div><div>11</div></div><div><span>def</span><span> </span><span>state</span><span>():</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>out</span><span>=</span><span>commands.</span><span>getoutput</span><span>(</span><span>'ps aux|grep frpc|grep -v grep'</span><span>)</span></div></div><div><div><div>13</div></div><div><span>    </span><span>return</span><span> out</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>def</span><span> </span><span>main</span><span>():</span></div></div><div><div><div>16</div></div><div><span>    </span><span>while</span><span>(</span><span>True</span><span>):</span></div></div><div><div><div>17</div></div><div><span>        </span><span>if</span><span> </span><span>"-c"</span><span> </span><span>in</span><span><span> </span><span>state</span><span>() :</span></span></div></div><div><div><div>18</div></div><div><span>            </span><span>pass</span></div></div><div><div><div>19</div></div><div><span>        </span><span>else</span><span>:</span></div></div><div><div><div>20</div></div><div><span><span>            </span></span><span>start</span><span>()</span></div></div><div><div><div>21</div></div><div><span><span>            </span></span><span>time.</span><span>sleep</span><span>(</span><span>15</span><span>)      </span><span>##休眠15秒后再次检查</span></div></div><div><div><div>22</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>'__main__'</span><span>:</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>time.</span><span>sleep</span><span>(</span><span>15</span><span>)        </span><span>##开机后延时15秒</span></div></div><div><div><div>24</div></div><div><span><span>    </span></span><span>main</span><span>()</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/13/</id>
      <title type="text">树莓派配置迅雷远程下载</title>
      <published>2017-12-04T00:00:00.000Z</published>
      <updated>2019-10-23T12:11:17.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/13/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>0x01.配置<a href="#0x01配置"><span>#</span></a></h1><p>所用固件为<code>Xware1.0.31_armel_v5te_glibc</code>固件，下载链接: <code>https://pan.baidu.com/s/1jI7YmEi</code> 密码: <code>gxxv</code></p><p>下载</p><p>首先在<code>/mnt</code>建立一个新文件夹：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>mkdir</span><span> </span><span>/mnt/thunder</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>将下载文件存放目录挂载在刚刚建的文件夹下：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>mount</span><span> </span><span>--bind</span><span> </span><span>/home/pi/download</span><span> </span><span>/mnt/thunder</span><span>(</span><span>解除挂载只需将--bind换为--move即可</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>将下载好的固件解压并运行portal文件：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>chmod</span><span> </span><span>+x</span><span> </span><span>./portal</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>./portal</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>运行后找到<code>the active code is</code>复制后面的激活码，等迅雷远程下载进行绑定。</p></section>
<section><h1>0x02.查看状态<a href="#0x02查看状态"><span>#</span></a></h1><p>同一局域网下浏览器输入：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>http://树莓派ip:9000/getsysinfo</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>其中有用的几项为：</p><p>第一项：0表示返回结果成功
第二项：1表示检测网络正常，0表示检测网络异常
第四项：1表示已绑定成功，0表示未绑定
第五项：未绑定的情况下，为绑定的需要的激活码
第六项：1表示磁盘挂载检测成功，0表示磁盘挂载检测失败</p></section>
<section><h1>0x03.迅雷路由器固件开机启动<a href="#0x03迅雷路由器固件开机启动"><span>#</span></a></h1><p>在<code>/etc/init.d/</code>下新建xunlei脚本，写入:</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/bin/sh</span></div></div><div><div><div>2</div></div><div><span>#</span></div></div><div><div><div>3</div></div><div><span># Xunlei initscript</span></div></div><div><div><div>4</div></div><div><span>#</span></div></div><div><div><div>5</div></div><div><span>### BEGIN INIT INFO</span></div></div><div><div><div>6</div></div><div><span># Provides: xunlei</span></div></div><div><div><div>7</div></div><div><span># Required-Start: $network $local_fs $remote_fs</span></div></div><div><div><div>8</div></div><div><span># Required-Stop:: $network $local_fs $remote_fs</span></div></div><div><div><div>9</div></div><div><span># Should-Start: $all</span></div></div><div><div><div>10</div></div><div><span># Should-Stop: $all</span></div></div><div><div><div>11</div></div><div><span># Default-Start: 2 3 4 5</span></div></div><div><div><div>12</div></div><div><span># Default-Stop: 0 1 6</span></div></div><div><div><div>13</div></div><div><span># Short-Description: Start xunlei at boot time</span></div></div><div><div><div>14</div></div><div><span># Description: A downloader</span></div></div><div><div><div>15</div></div><div><span>### END INIT INFO</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>do_start</span><span>()</span></div></div><div><div><div>18</div></div><div><span>{</span></div></div><div><div><div>19</div></div><div><span>./root/xunlei/portal</span></div></div><div><div><div>20</div></div><div><span>}</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>do_stop</span><span>()</span></div></div><div><div><div>23</div></div><div><span>{</span></div></div><div><div><div>24</div></div><div><span>./root/xunlei/portal</span><span> </span><span>-s</span></div></div><div><div><div>25</div></div><div><span>}</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>case</span><span> </span><span>"</span><span>$1</span><span>"</span><span> </span><span>in</span></div></div><div><div><div>28</div></div><div><span>start</span><span>)</span></div></div><div><div><div>29</div></div><div><span>do_start</span></div></div><div><div><div>30</div></div><div><span>;;</span></div></div><div><div><div>31</div></div><div><span>stop</span><span>)</span></div></div><div><div><div>32</div></div><div><span>do_stop</span></div></div><div><div><div>33</div></div><div><span>;;</span></div></div><div><div><div>34</div></div><div><span>esac</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><p>然后将该脚本加入默认自启动中</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>update-rc.d</span><span> </span><span>xunlei</span><span> </span><span>defaults</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/14/</id>
      <title type="text">Linux开机启动脚本编写</title>
      <published>2017-12-04T00:00:00.000Z</published>
      <updated>2019-10-23T12:17:26.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/14/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h2>两种方法：<a href="#两种方法"><span>#</span></a></h2></section>
<section><h1>0.编写rc.loacl脚本<a href="#0编写rcloacl脚本"><span>#</span></a></h1><p>Ubuntu开机之后会执行<code>/etc/rc.local</code>文件中的脚本，
所以我们可以直接在<code>/etc/rc.local</code>中添加启动脚本。
要添加到语句exit 0 前面才行。
此脚本在完全开机后才执行，所以优先级最低。</p></section>
<section><h1>1.编写init.d脚本<a href="#1编写initd脚本"><span>#</span></a></h1><p>在<code>/etc/init.d</code>建立脚本，然后用软链接链接到<code>rc?.d</code>文件夹中。</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>/etc  下有 rc0.d  -- rc6.d</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span>分别代表不同的级别：</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>0: 关闭计算机</span></div></div><div><div><div>6</div></div><div><span>1: 单用户模式</span></div></div><div><div><div>7</div></div><div><span>2: 无网络多用户模式</span></div></div><div><div><div>8</div></div><div><span>3: 有网络多用户模式</span></div></div><div><div><div>9</div></div><div><span>4: 保留作自定义，否则同运行级 3</span></div></div><div><div><div>10</div></div><div><span>5: 同运行级 4，一般用于图形界面(GUI)登录(如 X的 xdm 或 KDE的 kdm)</span></div></div><div><div><div>11</div></div><div><span>6: 重启动计算机</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>在 <code>/etc/rc?.d</code> 每个目录下都包含许多符号链接，其中一些以 K 字母开头，另外一些以 S 字母开头， 这些链接名在首字母后面都跟着两个数字。 这个 K 的含义是停止 (kill) 一个服务， S 的含义是启动一个服务。而数字则确定这些脚本的启动顺序，从 00 到 99(数字越小执行的越早)。 当 init 转换到其它运行级时， 一些相应的服务会停止， 而另一些服务则会启动。</p><p>真正的脚本在 <code>/etc/init.d</code> 目录下， 它们完成实际工作， 符号链接都是指向它们的。 停止脚本的链接和启动脚本的链接都指向 <code>/etc/init.d</code> 目录下的同一个脚本。 这是因为调用这些脚本时可以使用不同的参数，例如 <code>start</code>, <code>stop</code>, <code>restart</code>, <code>reload</code>, 和 <code>status</code>。 当调用 K 链接时，相应的脚本用 stop参数运行；当调用 S 链接时，相应的脚本用start 参数运行。</p><p>上面的说明有一个例外，在 <code>rc0.d</code> 和 <code>rc6.d</code> 目录下以 S 开头的链接不会启动任何东西， 而是用stop参数调用， 来停止某些服务。 这背后的逻辑是， 当用户要重启或关闭系统的时候， 不会要启动什么服务， 只会要系统停止。</p><p>以下是脚本参数的描述：</p><p><code>start</code>
启动服务。
<code>stop</code>
停止服务。
<code>restart</code>
关闭服务，然后再启动。
<code>reload</code>
该服务的配置已更新。如果修改了某个服务的配置文件，又不必重启这个服务的时候， 可以使用这个参数
<code>status</code>
显示服务的状态，如果服务正在运行，会显示该服务进程的 PID 。</p><p>您可以自由修改启动进程工作的方式。 我们这里给出的文件只是它们怎样工作的一个示例而已。</p><p>脚本实例：</p><div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>    </span><span>#!/bin/sh</span></div></div><div><div><div>2</div></div><div><span>    </span><span>#chkconfig:2345 80 05 --指定在哪几个级别执行，0一般指关机，6指的是重启，其他为正常启动。80为启动的优先级，05为关闭的优先级别</span></div></div><div><div><div>3</div></div><div><span>    </span><span>#description:simple example service</span></div></div><div><div><div>4</div></div><div><span>    </span><span>RETVAL</span><span>=</span><span>0</span></div></div><div><div><div>5</div></div><div><span>    </span><span>start</span><span>(){ </span><span>#启动服务的入口函数</span></div></div><div><div><div>6</div></div><div><span>        </span><span>echo</span><span>  </span><span>"simple example service is started..."</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>    </span><span>stop</span><span>(){ </span><span>#关闭服务的入口函数</span></div></div><div><div><div>10</div></div><div><span>        </span><span>echo</span><span>  </span><span>"simple example service is stoped..."</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span>    </span><span>#使用case选择</span></div></div><div><div><div>14</div></div><div><span>    </span><span>case</span><span><span> </span><span>$1</span><span> </span></span><span>in</span></div></div><div><div><div>15</div></div><div><span>    </span><span>start</span><span>)</span></div></div><div><div><div>16</div></div><div><span>        </span><span>start</span><span>  </span><span>#调用上面的start函数</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>18</div></div><div><span>    </span><span>stop</span><span>)</span></div></div><div><div><div>19</div></div><div><span>        </span><span>stop</span><span>   </span><span>#调用上面的stop函数</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>;;</span></div></div><div><div><div>21</div></div><div><span><span>    </span></span><span>*)</span></div></div><div><div><div>22</div></div><div><span>        </span><span>echo</span><span> </span><span>"error choice ! please input start or stop"</span><span>;;</span></div></div><div><div><div>23</div></div><div><span>    </span><span>esac</span></div></div><div><div><div>24</div></div><div><span>    </span><span>exit</span><span> </span><span>$RETVAL</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># chmod +x /etc/init.d/bin.sh //加可执行权限</span></div></div></code></pre><div><div></div><div></div></div></figure></div><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># /etc/init.d/bin.sh start //测试</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>将启动脚本链接到 <code>/etc/rc2.d</code></p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span># ln -s /etc/init.d/bin.sh /etc/rc2.d/S20bin //作用：开机启动时会执行 /etc/init.d/bin.sh start</span></div></div><div><div><div>2</div></div><div>
</div></div><div><div><div>3</div></div><div><span># ln -s /etc/init.d/bin.sh /etc/rc0.d/K20bin</span></div></div><div><div><div>4</div></div><div><span>//作用：</span><span> </span><span>关闭计算机时执行</span><span> </span><span>/etc/init.d/bin.sh</span><span> </span><span>stop</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>2.当上一中没效果是可以试试这个
脚本还是上一个的脚本，但链接方法有变。
使用：<code>update-rc.d xxx defaults NN</code>命令(NN为启动顺序)，
将脚本添加到初始化执行的队列中去。
注意如果脚本需要用到网络，则NN需设置一个比较大的数字，如99。</p><ol>
<li>将你的启动脚本复制到 /etc/init.d目录下
以下假设你的脚本文件名为 test。</li>
<li>设置脚本文件的权限</li>
<li>执行如下命令将脚本放到启动脚本中去：</li>
</ol><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>cd</span><span> </span><span>/etc/init.d</span></div></div><div><div><div>2</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>update-rc.d</span><span> </span><span>test</span><span> </span><span>defaults</span><span> </span><span>95</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注：其中数字95是脚本启动的顺序号，按照自己的需要相应修改即可。在你有多个启动脚本，而它们之间又有先后启动的依赖关系时你就知道这个数字的具体作用了。该命令的输出信息参考如下：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>update-rc.d: warning: /etc/init.d/test missing LSB information</span></div></div><div><div><div>2</div></div><div><span>update-rc.d: see &lt;http://wiki.debian.org/LSBInitScripts&gt;</span></div></div><div><div><div>3</div></div><div><span>Adding system startup for /etc/init.d/test ...</span></div></div><div><div><div>4</div></div><div><span>/etc/rc0.d/K95test -&gt; ../init.d/test</span></div></div><div><div><div>5</div></div><div><span>/etc/rc1.d/K95test -&gt; ../init.d/test</span></div></div><div><div><div>6</div></div><div><span>/etc/rc6.d/K95test -&gt; ../init.d/test</span></div></div><div><div><div>7</div></div><div><span>/etc/rc2.d/S95test -&gt; ../init.d/test</span></div></div><div><div><div>8</div></div><div><span>/etc/rc3.d/S95test -&gt; ../init.d/test</span></div></div><div><div><div>9</div></div><div><span>/etc/rc4.d/S95test -&gt; ../init.d/test</span></div></div><div><div><div>10</div></div><div><span>/etc/rc5.d/S95test -&gt; ../init.d/test</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>卸载启动脚本的方法：</p><div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>$</span><span> </span><span>cd</span><span> </span><span>/etc/init.d</span></div></div><div><div><div>2</div></div><div><span>$</span><span> </span><span>sudo</span><span> </span><span>update-rc.d</span><span> </span><span>-f</span><span> </span><span>test</span><span> </span><span>remove</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>命令输出的信息参考如下：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>Removing any system startup links for /etc/init.d/test ...</span></div></div><div><div><div>2</div></div><div><span>/etc/rc0.d/K95test</span></div></div><div><div><div>3</div></div><div><span>/etc/rc1.d/K95test</span></div></div><div><div><div>4</div></div><div><span>/etc/rc2.d/S95test</span></div></div><div><div><div>5</div></div><div><span>/etc/rc3.d/S95test</span></div></div><div><div><div>6</div></div><div><span>/etc/rc4.d/S95test</span></div></div><div><div><div>7</div></div><div><span>/etc/rc5.d/S95test</span></div></div><div><div><div>8</div></div><div><span>/etc/rc6.d/K95test</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/12/</id>
      <title type="text">树莓派U盘/移动硬盘安装系统</title>
      <published>2017-12-03T00:00:00.000Z</published>
      <updated>2019-10-23T12:07:38.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/12/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>之前都是用TF烧录系统来作为树莓派的系统盘，后来发现可以用<a href="/posts/4/">BerryBoot</a>来作为引导来用U盘/移动硬盘安装系统，但是berryboot需要用一张TF来作为引导盘。这时树莓派官方给出了一种方案可以直接从U盘/移动硬盘安装系统。</p>
<p>在树莓派3从u盘启动之前，需要从设置了使能usb boot mode的sd启动。该设置树莓派芯片上的OTP（一次性可编程内存），这将使得树莓派能够从usb设备启动。一旦设置了该选项，sd卡就不需要了。注意，OTP一旦做出任何改动，都不能复原。
你可以使用运行raspbian或者raspbian lite的sd卡来设置OTP,如果你还没有这样的sd卡，可按常规方式将系统烧入sd卡（推荐使用<a href="https://etcher.io/" target="_blank">Etcher</a>）。</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>sudo</span><span> </span><span>apt-get</span><span> </span><span>update</span><span> &amp;&amp; </span><span>sudo</span><span> </span><span>apt-get</span><span> </span><span>upgrade</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>然后，输入以下代码使能usb boot mode</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>echo</span><span> </span><span>program_usb_boot_mode=</span><span>1</span><span> | </span><span>sudo</span><span> </span><span>tee</span><span> </span><span>-a</span><span> </span><span>/boot/config.txt</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>这行代码将<code>program_usb_boot_mode=1</code>插入到<code>/boot/cinfig.txt</code>文件的末尾。使用<code>sudo reboot</code>命令重启树莓派后，用以下命令检查OTP设置：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>vcgencmd</span><span> </span><span>otp_dump</span><span> | </span><span>grep</span><span> </span><span>17:</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>确保输出是<code>17:3020000a</code>，如果输出不是这个，那就说明OTP没有设置成功。
之后，你可以在sd卡的<code>config.txt</code>末尾去掉<code>program_usb_boot_mode=1</code>这行代码，这样把这张sd用在其他树莓派上就不会设置OTP，注意，<code>config.txt</code>文件结尾不能有空行.
你可以直接将img镜像拷贝到usb存储设备，sd卡，u盘。其他系统按常规方式写入存储介质。</p>
<p>做完这些，你就可以把usb存储设备插入树莓派了。</p>
<p>在完成以上工作后，给树莓派上电，经过5到10秒，树莓派就开始启动了。</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/11/</id>
      <title type="text">Android隐藏标题栏代码失效</title>
      <published>2017-11-03T00:00:00.000Z</published>
      <updated>2019-10-24T02:22:30.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/11/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>相信很多android入门教程中隐藏状态栏都用到：<code>requestWindowFeature(Window.FEATURE_NO_TITLE);</code>但是有时候这代码无效，这是因为这句代码只能用在继承Activity的activity中，而现在AndroidStudio大多默认创建继承AppCompathActivity的activity.</p>
<p>解决方法：</p>
<p>（1）将AppCompatActivity改为Activity，此时 <code>requestWindowFeature(Window.FEATURE_NO_TITLE);</code>是有效的。</p>
<p>（2）换用<code>getSupportActionBar().hide();</code>注意：去掉标题栏注意这句一定要写在<code>setContentView()</code>方法的后面</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/10/</id>
      <title type="text">OkHttp3基本用法(一)</title>
      <published>2017-10-26T00:00:00.000Z</published>
      <updated>2019-10-23T11:55:58.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/10/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<section><h1>依赖包<a href="#依赖包"><span>#</span></a></h1><p>首先添加jar包，或着用maven或gradle自动导包。（我用的是3.9.1的包，自动导包时注意实际情况）
maven:</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>dependency</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>groupId</span><span>&gt;com.squareup.okhttp3&lt;/</span><span>groupId</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>artifactId</span><span>&gt;okhttp&lt;/</span><span>artifactId</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>version</span><span>&gt;3.9.1&lt;/</span><span>version</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>dependency</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>gradle:</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>compile </span><span>'com.squareup.okhttp3:okhttp:3.9.1'</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>注意：还需要okio的包
maven:</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>&lt;</span><span>dependency</span><span>&gt;</span></div></div><div><div><div>2</div></div><div><span><span>  </span></span><span>&lt;</span><span>groupId</span><span>&gt;com.squareup.okio&lt;/</span><span>groupId</span><span>&gt;</span></div></div><div><div><div>3</div></div><div><span><span>  </span></span><span>&lt;</span><span>artifactId</span><span>&gt;okio&lt;/</span><span>artifactId</span><span>&gt;</span></div></div><div><div><div>4</div></div><div><span><span>  </span></span><span>&lt;</span><span>version</span><span>&gt;1.13.0&lt;/</span><span>version</span><span>&gt;</span></div></div><div><div><div>5</div></div><div><span>&lt;/</span><span>dependency</span><span>&gt;</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>gradle:</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>compile </span><span>'com.squareup.okio:okio:1.13.0'</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>GET请求<a href="#get请求"><span>#</span></a></h1><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>String</span><span> path</span><span>=</span><span>"http://rehtt.cn"</span><span><span>;</span><span> </span></span><span>OkHttpClient</span><span> okHttpClient</span><span>=</span><span>new</span><span> </span><span>OkHttpClient</span><span><span>()</span><span>;</span><span> </span></span><span>Request</span><span> request</span><span>=</span><span>new</span><span><span> Request</span><span>.</span></span><span>Builder</span><span><span>()</span><span>         </span><span>.</span></span><span>url</span><span>(path)</span></div></div><div><div><div>2</div></div><div><span>//如果要在request的的header添加参数。例如Cookie，User-Agent什么的：</span></div></div><div><div><div>3</div></div><div><span><span>        </span></span><span>.</span><span>header</span><span>(</span><span>"键"</span><span>, </span><span>"值"</span><span>)</span></div></div><div><div><div>4</div></div><div><span><span>         </span></span><span>.</span><span>header</span><span>(</span><span>"键"</span><span>, </span><span>"值"</span><span>)</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>        </span></span><span>.</span><span>build</span><span><span>();</span><span> </span></span><span>Call</span><span> call</span><span>=</span><span>okHttpClient</span><span>.</span><span>newCall</span><span><span>(request);</span><span> </span></span><span>try</span><span> {</span></div></div><div><div><div>7</div></div><div><span>    </span><span>Response</span><span> response </span><span><span>=</span><span> </span></span><span>call</span><span>.</span><span>execute</span><span>();</span></div></div><div><div><div>8</div></div><div><span>    </span><span>Log</span><span>.</span><span>i</span><span>(</span><span>"返回："</span><span>,</span><span>response</span><span>.</span><span>body</span><span>().</span><span>string</span><span><span>());</span><span> </span></span><span>//返回网页body标签内容</span></div></div><div><div><div>9</div></div><div><span>//body()有多种输出方法，如果是下载文件就是response.body().bytes()，response.code()获取返回的状态码</span></div></div><div><div><div>10</div></div><div><span>} </span><span>catch</span><span> (</span><span>IOException</span><span><span> </span><span>e</span><span>) {</span></span></div></div><div><div><div>11</div></div><div><span>    </span><span>e</span><span>.</span><span>printStackTrace</span><span>();</span></div></div><div><div><div>12</div></div><div><span>}</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section>
<section><h1>POST请求<a href="#post请求"><span>#</span></a></h1><p>post请求与get请求几乎一样，只是post需要提交表单，使用RequestBody。</p><p>RequestBody的数据格式都要指定Content-Type，常见的有三种：</p><p><code>application/x-www-form-urlencoded</code> 数据是个普通表单
<code>multipart/form-data</code> 数据里有文件
<code>application/json</code> 数据是个json</p><section><h2>普通表单：<a href="#普通表单"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>RequestBody</span><span> body </span><span><span>=</span><span> </span></span><span>new</span><span><span> FormBody</span><span>.</span></span><span>Builder</span><span>()</span></div></div><div><div><div>2</div></div><div><span><span>         </span></span><span>.</span><span>add</span><span>(</span><span>"键"</span><span>, </span><span>"值"</span><span>)</span></div></div><div><div><div>3</div></div><div><span><span>         </span></span><span>.</span><span>add</span><span>(</span><span>"键"</span><span>, </span><span>"值"</span><span>)</span></div></div><div><div><div>4</div></div><div><span><span>         </span></span><span>...</span></div></div><div><div><div>5</div></div><div><span><span>         </span></span><span>.</span><span>build</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>文件表单：<a href="#文件表单"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>RequestBody</span><span> requestBody </span><span><span>=</span><span> </span></span><span>new</span><span><span> MultipartBody</span><span>.</span></span><span>Builder</span><span>()</span></div></div><div><div><div>2</div></div><div><span><span>         </span></span><span>.</span><span>setType</span><span>(</span><span>MultipartBody</span><span>.</span><span>FORM</span><span>)</span></div></div><div><div><div>3</div></div><div><span><span>         </span></span><span>.</span><span>addFormDataPart</span><span>(</span><span>"file"</span><span>, </span><span>file</span><span>.</span><span>getName</span><span>(),</span><span>RequestBody</span><span>.</span><span>create</span><span>(</span><span>MediaType</span><span>.</span><span>parse</span><span>(</span><span>"image/png"</span><span>), file))</span></div></div><div><div><div>4</div></div><div><span><span>         </span></span><span>.</span><span>build</span><span>();</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>另外如果你上传一个文件不是一张图片，但是MediaType.parse(“image/png”)里的”image/png”不知道该填什么，可以参考这个。</p></section><section><h2>JSON表单：<a href="#json表单"><span>#</span></a></h2><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>MediaType</span><span> JSON </span><span><span>=</span><span> </span></span><span>MediaType</span><span>.</span><span>parse</span><span>(</span><span>"application/json; charset=utf-8"</span><span>);</span></div></div><div><div><div>2</div></div><div><span>RequestBody</span><span> body </span><span><span>=</span><span> </span></span><span>RequestBody</span><span>.</span><span>create</span><span>(JSON, </span><span>"传入的json"</span><span>);</span></div></div></code></pre><div><div></div><div></div></div></figure></div></section><section><h2>同步与异步<a href="#同步与异步"><span>#</span></a></h2><p>上文采用call.execute()执行http请求，但这是一个同步动作，是在主线程运行的。如果在UI线程执行就会抛异常。</p><p>所以在UI线程执行就要用异步，将call.execute()替换：</p><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>call</span><span>.</span><span>enqueue</span><span>(</span><span>new</span><span> </span><span>Callback</span><span>() {</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>3</div></div><div><span>//请求失败调用</span></div></div><div><div><div>4</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>onFailure</span><span>(</span><span>Call</span><span><span> </span><span>call</span><span>, </span></span><span>IOException</span><span><span> </span><span>e</span><span>)</span><span> </span><span>{</span></span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>@</span><span>Override</span></div></div><div><div><div>8</div></div><div><span>//请求成功调用</span></div></div><div><div><div>9</div></div><div><span>    </span><span>public</span><span> </span><span>void</span><span> </span><span>onResponse</span><span>(</span><span>Call</span><span><span> </span><span>call</span><span>, </span></span><span>Response</span><span><span> </span><span>response</span><span>)</span><span> </span></span><span>throws</span><span> </span><span>IOException</span><span><span> </span><span>{</span></span></div></div><div><div><div>10</div></div><div><span>        </span><span>Log</span><span>.</span><span>e</span><span>(</span><span>"返回："</span><span>,</span><span>response</span><span>.</span><span>body</span><span>().</span><span>string</span><span>());</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>}</span></div></div><div><div><div>12</div></div><div><span>});</span></div></div></code></pre><div><div></div><div></div></div></figure></div><p>onFailure()和onResponse()是在异步线程里执行的，所以如果你在Android把更新UI的操作写在这两个方法里面是会报错的，这个时候可以用runOnUiThread这个方法。</p></section></section>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/9/</id>
      <title type="text">在debian上vbox虚拟机usb设备无法显示问题解决</title>
      <published>2017-10-03T00:00:00.000Z</published>
      <updated>2019-10-23T11:47:56.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/9/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>问题原因是当前用户没有包含在vbox用户组里，所以解决方法就是将当前用户添加进vbox的用户组。</p>
<p>我当前用户名是rehtt，将当前用户添加进vbox用户组：</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>usermod</span><span> </span><span>-a</span><span> </span><span>-G</span><span> </span><span>vboxusers</span><span> </span><span>rehtt</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>重启后即可解决。</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/8/</id>
      <title type="text">samba服务器配置</title>
      <published>2017-10-02T00:00:00.000Z</published>
      <updated>2019-10-23T11:45:45.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/8/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>samba是一个文件共享服务器。</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>apt</span><span> </span><span>install</span><span> </span><span>samba</span><span> </span><span>samba-common-bin</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>使用samba需要开启137,138,139,389,445,901端口。</p>
<p>samba配置文件在<code>/etc/samba/smb.conf</code></p>
<p>在文件最后添加：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>[global]</span></div></div><div><div><div>2</div></div><div><span><span>    </span></span><span>server </span><span>string</span><span><span> </span><span>=</span><span> Samba Server Version %v</span></span></div></div><div><div><div>3</div></div><div><span><span>    </span></span><span>passdb </span><span>backend</span><span><span> </span><span>=</span><span> tdbsam</span></span></div></div><div><div><div>4</div></div><div><span><span>    </span></span><span>cups </span><span>options</span><span><span> </span><span>=</span><span> raw</span></span></div></div><div><div><div>5</div></div><div><span>    </span><span>security</span><span><span> </span><span>=</span><span> user                            </span></span><span>#认证模式为User</span></div></div><div><div><div>6</div></div><div><span><span>    </span></span><span>map to </span><span>guest</span><span><span> </span><span>=</span><span> bad user            </span></span><span>#这个很关键，实现匿名无须交互输入用户名和密码就靠它了</span></div></div><div><div><div>7</div></div><div><span><span>    </span></span><span>guest </span><span>account</span><span><span> </span><span>=</span><span> guest               </span></span><span>#匿名用户映射为guest用户</span></div></div><div><div><div>8</div></div><div>
</div></div><div><div><div>9</div></div><div><span>[myshare]</span><span>                                       </span><span>#显示名称</span></div></div><div><div><div>10</div></div><div><span>    </span><span>comment</span><span><span> </span><span>=</span><span> My share</span></span></div></div><div><div><div>11</div></div><div><span>    </span><span>path</span><span><span> </span><span>=</span><span> /home/public                       </span></span><span>#共享路径</span></div></div><div><div><div>12</div></div><div><span>    </span><span>browseable</span><span><span> </span><span>=</span><span> Yes                          </span></span><span>#可以被浏览，就是在网络邻居中能看到共享名</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>read </span><span>only</span><span><span> </span><span>=</span><span> No                               </span></span><span>#可读写</span></div></div><div><div><div>14</div></div><div><span><span>    </span></span><span>guest </span><span>ok</span><span><span> </span><span>=</span><span> Yes                               </span></span><span>#允许匿名访问，这个也需要设置，否则匿名无法访问</span></div></div><div><div><div>15</div></div><div><span><span>    </span></span><span>valid </span><span>users</span><span><span> </span><span>=</span><span> samba liuag guest    </span></span><span>#有效的用户和组</span></div></div><div><div><div>16</div></div><div><span><span>    </span></span><span>invalid </span><span>users</span><span><span> </span><span>=</span><span> liuben                     </span></span><span>#无效用户和组</span></div></div><div><div><div>17</div></div><div><span><span>    </span></span><span>read </span><span>list</span><span><span> </span><span>=</span><span> samba                           </span></span><span>#只读用户和组(如果read only = No，只读用户需要在此设置)</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>write </span><span>list</span><span><span> </span><span>=</span><span> liuag                             </span></span><span>#可读写用户和组(如果read only = Yes，可读写用户需要在此设置)</span></div></div><div><div><div>19</div></div><div><span><span>    </span></span><span>allow </span><span>hosts</span><span><span> </span><span>=</span><span> 192.168.100.236     </span></span><span>#允许访问主机列表，支持通配符</span></div></div><div><div><div>20</div></div><div><span><span>    </span></span><span>deny </span><span>hosts</span><span><span> </span><span>=</span><span> 192.168.100.0/24    </span></span><span>#禁止访问主机列表，支持通配符</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>[MyNAS]</span></div></div><div><div><div>23</div></div><div><span>    </span><span># 说明信息</span></div></div><div><div><div>24</div></div><div><span>    </span><span>comment</span><span><span> </span><span>=</span><span> NAS Storage</span></span></div></div><div><div><div>25</div></div><div><span>    </span><span># 可以访问的用户</span></div></div><div><div><div>26</div></div><div><span><span>    </span></span><span>valid </span><span>users</span><span><span> </span><span>=</span><span> pi,root</span></span></div></div><div><div><div>27</div></div><div><span>    </span><span># 共享文件的路径,raspberry pi 会自动将连接到其上的外接存储设备挂载到/media/pi/目录下。</span></div></div><div><div><div>28</div></div><div><span>    </span><span>path</span><span><span> </span><span>=</span><span> /media/pi/</span></span></div></div><div><div><div>29</div></div><div><span>    </span><span># 可被其他人看到资源名称（非内容）</span></div></div><div><div><div>30</div></div><div><span>    </span><span>browseable</span><span><span> </span><span>=</span><span> yes</span></span></div></div><div><div><div>31</div></div><div><span>    </span><span># 可写</span></div></div><div><div><div>32</div></div><div><span>    </span><span>writable</span><span><span> </span><span>=</span><span> yes</span></span></div></div><div><div><div>33</div></div><div><span>    </span><span># 新建文件的权限为 664</span></div></div><div><div><div>34</div></div><div><span><span>    </span></span><span>create </span><span>mask</span><span><span> </span><span>=</span><span> 0664</span></span></div></div><div><div><div>35</div></div><div><span>    </span><span># 新建目录的权限为 775</span></div></div><div><div><div>36</div></div><div><span><span>    </span></span><span>directory </span><span>mask</span><span><span> </span><span>=</span><span> 0775</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<p>可以把配置文件中你不需要的分享名称删除，例如 [homes], [printers] 等。</p>
<p>测试配置文件是否有错误，根据提示做相应修改</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>testparm</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>添加登陆账户并创建密码，必须是 linux 已存在的用户</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>smbpasswd</span><span> </span><span>-a</span><span> </span><span>pi</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>重启 samba 服务</p>
<div><figure><figcaption><span></span><span>Terminal window</span></figcaption><pre><code><div><div><div>1</div></div><div><span>/etc/init.d/samba</span><span> </span><span>restart</span></div></div></code></pre><div><div></div><div></div></div></figure></div>
<p>测试
回到windows，就可以在网络当中发现共享的文件夹了</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/7/</id>
      <title type="text">穿透内网思路(vpn方法)</title>
      <published>2017-10-01T00:00:00.000Z</published>
      <updated>2019-10-23T11:41:04.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/7/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<ol>
<li>
<p>首先需要一台位于外网且拥有外网ip的服务器</p>
</li>
<li>
<p>在外网服务器上搭建vpn服务器和反向代理服务器</p>
</li>
<li>
<p>内网服务器连上外网服务器的vpn</p>
</li>
<li>
<p>外网服务器根据vpn地址反向代理到内网服务器</p>
</li>
</ol>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/6/</id>
      <title type="text">树莓派温控风扇脚本（使用三极管 s8050）</title>
      <published>2017-09-26T00:00:00.000Z</published>
      <updated>2019-10-23T11:39:18.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/6/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>这里均以s8050为开关，s8050为NPN型三极管，以平的那面为参考面，左边阵脚接电源正极，中间针脚为开关，右边阵脚接电源负极</p>
<p>不控速风扇：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/usr/bin/python</span></div></div><div><div><div>2</div></div><div><span>#coding:utf-8</span></div></div><div><div><div>3</div></div><div><span>import</span><span> time</span></div></div><div><div><div>4</div></div><div>
</div></div><div><div><div>5</div></div><div><span>import</span><span><span> RPi.</span><span>GPIO</span><span> </span></span><span>as</span><span><span> </span><span>GPIO</span></span></div></div><div><div><div>6</div></div><div>
</div></div><div><div><div>7</div></div><div><span>#这里选择14（BCM）号针脚作为开关</span></div></div><div><div><div>8</div></div><div><span><span>GPIO_OUT</span><span> </span><span>=</span><span> </span></span><span>14</span></div></div><div><div><div>9</div></div><div>
</div></div><div><div><div>10</div></div><div><span>def</span><span> </span><span>setup_GPIO</span><span>():</span></div></div><div><div><div>11</div></div><div><span><span>    </span></span><span>GPIO</span><span>.</span><span>setmode</span><span>(</span><span>GPIO</span><span>.</span><span>BCM</span><span>)</span></div></div><div><div><div>12</div></div><div><span><span>    </span></span><span>GPIO</span><span>.</span><span>setwarnings</span><span>(</span><span>False</span><span>)</span></div></div><div><div><div>13</div></div><div><span><span>    </span></span><span>GPIO</span><span>.</span><span>setup</span><span>(</span><span>GPIO_OUT</span><span>, </span><span>GPIO</span><span>.</span><span>OUT</span><span>)</span></div></div><div><div><div>14</div></div><div>
</div></div><div><div><div>15</div></div><div><span>#开启风扇</span></div></div><div><div><div>16</div></div><div>
</div></div><div><div><div>17</div></div><div><span>def</span><span> </span><span>start_fan</span><span>():</span></div></div><div><div><div>18</div></div><div><span><span>    </span></span><span>GPIO</span><span>.</span><span>output</span><span>(</span><span>GPIO_OUT</span><span>,</span><span>GPIO</span><span>.</span><span>HIGH</span><span>)</span></div></div><div><div><div>19</div></div><div>
</div></div><div><div><div>20</div></div><div><span>#关闭风扇</span></div></div><div><div><div>21</div></div><div>
</div></div><div><div><div>22</div></div><div><span>def</span><span> </span><span>stop_fan</span><span>():</span></div></div><div><div><div>23</div></div><div><span><span>    </span></span><span>GPIO</span><span>.</span><span>output</span><span>(</span><span>GPIO_OUT</span><span>,</span><span>GPIO</span><span>.</span><span>LOW</span><span>)</span></div></div><div><div><div>24</div></div><div>
</div></div><div><div><div>25</div></div><div><span>#获取cpu温度</span></div></div><div><div><div>26</div></div><div>
</div></div><div><div><div>27</div></div><div><span>def</span><span> </span><span>cpu_temp</span><span>():</span></div></div><div><div><div>28</div></div><div><span><span>    </span></span><span>tempFile</span><span>=</span><span>open</span><span>(</span><span>"/sys/class/thermal/thermal_zone0/temp"</span><span>)</span></div></div><div><div><div>29</div></div><div><span><span>    </span></span><span>cpu_temp</span><span>=</span><span>tempFile.</span><span>read</span><span>()</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>tempFile.</span><span>close</span><span>()</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>temp_c</span><span>=</span><span>(</span><span>int</span><span><span>(cpu_temp)</span><span>/</span></span><span>1000</span><span>)</span></div></div><div><div><div>32</div></div><div><span>    </span><span>return</span><span> </span><span>int</span><span>(temp_c)</span></div></div><div><div><div>33</div></div><div>
</div></div><div><div><div>34</div></div><div><span>#若温度大于等于55度开启风扇，小于等于45度关闭扇。中间相差温度作为缓冲，不然风扇就会一会开一会关。</span></div></div><div><div><div>35</div></div><div>
</div></div><div><div><div>36</div></div><div><span>def</span><span> </span><span>fen</span><span>():</span></div></div><div><div><div>37</div></div><div><span>    </span><span>if</span><span><span> </span><span>cpu_temp</span><span>()</span><span>&gt;=</span></span><span>55</span><span>:</span></div></div><div><div><div>38</div></div><div><span><span>        </span></span><span>start_fan</span><span>()</span></div></div><div><div><div>39</div></div><div><span><span>        </span></span><span>fen_state</span><span>(</span><span>1</span><span>)</span></div></div><div><div><div>40</div></div><div>
</div></div><div><div><div>41</div></div><div><span>    </span><span>elif</span><span><span> </span><span>cpu_temp</span><span>()</span><span>&lt;=</span></span><span>45</span><span>:</span></div></div><div><div><div>42</div></div><div><span><span>        </span></span><span>stop_fan</span><span>()</span></div></div><div><div><div>43</div></div><div><span><span>        </span></span><span>fen_state</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>44</div></div><div>
</div></div><div><div><div>45</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>46</div></div><div><span>        </span><span>pass</span></div></div><div><div><div>47</div></div><div>
</div></div><div><div><div>48</div></div><div><span>def</span><span> </span><span>fen_state</span><span>(</span><span>state</span><span>):</span></div></div><div><div><div>49</div></div><div><span><span>    </span></span><span>f</span><span>=</span><span>open</span><span>(</span><span>"/etc/startup-script/state.txt"</span><span>)</span></div></div><div><div><div>50</div></div><div><span>    </span><span>file</span><span><span>=</span><span>f.</span><span>readlines</span><span>()</span></span></div></div><div><div><div>51</div></div><div><span><span>    </span></span><span>i</span><span>=</span><span>0</span></div></div><div><div><div>52</div></div><div><span>    </span><span>for</span><span> line </span><span>in</span><span> </span><span>file</span><span>:</span></div></div><div><div><div>53</div></div><div><span><span>        </span></span><span>line </span><span>=</span><span> line.</span><span>strip</span><span>(</span><span>"</span><span>\n</span><span>"</span><span>)</span></div></div><div><div><div>54</div></div><div><span><span>        </span></span><span>v </span><span>=</span><span> line.</span><span>split</span><span>(</span><span>":"</span><span>)</span></div></div><div><div><div>55</div></div><div><span>        </span><span>if</span><span> v[</span><span>0</span><span><span>] </span><span>==</span><span> </span></span><span>"fen_state"</span><span>:</span></div></div><div><div><div>56</div></div><div><span>            </span><span>file</span><span><span>[i] </span><span>=</span><span> </span></span><span>"fen_state:"</span><span>+</span><span>str</span><span>(state)</span></div></div><div><div><div>57</div></div><div><span>            </span><span>break</span></div></div><div><div><div>58</div></div><div><span><span>        </span></span><span>i</span><span>=</span><span>i</span><span>+</span><span>1</span></div></div><div><div><div>59</div></div><div><span><span>    </span></span><span>f</span><span>=</span><span>open</span><span>(</span><span>"/etc/startup-script/state.txt"</span><span>,</span><span>'w+'</span><span>)</span></div></div><div><div><div>60</div></div><div><span><span>    </span></span><span>f.</span><span>writelines</span><span>(</span><span>file</span><span>)</span></div></div><div><div><div>61</div></div><div><span><span>    </span></span><span>f.</span><span>close</span><span>()</span></div></div><div><div><div>62</div></div><div>
</div></div><div><div><div>63</div></div><div>
</div></div><div><div><div>64</div></div><div>
</div></div><div><div><div>65</div></div><div><span>if</span><span> </span><span>__name__</span><span><span> </span><span>==</span><span> </span></span><span>'__main__'</span><span>:</span></div></div><div><div><div>66</div></div><div><span><span>    </span></span><span>setup_GPIO</span><span>()</span></div></div><div><div><div>67</div></div><div><span><span>    </span></span><span>fen_state</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>68</div></div><div><span>    </span><span>while</span><span> </span><span>True</span><span>:</span></div></div><div><div><div>69</div></div><div><span><span>        </span></span><span>fen</span><span>()</span></div></div><div><div><div>70</div></div><div><span><span>        </span></span><span>time.</span><span>sleep</span><span>(</span><span>5</span><span>)</span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>
<p>控速风扇：</p>
<div><div><div><figure><figcaption></figcaption><pre><code><div><div><div>1</div></div><div><span>#!/usr/bin/env python</span></div></div><div><div><div>2</div></div><div><span># encoding: utf-8</span></div></div><div><div><div>3</div></div><div><span>import</span><span><span> RPi.</span><span>GPIO</span><span> </span></span><span>as</span><span><span> </span><span>GPIO</span></span></div></div><div><div><div>4</div></div><div><span>import</span><span> time</span></div></div><div><div><div>5</div></div><div>
</div></div><div><div><div>6</div></div><div><span>#以14号(BCM)阵脚为开关</span></div></div><div><div><div>7</div></div><div><span><span>GPIO_OUT</span><span> </span><span>=</span><span> </span></span><span>14</span></div></div><div><div><div>8</div></div><div><span><span>GPIO</span><span>.</span><span>setmode</span><span>(</span><span>GPIO</span><span>.</span><span>BCM</span><span>)</span></span></div></div><div><div><div>9</div></div><div><span><span>GPIO</span><span>.</span><span>setwarnings</span><span>(</span></span><span>False</span><span>)</span></div></div><div><div><div>10</div></div><div><span><span>GPIO</span><span>.</span><span>setup</span><span>(</span><span>GPIO_OUT</span><span>,</span><span>GPIO</span><span>.</span><span>OUT</span><span>)</span></span></div></div><div><div><div>11</div></div><div><span><span>pwm </span><span>=</span><span> </span><span>GPIO</span><span>.</span><span>PWM</span><span>(</span><span>GPIO_OUT</span><span>, </span></span><span>100</span><span>)</span></div></div><div><div><div>12</div></div><div>
</div></div><div><div><div>13</div></div><div><span><span>speed</span><span>=</span></span><span>0</span></div></div><div><div><div>14</div></div><div><span><span>prv_temp</span><span>=</span></span><span>0</span></div></div><div><div><div>15</div></div><div><span>try</span><span>:</span></div></div><div><div><div>16</div></div><div><span>    </span><span>while</span><span> </span><span>True</span><span>:</span></div></div><div><div><div>17</div></div><div><span><span>        </span></span><span>tmpFile</span><span>=</span><span>open</span><span>(</span><span>'/sys/class/thermal/thermal_zone0/temp'</span><span>)</span></div></div><div><div><div>18</div></div><div><span><span>        </span></span><span>cpu_temp</span><span>=</span><span>int</span><span><span>(tmpFile.</span><span>read</span><span>())</span><span>/</span></span><span>1000</span></div></div><div><div><div>19</div></div><div><span><span>        </span></span><span>tmpFile.</span><span>close</span><span>()</span></div></div><div><div><div>20</div></div><div><span>        </span><span>if</span><span><span> cpu_temp </span><span>&gt;=</span><span> </span></span><span>34</span><span>:</span></div></div><div><div><div>21</div></div><div><span>            </span><span>if</span><span><span> prv_temp </span><span>&lt;</span><span> </span></span><span>34</span><span>:</span></div></div><div><div><div>22</div></div><div><span>            </span><span># 启动时防止风扇卡死先全功率转0.1秒</span></div></div><div><div><div>23</div></div><div><span><span>                </span></span><span>pwm.</span><span>start</span><span>(</span><span>0</span><span>)</span></div></div><div><div><div>24</div></div><div><span><span>                </span></span><span>pwm.</span><span>ChangeDutyCycle</span><span>(</span><span>100</span><span>)</span></div></div><div><div><div>25</div></div><div><span><span>                </span></span><span>time.</span><span>sleep</span><span>(</span><span>.1</span><span>)</span></div></div><div><div><div>26</div></div><div><span><span>            </span></span><span>speed</span><span>=</span><span>min</span><span>(cpu_temp, </span><span>100</span><span>)</span></div></div><div><div><div>27</div></div><div><span><span>            </span></span><span>pwm.</span><span>ChangeDutyCycle</span><span>(speed)</span></div></div><div><div><div>28</div></div><div><span>    </span><span>else</span><span>:</span></div></div><div><div><div>29</div></div><div><span><span>        </span></span><span>pwm.</span><span>stop</span><span>()</span></div></div><div><div><div>30</div></div><div><span><span>    </span></span><span>prv_temp</span><span>=</span><span>cpu_temp</span></div></div><div><div><div>31</div></div><div><span><span>    </span></span><span>time.</span><span>sleep</span><span>(</span><span>5</span><span>)</span></div></div><div><div><div>32</div></div><div><span>except</span><span> </span><span>KeyboardInterrupt</span><span>:</span></div></div><div><div><div>33</div></div><div><span>    </span><span>pass</span></div></div><div><div><div>34</div></div><div><span><span>pwm.</span><span>stop</span><span>()</span></span></div></div></code></pre><div><div></div><div></div></div></figure><div></div></div><span>展开</span><span>收起</span></div></div>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/5/</id>
      <title type="text">关于/etc/init.d目录与/etc/rc.local脚本</title>
      <published>2017-09-24T00:00:00.000Z</published>
      <updated>2019-10-23T11:35:30.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/5/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>它们都是linux自启动文件，区别在于<code>/etc/rc.local</code>是在系统初始化之后才执行，而<code>/etc/init.d</code>里面的是系统初始化级别脚本。</p>
<p>执行级别：/etc/init.d  &gt;  /etc/rc.local</p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/4/</id>
      <title type="text">Berryboot安装</title>
      <published>2017-09-23T00:00:00.000Z</published>
      <updated>2019-10-23T11:33:03.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/4/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<blockquote><p>BerryBoot是一款基于树莓派启动的启动管理工具， 它最大的优势是可以在不通过SD卡的前提下在多个系统中选择启动， 你既可以将系统存放在卡上，也可以, 如果你需要更多空间的话，将系统运行在外接的硬盘上并配置BerryBoot只将SD卡作为一个启动器。</p></blockquote>
<p>也就是说berryboot是一个系统启动的引导。</p>
<p>步骤：</p>
<ol>
<li>官网下载berryboot</li>
<li>解压并放入sd内</li>
<li>通电开机</li>
</ol>
<p>参考：<a href="http://shumeipai.nxez.com/2014/01/25/use-berryboot-make-raspberry-pi-supports-multi-system-boot.html" target="_blank">http://shumeipai.nxez.com/2014/01/25/use-berryboot-make-raspberry-pi-supports-multi-system-boot.html</a></p>]]></content>
    </entry>
    <entry>
      <id>https://rehtt.com/posts/3/</id>
      <title type="text">nextcloud/owncloud网页版设置中文</title>
      <published>2017-09-22T00:00:00.000Z</published>
      <updated>2019-10-23T11:26:08.000Z</updated>
      <author><name>Rehtt</name></author>
      <link rel="alternate" href="https://rehtt.com/posts/3/"/>
      <summary type="text"></summary>
      <content type="html"><![CDATA[<p>在页面的语言设置中只有”English”选项，这个问题是php的<code>scandir()</code>函数被禁用而导致的。</p>
<p>解决方法：编辑<code>php.ini</code>文件，找到”disable_functions”，并删除其中<code>scandir</code>，最后重启php服务即可。</p>]]></content>
    </entry>
</feed>
