﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-魔のkyo的工作室</title><link>http://www.cnitblog.com/luckydmz/</link><description /><language>zh-cn</language><lastBuildDate>Sat, 18 Apr 2026 23:35:03 GMT</lastBuildDate><pubDate>Sat, 18 Apr 2026 23:35:03 GMT</pubDate><ttl>60</ttl><item><title>Blog迁移公告</title><link>http://www.cnitblog.com/luckydmz/archive/2022/04/12/92587.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 12 Apr 2022 07:10:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2022/04/12/92587.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92587.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2022/04/12/92587.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92587.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92587.html</trackback:ping><description><![CDATA[<span style="color: #4d4d4d; font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun; font-size: 16px;">个人博客已迁移到：</span><a href="http://www.kyo86.com/" style="box-sizing: border-box; outline: none; margin: 0px; padding: 0px; cursor: pointer; color: #4ea1db; overflow-wrap: break-word; font-family: -apple-system, &quot;SF UI Text&quot;, Arial, &quot;PingFang SC&quot;, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif, SimHei, SimSun; font-size: 16px;">www.kyo86.com<br /></a>新博文将发布在新地址，旧博文会陆续迁移至新地址<img src ="http://www.cnitblog.com/luckydmz/aggbug/92587.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2022-04-12 15:10 <a href="http://www.cnitblog.com/luckydmz/archive/2022/04/12/92587.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>docker常用命令</title><link>http://www.cnitblog.com/luckydmz/archive/2022/03/28/92584.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Mon, 28 Mar 2022 08:57:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2022/03/28/92584.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92584.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2022/03/28/92584.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92584.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92584.html</trackback:ping><description><![CDATA[启动一个容器<br />docker run -h 容器主机名 --name 容器名 -Pdit 镜像名<br />启动一个新的bash进行管理<br />
docker exec -it 容器名 bash<br />
<br />其他常用命令<br />
<table border="0" cellpadding="0" cellspacing="0" width="412" height="336" style="border-collapse:collapse;width:300pt;">
     <colgroup><col width="127" style="width:76.20pt;"> <col width="178" style="width:106.80pt;"> <col width="107" style="width:64.20pt;"> </colgroup>
     <tbody>
         <tr height="24" style="height:14.40pt;">
             <td height="24" width="127" style="height:14.40pt;width:100pt;">&nbsp;</td>
             <td width="178" x:str="" style="width:100pt;">镜像</td>
             <td width="107" x:str="" style="width:100pt;">容器</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">创建</td>
             <td x:str="">build -t/commit</td>
             <td x:str="">create/run</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">删除</td>
             <td x:str="">rmi</td>
             <td x:str="">rm</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">重命名</td>
             <td x:str="">tag+rmi</td>
             <td x:str="">rename</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">查看列表</td>
             <td x:str="">images</td>
             <td x:str="">ps/ps -a/ps -l -q</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">运行状态</td>
             <td x:str="">stats</td>
             <td x:str="">top</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">查看日志</td>
             <td x:str="">history</td>
             <td x:str="">logs</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">拉取</td>
             <td x:str="">pull</td>
             <td></td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">推送</td>
             <td x:str="">push</td>
             <td></td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">查找</td>
             <td x:str="">search</td>
             <td></td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">查看容器信息</td>
             <td></td>
             <td x:str="">inspect</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">发信号</td>
             <td></td>
             <td x:str="">kill</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">附到主进程</td>
             <td></td>
             <td x:str="">attach</td>
         </tr>
         <tr height="24" style="height:14.40pt;">
             <td height="24" x:str="" style="height:14.40pt;">执行新进程</td>
             <td></td>
             <td x:str="">exec</td>
         </tr>
     </tbody>
</table>
<br />
<span style="font-size: 18pt;">docker run</span> 常用参数<br />
-d&nbsp; &nbsp;# 后台运行<br />
-it&nbsp; &nbsp;# 打开STDIN，<span style="color: #24292e; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Helvetica, Arial, sans-serif, &quot;Apple Color Emoji&quot;, &quot;Segoe UI Emoji&quot;, &quot;Segoe UI Symbol&quot;; font-size: 16px;">支持终端登录</span><br />
--name &lt;容器名&gt;<br />
-h &lt;主机名&gt;<br />
-P&nbsp; &nbsp;# 随机映射所有配置在EXPOSE中的端口<br />
-p [&lt;宿主端口&gt;:]&lt;容器端口&gt; # 指定映射一个端口，不指定宿主端口时表示随机<br />
-v &lt;宿主路径&gt;:&lt;容器路径&gt;[:ro|:rw] # 卷映射，容器路径不存在时自动创建，ro表示只读，默认是rw表示读写<br />
--volumes-from &lt;容器名&gt; # 指定容器里的所有卷都将加入到新创建的容器里<br />
--network &lt;网络名&gt; # 默认bridge，同一个非默认网络下的容器可以使用主机名相互访问<br />
--link &lt;容器名&gt;:&lt;主机名&gt;&nbsp; # 在新创建的容器里可以通过主机名访问另一个运行中的容器<br />
--add-host &lt;主机名&gt;:&lt;IP&gt; # 指定主机名解析添加到/etc/hosts文件<br />
--env &lt;环境变量名&gt;=&lt;环境变量值&gt;&nbsp; # 设置环境变量，-e 选项可以重复多次<br />
--env-file &lt;环境变量文件&gt;&nbsp; # 指定环境变量文件，换行符分割<br />
--user &lt;用户名&gt;<br />
--workdir &lt;工作目录&gt;<br />
--mac-address="xx:xx:xx:xx:xx:xx"&nbsp; &nbsp;# 指定MAC地址<br />关于资源限制的参数：<br />--cpuset-cpus="1,3" 限制在核1、3上运行<br />--memory=1G 限制内存最大使用1G<br />--device-read-bps /dev/sdd:40mb 限制读取sdd的速度最大40mb<br /><span style="background-color: #ffffff;">--</span>device-write-bps /dev/sdd:30mb 限制写入sdd的速度最大30mb<br />（机械硬盘读写速度是<span style="color: #666666; font-family: Arial, Helvetica, sans-serif; font-size: 14px;">60-80MB，固态硬盘读写速度是130~300MB，都是写慢读快</span>）<br />
<br />
<span style="font-size: 18pt;">docker network</span> 常用参数<br />
&nbsp; create&nbsp; &nbsp; &nbsp; 创建一个新的网络<br />
&nbsp; connect&nbsp; &nbsp;向一个网络中添加一个容器<br />
&nbsp; disconnect&nbsp; 从一个网络中移除一个容器<br />
&nbsp; inspect&nbsp; &nbsp; 查看指定网络详细信息<br />
&nbsp; ls&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;查看网络列表<br />
&nbsp; rm&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;删除指定网络<br />
&nbsp; prune&nbsp; &nbsp; &nbsp; 删除所有未使用的网络<br />
<br />
<span style="font-size: 18pt;">docker inspect</span><br />
--format format的用法比较复杂，用3个逐级深入的例子演示<br />
<br />
docker_id 查看容器的Id<br />
docker inspect --format='{{.Id}}' 容器名<br />
<br />
docker_ip 查看容器在所有网络中分配的所有的ip<br />
docker inspect --format='{{range .NetworkSettings.Networks}}{{println .IPAddress}}{{end}}' 容器名<br />
<br />
docker_port 查看容器所有的端口映射情况，用docker inspect实现 docker port命令<br />
docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}{{range $conf}}{{$p}} -&gt; {{.HostIp}}:{{.HostPort}}{{println}}{{end}}{{end}}' 容器名<img src ="http://www.cnitblog.com/luckydmz/aggbug/92584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2022-03-28 16:57 <a href="http://www.cnitblog.com/luckydmz/archive/2022/03/28/92584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux中查看文件创建时间的脚本</title><link>http://www.cnitblog.com/luckydmz/archive/2022/03/25/92581.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Fri, 25 Mar 2022 11:52:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2022/03/25/92581.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92581.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2022/03/25/92581.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92581.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92581.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#!/bin/bash<br /><br />[&nbsp;$#&nbsp;-ne&nbsp;1&nbsp;]&nbsp;&amp;&amp;&nbsp;echo&nbsp;"Usage:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$0&nbsp;{FILENAME}"&nbsp;&amp;&amp;&nbsp;<span style="color: #0000FF; ">exit</span>&nbsp;1<br /><br />INODE=`ls&nbsp;-i&nbsp;$1&nbsp;|awk&nbsp;<span style="color: #008000; ">'</span><span style="color: #008000; ">{print&nbsp;$1}'`</span><span style="color: #008000; "><br /></span>FILENAME=$1<br /><br />#如果传入参数带/，则获取这个传入参数的目录路径并进入目录<br />`echo&nbsp;$FILENAME&nbsp;|grep&nbsp;/&nbsp;1&gt;&nbsp;/dev/<span style="color: #0000FF; ">null</span>`&nbsp;&nbsp;&amp;&amp;&nbsp;&nbsp;{&nbsp;FPWD=${FILENAME%/*};FPWD=${FPWD:=/};cd&nbsp;${FPWD};FPWD=`pwd`;&nbsp;}&nbsp;&nbsp;||&nbsp;FPWD=`pwd`<br /><br /><span style="color: #0000FF; ">array</span>=(`echo&nbsp;${FPWD}&nbsp;|&nbsp;sed&nbsp;<span style="color: #008000; ">'</span><span style="color: #008000; ">s@/@&nbsp;@g'`)</span><span style="color: #008000; "><br /></span>array_length=${#<span style="color: #0000FF; ">array</span>[@]}<br /><br /><span style="color: #0000FF; ">for</span>&nbsp;((i=${array_length};i&gt;=0;i--))<br /><span style="color: #0000FF; ">do</span><br />&nbsp;&nbsp;unset&nbsp;<span style="color: #0000FF; ">array</span>[$i]<br />&nbsp;&nbsp;SUBPWD=`echo&nbsp;"&nbsp;"${<span style="color: #0000FF; ">array</span>[@]}&nbsp;|&nbsp;sed&nbsp;<span style="color: #008000; ">'</span><span style="color: #008000; ">s@&nbsp;@/@g'`</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;DISK=`df&nbsp;-h&nbsp;|grep&nbsp;${SUBPWD}$&nbsp;|awk&nbsp;<span style="color: #008000; ">'</span><span style="color: #008000; ">{print&nbsp;$1}'`</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;[[&nbsp;-n&nbsp;$DISK&nbsp;]]&nbsp;&amp;&amp;&nbsp;break<br />done<br /><br />#不是ext4就退出<br />[[&nbsp;"`mount&nbsp;|grep&nbsp;${DISK}&nbsp;|awk&nbsp;'{print&nbsp;$5}'`"&nbsp;!=&nbsp;"ext4"&nbsp;]]&nbsp;&amp;&amp;&nbsp;{&nbsp;echo&nbsp;${DISK}&nbsp;<span style="color: #0000FF; ">is</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;mount&nbsp;<span style="color: #0000FF; ">on</span>&nbsp;type&nbsp;ext4!&nbsp;Only&nbsp;ext4&nbsp;file&nbsp;system&nbsp;support!;<span style="color: #0000FF; ">exit</span>&nbsp;2;&nbsp;}<br /><br />debugfs&nbsp;-R&nbsp;"stat&nbsp;&lt;${INODE}&gt;"&nbsp;${DISK}</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92581.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2022-03-25 19:52 <a href="http://www.cnitblog.com/luckydmz/archive/2022/03/25/92581.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Shell脚本输入密码</title><link>http://www.cnitblog.com/luckydmz/archive/2022/02/21/92563.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Mon, 21 Feb 2022 10:44:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2022/02/21/92563.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92563.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2022/02/21/92563.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92563.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92563.html</trackback:ping><description><![CDATA[首先在Shell脚本中使用sudo不是一个好主意。<br />
可以考虑的替代方案有，<br />
1. 在脚本中去掉sudo，而要求在运行脚本时使用sudo。<br />
2. 如果是任务计划，考虑配置在root用户下。<br />
如果确实确定要在Shell中sudo，可以使用如下方式<br />
<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->echo&nbsp;<span style="color: #008000; ">'</span><span style="color: #008000;">密码'&nbsp;|&nbsp;sudo&nbsp;-S&nbsp;命令</span>
</div>
<br />
如果是通过SSH建立远程连接，考虑用SSH密钥登录。搜索SSH秘钥，<span style="background-color: #ffffff; white-space: pre-wrap;">ssh-keygen，</span>ssh-copy-id<br />如果是其他程序需要输入密码，可以用<span style="font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 14px;">expect工具</span><span style="font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif; font-size: 14px;"><br />expect在shell脚本中的用法<br /></span><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#!/bin/bash<br /><br />passwd=<span style="color: #008000; ">'</span><span style="color: #008000; ">123456'</span><span style="color: #008000; "><br /></span><br />/usr/bin/expect&nbsp;&lt;&lt;-EOF<br /><br /><span style="color: #0000FF; ">set</span>&nbsp;<span style="color: #0000FF; ">time</span>&nbsp;10<br />spawn&nbsp;ssh&nbsp;saneri@192.168.56.103&nbsp;df&nbsp;-Th<br />expect&nbsp;{<br />"*yes/no"&nbsp;{&nbsp;send&nbsp;"yes\r";&nbsp;exp_continue&nbsp;}<br />"*password:"&nbsp;{&nbsp;send&nbsp;"$passwd\r"&nbsp;}<br />}<br />expect&nbsp;eof<br />EOF</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92563.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2022-02-21 18:44 <a href="http://www.cnitblog.com/luckydmz/archive/2022/02/21/92563.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>迁移git项目</title><link>http://www.cnitblog.com/luckydmz/archive/2022/02/08/92551.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 08 Feb 2022 10:42:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2022/02/08/92551.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92551.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2022/02/08/92551.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92551.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92551.html</trackback:ping><description><![CDATA[<br /><span style="color: #262626; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Noto Sans&quot;, &quot;Noto Sans CJK SC&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, sans-serif; font-size: 14px; white-space: pre-line;">git clone --mirror &lt;原地址&gt;&nbsp; &nbsp; &nbsp;# 会取得 项目名.git 的目录，里面是包含了提交历史、分支等的完整项目库<br />cd &lt;项目目录&gt;<br />git remote set-url --push origin &lt;新地址&gt;&nbsp; &nbsp; &nbsp;# 新地址是提前创建好的（空白的）新项目库路径<br />git push --mirror<br /><br />告知其他合作开发者修改远程库路径到新地址<br /></span><span style="color: #262626; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Noto Sans&quot;, &quot;Noto Sans CJK SC&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, sans-serif; font-size: 14px; white-space: pre-line;">git remote set-url origin &lt;新地址&gt;<br /></span><span style="color: #262626; font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, &quot;Helvetica Neue&quot;, &quot;PingFang SC&quot;, &quot;Noto Sans&quot;, &quot;Noto Sans CJK SC&quot;, &quot;Microsoft YaHei&quot;, 微软雅黑, sans-serif; font-size: 14px; white-space: pre-line;">git remote -v&nbsp; # 可以查看当前设置的地址</span><img src ="http://www.cnitblog.com/luckydmz/aggbug/92551.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2022-02-08 18:42 <a href="http://www.cnitblog.com/luckydmz/archive/2022/02/08/92551.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>pandas df.to_excel 设置列宽遇到 AttributeError: 'Worksheet' object has no attribute 'column_dimensions'</title><link>http://www.cnitblog.com/luckydmz/archive/2021/12/23/92522.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Thu, 23 Dec 2021 02:11:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/12/23/92522.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92522.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/12/23/92522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92522.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92522.html</trackback:ping><description><![CDATA[df.to_excel底层默认优先用的是xlsxwriter，sheet对象的类型是 xlsxwriter.worksheet.Worksheet，它没有column_dimensions属性。<br />可以通过在创建ExcelWriter的时候指定engine="openpyxl"让底层使用openpyxl，sheet对象的类型会变成openpyxl.worksheet.worksheet.Worksheet，它是有column_dimensions属性的。<br />网上的代码没有指定engine仍然可以工作可能是因为他们的环境没有安装xlwt只安装了openpyxl。<br /><br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->with&nbsp;pd.ExcelWriter(f<span style="color: #800000; ">"</span><span style="color: #800000; ">./净值列表{datetime.datetime.now().date()}&nbsp;({i}).xlsx</span><span style="color: #800000; ">"</span>,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;engine=<span style="color: #800000; ">"</span><span style="color: #800000; ">openpyxl</span><span style="color: #800000; ">"</span>,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;date_format=<span style="color: #800000; ">"</span><span style="color: #800000; ">YYYY-MM-DD</span><span style="color: #800000; ">"</span>,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;datetime_format=<span style="color: #800000; ">"</span><span style="color: #800000; ">YYYY-MM-DD&nbsp;HH:MM:SS</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;as&nbsp;writer:<br />&nbsp;&nbsp;&nbsp;&nbsp;df.to_excel(writer)<br />&nbsp;&nbsp;&nbsp;&nbsp;sheet&nbsp;=&nbsp;writer.sheets[<span style="color: #800000; ">"</span><span style="color: #800000; ">Sheet1</span><span style="color: #800000; ">"</span>]<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;设置列宽</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;sheet.column_dimensions[<span style="color: #800000; ">'</span><span style="color: #800000; ">A</span><span style="color: #800000; ">'</span>].width&nbsp;=&nbsp;12.5<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;设置行高</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;sheet.row_dimensions[1].height&nbsp;=&nbsp;72<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;设置表头（第一行）自动换行</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;sheet[1]<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;c&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;r:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c.alignment&nbsp;=&nbsp;openpyxl.styles.Alignment(wrapText=True)<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;设置表体数字格式显示4位小数</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i,&nbsp;r&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;enumerate(sheet):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;j,&nbsp;c&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;enumerate(r):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;i&nbsp;!=&nbsp;0&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;j&nbsp;!=&nbsp;0:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c.number_format&nbsp;=&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">0.0000</span><span style="color: #800000; ">"</span></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-12-23 10:11 <a href="http://www.cnitblog.com/luckydmz/archive/2021/12/23/92522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用PyArrow序列化和反序列化pd.DataFrame</title><link>http://www.cnitblog.com/luckydmz/archive/2021/11/11/92519.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Thu, 11 Nov 2021 09:27:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/11/11/92519.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92519.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/11/11/92519.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92519.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92519.html</trackback:ping><description><![CDATA[<br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">import</span>&nbsp;pyarrow&nbsp;as&nbsp;pa<br /><span style="color: #0000FF; ">import</span>&nbsp;zlib<br /><br /><span style="color: #0000FF; ">class</span>&nbsp;PyArrowEncoder:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;compress_level=-1):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.compress_level&nbsp;=&nbsp;compress_level<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;serialize(self,&nbsp;df):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table&nbsp;=&nbsp;pa.Table.from_pandas(df)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sink&nbsp;=&nbsp;pa.BufferOutputStream()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;pa.ipc.new_stream(sink,&nbsp;table.schema)&nbsp;as&nbsp;writer:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;writer.write_table(table)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;buf&nbsp;=&nbsp;sink.getvalue()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pybytes&nbsp;=&nbsp;buf.to_pybytes()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;zlib.compress(pybytes,&nbsp;self.compress_level)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;deserialize(self,&nbsp;data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;pa.ipc.open_stream(zlib.decompress(data))&nbsp;as&nbsp;reader:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;df&nbsp;=&nbsp;reader.read_pandas()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;df</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92519.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-11-11 17:27 <a href="http://www.cnitblog.com/luckydmz/archive/2021/11/11/92519.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>记一次Linux因硬盘设备编号错位挂载失败引起启动失败的解决过程</title><link>http://www.cnitblog.com/luckydmz/archive/2021/10/25/92515.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Mon, 25 Oct 2021 05:54:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/10/25/92515.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92515.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/10/25/92515.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92515.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92515.html</trackback:ping><description><![CDATA[问题描述<br />周末办公楼电力系统维护停电3小时，服务器关机，电力恢复后服务器启动失败，现象是启动报错，提示让输入密码进入紧急模式。<br />看到主要的错误描述是：<br />CIFS VFS: ioctl error in smb2_get_dfs_refer rc=-5<br />怀疑和mount有关。<br />输入密码进入紧急模式，输入命令mount -a，即根据配置文件/etc/fstab进行挂载(正常启动时也是根据此文件进行挂载)<br />其中/etc/fstab的内容如下<br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><img src="http://www.cnitblog.com/Images/dot.gif"  alt="" /><img src="http://www.cnitblog.com/Images/dot.gif"  alt="" />省略若干<br />/dev/md126p1&nbsp;&nbsp;&nbsp;&nbsp;/data&nbsp;&nbsp;&nbsp;ext4&nbsp;&nbsp;&nbsp;&nbsp;defaults&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0<br />/dev/sdd1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/data2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ext4&nbsp;&nbsp;&nbsp;&nbsp;defaults&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0<br /><img src="http://www.cnitblog.com/Images/dot.gif"  alt="" /><img src="http://www.cnitblog.com/Images/dot.gif"  alt="" />省略若干</div><br />执行后看到了具体的挂载错误条目是找不到设备 /dev/sdd1<br />使用命令<br />fdisk -l<br />可以看到存在/dev/sdd和/dev/sdd1<br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->Disk&nbsp;/dev/sdd:&nbsp;3.7&nbsp;TiB,&nbsp;4000787030016&nbsp;bytes,&nbsp;7814037168&nbsp;sectors<br />Units:&nbsp;sectors&nbsp;of&nbsp;1&nbsp;*&nbsp;512&nbsp;=&nbsp;512&nbsp;bytes<br />Sector&nbsp;size&nbsp;(logical/physical):&nbsp;512&nbsp;bytes&nbsp;/&nbsp;512&nbsp;bytes<br />I/O&nbsp;size&nbsp;(minimum/optimal):&nbsp;512&nbsp;bytes&nbsp;/&nbsp;512&nbsp;bytes<br />Disklabel&nbsp;type:&nbsp;gpt<br />Disk&nbsp;identifier:&nbsp;737D5D12-456A-414A-86DC-0F8279EDA29B<br /><br />Device&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Start&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;End&nbsp;&nbsp;&nbsp;&nbsp;Sectors&nbsp;Size&nbsp;Type<br />/dev/sdd1&nbsp;&nbsp;&nbsp;2048&nbsp;4294969343&nbsp;4294967296&nbsp;&nbsp;&nbsp;2T&nbsp;Linux&nbsp;filesystem</div><br />使用<span style="color: #4b4b4b; font-family: Verdana; font-size: 13px; background-color: #ffffff; white-space: pre-wrap;">lsblk，看到<br /></span><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MAJ:MIN&nbsp;RM&nbsp;&nbsp;&nbsp;SIZE&nbsp;RO&nbsp;TYPE&nbsp;&nbsp;MOUNTPOINT<br />loop0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7:0&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;99.4M&nbsp;&nbsp;1&nbsp;loop&nbsp;&nbsp;/snap/core/11993<br />loop1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7:1&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;99.5M&nbsp;&nbsp;1&nbsp;loop&nbsp;&nbsp;/snap/core/11798<br />sda&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8:0&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;931.5G&nbsp;&nbsp;0&nbsp;disk<br />&#9500;&#9472;sda1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8:1&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;512M&nbsp;&nbsp;0&nbsp;part<br />&#9492;&#9472;sda2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8:2&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;931G&nbsp;&nbsp;0&nbsp;part<br />sdb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8:16&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;1.8T&nbsp;&nbsp;0&nbsp;disk<br />&#9500;&#9472;sdb1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8:17&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;512M&nbsp;&nbsp;0&nbsp;part&nbsp;&nbsp;/boot/efi<br />&#9492;&#9472;sdb2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8:18&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;1.8T&nbsp;&nbsp;0&nbsp;part&nbsp;&nbsp;/<br />sdc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8:32&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;1.8T&nbsp;&nbsp;0&nbsp;disk<br />&#9492;&#9472;sdc1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8:33&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;1.8T&nbsp;&nbsp;0&nbsp;part&nbsp;&nbsp;/data2<br />sdd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8:48&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;3.7T&nbsp;&nbsp;0&nbsp;disk<br />&#9492;&#9472;md126&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;9:126&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;3.7T&nbsp;&nbsp;0&nbsp;raid0<br />&nbsp;&nbsp;&#9492;&#9472;md126p1&nbsp;259:0&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2T&nbsp;&nbsp;0&nbsp;md&nbsp;&nbsp;&nbsp;&nbsp;/data<br />sr0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;11:0&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;1024M&nbsp;&nbsp;0&nbsp;rom</div><span style="color: #4b4b4b; font-family: Verdana; font-size: 13px; background-color: #ffffff; white-space: pre-wrap;"><br /></span>发现sdd下面是md126 md126p1，想起来有一块盘做成了raid0，挂载时不能按照sda、sdb、sdc的命名方式挂载，需要用/dev/md126p1，但这不是问题，因为fstab文件中确实使用了/dev/md126p1，但不应该挂载/dev/sdd1了啊，其实是这次重启之后原来的sdd1变成了现在的sdc1，可能因为上次的磁盘是热插入的，重启之后根据插入口的顺序重新分配了设备名，把fstab文件中的sdd1改成sdc1，重新mount -a成功，进入/data2查看文件，确实是之前sdd1上的。<br /><br />重启会重新分配设备名导致挂载失败的问题，根据<a href="https://blog.csdn.net/weixin_34552525/article/details/116731517">linux下磁盘sda,Linux下磁盘设备文件（sda,sdb,sdc&#8230;.）变化问题_林声飘扬的博客-CSDN博客</a>这篇博文的说法，目前没有办法直接解决，但是可以通过指定id和uuid的方式挂载而不使用sda、sdb这种名称来绕过这个问题<br />使用<br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->ls&nbsp;-la&nbsp;/dev/disk/by-id</div><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->ls&nbsp;-la&nbsp;/dev/disk/by-uuid</div>可以看到这些id和uuid就是指向sda、sdb之类的软连接，而id和uuid每次启动是固定的，那么这些软连接应该是在启动过程中生成的。<br />最后保险起见，我将fstab文件中的挂载设备改成了id表示<br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;/dev/sdc1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/data2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ext4&nbsp;&nbsp;&nbsp;&nbsp;defaults&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0</span><span style="color: #008000; "><br /></span>/dev/disk/by-id/ata-ST2000NM0055-1V4104_ZC20W9TN-part1&nbsp;/data2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ext4&nbsp;&nbsp;&nbsp;&nbsp;defaults&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92515.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-10-25 13:54 <a href="http://www.cnitblog.com/luckydmz/archive/2021/10/25/92515.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python实现的瓶颈分析计时</title><link>http://www.cnitblog.com/luckydmz/archive/2021/10/08/92508.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Fri, 08 Oct 2021 02:45:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/10/08/92508.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92508.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/10/08/92508.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92508.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92508.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">import</span>&nbsp;time<br /><br /><span style="color: #0000FF; ">class</span>&nbsp;PerfCounter():<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;get_time(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;time.perf_counter()<br /><br /><br /><span style="color: #0000FF; ">class</span>&nbsp;Node:<br />&nbsp;&nbsp;&nbsp;&nbsp;clock&nbsp;=&nbsp;None<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;name,&nbsp;parent):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;带父节点的孩子兄弟树结构字段</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.parent&nbsp;=&nbsp;parent<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.child&nbsp;=&nbsp;None<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.sibling&nbsp;=&nbsp;None<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.name&nbsp;=&nbsp;name<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.total_calls&nbsp;=&nbsp;0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.recursion_counter&nbsp;=&nbsp;0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.total_ticks&nbsp;=&nbsp;0<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__del__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.child:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">del</span>&nbsp;self.child<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.child&nbsp;=&nbsp;None<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.sibling:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">del</span>&nbsp;self.sibling<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.sibling&nbsp;=&nbsp;None<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;get_child(self,&nbsp;name):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;child&nbsp;=&nbsp;self.child<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;child:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;child.name&nbsp;==&nbsp;name:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;child<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;child&nbsp;=&nbsp;child.sibling<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;如果没有找到就新建结点，并插入作为第一个孩子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node&nbsp;=&nbsp;Node(name=name,&nbsp;parent=self)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node.sibling&nbsp;=&nbsp;self.child<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.child&nbsp;=&nbsp;node<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;node<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;reset(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.total_calls&nbsp;=&nbsp;0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.total_ticks&nbsp;=&nbsp;0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.child:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.child.reset()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.sibling:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.sibling.reset()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;enter(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.total_calls&nbsp;+=&nbsp;1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.recursion_counter&nbsp;+=&nbsp;1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.recursion_counter&nbsp;==&nbsp;1:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.start_tick&nbsp;=&nbsp;self.clock.get_time()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;exit(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.recursion_counter&nbsp;-=&nbsp;1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.recursion_counter&nbsp;==&nbsp;0&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;self.total_calls&nbsp;!=&nbsp;0:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tick&nbsp;=&nbsp;self.clock.get_time()&nbsp;-&nbsp;self.start_tick;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.total_ticks&nbsp;+=&nbsp;tick;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(self.recursion_counter&nbsp;==&nbsp;0)<br /><br /><br /><span style="color: #0000FF; ">class</span>&nbsp;Profiler:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;clock=None):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Node.clock&nbsp;=&nbsp;clock&nbsp;<span style="color: #0000FF; ">or</span>&nbsp;PerfCounter()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.root&nbsp;=&nbsp;Node(<span style="color: #800000; ">""</span>,&nbsp;None)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.current_node&nbsp;=&nbsp;self.root<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.root.enter()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__del__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.root:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">del</span>&nbsp;self.root<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;set_clock(self,&nbsp;clock):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Node.clock&nbsp;=&nbsp;clock<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;reset(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.root.reset()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.root.enter()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;enter(self,&nbsp;name):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;name&nbsp;!=&nbsp;self.current_node.name:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.current_node&nbsp;=&nbsp;self.current_node.get_child(name)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.current_node.enter()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;exit(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.current_node.exit():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.current_node&nbsp;=&nbsp;self.current_node.parent<br /><br />profiler&nbsp;=&nbsp;Profiler()<br /><br /><span style="color: #0000FF; ">def</span>&nbsp;time_me(fn,&nbsp;profiler=profiler):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;wrapper(*args,&nbsp;**kw):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;profiler.enter(fn.<span style="color: #800080; ">__name__</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;=&nbsp;fn(*args,&nbsp;**kw)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;profiler.exit()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;ret<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;wrapper<br /><br /><span style="color: #0000FF; ">def</span>&nbsp;enter_region(name,&nbsp;profiler=profiler):<br />&nbsp;&nbsp;&nbsp;&nbsp;profiler.enter(name)<br /><br /><span style="color: #0000FF; ">def</span>&nbsp;exit_region(profiler=profiler):<br />&nbsp;&nbsp;&nbsp;&nbsp;profiler.exit()<br /><br /><span style="color: #0000FF; ">def</span>&nbsp;dfs(node,&nbsp;depth,&nbsp;cb):<br />&nbsp;&nbsp;&nbsp;&nbsp;cb(node,&nbsp;depth)<br />&nbsp;&nbsp;&nbsp;&nbsp;node&nbsp;=&nbsp;node.child<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;node:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dfs(node,&nbsp;depth+1,&nbsp;cb)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node&nbsp;=&nbsp;node.sibling<br /><br /><span style="color: #0000FF; ">def</span>&nbsp;travel(cb,&nbsp;profiler=profiler):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;profiler.root:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;profiler.root.exit()<br />&nbsp;&nbsp;&nbsp;&nbsp;dfs(profiler.root,&nbsp;0,&nbsp;cb)<br /><br /><span style="color: #0000FF; ">def</span>&nbsp;view(node,&nbsp;depth):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(<span style="color: #800000; ">"</span><span style="color: #800000; ">{space}[{name}]&nbsp;{calls}&nbsp;times&nbsp;{ticks:.3f}&nbsp;seconds&nbsp;{rate:.2f}%</span><span style="color: #800000; ">"</span>.format(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;space=<span style="color: #800000; ">"</span><span style="color: #800000; ">&nbsp;</span><span style="color: #800000; ">"</span>*depth,&nbsp;name=node.name,&nbsp;calls=node.total_calls,&nbsp;ticks=node.total_ticks,&nbsp;rate=node.total_ticks*100/(node.parent&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;node.parent.total_ticks&nbsp;<span style="color: #0000FF; ">or</span>&nbsp;node.total_ticks)&nbsp;))<br /><br /><br /><span style="color: #0000FF; ">if</span>&nbsp;<span style="color: #800080; ">__name__</span>&nbsp;==&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">__main__</span><span style="color: #800000; ">'</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;@time_me<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;func1():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(0.5)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func3()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;@time_me<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;func2(n):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;n&nbsp;&lt;=&nbsp;2:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func3()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;func2(n-1)&nbsp;+&nbsp;func2(n-2)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;@time_me<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;func3():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;enter_region(<span style="color: #800000; ">"</span><span style="color: #800000; ">func3&nbsp;sleep</span><span style="color: #800000; ">"</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time.sleep(0.1)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit_region()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;func1()<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;range(1,&nbsp;5):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(func2(i))<br />&nbsp;&nbsp;&nbsp;&nbsp;func1()<br />&nbsp;&nbsp;&nbsp;&nbsp;travel(view)</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92508.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-10-08 10:45 <a href="http://www.cnitblog.com/luckydmz/archive/2021/10/08/92508.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决matplotlib中文乱码</title><link>http://www.cnitblog.com/luckydmz/archive/2021/08/25/92493.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Wed, 25 Aug 2021 09:25:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/08/25/92493.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92493.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/08/25/92493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92493.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92493.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">import</span>&nbsp;matplotlib.pyplot&nbsp;as&nbsp;plt<br />plt.rcParams[<span style="color: #800000; ">"</span><span style="color: #800000; ">font.sans-serif</span><span style="color: #800000; ">"</span>]=[<span style="color: #800000; ">"</span><span style="color: #800000; ">SimHei</span><span style="color: #800000; ">"</span>]<br />plt.rcParams[<span style="color: #800000; ">"</span><span style="color: #800000; ">axes.unicode_minus</span><span style="color: #800000; ">"</span>]=False</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-08-25 17:25 <a href="http://www.cnitblog.com/luckydmz/archive/2021/08/25/92493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SSH Tunnel</title><link>http://www.cnitblog.com/luckydmz/archive/2021/02/18/92414.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Thu, 18 Feb 2021 11:02:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/02/18/92414.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92414.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/02/18/92414.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92414.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92414.html</trackback:ping><description><![CDATA[<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">SSH Tunnel解决的问题是让原本不能访问的端口（通常是因为在不同局域网）可以访问。</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">假设A要访问D:6379，A、D在不同局域网，最简单方法是在D所在的局域网网关上配置端口映射把D:6379映射到公网，但是很多时候出于某些因素（例如：安全考量、没有配置网关的权限、服务本身配置了只允许本地访问），不希望或无法通过把D:6379映射到公网解决，就可以考虑使用SSH Tunnel。</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">情形1：D所在的局域网有主机C的22端口是被映射到公网的，不妨假设映射成了X:30022，X是C和D所在局域网网关在公网的IP地址，那么可以在主机A上通过命令</span></div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;"><span style="color: #393939;">HostA$ ssh -L 36379:D:6379 root@X -p 30022</span></div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">把D:6379映射成了A:36379，特别情况C和D是同一台主机，D可以写成localhost。</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">情形2：A所在的局域网有主机B的22端口是被映射到公网的，不妨假设映射成了X:30022，X是A和B所在局域网网关在公网的IP地址，那么可以在主机D上通过命令</span></div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;"><span style="color: #393939;">HostD</span>$<span style="color: #393939;"> ssh -g -R 36379:D:6379 root@X -p 30022</span></div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">把D:6379映射成了B:36379，而A和B是同一局域网的，因此A可以访问到B:36379。</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">按理说上面的命令加了-g参数，B:36379应该被绑定在0.0.0.0:36379，但实际测试发现绑定在了127.0.0.1:36379，导致无法在A上访问，原因暂时未知（确定不是因为redis配置了保护模式），不过可以通过类似情形1的方式再把B:36379映射成A:36379，这样A就可以访问了。</span></div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">HostA$ ssh -L 36379:localhost:36379 root@B</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">情形3：A和D所在局域网都没有主机的ssh端口被映射到公网，但我有另一台具有公网IP的主机，不妨假设为X开启着22端口，类似情形2通过命令</div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">HostD$ ssh -R 36379:D:6379 root@X</div></div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">HostA$ ssh -L 36379:localhost:36379 root@X</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">之后让A访问A:36379即可。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">通过命令建立SSH Tunnel之后会登录到作为跳板的机器，通常我们是不需要使用这个控制台的，因此可以通过-f参数让ssh在后台运行，需要关闭tunnel时直接杀死进程。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">其他常用选项：</span></div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">C表示压缩数据传输</div></div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">f表示后台用户验证,这个选项很有用,没有shell的不可登陆账号也能使用.</div></div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">N表示不执行脚本或命令</div></div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">g表示允许远程主机连接转发端口</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">例如情形1中的命令可以写成</div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">ssh -CfNg -L 36379:D:6379 root@X -p 30022</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">通过</div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">ps -ef|grep ssh -CfNg</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">可以查看打开的tunnel。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">当网络不稳定时，ssh tunnel会自动断开，如果是前台的运行方式，会自动退出远程控制台，回到本地控制台提示符，如果是后台运行方式，进程会自动结束，这时候可以使用autossh工具来帮助自动重连。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">只需要把ssh命令中的ssh换成autossh -M &lt;port&gt;</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">例如情形1中的命令可以写成</div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">autossh -M 46379 -CfNg -L 36379:D:6379 root@X -p 30022</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">-M 后面的端口号是用来监视连接状态的，允许指定为0，这里指定为0是否可以正常监视重连以及如何监视有待研究。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.5; font-size: 14px;">另外autossh不支持输入密码，可以配合expect脚本自动输入密码或者通过密钥登录，更推荐使用密钥方式。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.5; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">先在本地生成密钥</div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">ssh-keygen -t rsa</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">会询问将密钥放在何处，默认即可。然后是输入密码，留空(否则你登录不仅需要私钥还要输入密码)。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">完成后在<span style="font-family: monospace;">~/.ssh</span>目录下会生成另个文件<span style="font-family: monospace;">id_rsa</span>和<span style="font-family: monospace;">id_rsa.pub</span>，一个私钥一个公钥。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">然后将公钥写入远程用户家目录下的~/.ssh/authorized_keys文件中，通过ssh-copy-id命令可以帮我们实现这一操作（相当于把公钥复制过去再追加到authorized_keys的尾部）</div><div><div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;">ssh-copy-id [-p SSH端口默认22] [user@]hostname</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">参考：</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><a href="https://blog.csdn.net/wxqee/article/details/49234595"><span style="color: #003884; text-decoration-line: underline;">https://blog.csdn.net/wxqee/article/details/49234595</span></a></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><a href="https://www.cnblogs.com/youxin/p/5220916.html"><span style="color: #003884; text-decoration-line: underline;">https://www.cnblogs.com/youxin/p/5220916.html</span></a></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><a href="https://blog.csdn.net/wesleyflagon/article/details/85304336"><span style="color: #003884; text-decoration-line: underline;">https://blog.csdn.net/wesleyflagon/article/details/85304336</span></a></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92414.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-02-18 19:02 <a href="http://www.cnitblog.com/luckydmz/archive/2021/02/18/92414.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux限制目录大小</title><link>http://www.cnitblog.com/luckydmz/archive/2021/02/02/92411.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 02 Feb 2021 07:36:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/02/02/92411.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92411.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/02/02/92411.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92411.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92411.html</trackback:ping><description><![CDATA[需求情景：存放日志或接收并存储数据的目录，为了防止程序出错时疯狂写日志硬盘被日志或存储的数据塞满。<br /><br />原理，创建一个固定大小的img文件，映射成一个目录<br /><br /><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->#&nbsp;创建Log.img大小1G<br />dd&nbsp;<span style="color: #0000FF; ">if</span>=/dev/zero&nbsp;of=./Log.img&nbsp;bs=1M&nbsp;count=1024<br />#&nbsp;格式化&nbsp;ext4<br />mkfs.ext4&nbsp;./Log.img<br />#&nbsp;创建挂载目录<br />mkdir&nbsp;./Log<br />#&nbsp;挂载<br />sudo&nbsp;mount&nbsp;-o&nbsp;loop&nbsp;./Log.img&nbsp;./Log<br />#&nbsp;修改权限<br />sudo&nbsp;chown&nbsp;daimingzhuang:daimingzhuang&nbsp;./Log</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92411.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-02-02 15:36 <a href="http://www.cnitblog.com/luckydmz/archive/2021/02/02/92411.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Vue.js前端跨域请求代理设置方法</title><link>http://www.cnitblog.com/luckydmz/archive/2021/02/02/92410.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Tue, 02 Feb 2021 06:59:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/02/02/92410.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92410.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/02/02/92410.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92410.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92410.html</trackback:ping><description><![CDATA[开发环境下通过 <span style="background-color: yellow;">config/index.js</span> 配置代理<br />
<br />
<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;see&nbsp;http://vuejs-templates.github.io/webpack&nbsp;for&nbsp;documentation.</span><span style="color: #008000; "><br />
</span><span style="color: #0000FF; ">var</span>&nbsp;path&nbsp;=&nbsp;require('path')<br />
<br />
module.exports&nbsp;=&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;build:&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env:&nbsp;require('./prod.env'),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;index:&nbsp;path.resolve(__dirname,&nbsp;'../dist/index.html'),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assetsRoot:&nbsp;path.resolve(__dirname,&nbsp;'../dist'),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assetsSubDirectory:&nbsp;'static',<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assetsPublicPath:&nbsp;'/view/',<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;productionSourceMap:&nbsp;<span style="color: #0000FF; ">true</span>,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Gzip&nbsp;off&nbsp;by&nbsp;default&nbsp;as&nbsp;many&nbsp;popular&nbsp;static&nbsp;hosts&nbsp;such&nbsp;as</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Surge&nbsp;or&nbsp;Netlify&nbsp;already&nbsp;gzip&nbsp;all&nbsp;static&nbsp;assets&nbsp;for&nbsp;you.</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Before&nbsp;setting&nbsp;to&nbsp;`true`,&nbsp;make&nbsp;sure&nbsp;to:</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;npm&nbsp;install&nbsp;--save-dev&nbsp;compression-webpack-plugin</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;productionGzip:&nbsp;<span style="color: #0000FF; ">false</span>,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;productionGzipExtensions:&nbsp;['js',&nbsp;'css'],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Run&nbsp;the&nbsp;build&nbsp;command&nbsp;with&nbsp;an&nbsp;extra&nbsp;argument&nbsp;to</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;View&nbsp;the&nbsp;bundle&nbsp;analyzer&nbsp;report&nbsp;after&nbsp;build&nbsp;finishes:</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;`npm&nbsp;run&nbsp;build&nbsp;--report`</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Set&nbsp;to&nbsp;`true`&nbsp;or&nbsp;`false`&nbsp;to&nbsp;always&nbsp;turn&nbsp;it&nbsp;on&nbsp;or&nbsp;off</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bundleAnalyzerReport:&nbsp;process.env.npm_config_report<br />
&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;dev:&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;env:&nbsp;require('./dev.env'),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;port:&nbsp;8080,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;autoOpenBrowser:&nbsp;<span style="color: #0000FF; ">true</span>,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assetsSubDirectory:&nbsp;'static',<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assetsPublicPath:&nbsp;'/',<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxyTable:&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'/api':&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target:&nbsp;"http://backend-server:30101",&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;测试环境下配置端口转发</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;changeOrigin:&nbsp;<span style="color: #0000FF; ">true</span>,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pathRewrite:&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"^/api":&nbsp;"",&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;重写路径，去掉前缀api</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;CSS&nbsp;Sourcemaps&nbsp;off&nbsp;by&nbsp;default&nbsp;because&nbsp;relative&nbsp;paths&nbsp;are&nbsp;"buggy"</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;with&nbsp;this&nbsp;option,&nbsp;according&nbsp;to&nbsp;the&nbsp;CSS-Loader&nbsp;README</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;(https://github.com/webpack/css-loader#sourcemaps)</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;In&nbsp;our&nbsp;experience,&nbsp;they&nbsp;generally&nbsp;work&nbsp;as&nbsp;expected,</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;just&nbsp;be&nbsp;aware&nbsp;of&nbsp;this&nbsp;issue&nbsp;when&nbsp;enabling&nbsp;this&nbsp;option.</span><span style="color: #008000; "><br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cssSourceMap:&nbsp;<span style="color: #0000FF; ">false</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</div>
<br /><br /><div>生产环境下通过前端所在服务器上的Nginx配置代理在 <br /><span style="background-color: yellow;">/etc/nginx/sites-enabled/default</span><br />中添加 location ^~/api/ 对应的块</div><div><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->server&nbsp;{<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;<img src="http://www.cnitblog.com/Images/dot.gif" alt="" /><img src="http://www.cnitblog.com/Images/dot.gif" alt="" /><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;location&nbsp;/&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;First&nbsp;attempt&nbsp;to&nbsp;serve&nbsp;request&nbsp;as&nbsp;file,&nbsp;then<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;as&nbsp;directory,&nbsp;then&nbsp;fall&nbsp;back&nbsp;to&nbsp;displaying&nbsp;a&nbsp;404.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try_files&nbsp;$uri&nbsp;$uri/&nbsp;=404;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;location&nbsp;^~/api/&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_set_header&nbsp;Host&nbsp;$host;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_set_header&nbsp;&nbsp;X-Real-IP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$remote_addr;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_set_header&nbsp;&nbsp;X-Forwarded-For&nbsp;&nbsp;$proxy_add_x_forwarded_for;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_set_header&nbsp;X-NginX-Proxy&nbsp;<span style="color: #0000FF; ">true</span>;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rewrite&nbsp;^/api/(.*)$&nbsp;/$1&nbsp;<span style="color: #0000FF; ">break</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_pass&nbsp;http:<span style="color: #008000; ">//</span><span style="color: #008000; ">backend-server:30101/;</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;<img src="http://www.cnitblog.com/Images/dot.gif" alt="" /><img src="http://www.cnitblog.com/Images/dot.gif" alt="" /><br />}</div><br /><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">检验配置文件是否正确</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">nginx -t</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">重启（重新读取配置）</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">nginx -s reload</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">或 serivice nginx restart</div><br /><br />当我们在前端通过axios请求地址 /api/Token 时，就会被转发到 http://backend-server:30101/Token</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92410.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-02-02 14:59 <a href="http://www.cnitblog.com/luckydmz/archive/2021/02/02/92410.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ubuntu下使用PPTPD搭建VPN</title><link>http://www.cnitblog.com/luckydmz/archive/2021/02/01/92408.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Mon, 01 Feb 2021 07:17:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2021/02/01/92408.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92408.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2021/02/01/92408.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92408.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92408.html</trackback:ping><description><![CDATA[<div yne-bulb-block="heading" yne-bulb-level="2" id="1225-1610942530960" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-size: 20px; font-weight: bold;">Ubuntu PPTP服务器</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">参考：</span><a href="https://blog.csdn.net/sanve/article/details/80882731"><span style="color: #003884; text-decoration-line: underline;">https://blog.csdn.net/sanve/article/details/80882731</span></a></div><div yne-bulb-block="heading" yne-bulb-level="4" id="6848-1611822217961" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-weight: bold;">安装</span></div><div yne-bulb-block="code" id="9251-1612161435395" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">apt install pptpd </div><div yne-bulb-block="heading" yne-bulb-level="4" id="5435-1611822221402" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-weight: bold;">配置IP</span></div><div yne-bulb-block="code" id="3016-1612161438661" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">vim /etc/pptpd.conf </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">解开这3处的注释并修改相应配置</div><div yne-bulb-block="code" id="3133-1612161038046" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">bcrelay&nbsp;eth1&nbsp;</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">localip&nbsp;192.168.10.1</span><span style="color: #008000; "><br />#</span><span style="color: #008000;">remoteip&nbsp;192.168.10.234-238,192.168.10.245</span></div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">bcrelay的意思我理解是来自虚拟局域网的广播要从哪个物理网卡转发出去</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">localip的意思本机是VPN服务器的IP地址</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">remoteip的意思是当有远程VPN客户端连接上来时被分配的IP段</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">我认为应该把虚拟局域网的网段和物理局域网分开，而且localip和remoteip应该在同一个网段，网上有localip和remoteip不应该在同一个网段的说法我并不认同。</div><div yne-bulb-block="heading" yne-bulb-level="4" id="9031-1612161484914" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-weight: bold;">配置DNS</span></div><div yne-bulb-block="code" id="6532-1612161481851" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">vim /etc/ppp/pptpd-options </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">找到ms-dns解开注释并修改相应配置</div><div yne-bulb-block="code" id="1357-1612161601799" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->ms-dns&nbsp;114.114.114.114<br />ms-dns&nbsp;8.8.8.8</div></div><div yne-bulb-block="heading" yne-bulb-level="4" id="5684-1612161559872" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-weight: bold;">配置用户名密码</span></div><div yne-bulb-block="code" id="4339-1612161761032" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">vim /etc/ppp/chap-secrets </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="code" id="2010-1612161781403" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;Secrets&nbsp;for&nbsp;authentication&nbsp;using&nbsp;CHAP</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">&nbsp;client&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; server   &nbsp;&nbsp;secret&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IP&nbsp;addresses</span><span style="color: #008000; "><br /></span>&lt;username&gt;&nbsp;&nbsp;&nbsp;pptpd&nbsp;&nbsp;&nbsp;&lt;password&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">修改配置后重启PPTP服务器</div><div yne-bulb-block="code" id="4169-1612161450152" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">service pptpd restart </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="heading" yne-bulb-level="4" id="5073-1612162078385" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-weight: bold;">打开IPv4转发</span></div><div yne-bulb-block="code" id="9290-1612162102976" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">vim /etc/sysctl.conf </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">找到并修改或添加</div><div yne-bulb-block="code" id="6699-1612162210157" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">net.ipv4.ip_forward = 1 </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">使配置生效</div><div yne-bulb-block="code" id="7010-1612162254710" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">sysctl -p service<br />procps restart </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">在需要通过VPN访问的机器上添加指向VPN网段的路由的下一跳地址是VPN服务器</div><div yne-bulb-block="code" id="7492-1612162724307" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">ip route add 192.168.10.0/24 via 192.168.1.99 </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">192.168.1.99 是VPN Server的内网IP地址，只有它知道VPN所在网段的的IP地址应该如何发送。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">或者直接把静态路由设置在网关上，设置下一跳地址为VPN服务器的IP，这样整个局域网都是可以通过VPN正常访问的。</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="heading" yne-bulb-level="2" id="9290-1612161460371" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-size: 20px; font-weight: bold;">Ubuntu PPTP客户端</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">参考：</span><a href="https://www.jianshu.com/p/1680c721f397"><span style="color: #003884; text-decoration-line: underline;">https://www.jianshu.com/p/1680c721f397</span></a> <a href="http://www.linuxfly.org/post/641/"><span style="color: #003884; text-decoration-line: underline;">http://www.linuxfly.org/post/641/</span></a></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="code" id="8352-1612162566300" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">pptpsetup --create 连接名 --server VPN服务器地址 --username 用户名 --password 密码 --encrypt </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">启动VPN连接</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">pon <span style="color: #393939;">连接名</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">关闭VPN连接</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">poff <span style="color: #393939;">连接名</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">查看路由表</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">route -n</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">添加路由，将通过VPN接入的物理局域网网段路由指定通过ppp0网口转发</span></div><div yne-bulb-block="code" id="4769-1612162563107" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">route add -net 192.168.1.0 netmask 255.255.255.0 dev ppp0 </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">每次重连后路由会丢失，需要重新配置，可以用下面的方法在ppp0 up时自动添加路由</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="heading" yne-bulb-level="3" id="6482-1611822587783" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-size: 16px; color: #222226; font-weight: bold;">pptp连接时自启动添加路由</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">参考：</span><a href="https://blog.csdn.net/qq_27434019/article/details/102920504"><span style="color: #003884; text-decoration-line: underline;">https://blog.csdn.net/qq_27434019/article/details/102920504</span></a></div><div yne-bulb-block="code" id="5142-1612162896938" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">vim /etc/ppp/peers/连接名 </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">增加ipparam一行</div><div yne-bulb-block="code" id="1777-1612163399524" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">ipparam 连接名 </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">======下面这步似乎不必要，不清楚作用======</div><div yne-bulb-block="code" id="4343-1612163533433" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">vim /etc/network/interfaces </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">增加</div><div yne-bulb-block="code" id="1018-1612163549340" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->auto&nbsp;tunnel<br />iface&nbsp;tunnel&nbsp;inet&nbsp;ppp<br />provider&nbsp;连接名</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">======================================</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">新建脚本文件并修改权限</div><div yne-bulb-block="code" id="4353-1612163650447" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->touch&nbsp;/etc/ppp/ip-up.d/连接名<br />chmod&nbsp;a+x&nbsp;/etc/ppp/ip-up.d/连接名</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">编辑脚本</div><div yne-bulb-block="code" id="1632-1612163728569" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">vim /etc/ppp/ip-up.d/连接名 </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">在脚本中加入添加路由的语句</div><div yne-bulb-block="code" id="7397-1612163721340" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->route&nbsp;add&nbsp;-net&nbsp;192.168.1.0&nbsp;netmask&nbsp;255.255.255.0&nbsp;dev&nbsp;ppp0</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">可以poff 再 pon 再 route -n 看看路由是否自动添加</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92408.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2021-02-01 15:17 <a href="http://www.cnitblog.com/luckydmz/archive/2021/02/01/92408.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>记一次硬盘IO占用过高排查</title><link>http://www.cnitblog.com/luckydmz/archive/2020/12/04/92375.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Fri, 04 Dec 2020 04:00:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/12/04/92375.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92375.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/12/04/92375.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92375.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92375.html</trackback:ping><description><![CDATA[<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">通过sar -d -p 3命令发现硬盘占用率比较高</div>
<div yne-bulb-block="image"><img src="http://www.cnitblog.com/images/cnitblog_com/luckydmz/1.jpg" width="800" alt="" /></div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">通过 iotop命令发现主要是被一个名为 <span style="font-size: 12px; font-family: Arial; color: #393939;">&nbsp;[jbd2/sda2-8] 的进程占用</span></div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-size: 12px; font-family: Arial; color: #393939;">网上说法是 </span><a href="https://blog.csdn.net/hualusiyu/article/details/71703072"><span style="color: #003884; text-decoration-line: underline;">(13条消息) 性能分析之IO分析-jbd2引起的IO高_hualusiyu的专栏-CSDN博客</span></a></div>
<div>
<div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;"><span style="font-size: 16px; color: #4d4d4d;">jbd2的全称是journaling block driver 。这个进程实现的是文件系统的日志功能，磁盘使用日志功能来保证数据的完整性。这个需要评估一下安全和性能哪个更重要，解决方案是升级内核或者牺牲完整性来换性能。</span></div>
</div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-size: 12px; font-family: Arial; color: #393939;">差点被误导。</span></div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="font-size: 12px; font-family: Arial; color: #393939;">而使用命令 atop -d 发现其实是 snapd 占用</span></div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #393939;">和这篇帖子情况一样 </span><a href="https://forum.ubuntu.org.cn/viewtopic.php?t=491212"><span style="color: #003884; text-decoration-line: underline;">snapd持续运行，引起jbd2/sda2-8持续访问硬盘，占用大量io - Ubuntu中文论坛</span></a></div>
<div>
<div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;"><a href="https://forum.ubuntu.org.cn/viewtopic.php?t=491212#p3221983"><span style="font-size: 16px; font-family: Arial; color: #978464;">snapd持续运行，引起jbd2/sda2-8持续访问硬盘，占用大量io</span></a></div>
</div>
<div>
<div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;"><a href="https://forum.ubuntu.org.cn/viewtopic.php?p=3221983#p3221983"><span style="font-size: 11px; font-family: Verdana; color: #654c22;">#6</span></a></div>
</div>
<div>
<div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;"><a href="https://forum.ubuntu.org.cn/viewtopic.php?p=3221983#p3221983"><span style="font-size: 11px; font-family: Verdana; color: #654c22;">帖子</span></a><span style="font-size: 11px; font-family: Verdana; color: #271b08; background-color: #f0ece0;">&nbsp;由&nbsp;</span><a href="https://forum.ubuntu.org.cn/memberlist.php?mode=viewprofile&amp;u=526640"><span style="font-size: 11px; font-family: Verdana; color: #654c22; font-weight: bold;">sffred</span></a><span style="font-size: 11px; font-family: Verdana; color: #271b08; background-color: #f0ece0;">&nbsp;&#187;&nbsp;2020-06-06 16:04</span></div>
</div>
<div>
<div yne-bulb-block="quote" style="white-space: pre-wrap; padding: 0px 10px 0px 17px; border-left-width: 3px; border-left-color: #e8e8e8; margin: 0px 5px;"><span style="font-size: 13px; font-family: Verdana; color: #271b08; background-color: #f0ece0;">我最终解决这个问题的方式是卸载snapd。反正我也用不着</span></div>
</div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.4; font-size: 14px;"></div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.4; font-size: 14px;">了解到snapd是ubuntu预装的一个软件包管理工具。</div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.4; font-size: 14px;">使用snap list发现只有一个core，也就是我没有基于snap安装过软件包。</div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.4; font-size: 14px;">通过 service snapd stop 关闭snapd，在通过sar -d -p 3观察硬盘占用，已经完全正常</div>
<div yne-bulb-block="image"><img src="http://www.cnitblog.com/images/cnitblog_com/luckydmz/2.jpg" width="800" alt="" /></div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.4; font-size: 14px;">至此确定是由snapd引发.</div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.4; font-size: 14px;">通过service snapd start 启动snapd，观察硬盘占用，先是再次上升数十秒后回到了正常。</div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.4; font-size: 14px;">如果下次再出现占用过高准备禁用或卸载snap。</div>
<div yne-bulb-block="code" id="7250-1607054150235" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">禁用 systemctl disable snapd.service 卸载 apt purge snapd </div>
<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92375.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-12-04 12:00 <a href="http://www.cnitblog.com/luckydmz/archive/2020/12/04/92375.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python实现滚动数组，Python特殊方法的使用，Python运算符重载</title><link>http://www.cnitblog.com/luckydmz/archive/2020/09/07/92340.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Mon, 07 Sep 2020 07:48:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/09/07/92340.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92340.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/09/07/92340.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92340.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92340.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-</span><span style="color: #008000; "><br /></span><br /><span style="color: #0000FF; ">class</span>&nbsp;RollArray:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">class</span>&nbsp;Iterator:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;subject):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.subject&nbsp;=&nbsp;subject<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.start&nbsp;=&nbsp;self.subject.idx<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.i&nbsp;=&nbsp;0<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__next__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>&nbsp;self.i&nbsp;&lt;&nbsp;self.subject.capability:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.start&nbsp;+&nbsp;self.i&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self.subject:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;o&nbsp;=&nbsp;self.subject[self.start&nbsp;+&nbsp;self.i]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.i&nbsp;+=&nbsp;1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;o<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.i&nbsp;+=&nbsp;1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">raise</span>&nbsp;StopIteration()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;capability,&nbsp;items=[]):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.data&nbsp;=&nbsp;[None]&nbsp;*&nbsp;capability<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.used&nbsp;=&nbsp;[False]&nbsp;*&nbsp;capability<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.idx&nbsp;=&nbsp;0<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.capability&nbsp;=&nbsp;capability<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;e&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;items:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.append(e)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;append(self,&nbsp;obj):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.data[self.idx]&nbsp;=&nbsp;obj<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.used[self.idx]&nbsp;=&nbsp;True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.idx&nbsp;=&nbsp;(self.idx&nbsp;+&nbsp;1)&nbsp;%&nbsp;10<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;for&nbsp;e&nbsp;in&nbsp;x:</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__iter__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;RollArray.Iterator(self)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;[]&nbsp;const</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__getitem__</span>(self,&nbsp;i):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.used[i%self.capability]:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;self.data[i%self.capability]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">raise</span>&nbsp;IndexError()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;[]</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__setitem__</span>(self,&nbsp;i,&nbsp;v):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.data[i%self.capability]&nbsp;=&nbsp;v<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.used[i%self.capability]&nbsp;=&nbsp;True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;v<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;del&nbsp;x[]</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__delitem__</span>(self,&nbsp;i):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.used[i%self.capability]&nbsp;=&nbsp;False<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;重载&nbsp;if&nbsp;e&nbsp;in&nbsp;x:</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__contains__</span>(self,&nbsp;i):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;self.used[i%self.capability]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;tolist(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l&nbsp;=&nbsp;[]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;e&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l.append(e)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;l<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__repr__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">{self.__class__.__name__}({self.capability},&nbsp;items={self.tolist()})</span><span style="color: #800000; ">"</span><br /><br /><br /><span style="color: #0000FF; ">if</span>&nbsp;<span style="color: #800080; ">__name__</span>&nbsp;==&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">__main__</span><span style="color: #800000; ">'</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;arr&nbsp;=&nbsp;RollArray(10,&nbsp;range(5))<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">del</span>&nbsp;arr[3]<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(arr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;range(5,&nbsp;11):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arr.append(i)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(arr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;arr[11]&nbsp;=&nbsp;11<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(arr)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;e&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;arr:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(e)</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92340.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-09-07 15:48 <a href="http://www.cnitblog.com/luckydmz/archive/2020/09/07/92340.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>通用的插入更新(Upsert)实现</title><link>http://www.cnitblog.com/luckydmz/archive/2020/08/31/92335.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Mon, 31 Aug 2020 10:31:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/08/31/92335.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92335.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/08/31/92335.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92335.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92335.html</trackback:ping><description><![CDATA[<div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;-*-&nbsp;coding:&nbsp;utf-8&nbsp;-*-</span><span style="color: #008000; "><br /></span><br /><span style="color: #0000FF; ">import</span>&nbsp;math<br /><span style="color: #0000FF; ">import</span>&nbsp;datetime<br /><span style="color: #0000FF; ">import</span>&nbsp;numpy&nbsp;as&nbsp;np<br /><span style="color: #0000FF; ">import</span>&nbsp;pandas&nbsp;as&nbsp;pd<br /><span style="color: #0000FF; ">import</span>&nbsp;sqlalchemy<br /><br /><br /><span style="color: #800000; ">'''</span><span style="color: #800000; "><br />engine:&nbsp;SQLAlchemy&nbsp;Engine<br />buffer_size:&nbsp;缓存条目数，当缓存满时自动flush<br />update_on_duplicate:&nbsp;当唯一键重复时的行为，默认是update，设置为False表示不更新，即忽略插入失败。<br /></span><span style="color: #800000; ">'''</span><br /><span style="color: #0000FF; ">def</span>&nbsp;create_upsert_handler(engine,&nbsp;buffer_size=5000,&nbsp;update_on_duplicate=True):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;engine.dialect.name.lower().find(<span style="color: #800000; ">"</span><span style="color: #800000; ">mysql</span><span style="color: #800000; ">"</span>)&nbsp;!=&nbsp;-1:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;MySQLUpsertHandler(engine,&nbsp;buffer_size,&nbsp;update_on_duplicate)<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">elif</span>&nbsp;engine.dialect.name.lower().find(<span style="color: #800000; ">"</span><span style="color: #800000; ">postgresql</span><span style="color: #800000; ">"</span>)&nbsp;!=&nbsp;-1:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;PSQLUpsertHandler(engine,&nbsp;buffer_size,&nbsp;update_on_duplicate)<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">print</span>(f<span style="color: #800000; ">"</span><span style="color: #800000; ">没有为{engine.dialect.name}实现特殊的Upsert，使用默认版本，请确认可以正常工作，建议特化一个专门版本</span><span style="color: #800000; ">"</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;UpsertHandlerBase(engine,&nbsp;buffer_size,&nbsp;update_on_duplicate)<br /><br /><br /><span style="color: #0000FF; ">def</span>&nbsp;is_duplicate_key(e):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;T&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;UpsertHandlerBase.<span style="color: #800080; ">__subclasses__</span>():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;T.is_duplicate_key(e):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;True<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;UpsertHandlerBase.is_duplicate_key(e)<br /><br /><br /><span style="color: #800000; ">'''</span><span style="color: #800000; "><br />class&nbsp;UpsertHandler:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;传入的engine类型应该和使用的UpsertHandler支持的数据库类型相匹配<br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;buffer_size表示插入或更新数据缓存到多少才flush(即向数据库插入或更新)，None表示在析构时flush，0表示不缓存<br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;update_on_duplicate当唯一键重复时的行为，默认是update，设置为False表示不更新，即忽略插入失败。<br />&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;__init__(self,&nbsp;engine,&nbsp;buffer_size=None,&nbsp;update_on_duplicate=True):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;tablename为数据库表名<br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;pk为主键的元组，可以不是真正的表主键，但是可以用来判重决定insert还是update，例如('exchange_id',&nbsp;'trade_id')<br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;data为单条数据，dict的形式，例如{'exchange_id':&nbsp;'DCE',&nbsp;'trade_id':&nbsp;'&nbsp;&nbsp;1',&nbsp;'price':&nbsp;1.2,&nbsp;'volume':&nbsp;1}<br />&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;upsert(self,&nbsp;tablename,&nbsp;pk,&nbsp;data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;#&nbsp;立即把缓冲器的数据推到数据库，会在buffer_size满了或者析构时自动调用，也可以手动调用<br />&nbsp;&nbsp;&nbsp;&nbsp;def&nbsp;flush(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pass<br /></span><span style="color: #800000; ">'''</span><br /><span style="color: #0000FF; ">class</span>&nbsp;UpsertHandlerBase:<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;engine,&nbsp;buffer_size=None,&nbsp;update_on_duplicate=True):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.engine&nbsp;=&nbsp;engine<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.tablename2pk&nbsp;=&nbsp;{}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.tablename2datas&nbsp;=&nbsp;{}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.buffer_size&nbsp;=&nbsp;buffer_size<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.update_on_duplicate&nbsp;=&nbsp;update_on_duplicate<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__del__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.flush()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;flush(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;(tablename,&nbsp;pk)&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self.tablename2pk.items():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;datas&nbsp;=&nbsp;self.tablename2datas[tablename]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;len(datas)&nbsp;&gt;&nbsp;0:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;self.engine.connect()&nbsp;as&nbsp;conn:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self._flush(conn,&nbsp;tablename,&nbsp;pk,&nbsp;datas)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.tablename2datas[tablename]&nbsp;=&nbsp;[]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_flush(self,&nbsp;conn,&nbsp;tablename,&nbsp;pk,&nbsp;datas):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columns&nbsp;=&nbsp;datas[0].keys()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sql&nbsp;=&nbsp;f<span style="color: #800000; ">"""</span><span style="color: #800000; ">INSERT&nbsp;INTO&nbsp;{tablename}({",&nbsp;".join(columns)})&nbsp;VALUES\n</span><span style="color: #800000; ">"""</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i,&nbsp;data&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;enumerate(datas):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;i&nbsp;!=&nbsp;len(datas)&nbsp;-&nbsp;1:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sql&nbsp;+=&nbsp;f<span style="color: #800000; ">"""</span><span style="color: #800000; ">&nbsp;&nbsp;({self._format_values(data.values())}),\n</span><span style="color: #800000; ">"""</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sql&nbsp;+=&nbsp;f<span style="color: #800000; ">"""</span><span style="color: #800000; ">&nbsp;&nbsp;({self._format_values(data.values())});\n</span><span style="color: #800000; ">"""</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.execute(sql)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">except</span>&nbsp;sqlalchemy.exc.IntegrityError&nbsp;as&nbsp;e:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.is_duplicate_key(e):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;插入遇到重复KEY</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;len(datas)&nbsp;&lt;=&nbsp;500:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;data&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;datas:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.upsert_one(conn,&nbsp;tablename,&nbsp;pk,&nbsp;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l&nbsp;=&nbsp;len(datas)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;=&nbsp;int(l&nbsp;//&nbsp;2)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self._flush(conn,&nbsp;tablename,&nbsp;pk,&nbsp;datas[:p])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self._flush(conn,&nbsp;tablename,&nbsp;pk,&nbsp;datas[p:])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">raise</span>&nbsp;e<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;upsert_one(self,&nbsp;conn,&nbsp;tablename,&nbsp;pk,&nbsp;data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;None<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.update_on_duplicate:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;update_str&nbsp;=&nbsp;self._format_update_values(pk,&nbsp;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.update_on_duplicate&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;update_str.strip():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;conn.execute(f<span style="color: #800000; ">"</span><span style="color: #800000; ">UPDATE&nbsp;{tablename}&nbsp;SET&nbsp;{update_str}&nbsp;WHERE&nbsp;{self._format_update_conditions(pk,&nbsp;data)}</span><span style="color: #800000; ">"</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;r&nbsp;<span style="color: #0000FF; ">or</span>&nbsp;r.rowcount&nbsp;==&nbsp;0:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">try</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;conn.execute(f<span style="color: #800000; ">"</span><span style="color: #800000; ">INSERT&nbsp;INTO&nbsp;{tablename}({',&nbsp;'.join(data.keys())})&nbsp;VALUES({self._format_values(data.values())})</span><span style="color: #800000; ">"</span>)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">except</span>&nbsp;sqlalchemy.exc.IntegrityError&nbsp;as&nbsp;e:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.is_duplicate_key(e):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">pass</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">raise</span>&nbsp;e<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;@staticmethod<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;is_duplicate_key(e):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;type(e)&nbsp;!=&nbsp;sqlalchemy.exc.IntegrityError:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;False<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;(str(e.orig).lower().find(<span style="color: #800000; ">"</span><span style="color: #800000; ">duplicate</span><span style="color: #800000; ">"</span>)&nbsp;!=&nbsp;-1)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_isinf(self,&nbsp;x):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;x&gt;=9223372036854775807&nbsp;<span style="color: #0000FF; ">or</span>&nbsp;x&lt;=-9223372036854775808<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_format_value(self,&nbsp;v):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;v&nbsp;<span style="color: #0000FF; ">is</span>&nbsp;None:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">null</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">elif</span>&nbsp;type(v)&nbsp;==&nbsp;float:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;math.isnan(v)&nbsp;<span style="color: #0000FF; ">or</span>&nbsp;math.isinf(v)&nbsp;<span style="color: #0000FF; ">or</span>&nbsp;self._isinf(v):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">null</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">{v}</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">elif</span>&nbsp;type(v)&nbsp;==&nbsp;int:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self._isinf(v):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">null</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">{v}</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">elif</span>&nbsp;type(v)&nbsp;==&nbsp;datetime.datetime:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">'</span><span style="color: #800000; ">"</span>+v.strftime(<span style="color: #800000; ">"</span><span style="color: #800000; ">%Y-%m-%d&nbsp;%H:%M:%S</span><span style="color: #800000; ">"</span>)+<span style="color: #800000; ">"</span><span style="color: #800000; ">'</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">elif</span>&nbsp;type(v)&nbsp;==&nbsp;datetime.date:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">'</span><span style="color: #800000; ">"</span>+v.strftime(<span style="color: #800000; ">"</span><span style="color: #800000; ">%Y-%m-%d</span><span style="color: #800000; ">"</span>)+<span style="color: #800000; ">"</span><span style="color: #800000; ">'</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">elif</span>&nbsp;type(v)&nbsp;==&nbsp;pd.Timestamp:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;<span style="color: #800000; ">"</span><span style="color: #800000; ">'</span><span style="color: #800000; ">"</span>+v.strftime(<span style="color: #800000; ">"</span><span style="color: #800000; ">%Y-%m-%d&nbsp;%H:%M:%S</span><span style="color: #800000; ">"</span>)+<span style="color: #800000; ">"</span><span style="color: #800000; ">'</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">elif</span>&nbsp;type(v)&nbsp;==&nbsp;str:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">'{v}'</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">'{v}'</span><span style="color: #800000; ">"</span><br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_format_values(self,&nbsp;data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;=&nbsp;<span style="color: #800000; ">''</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i,&nbsp;e&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;enumerate(data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;+=&nbsp;self._format_value(e)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;+=&nbsp;<span style="color: #800000; ">'</span><span style="color: #800000; ">,&nbsp;</span><span style="color: #800000; ">'</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;s[:-2]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_format_update_values(self,&nbsp;pk,&nbsp;data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;=&nbsp;<span style="color: #800000; ">''</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i,&nbsp;(k,&nbsp;v)&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;enumerate(data.items()):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;k&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;pk:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;+=&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">{k}={self._format_value(v)},&nbsp;</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;s[:-2]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;_format_update_conditions(self,&nbsp;pk,&nbsp;data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;=&nbsp;<span style="color: #800000; ">''</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;i,&nbsp;(k,&nbsp;v)&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;enumerate(data.items()):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;k&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;pk:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s&nbsp;+=&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">{k}={self._format_value(v)}&nbsp;and&nbsp;</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;s[:-4]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;upsert(self,&nbsp;tablename,&nbsp;pk,&nbsp;data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.buffer_size&nbsp;<span style="color: #0000FF; ">is</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;None&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;self.buffer_size&nbsp;==&nbsp;0:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;self.engine.connect()&nbsp;as&nbsp;conn:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.upsert_one(conn,&nbsp;tablename,&nbsp;pk,&nbsp;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;pk:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.tablename2pk[tablename]&nbsp;=&nbsp;pk<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;tablename&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;self.tablename2datas:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.tablename2datas[tablename]&nbsp;=&nbsp;[]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.tablename2datas[tablename].append(data)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.buffer_size&nbsp;<span style="color: #0000FF; ">is</span>&nbsp;<span style="color: #0000FF; ">not</span>&nbsp;None&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;len(self.tablename2datas[tablename])&nbsp;&gt;=&nbsp;self.buffer_size:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;self.engine.connect()&nbsp;as&nbsp;conn:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self._flush(conn,&nbsp;tablename,&nbsp;self.tablename2pk[tablename],&nbsp;self.tablename2datas[tablename])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.tablename2datas[tablename]&nbsp;=&nbsp;[]<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;upsert_dataframe(self,&nbsp;tablename,&nbsp;pk,&nbsp;df):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;len(df)&nbsp;&lt;=&nbsp;2000:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;with&nbsp;self.engine.connect()&nbsp;as&nbsp;conn:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>&nbsp;index,&nbsp;row&nbsp;<span style="color: #0000FF; ">in</span>&nbsp;df.iterrows():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.upsert_one(conn,&nbsp;tablename,&nbsp;pk,&nbsp;row.to_dict())<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l&nbsp;=&nbsp;len(df)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;=&nbsp;int(l&nbsp;//&nbsp;2)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.upsert_dataframe(tablename,&nbsp;pk,&nbsp;df[:p])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.upsert_dataframe(tablename,&nbsp;pk,&nbsp;df[p:])<br /><br /><br /><span style="color: #0000FF; ">class</span>&nbsp;MySQLUpsertHandler(UpsertHandlerBase):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;engine,&nbsp;buffer_size=None,&nbsp;update_on_duplicate=True):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super().<span style="color: #800080; ">__init__</span>(engine,&nbsp;buffer_size,&nbsp;update_on_duplicate)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__del__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super().<span style="color: #800080; ">__del__</span>()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;@staticmethod<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;is_duplicate_key(e):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;type(e)&nbsp;!=&nbsp;sqlalchemy.exc.IntegrityError:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;False<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;len(e.orig.args)&nbsp;&gt;&nbsp;1&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;str(e.orig.args[1]).startswith(<span style="color: #800000; ">"</span><span style="color: #800000; ">Duplicate&nbsp;entry</span><span style="color: #800000; ">"</span>):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;False<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;upsert_one(self,&nbsp;conn,&nbsp;tablename,&nbsp;pk,&nbsp;data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.update_on_duplicate:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;update_str&nbsp;=&nbsp;self._format_update_values(pk,&nbsp;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.update_on_duplicate&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;update_str.strip():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;duplicate_do_str&nbsp;=&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">UPDATE&nbsp;{update_str}</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;duplicate_do_str&nbsp;=&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">UPDATE&nbsp;{pk[0]}=VALUES({pk[0]})</span><span style="color: #800000; ">"</span>&nbsp;&nbsp;<span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;等价于do&nbsp;nothing</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sql&nbsp;=&nbsp;f<span style="color: #800000; ">"""</span><span style="color: #800000; ">INSERT&nbsp;INTO&nbsp;{tablename}({",&nbsp;".join(data.keys())})&nbsp;VALUES<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;({self._format_values(data.values())})<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ON&nbsp;DUPLICATE&nbsp;KEY<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{duplicate_do_str}\n</span><span style="color: #800000; ">"""</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.execute(sql)<br /><br /><br /><span style="color: #0000FF; ">class</span>&nbsp;PSQLUpsertHandler(UpsertHandlerBase):<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__init__</span>(self,&nbsp;engine,&nbsp;buffer_size=None,&nbsp;update_on_duplicate=True):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super().<span style="color: #800080; ">__init__</span>(engine,&nbsp;buffer_size,&nbsp;update_on_duplicate)<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;<span style="color: #800080; ">__del__</span>(self):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super().<span style="color: #800080; ">__del__</span>()<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;@staticmethod<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;is_duplicate_key(e):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;type(e)&nbsp;!=&nbsp;sqlalchemy.exc.IntegrityError:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;False<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;str(e.orig).startswith(<span style="color: #800000; ">"</span><span style="color: #800000; ">duplicate&nbsp;key</span><span style="color: #800000; ">"</span>):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;True<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;False<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">def</span>&nbsp;upsert_one(self,&nbsp;conn,&nbsp;tablename,&nbsp;pk,&nbsp;data):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.update_on_duplicate:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;update_str&nbsp;=&nbsp;self._format_update_values(pk,&nbsp;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;self.update_on_duplicate&nbsp;<span style="color: #0000FF; ">and</span>&nbsp;update_str.strip():<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;duplicate_do_str&nbsp;=&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">do&nbsp;update&nbsp;set&nbsp;{update_str}</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;duplicate_do_str&nbsp;=&nbsp;f<span style="color: #800000; ">"</span><span style="color: #800000; ">do&nbsp;nothing</span><span style="color: #800000; ">"</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sql&nbsp;=&nbsp;f<span style="color: #800000; ">"""</span><span style="color: #800000; ">INSERT&nbsp;INTO&nbsp;{tablename}({",&nbsp;".join(data.keys())})&nbsp;VALUES<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;({self._format_values(data.values())})<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;on&nbsp;conflict&nbsp;({",&nbsp;".join(pk)})<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{duplicate_do_str}\n</span><span style="color: #800000; ">"""</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.execute(sql)<br /></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92335.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-08-31 18:31 <a href="http://www.cnitblog.com/luckydmz/archive/2020/08/31/92335.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux配置共享目录</title><link>http://www.cnitblog.com/luckydmz/archive/2020/08/27/92331.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Thu, 27 Aug 2020 09:20:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/08/27/92331.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92331.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/08/27/92331.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92331.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92331.html</trackback:ping><description><![CDATA[<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">在需要被挂载的服务器上安装nfs-kernel-server</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">apt install nfs-kernel-server</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">编辑</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">sudo vim /etc/exports</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">样例</div><div yne-bulb-block="code" id="4529-1592965322011" data-theme="default" data-language="javascript" style="white-space: pre-wrap;"><div style="background-color: #eeeeee; font-size: 13px; border-color: #cccccc; border-image: initial; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">#</span><span style="color: #008000; ">&nbsp;/etc/exports:&nbsp;the&nbsp;access&nbsp;control&nbsp;list&nbsp;for&nbsp;filesystems&nbsp;which&nbsp;may&nbsp;be&nbsp;exported</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to&nbsp;NFS&nbsp;clients.&nbsp;&nbsp;See&nbsp;exports(5).</span><span style="color: #008000; "><br />#<br />#</span><span style="color: #008000; ">&nbsp;Example&nbsp;for&nbsp;NFSv2&nbsp;and&nbsp;NFSv3:</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">&nbsp;/srv/homes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hostname1(rw,sync,no_subtree_check)&nbsp;hostname2(ro,sync,no_subtree_check)</span><span style="color: #008000; "><br />#<br />#</span><span style="color: #008000; ">&nbsp;Example&nbsp;for&nbsp;NFSv4:</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">&nbsp;/srv/nfs4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)</span><span style="color: #008000; "><br />#</span><span style="color: #008000; ">&nbsp;/srv/nfs4/homes&nbsp;&nbsp;gss/krb5i(rw,sync,no_subtree_check)</span><span style="color: #008000; "><br /></span>/data&nbsp;192.168.1.150(rw,sync,no_root_squash)<br />/home/data_manager/database&nbsp;192.168.1.157(rw,sync,no_root_squash)&nbsp;*(ro,async,root_squash)</div></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">把共享目录的owner改成 nobody:nogroup</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">sudo chown nobody:nogroup &lt;共享路径&gt;</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">设置共享目录的权限</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">sudo chmod 777 &lt;共享路径&gt;</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">重新加载配置文件</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">sudo exportfs -a</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">在需要挂载的服务器需要安装nfs-common</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">apt install nfs-common</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">挂载命令样例 ，把140上的/data共享目录挂载到本地/mnt/140data</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">mount 192.168.1.140:/data /mnt/140data</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">使用到的端口，如果有防火墙需要设置</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">111/tcp+udp</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">825/tcp</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">2049/tcp</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">4046/udp</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">如果希望系统启动时自动加载文件系统，则还需要在 /etc/fstab 中添加内容：</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">192.168.1.140:/data /mnt/140data nfs defaults 0 0</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">其中nfs是被挂载的路径的类型</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">常用的类型有：</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">nfs表示远程linux的共享路径</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">cifs表示远程windows的共享路径</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">ext4表示本地ext4路径</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92331.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-08-27 17:20 <a href="http://www.cnitblog.com/luckydmz/archive/2020/08/27/92331.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PostgreSQL 10 主从同步配置</title><link>http://www.cnitblog.com/luckydmz/archive/2020/08/27/92330.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Thu, 27 Aug 2020 09:06:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/08/27/92330.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92330.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/08/27/92330.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92330.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92330.html</trackback:ping><description><![CDATA[<div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">我进行的配置有：</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">改大wal_keep_segments值到64，即保留1GB的WAL缓存</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">主库的postgresql.conf文件中：</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">archive_mode = on</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">archive_command = '<span style="color: #df402a;">rsync -zaq %p postgres@pg-slave:/var/lib/postgresql/wal_restore/%f</span> &amp;&amp; test ! -f /var/lib/postgresql/archivedir/%f &amp;&amp; cp %p /var/lib/postgresql/archivedir/%f'</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">备库的recovery.conf文件中：</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">结尾追加</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">restore_command = 'cp /var/lib/postgresql/wal_restore/%f %p'</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><span style="color: #df402a;">archive_cleanup_command = 'pg_archivecleanup /var/lib/postgresql/wal_restore/ %r'</span></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">归档命令不加入rsync也可以，只需要在建立主从同步时手动把完整同步之后的归档复制到从库，比如复制最近一天内修改过的归档</div><div yne-bulb-block="code" id="7327-1631599540536" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">cd /var/lib/postgresql/archivedir find -mtime -1|xargs -n 1 -I{} scp /var/lib/postgresql/archivedir/{} postgres@192.168.1.150:/var/lib/postgresql/wal_restore/ </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">其中核心就是红字部分，即用主库的归档来还原从库</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">相当于整体上从库建立起同步需要的数据 = 完整备份 + 归档文件 + WAL缓存主服务器：192.168.1.99</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">从服务器：192.168.1.150</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">在主服务器上：</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">在主服务器创建repl用户</div><div yne-bulb-block="code" id="1595-1598516570273" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">CREATE ROLE repl login replication password 'd71ea3'; </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">配置repl用户访问权限</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">vim /etc/postgresql/10/main/pg_hba.conf</div><div yne-bulb-block="code" id="1182-1598516566245" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">host    replication     repl            192.168.1.150/32               md5 </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">配置主服务器</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">vim /etc/postgresql/10/main/postgresql.conf</div><div yne-bulb-block="code" id="2459-1598516562035" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">wal_level = replica max_wal_senders = 10 wal_keep_segments = 16 wal_sender_timeout = 60s </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">重启服务</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">service postgresql restart</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">在从服务器上：</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">停止服务</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">service postgresql stop</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">删除所有数据</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">cd /var/lib/postgresql/10/main</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">rm -rf *</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">配置从服务器</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">vim /etc/postgresql/10/main/postgresql.conf</div><div yne-bulb-block="code" id="3760-1598516580094" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">hot_standby = on </div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">切换到postgres用户</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">sudo su - postgres</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">从主服务器创建初始备份，上面切换用户就不用调整文件权限了</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">pg_basebackup -h 192.168.1.99 -U repl -D /var/lib/postgresql/10/main -F p -X stream -P -R -p 5432</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">Password: d71ea3</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">会自动生成 recovery.conf 启动之后会读取里面的配置进行主从同步</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">切回root</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">sudo su -</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">启动服务</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">service postgresql start</div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;"><hr /></div><div yne-bulb-block="paragraph" style="white-space: pre-wrap; line-height: 1.75; font-size: 14px;">补充：<br /><br /><span style="color: #003884; text-decoration-line: underline;">FATAL: requested WAL segment00800002A0 has already been removed<br /><br /></span><div yne-bulb-block="paragraph" style="line-height: 1.75;">我进行的配置有：</div><div yne-bulb-block="paragraph" style="line-height: 1.75;">改大wal_keep_segments值到64，即保留1GB的WAL缓存</div><div yne-bulb-block="paragraph" style="line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="line-height: 1.75;">主库的postgresql.conf文件中：</div><div yne-bulb-block="paragraph" style="line-height: 1.75;">archive_mode = on</div><div yne-bulb-block="paragraph" style="line-height: 1.75;">archive_command = '<span style="color: #df402a;">rsync -zaq %p postgres@pg-slave:/var/lib/postgresql/wal_restore/%f</span> &amp;&amp; test ! -f /var/lib/postgresql/archivedir/%f &amp;&amp; cp %p /var/lib/postgresql/archivedir/%f'</div><div yne-bulb-block="paragraph" style="line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="line-height: 1.75;">备库的recovery.conf文件中：</div><div yne-bulb-block="paragraph" style="line-height: 1.75;">结尾追加</div><div yne-bulb-block="paragraph" style="line-height: 1.75;"><span style="color: #df402a;">restore_command = 'cp /var/lib/postgresql/wal_restore/%f %p'</span></div><div yne-bulb-block="paragraph" style="line-height: 1.75;"><span style="color: #df402a;">archive_cleanup_command = 'pg_archivecleanup /var/lib/postgresql/wal_restore/ %r'</span></div><div yne-bulb-block="paragraph" style="line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="line-height: 1.75;">归档命令不加入rsync也可以，只需要在建立主从同步时手动把完整同步之后的归档复制到从库，比如复制最近一天内修改过的归档</div><div yne-bulb-block="code" id="7327-1631599540536" data-theme="default" data-language="javascript">cd /var/lib/postgresql/archivedir
find -mtime -1|xargs -n 1 -I{} scp /var/lib/postgresql/archivedir/{} postgres@192.168.1.150:/var/lib/postgresql/wal_restore/
</div><div yne-bulb-block="paragraph" style="line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="line-height: 1.75;">其中核心就是红字部分，即用主库的归档来还原从库</div><div yne-bulb-block="paragraph" style="line-height: 1.75;"></div><div yne-bulb-block="paragraph" style="line-height: 1.75;">相当于整体上从库建立起同步需要的数据 = 完整备份 + 归档文件 + WAL缓存</div><!--5f39ae17-8c62-4a45-bc43-b32064c9388a:W3siYmxvY2tJZCI6IjE0NzQtMTYzMTU5ODk5NzIxMCIsImJsb2NrVHlwZSI6InBhcmFncmFwaCIsInN0eWxlcyI6eyJhbGlnbiI6ImxlZnQiLCJpbmRlbnQiOjAsInRleHQtaW5kZW50IjowLCJsaW5lLWhlaWdodCI6MS43NSwiYmFjay1jb2xvciI6IiIsInBhZGRpbmciOiIifSwidHlwZSI6InBhcmFncmFwaCIsInJpY2hUZXh0Ijp7ImRhdGEiOlt7ImNoYXIiOiLmiJEifSx7ImNoYXIiOiLov5sifSx7ImNoYXIiOiLooYwifSx7ImNoYXIiOiLnmoQifSx7ImNoYXIiOiLphY0ifSx7ImNoYXIiOiLnva4ifSx7ImNoYXIiOiLmnIkifSx7ImNoYXIiOiLvvJoifV0sImlzUmljaFRleHQiOnRydWUsImtlZXBMaW5lQnJlYWsiOnRydWV9fSx7ImJsb2NrSWQiOiI4Njk1LTE2MzE1OTkwMTMyNDkiLCJibG9ja1R5cGUiOiJwYXJhZ3JhcGgiLCJzdHlsZXMiOnsiYWxpZ24iOiJsZWZ0IiwiaW5kZW50IjowLCJ0ZXh0LWluZGVudCI6MCwibGluZS1oZWlnaHQiOjEuNzUsImJhY2stY29sb3IiOiIiLCJwYWRkaW5nIjoiIn0sInR5cGUiOiJwYXJhZ3JhcGgiLCJyaWNoVGV4dCI6eyJkYXRhIjpbeyJjaGFyIjoi5pS5In0seyJjaGFyIjoi5aSnIn0seyJjaGFyIjoidyJ9LHsiY2hhciI6ImEifSx7ImNoYXIiOiJsIn0seyJjaGFyIjoiXyJ9LHsiY2hhciI6ImsifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoiZSJ9LHsiY2hhciI6InAifSx7ImNoYXIiOiJfIn0seyJjaGFyIjoicyJ9LHsiY2hhciI6ImUifSx7ImNoYXIiOiJnIn0seyJjaGFyIjoibSJ9LHsiY2hhciI6ImUifSx7ImNoYXIiOiJuIn0seyJjaGFyIjoidCJ9LHsiY2hhciI6InMifSx7ImNoYXIiOiLlgLwifSx7ImNoYXIiOiLliLAifSx7ImNoYXIiOiI2In0seyJjaGFyIjoiNCJ9LHsiY2hhciI6Iu+8jCJ9LHsiY2hhciI6IuWNsyJ9LHsiY2hhciI6IuS/nSJ9LHsiY2hhciI6IueVmSJ9LHsiY2hhciI6IjEifSx7ImNoYXIiOiJHIn0seyJjaGFyIjoiQiJ9LHsiY2hhciI6IueahCJ9LHsiY2hhciI6IlcifSx7ImNoYXIiOiJBIn0seyJjaGFyIjoiTCJ9LHsiY2hhciI6Iue8kyJ9LHsiY2hhciI6IuWtmCJ9XSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX19LHsiYmxvY2tJZCI6IjUzMzktMTYzMTU5ODg3NDM0MSIsImJsb2NrVHlwZSI6InBhcmFncmFwaCIsInN0eWxlcyI6eyJhbGlnbiI6ImxlZnQiLCJpbmRlbnQiOjAsInRleHQtaW5kZW50IjowLCJsaW5lLWhlaWdodCI6MS43NSwiYmFjay1jb2xvciI6IiIsInBhZGRpbmciOiIifSwidHlwZSI6InBhcmFncmFwaCIsInJpY2hUZXh0Ijp7ImRhdGEiOltdLCJpc1JpY2hUZXh0Ijp0cnVlLCJrZWVwTGluZUJyZWFrIjp0cnVlfX0seyJibG9ja0lkIjoiMjY1Mi0xNjMxNTk4ODYzMTk0IiwiYmxvY2tUeXBlIjoicGFyYWdyYXBoIiwic3R5bGVzIjp7ImFsaWduIjoibGVmdCIsImluZGVudCI6MCwidGV4dC1pbmRlbnQiOjAsImxpbmUtaGVpZ2h0IjoxLjc1LCJiYWNrLWNvbG9yIjoiIiwicGFkZGluZyI6IiJ9LCJ0eXBlIjoicGFyYWdyYXBoIiwicmljaFRleHQiOnsiZGF0YSI6W3siY2hhciI6IuS4uyJ9LHsiY2hhciI6IuW6kyJ9LHsiY2hhciI6IueahCJ9LHsiY2hhciI6InAifSx7ImNoYXIiOiJvIn0seyJjaGFyIjoicyJ9LHsiY2hhciI6InQifSx7ImNoYXIiOiJnIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6ImUifSx7ImNoYXIiOiJzIn0seyJjaGFyIjoicSJ9LHsiY2hhciI6ImwifSx7ImNoYXIiOiIuIn0seyJjaGFyIjoiYyJ9LHsiY2hhciI6Im8ifSx7ImNoYXIiOiJuIn0seyJjaGFyIjoiZiJ9LHsiY2hhciI6IuaWhyJ9LHsiY2hhciI6IuS7tiJ9LHsiY2hhciI6IuS4rSJ9LHsiY2hhciI6Iu+8miJ9XSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX19LHsiYmxvY2tJZCI6IjM0NTQtMTYzMTU5ODg2MzY0NiIsImJsb2NrVHlwZSI6InBhcmFncmFwaCIsInN0eWxlcyI6eyJhbGlnbiI6ImxlZnQiLCJiYWNrLWNvbG9yIjoiIiwicGFkZGluZyI6IiIsImluZGVudCI6MCwidGV4dC1pbmRlbnQiOjAsImxpbmUtaGVpZ2h0IjoxLjc1fSwidHlwZSI6InBhcmFncmFwaCIsInJpY2hUZXh0Ijp7ImRhdGEiOlt7ImNoYXIiOiJhIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6ImMifSx7ImNoYXIiOiJoIn0seyJjaGFyIjoiaSJ9LHsiY2hhciI6InYifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoiXyJ9LHsiY2hhciI6Im0ifSx7ImNoYXIiOiJvIn0seyJjaGFyIjoiZCJ9LHsiY2hhciI6ImUifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiPSJ9LHsiY2hhciI6IiAifSx7ImNoYXIiOiJvIn0seyJjaGFyIjoibiJ9XSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX19LHsiYmxvY2tJZCI6IjM3NDctMTYzMTU5ODg2MzY0NiIsImJsb2NrVHlwZSI6InBhcmFncmFwaCIsInN0eWxlcyI6eyJhbGlnbiI6ImxlZnQiLCJiYWNrLWNvbG9yIjoiIiwicGFkZGluZyI6IiIsImluZGVudCI6MCwidGV4dC1pbmRlbnQiOjAsImxpbmUtaGVpZ2h0IjoxLjc1fSwidHlwZSI6InBhcmFncmFwaCIsInJpY2hUZXh0Ijp7ImRhdGEiOlt7ImNoYXIiOiJhIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6ImMifSx7ImNoYXIiOiJoIn0seyJjaGFyIjoiaSJ9LHsiY2hhciI6InYifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoiXyJ9LHsiY2hhciI6ImMifSx7ImNoYXIiOiJvIn0seyJjaGFyIjoibSJ9LHsiY2hhciI6Im0ifSx7ImNoYXIiOiJhIn0seyJjaGFyIjoibiJ9LHsiY2hhciI6ImQifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiPSJ9LHsiY2hhciI6IiAifSx7ImNoYXIiOiInIn0seyJjaGFyIjoiciIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoieSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoibiIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiYyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiICIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiLSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoieiIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiYSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiICIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiJSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiICIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoibyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoidCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiZyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiciIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiZSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiQCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiZyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiLSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoibCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiYSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoidiIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiZSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiOiIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiLyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoidiIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiYSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiciIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiLyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoibCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiaSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiYiIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiLyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoibyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoidCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiZyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiciIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiZSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoibCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiLyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoidyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiYSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoibCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiXyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiciIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiZSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoicyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoidCIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoibyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiciIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiZSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiLyIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiJSIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiZiIsInN0eWxlcyI6eyJjb2xvciI6IiNkZjQwMmEifX0seyJjaGFyIjoiICJ9LHsiY2hhciI6IiYifSx7ImNoYXIiOiImIn0seyJjaGFyIjoiICJ9LHsiY2hhciI6InQifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoicyJ9LHsiY2hhciI6InQifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiISJ9LHsiY2hhciI6IiAifSx7ImNoYXIiOiItIn0seyJjaGFyIjoiZiJ9LHsiY2hhciI6IiAifSx7ImNoYXIiOiIvIn0seyJjaGFyIjoidiJ9LHsiY2hhciI6ImEifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiLyJ9LHsiY2hhciI6ImwifSx7ImNoYXIiOiJpIn0seyJjaGFyIjoiYiJ9LHsiY2hhciI6Ii8ifSx7ImNoYXIiOiJwIn0seyJjaGFyIjoibyJ9LHsiY2hhciI6InMifSx7ImNoYXIiOiJ0In0seyJjaGFyIjoiZyJ9LHsiY2hhciI6InIifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoicyJ9LHsiY2hhciI6InEifSx7ImNoYXIiOiJsIn0seyJjaGFyIjoiLyJ9LHsiY2hhciI6ImEifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiYyJ9LHsiY2hhciI6ImgifSx7ImNoYXIiOiJpIn0seyJjaGFyIjoidiJ9LHsiY2hhciI6ImUifSx7ImNoYXIiOiJkIn0seyJjaGFyIjoiaSJ9LHsiY2hhciI6InIifSx7ImNoYXIiOiIvIn0seyJjaGFyIjoiJSJ9LHsiY2hhciI6ImYifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiJiJ9LHsiY2hhciI6IiYifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiYyJ9LHsiY2hhciI6InAifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiJSJ9LHsiY2hhciI6InAifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiLyJ9LHsiY2hhciI6InYifSx7ImNoYXIiOiJhIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6Ii8ifSx7ImNoYXIiOiJsIn0seyJjaGFyIjoiaSJ9LHsiY2hhciI6ImIifSx7ImNoYXIiOiIvIn0seyJjaGFyIjoicCJ9LHsiY2hhciI6Im8ifSx7ImNoYXIiOiJzIn0seyJjaGFyIjoidCJ9LHsiY2hhciI6ImcifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiZSJ9LHsiY2hhciI6InMifSx7ImNoYXIiOiJxIn0seyJjaGFyIjoibCJ9LHsiY2hhciI6Ii8ifSx7ImNoYXIiOiJhIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6ImMifSx7ImNoYXIiOiJoIn0seyJjaGFyIjoiaSJ9LHsiY2hhciI6InYifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoiZCJ9LHsiY2hhciI6ImkifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiLyJ9LHsiY2hhciI6IiUifSx7ImNoYXIiOiJmIn0seyJjaGFyIjoiJyJ9XSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX19LHsiYmxvY2tJZCI6IjE5MDAtMTYzMTU5ODg2MzY0NiIsImJsb2NrVHlwZSI6InBhcmFncmFwaCIsInN0eWxlcyI6eyJhbGlnbiI6ImxlZnQiLCJiYWNrLWNvbG9yIjoiIiwicGFkZGluZyI6IiIsImluZGVudCI6MCwidGV4dC1pbmRlbnQiOjAsImxpbmUtaGVpZ2h0IjoxLjc1fSwidHlwZSI6InBhcmFncmFwaCIsInJpY2hUZXh0Ijp7ImRhdGEiOltdLCJpc1JpY2hUZXh0Ijp0cnVlLCJrZWVwTGluZUJyZWFrIjp0cnVlfX0seyJibG9ja0lkIjoiNDIzNS0xNTk4NDM2NDY2Mzg0IiwiYmxvY2tUeXBlIjoicGFyYWdyYXBoIiwic3R5bGVzIjp7ImFsaWduIjoibGVmdCIsImluZGVudCI6MCwidGV4dC1pbmRlbnQiOjAsImxpbmUtaGVpZ2h0IjoxLjc1LCJiYWNrLWNvbG9yIjoiIiwicGFkZGluZyI6IiJ9LCJ0eXBlIjoicGFyYWdyYXBoIiwicmljaFRleHQiOnsiZGF0YSI6W3siY2hhciI6IuWkhyJ9LHsiY2hhciI6IuW6kyJ9LHsiY2hhciI6IueahCJ9LHsiY2hhciI6InIifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoiYyJ9LHsiY2hhciI6Im8ifSx7ImNoYXIiOiJ2In0seyJjaGFyIjoiZSJ9LHsiY2hhciI6InIifSx7ImNoYXIiOiJ5In0seyJjaGFyIjoiLiJ9LHsiY2hhciI6ImMifSx7ImNoYXIiOiJvIn0seyJjaGFyIjoibiJ9LHsiY2hhciI6ImYifSx7ImNoYXIiOiLmlocifSx7ImNoYXIiOiLku7YifSx7ImNoYXIiOiLkuK0ifSx7ImNoYXIiOiLvvJoifV0sImlzUmljaFRleHQiOnRydWUsImtlZXBMaW5lQnJlYWsiOnRydWV9fSx7ImJsb2NrSWQiOiIyNzU4LTE2MzE1OTg4OTA3NDkiLCJibG9ja1R5cGUiOiJwYXJhZ3JhcGgiLCJzdHlsZXMiOnsiYWxpZ24iOiJsZWZ0IiwiYmFjay1jb2xvciI6IiIsInBhZGRpbmciOiIiLCJpbmRlbnQiOjAsInRleHQtaW5kZW50IjowLCJsaW5lLWhlaWdodCI6MS43NX0sInR5cGUiOiJwYXJhZ3JhcGgiLCJyaWNoVGV4dCI6eyJkYXRhIjpbeyJjaGFyIjoi57uTIn0seyJjaGFyIjoi5bC+In0seyJjaGFyIjoi6L+9In0seyJjaGFyIjoi5YqgIn1dLCJpc1JpY2hUZXh0Ijp0cnVlLCJrZWVwTGluZUJyZWFrIjp0cnVlfX0seyJibG9ja0lkIjoiODE3OS0xNjMxNTk4ODkwNzQ5IiwiYmxvY2tUeXBlIjoicGFyYWdyYXBoIiwic3R5bGVzIjp7ImFsaWduIjoibGVmdCIsImJhY2stY29sb3IiOiIiLCJwYWRkaW5nIjoiIiwiaW5kZW50IjowLCJ0ZXh0LWluZGVudCI6MCwibGluZS1oZWlnaHQiOjEuNzV9LCJ0eXBlIjoicGFyYWdyYXBoIiwicmljaFRleHQiOnsiZGF0YSI6W3siY2hhciI6InIiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImUiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InMiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InQiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Im8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InIiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImUiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Il8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImMiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Im8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Im0iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Im0iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImEiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Im4iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImQiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6IiAiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Ij0iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6IiAiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6IiciLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImMiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InAiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6IiAiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Ii8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InYiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImEiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InIiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Ii8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImwiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImkiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImIiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Ii8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InAiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Im8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InMiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InQiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImciLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InIiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImUiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InMiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InEiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImwiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Ii8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InciLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImEiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImwiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Il8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InIiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImUiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InMiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InQiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Im8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InIiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImUiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6Ii8iLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6IiUiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6ImYiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6IiAiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6IiUiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6InAiLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19LHsiY2hhciI6IiciLCJzdHlsZXMiOnsiY29sb3IiOiIjZGY0MDJhIn19XSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX19LHsiYmxvY2tJZCI6IjIwNTUtMTYzMTU5ODg5MDc0OSIsImJsb2NrVHlwZSI6InBhcmFncmFwaCIsInN0eWxlcyI6eyJhbGlnbiI6ImxlZnQiLCJiYWNrLWNvbG9yIjoiIiwicGFkZGluZyI6IiIsImluZGVudCI6MCwidGV4dC1pbmRlbnQiOjAsImxpbmUtaGVpZ2h0IjoxLjc1fSwidHlwZSI6InBhcmFncmFwaCIsInJpY2hUZXh0Ijp7ImRhdGEiOlt7ImNoYXIiOiJhIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJyIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJjIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJoIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJpIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJ2Iiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJlIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJfIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJjIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJsIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJlIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJhIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJuIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJ1Iiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJwIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJfIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJjIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJvIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJtIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJtIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJhIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJuIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJkIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIgIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiI9Iiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIgIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiInIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJwIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJnIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJfIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJhIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJyIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJjIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJoIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJpIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJ2Iiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJlIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJjIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJsIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJlIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJhIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJuIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJ1Iiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJwIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIgIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIvIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJ2Iiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJhIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJyIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIvIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJsIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJpIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJiIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIvIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJwIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJvIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJzIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJ0Iiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJnIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJyIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJlIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJzIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJxIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJsIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIvIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJ3Iiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJhIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJsIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJfIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJyIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJlIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJzIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJ0Iiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJvIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJyIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJlIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIvIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIgIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiIlIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiJyIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fSx7ImNoYXIiOiInIiwic3R5bGVzIjp7ImNvbG9yIjoiI2RmNDAyYSJ9fV0sImlzUmljaFRleHQiOnRydWUsImtlZXBMaW5lQnJlYWsiOnRydWV9fSx7ImJsb2NrSWQiOiI1NzQzLTE2MzE1OTg5Mzg2NTAiLCJibG9ja1R5cGUiOiJwYXJhZ3JhcGgiLCJzdHlsZXMiOnsiYWxpZ24iOiJsZWZ0IiwiYmFjay1jb2xvciI6IiIsInBhZGRpbmciOiIiLCJpbmRlbnQiOjAsInRleHQtaW5kZW50IjowLCJsaW5lLWhlaWdodCI6MS43NX0sInR5cGUiOiJwYXJhZ3JhcGgiLCJyaWNoVGV4dCI6eyJkYXRhIjpbXSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX19LHsiYmxvY2tJZCI6IjE0OTEtMTYzMTU5ODkzODgyNyIsImJsb2NrVHlwZSI6InBhcmFncmFwaCIsInN0eWxlcyI6eyJhbGlnbiI6ImxlZnQiLCJiYWNrLWNvbG9yIjoiIiwicGFkZGluZyI6IiIsImluZGVudCI6MCwidGV4dC1pbmRlbnQiOjAsImxpbmUtaGVpZ2h0IjoxLjc1fSwidHlwZSI6InBhcmFncmFwaCIsInJpY2hUZXh0Ijp7ImRhdGEiOlt7ImNoYXIiOiLlvZIifSx7ImNoYXIiOiLmoaMifSx7ImNoYXIiOiLlkb0ifSx7ImNoYXIiOiLku6QifSx7ImNoYXIiOiLkuI0ifSx7ImNoYXIiOiLliqAifSx7ImNoYXIiOiLlhaUifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoicyJ9LHsiY2hhciI6InkifSx7ImNoYXIiOiJuIn0seyJjaGFyIjoiYyJ9LHsiY2hhciI6IuS5nyJ9LHsiY2hhciI6IuWPryJ9LHsiY2hhciI6IuS7pSJ9LHsiY2hhciI6Iu+8jCJ9LHsiY2hhciI6IuWPqiJ9LHsiY2hhciI6IumcgCJ9LHsiY2hhciI6IuimgSJ9LHsiY2hhciI6IuWcqCJ9LHsiY2hhciI6IuW7uiJ9LHsiY2hhciI6IueriyJ9LHsiY2hhciI6IuS4uyJ9LHsiY2hhciI6IuS7jiJ9LHsiY2hhciI6IuWQjCJ9LHsiY2hhciI6IuatpSJ9LHsiY2hhciI6IuaXtiJ9LHsiY2hhciI6IuaJiyJ9LHsiY2hhciI6IuWKqCJ9LHsiY2hhciI6IuaKiiJ9LHsiY2hhciI6IuWujCJ9LHsiY2hhciI6IuaVtCJ9LHsiY2hhciI6IuWQjCJ9LHsiY2hhciI6IuatpSJ9LHsiY2hhciI6IuS5iyJ9LHsiY2hhciI6IuWQjiJ9LHsiY2hhciI6IueahCJ9LHsiY2hhciI6IuW9kiJ9LHsiY2hhciI6IuahoyJ9LHsiY2hhciI6IuWkjSJ9LHsiY2hhciI6IuWItiJ9LHsiY2hhciI6IuWIsCJ9LHsiY2hhciI6IuS7jiJ9LHsiY2hhciI6IuW6kyJ9LHsiY2hhciI6Iu+8jCJ9LHsiY2hhciI6IuavlCJ9LHsiY2hhciI6IuWmgiJ9LHsiY2hhciI6IuWkjSJ9LHsiY2hhciI6IuWItiJ9LHsiY2hhciI6IuacgCJ9LHsiY2hhciI6Iui/kSJ9LHsiY2hhciI6IuS4gCJ9LHsiY2hhciI6IuWkqSJ9LHsiY2hhciI6IuWGhSJ9LHsiY2hhciI6IuS/riJ9LHsiY2hhciI6IuaUuSJ9LHsiY2hhciI6Iui/hyJ9LHsiY2hhciI6IueahCJ9LHsiY2hhciI6IuW9kiJ9LHsiY2hhciI6IuahoyJ9XSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX19LHsiYmxvY2tJZCI6IjczMjctMTYzMTU5OTU0MDUzNiIsImJsb2NrVHlwZSI6ImNvZGUiLCJzdHlsZXMiOnsiYmFjay1jb2xvciI6IiJ9LCJ0eXBlIjoiY29kZSIsInJpY2hUZXh0Ijp7ImRhdGEiOlt7ImNoYXIiOiJjIn0seyJjaGFyIjoiZCJ9LHsiY2hhciI6IiAifSx7ImNoYXIiOiIvIn0seyJjaGFyIjoidiJ9LHsiY2hhciI6ImEifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiLyJ9LHsiY2hhciI6ImwifSx7ImNoYXIiOiJpIn0seyJjaGFyIjoiYiJ9LHsiY2hhciI6Ii8ifSx7ImNoYXIiOiJwIn0seyJjaGFyIjoibyJ9LHsiY2hhciI6InMifSx7ImNoYXIiOiJ0In0seyJjaGFyIjoiZyJ9LHsiY2hhciI6InIifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoicyJ9LHsiY2hhciI6InEifSx7ImNoYXIiOiJsIn0seyJjaGFyIjoiLyJ9LHsiY2hhciI6ImEifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiYyJ9LHsiY2hhciI6ImgifSx7ImNoYXIiOiJpIn0seyJjaGFyIjoidiJ9LHsiY2hhciI6ImUifSx7ImNoYXIiOiJkIn0seyJjaGFyIjoiaSJ9LHsiY2hhciI6InIifSx7ImNoYXIiOiJcbiJ9LHsiY2hhciI6ImYifSx7ImNoYXIiOiJpIn0seyJjaGFyIjoibiJ9LHsiY2hhciI6ImQifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiLSJ9LHsiY2hhciI6Im0ifSx7ImNoYXIiOiJ0In0seyJjaGFyIjoiaSJ9LHsiY2hhciI6Im0ifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoiICJ9LHsiY2hhciI6Ii0ifSx7ImNoYXIiOiIxIn0seyJjaGFyIjoifCJ9LHsiY2hhciI6IngifSx7ImNoYXIiOiJhIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6ImcifSx7ImNoYXIiOiJzIn0seyJjaGFyIjoiICJ9LHsiY2hhciI6Ii0ifSx7ImNoYXIiOiJuIn0seyJjaGFyIjoiICJ9LHsiY2hhciI6IjEifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiLSJ9LHsiY2hhciI6IkkifSx7ImNoYXIiOiJ7In0seyJjaGFyIjoifSJ9LHsiY2hhciI6IiAifSx7ImNoYXIiOiJzIn0seyJjaGFyIjoiYyJ9LHsiY2hhciI6InAifSx7ImNoYXIiOiIgIn0seyJjaGFyIjoiLyJ9LHsiY2hhciI6InYifSx7ImNoYXIiOiJhIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6Ii8ifSx7ImNoYXIiOiJsIn0seyJjaGFyIjoiaSJ9LHsiY2hhciI6ImIifSx7ImNoYXIiOiIvIn0seyJjaGFyIjoicCJ9LHsiY2hhciI6Im8ifSx7ImNoYXIiOiJzIn0seyJjaGFyIjoidCJ9LHsiY2hhciI6ImcifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiZSJ9LHsiY2hhciI6InMifSx7ImNoYXIiOiJxIn0seyJjaGFyIjoibCJ9LHsiY2hhciI6Ii8ifSx7ImNoYXIiOiJhIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6ImMifSx7ImNoYXIiOiJoIn0seyJjaGFyIjoiaSJ9LHsiY2hhciI6InYifSx7ImNoYXIiOiJlIn0seyJjaGFyIjoiZCJ9LHsiY2hhciI6ImkifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiLyJ9LHsiY2hhciI6InsifSx7ImNoYXIiOiJ9In0seyJjaGFyIjoiICJ9LHsiY2hhciI6InAifSx7ImNoYXIiOiJvIn0seyJjaGFyIjoicyJ9LHsiY2hhciI6InQifSx7ImNoYXIiOiJnIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6ImUifSx7ImNoYXIiOiJzIn0seyJjaGFyIjoiQCJ9LHsiY2hhciI6IjEifSx7ImNoYXIiOiI5In0seyJjaGFyIjoiMiJ9LHsiY2hhciI6Ii4ifSx7ImNoYXIiOiIxIn0seyJjaGFyIjoiNiJ9LHsiY2hhciI6IjgifSx7ImNoYXIiOiIuIn0seyJjaGFyIjoiMSJ9LHsiY2hhciI6Ii4ifSx7ImNoYXIiOiIxIn0seyJjaGFyIjoiNSJ9LHsiY2hhciI6IjAifSx7ImNoYXIiOiI6In0seyJjaGFyIjoiLyJ9LHsiY2hhciI6InYifSx7ImNoYXIiOiJhIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6Ii8ifSx7ImNoYXIiOiJsIn0seyJjaGFyIjoiaSJ9LHsiY2hhciI6ImIifSx7ImNoYXIiOiIvIn0seyJjaGFyIjoicCJ9LHsiY2hhciI6Im8ifSx7ImNoYXIiOiJzIn0seyJjaGFyIjoidCJ9LHsiY2hhciI6ImcifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiZSJ9LHsiY2hhciI6InMifSx7ImNoYXIiOiJxIn0seyJjaGFyIjoibCJ9LHsiY2hhciI6Ii8ifSx7ImNoYXIiOiJ3In0seyJjaGFyIjoiYSJ9LHsiY2hhciI6ImwifSx7ImNoYXIiOiJfIn0seyJjaGFyIjoiciJ9LHsiY2hhciI6ImUifSx7ImNoYXIiOiJzIn0seyJjaGFyIjoidCJ9LHsiY2hhciI6Im8ifSx7ImNoYXIiOiJyIn0seyJjaGFyIjoiZSJ9LHsiY2hhciI6Ii8ifSx7ImNoYXIiOiJcbiJ9XSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX0sImlzU2VsZWN0ZWRCbG9jayI6ZmFsc2UsInRoZW1lIjoiZGVmYXVsdCIsImxhbmd1YWdlIjoiamF2YXNjcmlwdCJ9LHsiYmxvY2tJZCI6Ijg1NzktMTYzMTU5OTQ5NjM4NSIsImJsb2NrVHlwZSI6InBhcmFncmFwaCIsInN0eWxlcyI6eyJhbGlnbiI6ImxlZnQiLCJiYWNrLWNvbG9yIjoiIiwicGFkZGluZyI6IiIsImluZGVudCI6MCwidGV4dC1pbmRlbnQiOjAsImxpbmUtaGVpZ2h0IjoxLjc1fSwidHlwZSI6InBhcmFncmFwaCIsInJpY2hUZXh0Ijp7ImRhdGEiOltdLCJpc1JpY2hUZXh0Ijp0cnVlLCJrZWVwTGluZUJyZWFrIjp0cnVlfX0seyJibG9ja0lkIjoiNDA4Ny0xNjMxNTk5MTYxNTE5IiwiYmxvY2tUeXBlIjoicGFyYWdyYXBoIiwic3R5bGVzIjp7ImFsaWduIjoibGVmdCIsImJhY2stY29sb3IiOiIiLCJwYWRkaW5nIjoiIiwiaW5kZW50IjowLCJ0ZXh0LWluZGVudCI6MCwibGluZS1oZWlnaHQiOjEuNzV9LCJ0eXBlIjoicGFyYWdyYXBoIiwicmljaFRleHQiOnsiZGF0YSI6W3siY2hhciI6IuWFtiJ9LHsiY2hhciI6IuS4rSJ9LHsiY2hhciI6IuaguCJ9LHsiY2hhciI6IuW/gyJ9LHsiY2hhciI6IuWwsSJ9LHsiY2hhciI6IuaYryJ9LHsiY2hhciI6Iue6oiJ9LHsiY2hhciI6IuWtlyJ9LHsiY2hhciI6IumDqCJ9LHsiY2hhciI6IuWIhiJ9LHsiY2hhciI6Iu+8jCJ9LHsiY2hhciI6IuWNsyJ9LHsiY2hhciI6IueUqCJ9LHsiY2hhciI6IuS4uyJ9LHsiY2hhciI6IuW6kyJ9LHsiY2hhciI6IueahCJ9LHsiY2hhciI6IuW9kiJ9LHsiY2hhciI6IuahoyJ9LHsiY2hhciI6IuadpSJ9LHsiY2hhciI6Iui/mCJ9LHsiY2hhciI6IuWOnyJ9LHsiY2hhciI6IuS7jiJ9LHsiY2hhciI6IuW6kyJ9XSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX19LHsiYmxvY2tJZCI6IjIzOTUtMTYzMTU5OTIyMDg4MyIsImJsb2NrVHlwZSI6InBhcmFncmFwaCIsInN0eWxlcyI6eyJhbGlnbiI6ImxlZnQiLCJiYWNrLWNvbG9yIjoiIiwicGFkZGluZyI6IiIsImluZGVudCI6MCwidGV4dC1pbmRlbnQiOjAsImxpbmUtaGVpZ2h0IjoxLjc1fSwidHlwZSI6InBhcmFncmFwaCIsInJpY2hUZXh0Ijp7ImRhdGEiOltdLCJpc1JpY2hUZXh0Ijp0cnVlLCJrZWVwTGluZUJyZWFrIjp0cnVlfX0seyJibG9ja0lkIjoiMzAyMS0xNjMxNTk5MjIxMjE5IiwiYmxvY2tUeXBlIjoicGFyYWdyYXBoIiwic3R5bGVzIjp7ImFsaWduIjoibGVmdCIsImJhY2stY29sb3IiOiIiLCJwYWRkaW5nIjoiIiwiaW5kZW50IjowLCJ0ZXh0LWluZGVudCI6MCwibGluZS1oZWlnaHQiOjEuNzV9LCJ0eXBlIjoicGFyYWdyYXBoIiwicmljaFRleHQiOnsiZGF0YSI6W3siY2hhciI6IuebuCJ9LHsiY2hhciI6IuW9kyJ9LHsiY2hhciI6IuS6jiJ9LHsiY2hhciI6IuaVtCJ9LHsiY2hhciI6IuS9kyJ9LHsiY2hhciI6IuS4iiJ9LHsiY2hhciI6IuS7jiJ9LHsiY2hhciI6IuW6kyJ9LHsiY2hhciI6IuW7uiJ9LHsiY2hhciI6IueriyJ9LHsiY2hhciI6Iui1tyJ9LHsiY2hhciI6IuWQjCJ9LHsiY2hhciI6IuatpSJ9LHsiY2hhciI6IumcgCJ9LHsiY2hhciI6IuimgSJ9LHsiY2hhciI6IueahCJ9LHsiY2hhciI6IuaVsCJ9LHsiY2hhciI6IuaNriJ9LHsiY2hhciI6IiAifSx7ImNoYXIiOiI9In0seyJjaGFyIjoiICJ9LHsiY2hhciI6IuWujCJ9LHsiY2hhciI6IuaVtCJ9LHsiY2hhciI6IuWkhyJ9LHsiY2hhciI6IuS7vSJ9LHsiY2hhciI6IiAifSx7ImNoYXIiOiIrIn0seyJjaGFyIjoiICJ9LHsiY2hhciI6IuW9kiJ9LHsiY2hhciI6IuahoyJ9LHsiY2hhciI6IuaWhyJ9LHsiY2hhciI6IuS7tiJ9LHsiY2hhciI6IiAifSx7ImNoYXIiOiIrIn0seyJjaGFyIjoiICJ9LHsiY2hhciI6IlcifSx7ImNoYXIiOiJBIn0seyJjaGFyIjoiTCJ9LHsiY2hhciI6Iue8kyJ9LHsiY2hhciI6IuWtmCJ9XSwiaXNSaWNoVGV4dCI6dHJ1ZSwia2VlcExpbmVCcmVhayI6dHJ1ZX19XQ==--><span style="color: #003884; text-decoration-line: underline;"><br /><br /></span></div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92330.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-08-27 17:06 <a href="http://www.cnitblog.com/luckydmz/archive/2020/08/27/92330.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux .service文件 创建服务、配置服务自启动</title><link>http://www.cnitblog.com/luckydmz/archive/2020/06/28/92250.html</link><dc:creator>魔のkyo</dc:creator><author>魔のkyo</author><pubDate>Sun, 28 Jun 2020 01:53:00 GMT</pubDate><guid>http://www.cnitblog.com/luckydmz/archive/2020/06/28/92250.html</guid><wfw:comment>http://www.cnitblog.com/luckydmz/comments/92250.html</wfw:comment><comments>http://www.cnitblog.com/luckydmz/archive/2020/06/28/92250.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/luckydmz/comments/commentRss/92250.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/luckydmz/services/trackbacks/92250.html</trackback:ping><description><![CDATA[<div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">查看系统进程运行状态，包括服务</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #222222; background-color: #ebf1f5;">systemctl status</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #222222;">所有可用的单元文件存放在&nbsp;</span><span style="font-family: monospace; color: #222222; background-color: #ebf1f5;">/lib/systemd/system/</span><span style="color: #222222;">&nbsp;和&nbsp;</span><span style="font-family: monospace; color: #222222; background-color: #ebf1f5;">/etc/systemd/system/</span><span style="color: #222222;">&nbsp;目录。</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #222222;">根据我的实验情况是我们应该在</span><span style="font-family: monospace; color: #222222; background-color: #ebf1f5;">/lib/systemd/system/</span> 下存放.service文件，当设置了自启动后，会自动在 <span style="font-family: monospace; color: #222222; background-color: #ebf1f5;">/etc/systemd/system/</span> 下创建一个软链接指向 <span style="font-family: monospace; color: #222222; background-color: #ebf1f5;">/lib/systemd/system/</span> 下的文件。</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"><span style="color: #222222;">查看所有已安装服务：</span></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">systemctl list-units --type=service</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">通过服务状态可以查看启动服务的.service配置文件</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">例如</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">service mongodb status</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">可以看到</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">/lib/systemd/system/mongodb.service</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">最重要的，运行命令，</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">ExecStart=/usr/bin/mongod --unixSocketPrefix=${SOCKETPATH} --config ${CONF} $DAEMON_OPTS</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">PS:要注意的是ExecStart指定的是一个阻塞的程序，不需要后台执行，如果不阻塞，服务会认为程序执行完了，认为服务不在启动状态。</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">以Kafka为例</div><div id="2342-1592818446056" data-theme="default" data-language="javascript" style="white-space: pre-wrap;">[Unit]
Description=Kafka Server
After=network.target zookeeper.service

[Service]
Type=simple
ExecStart=/opt/kafka_2.12-2.3.1/bin/kafka-server-start.sh /opt/kafka_2.12-2.3.1/config/server.properties
Restart=on-failure
RestartPreventExitStatus=255

[Install]
WantedBy=multi-user.target
Alias=kafka.service

</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">详细的.service文件编写方法可以参考 http://www.jinbuguo.com/systemd/systemd.service.html</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">修改服务配置文件后需要</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">systemctl daemon-reload</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">设置服务开机自启动</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">systemctl enable postgresql.service</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">查询是否自启动服务</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">systemctl is-enabled postgresql.service</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;"></div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">取消服务器开机自启动</div><div style="white-space: pre-wrap; text-align: left; line-height: 1.75; font-size: 14px;">systemctl disable postgresql.service</div><img src ="http://www.cnitblog.com/luckydmz/aggbug/92250.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/luckydmz/" target="_blank">魔のkyo</a> 2020-06-28 09:53 <a href="http://www.cnitblog.com/luckydmz/archive/2020/06/28/92250.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>