-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeed.xml
796 lines (501 loc) · 68.2 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Echo's Blog</title>
<description>你好,我是 Echo Han。我是一名运维工程师/奶爸/Ruby 爱好者。我不时在这里记录一些自己的想法。欢迎你与我交流。</description>
<link>https://echohn.github.io/</link>
<atom:link href="https://echohn.github.io/feed.xml" rel="self" type="application/rss+xml" />
<pubDate>Sat, 23 Jan 2021 21:11:34 +0800</pubDate>
<lastBuildDate>Sat, 23 Jan 2021 21:11:34 +0800</lastBuildDate>
<generator>Jekyll v4.2.0</generator>
<item>
<title>修复 RubyMine 在 Alfred workflow 打开项目时,出现 yarn packages are out of date 的错误</title>
<description><p>近来发现 RubyMine 在启动项目的服务时,有时正常,有时候异常,异常就如下图所示(启动 rails s):
<img src="/img/in-post/16113234582855.jpg" alt="16113234582855" /></p>
<p>在直接启动 RubyMine 的时候是不会出现该问题的,但是通过 Alfred 的 jetbrains workflow 直接启动项目时会出现此现象。</p>
<p>排查中发现,我在项目中实际用到的是 node 12, 但是在服务启动时,总是在调用 node 14。然而在 RubyMine 的偏好设置中指定 node 解释器版本并不能解决此问题。</p>
<p><a href="https://intellij-support.jetbrains.com/hc/en-us/community/posts/360000160444-Wrong-node-version-used-when-running-from-run-after-update-to-Webstorm-2018-">搜到一篇资料</a>,在 RubyMine 启动时,它并不能加载到我配置在 <code class="language-plaintext highlighter-rouge">~/.bash_profile</code> 中的 PATH 信息。</p>
<p>于是我 debug jetbrains workflow,发现它实际调用的是 JetBrains Toolbox 生成的 <code class="language-plaintext highlighter-rouge">~/.scripts/bin/rubymine</code> 脚本。</p>
<p>因此只需要在这个脚本的 Shabang 下面添加 <code class="language-plaintext highlighter-rouge">source ~/.bash_profile</code> 就解决了问题。</p>
</description>
<pubDate>Sat, 23 Jan 2021 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2021/01/23/fix-rubymine-not-found-node/</link>
<guid isPermaLink="true">https://echohn.github.io/2021/01/23/fix-rubymine-not-found-node/</guid>
<category>Ruby</category>
<category>RubyMine</category>
</item>
<item>
<title>在 Ruby 中使用行注释生成 apiDoc</title>
<description><p>以前我试过很多生成 api 文档的方法。</p>
<p>起初使用过 Markdown 独自维护一份文档,但是文档和代码不同步的话,会经常忘记更新。</p>
<p>后来尝试过使用 rDoc、<a href="http://sphinx-doc.org">Sphinx</a> 等工具对代码注释进行解析直接生成 api 文档,Sphinx 是一种基于 reStructuredText 格式的文档生成工具。</p>
<p>最近发现了 <a href="http://apidocjs.com">apiDoc</a> ,它相对于 Sphinx 来说,不用学习 rst 语法,学习成本更低,因此在新的项目中,我尝试使用 apiDoc 生成 api 文档。</p>
<p>然而在 apiDoc 官网的示例中,Ruby 语言是通过多行注释的方式生成的的文档,如下面的例子。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>=begin
@api {get} /user/:id Request User information
@apiName GetUser
@apiGroup User
@apiParam {Number} id Users unique ID.
@apiSuccess {String} firstname Firstname of the User.
@apiSuccess {String} lastname Lastname of the User.
=end
</code></pre></div></div>
<p>但是多行注释有很多缺点,它必须顶格书写,不能缩进,在代码中也不容易辨认。在<a href="https://ruby-china.org/wiki/coding-style">Ruby 风格指南</a>中不推荐使用,也不符合我们团队的开发规范。</p>
<p>于是我查看了 apiDoc 的源码,想看能否对其进行修改。很开心的是,我看到了它在源码中是这样进行的匹配。</p>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="cm">/**
* apidoc-core/lib/languages/rb.js
*/</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
<span class="c1">// find document blocks between '=begin' and '=end'</span>
<span class="na">docBlocksRegExp</span><span class="p">:</span> <span class="sr">/#</span><span class="se">\*\*\u</span><span class="sr">ffff</span><span class="se">?(</span><span class="sr">.+</span><span class="se">?)\u</span><span class="sr">ffff</span><span class="se">?(?:\s</span><span class="sr">*</span><span class="se">)?</span><span class="sr">#</span><span class="se">\*</span><span class="sr">|=begin</span><span class="se">\u</span><span class="sr">ffff</span><span class="se">?(</span><span class="sr">.+</span><span class="se">?)\u</span><span class="sr">ffff</span><span class="se">?(?:\s</span><span class="sr">*</span><span class="se">)?</span><span class="sr">=end/g</span><span class="p">,</span>
<span class="c1">// remove not needed ' # ' and tabs at the beginning</span>
<span class="na">inlineRegExp</span><span class="p">:</span> <span class="sr">/^</span><span class="se">(\s</span><span class="sr">*</span><span class="se">)?(</span><span class="sr">#</span><span class="se">)[</span><span class="sr"> </span><span class="se">]?</span><span class="sr">/gm</span>
<span class="p">};</span></code></pre></figure>
<p>这个正则看起来有点乱,分析一下。</p>
<iframe frameborder="0" width="100%" height="283" src="https://jex.im/regulex/#!embed=true&amp;flags=m&amp;re=%23%5C*%5C*%5Cuffff%3F(.%2B%3F)%5Cuffff%3F(%3F%3A%5Cs*)%3F%23%5C*%7C%3Dbegin%5Cuffff%3F(.%2B%3F)%5Cuffff%3F(%3F%3A%5Cs*)%3F%3Dend"></iframe>
<p>可以看到,它在支持多行注释的同时,也支持另外一种行注释的方式。</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#**</span>
<span class="c1"># @api {get} /user/:id Request User information</span>
<span class="c1"># @apiName GetUser</span>
<span class="c1"># @apiGroup User</span>
<span class="c1"># @apiParam {Number} id Users unique ID.</span>
<span class="c1"># @apiSuccess {String} firstname Firstname of the User.</span>
<span class="c1"># @apiSuccess {String} lastname Lastname of the User.</span>
<span class="c1">#*</span></code></pre></figure>
<p>因此问题解决。</p>
<p><strong><em>PS:</em></strong> 在看到这个正则的时候,字符<code class="language-plaintext highlighter-rouge">\uFFFF</code>引起了我的注意。我在 Unicode 码表中并未查到这个字符,于是我以为这个字符在 Javascript 中代表了某种特殊的涵义,但是查了一下,也没有查到结果。</p>
<p>直到我在看到一篇<a href="https://gxnotes.com/article/178667.html">文章</a>中引用的一段文字:</p>
<blockquote>
<p>In effect, noncharacters can be thought of as application-internal private-use code points. Unlike the private-use characters discussed in Section 16.5, Private-Use Characters, which are assigned characters and which are intended for use in open interchange, subject to interpretation by private agreement, noncharacters are permanently reserved (unassigned) and have no interpretation whatsoever outside of their possible application-internal private uses.</p>
</blockquote>
<blockquote>
<p>U+FFFF and U+10FFFF. These two noncharacter code points have the attribute of being associated with the largest code unit values for particular Unicode encoding forms. In UTF-16, U+FFFF is associated with the largest 16-bit code unit value, FFFF16. U+10FFFF is associated with the largest legal UTF-32 32-bit code unit value, 10FFFF16. This attribute renders these two noncharacter code points useful for internal purposes as sentinels. For example, they might be used to indicate the end of a list, to represent a value in an index guaranteed to be higher than any valid character value, and so on.</p>
</blockquote>
<p>又看了一下代码:</p>
<figure class="highlight"><pre><code class="language-js" data-lang="js"><span class="c1">// Replace Linebreak with Unicode</span>
<span class="nx">src</span> <span class="o">=</span> <span class="nx">src</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\n</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">'</span><span class="se">\</span><span class="s1">uffff</span><span class="dl">'</span><span class="p">);</span></code></pre></figure>
<p>于是真相大白。</p>
</description>
<pubDate>Thu, 10 Aug 2017 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2017/08/10/use-line-comment-with-apidoc-in-ruby-language/</link>
<guid isPermaLink="true">https://echohn.github.io/2017/08/10/use-line-comment-with-apidoc-in-ruby-language/</guid>
<category>Ruby</category>
<category>apiDoc</category>
</item>
<item>
<title>解决 Confluence 5.10 中文补丁导致的 web 界面 UI 错误</title>
<description><p>最近把公司原来用的 Confluence 从 3.4.5 升到了 5.10.7 。</p>
<p>虽然这两个版本跨了六年,但是整个升级过程还是挺顺利的,就是麻烦了一些,根据官网要求,要按照 3.4.5 =&gt; 3.5 =&gt; 5.0 =&gt; 5.10 这样一步步进行升级。</p>
<p>然后在使用的时候发现了一些问题,花了不少时间排错。</p>
<p>起初是发现无法发送通知邮件,虽然测试邮件可以成功发送,但是一直收不到通知邮件。</p>
<p>后来 Google 了一下,大概了解是中文补丁导致的,卸载了中文补丁,果然可以收到邮件了。</p>
<p>当时那个中文补丁是上网随便下的,于是我又从<a href="https://translations.atlassian.com/dashboard/dashboard?lang=zh_CN">官网</a>下了一个,直接在插件页面上传上去,发现可以收到通知邮件了。</p>
<p>但是发现首页的布局却出现了问题。</p>
<p><img src="/img/in-post/confluence-ui-error.jpg" alt="" /></p>
<p>打开 web 控制台,发现报了一个错误。</p>
<blockquote>
<p>[Error] SyntaxError: Unexpected EOF
(匿名函数) (batch.js:392)</p>
</blockquote>
<p>跳到源代码看了一下,非常明显,那行多了一个换行符导致了代码解析出现了问题。</p>
<p>既然是中文补丁导致的,那出错的代码肯定是在中文补丁里了。</p>
<p>我打开了补丁包,试着过滤了一下代码的关键字。</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>unzip Confluence-5.10.0-rc1-language-pack-zh_CN.jar
<span class="nv">$ </span><span class="nb">grep</span> <span class="nt">-r</span> start ./
.//atlassian-plugin.xml: &lt;resource <span class="nv">name</span><span class="o">=</span><span class="s2">"i18n-101"</span> <span class="nb">type</span><span class="o">=</span><span class="s2">"i18n"</span> <span class="nv">location</span><span class="o">=</span><span class="s2">"com/atlassian/confluence/plugins/gettingstarted/i18n"</span>/&gt;
.//com/atlassian/confluence/plugins/gettingstarted/i18n_zh_CN.properties:confluence.gettingstarted.movie<span class="o">=</span>//www.atlassian.com/software/confluence/videos/<span class="o">{</span>0<span class="o">}</span>.html<span class="se">\n</span>
...</code></pre></figure>
<p>果然发现了问题所在。</p>
<p>于是将文件中多余的换行符去掉,重新打包。</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>jar cvf ../Confluence-5.10.0-rc1-language-pack-zh_CN.jar ./</code></pre></figure>
<p>将修改后的中文补丁传上去,刷新主页面,咦,居然错误还在?</p>
<p>不应该啊。。。尝试停用了浏览器的缓存。</p>
<p>刷新页面,果然,恢复正常!</p>
</description>
<pubDate>Sun, 23 Oct 2016 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2016/10/23/fix-confluence-chinese-pack-lead-to-web-ui-error/</link>
<guid isPermaLink="true">https://echohn.github.io/2016/10/23/fix-confluence-chinese-pack-lead-to-web-ui-error/</guid>
<category>Confluence</category>
</item>
<item>
<title>批量导入密码到 iTerm 密码管理器</title>
<description><p>定期修改密码是非常常见的安全策略,我们这每隔几个月会将所有线上服务器的密码统一更新。</p>
<p>起初我是将服务器密码直接存储在 Keychain 里。</p>
<p>每次要登录服务器的时候,打开 Keychain,搜索相关服务器的信息,然后点击「将密码复制到剪贴板」,再回到终端里粘贴。</p>
<p>当时觉得虽然不太方便,但是总比从 Excel 里粘密码要好吧。</p>
<p>后来,iTerm 升到 3,多了一项密码管理器的功能。</p>
<p>身为 iTerm 的重度使用者,我觉得这项功能真的超级实用。</p>
<p>只要按下快捷键 ⌘ + P ,设定的关键字一输,密码就可以直接上屏。</p>
<p>所以在我发现这个功能之后,我就把 Keychain 里所有常用服务器的密码都一条条粘到了 iTerm 里。</p>
<p>然而,最近到了公司定期修改密码的日子,当系统组的同事拿着 U 盘过来找我的时候,想到又要一条条的粘,我的内心其实是崩溃的。</p>
<p>我试着 Google ,但是并没有发现特别好将密码导入到 iTerm 的方法,于是我去 iTerm 的论坛发了<a href="https://groups.google.com/forum/#!topic/iterm2-discuss/hrfJL7GA4ZA">一张求助帖</a>。</p>
<p>很快就有人回复了。</p>
<p>因为 iTerm 中的密码也是存在 Keychain 的,可以通过命令行将密码添加到 Keychain :</p>
<blockquote>
<p>On Wednesday, October 19, 2016 at 9:10:07 PM UTC-4, Flare Han wrote:
Is there any way to import a lot of passwords to the Password Manager?</p>
</blockquote>
<p>While googling a similar topic a couple months ago, I found</p>
<p>Save the password in keychain, either by the GUI (see https://www.netmeister.org/blog/keychain-passwords.html) or:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">security add-generic-password <span class="nt">-a</span> <span class="k">${</span><span class="nv">USER</span><span class="k">}</span> <span class="nt">-s</span> LDAPbindPW <span class="nt">-w</span> <span class="s1">'&lt;your-password-goes-here&gt;'</span></code></pre></figure>
<p>The thing I was playing with at the time would have used the above via something like this in my .bashrc:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">LDAP_PW</span><span class="o">=</span><span class="si">$(</span>security find-generic-password <span class="nt">-a</span> <span class="k">${</span><span class="nv">USER</span><span class="k">}</span> <span class="nt">-s</span> LDAPbindPW <span class="nt">-w</span><span class="si">)</span></code></pre></figure>
<p>I also found you can use variations of the security command to list and see what passwords iTerm2 has created.
From that, you can figure out how to use a security command to create/update what iTerm2 uses.</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">security add-generic-password <span class="nt">-U</span> <span class="nt">-s</span> iTerm2 <span class="nt">-T</span> /Applications/iTerm.app <span class="nt">-a</span> <span class="s1">'&lt;hostname&gt; &lt;userid&gt;'</span> <span class="nt">-w</span> <span class="s1">'&lt;userid'</span>s password&gt;<span class="s1">' -l '</span>a label<span class="s1">'</span></code></pre></figure>
<p>iTerm2’s password manager shows the account name (the -a switch). So you don’t really need the -l label. The -l label makes it easier to see in Keychain Access.</p>
<p>于是我写了个脚本将密码表导进了 iTerm 。</p>
<p>其实 iTerm 的密码管理器仍有需要改进的地方,比如它不支持类似 Sublime Text 中的全文匹配,不能跳着输入,所以要输入 ops@zone-application-server 这种名字很长的超麻烦。</p>
<p>我只能给每组账号都设置了一个关键字用来进行快速输入,比如上面这条记录可缩写为 zasop 。</p>
<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#!/usr/bin/env ruby -w</span>
<span class="c1"># encoding: utf-8</span>
<span class="c1"># data csv format</span>
<span class="c1"># jcjz,bj,user1,user1_password,user2,user2_password,...</span>
<span class="c1"># command</span>
<span class="c1"># security add-generic-password -U -s iTerm2 -T /Applications/iTerm.app -a 'user' -w 'password'</span>
<span class="nb">require</span> <span class="s1">'pathname'</span>
<span class="nb">require</span> <span class="s1">'csv'</span>
<span class="k">class</span> <span class="nc">ItermPassword</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="vi">@long_name</span> <span class="o">=</span> <span class="n">args</span><span class="p">.</span><span class="nf">shift</span>
<span class="n">short_name</span> <span class="o">=</span> <span class="n">args</span><span class="p">.</span><span class="nf">shift</span>
<span class="vi">@short_name</span> <span class="o">=</span> <span class="n">short_name</span><span class="p">.</span><span class="nf">nil?</span> <span class="p">?</span> <span class="vi">@long_name</span><span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="mi">1</span><span class="p">]</span> <span class="p">:</span> <span class="n">short_name</span>
<span class="vi">@users_and_passwordes</span> <span class="o">=</span> <span class="no">Hash</span><span class="p">[</span><span class="o">*</span><span class="n">args</span><span class="p">]</span>
<span class="k">end</span>
<span class="no">COMMAND_PREFIX</span> <span class="o">=</span> <span class="s2">"security add-generic-password -U -s iTerm2 -T /Applications/iTerm.app"</span>
<span class="k">def</span> <span class="nf">write_password</span><span class="p">(</span><span class="n">user_name</span><span class="p">,</span><span class="n">user_pass</span><span class="p">)</span>
<span class="nb">system</span> <span class="s2">"</span><span class="si">#{</span><span class="no">COMMAND_PREFIX</span><span class="si">}</span><span class="s2"> -a '</span><span class="si">#{</span><span class="vi">@short_name</span><span class="si">}#{</span><span class="n">user_name</span><span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">user_name</span><span class="si">}</span><span class="s2">@</span><span class="si">#{</span><span class="vi">@long_name</span><span class="si">}</span><span class="s2">' -w '</span><span class="si">#{</span><span class="n">user_pass</span><span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/'/</span><span class="p">,</span><span class="s2">"'</span><span class="se">\"</span><span class="s2">'</span><span class="se">\"</span><span class="s2">'"</span><span class="p">)</span><span class="si">}</span><span class="s2">'"</span> <span class="k">if</span> <span class="n">user_name</span> <span class="o">&amp;&amp;</span> <span class="n">user_pass</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">write</span>
<span class="vi">@users_and_passwordes</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">user</span><span class="p">,</span><span class="n">pass</span><span class="o">|</span>
<span class="n">write_password</span><span class="p">(</span><span class="n">user</span><span class="p">,</span><span class="n">pass</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">data_file</span> <span class="o">=</span> <span class="no">Pathname</span><span class="p">(</span><span class="no">ARGV</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="no">CSV</span><span class="p">.</span><span class="nf">foreach</span><span class="p">(</span><span class="n">data_file</span><span class="p">,</span> <span class="ss">:headers</span> <span class="o">=&gt;</span> <span class="kp">false</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">row</span><span class="o">|</span>
<span class="n">iterm_passes</span> <span class="o">=</span> <span class="no">ItermPassword</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="o">*</span><span class="n">row</span><span class="p">)</span>
<span class="n">iterm_passes</span><span class="p">.</span><span class="nf">write</span>
<span class="k">end</span></code></pre></figure>
<p>(修改于 2017.04.02)</p>
</description>
<pubDate>Sat, 22 Oct 2016 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2016/10/22/import-passwords-to-iterm-password-management/</link>
<guid isPermaLink="true">https://echohn.github.io/2016/10/22/import-passwords-to-iterm-password-management/</guid>
<category>Mac</category>
<category>iTerm</category>
</item>
<item>
<title>尝试提高 ZSH 的响应速度</title>
<description><p>事情的起因是某一天我突然发现,我的 zsh 怎么这么卡?</p>
<p>以前实在没在意 zsh 的响应速度,但是一旦注意到,就开始各种接受不了。</p>
<ul>
<li>打开一个 iTerm 标签页需要十几秒?</li>
<li>cd 一个目录需要一到两秒才有响应?</li>
<li>ls 一个目录要返回结果一两秒后才能操作?</li>
<li>^C 结束进程反而卡在这不动?</li>
</ul>
<p>我想到最近机器做过的变更实在太多。升级 macOS Sierra,iTerm 升级,oh-my-zsh 更新,实在有太多东西可能导致速度下降了。</p>
<p>然而 Google 实在搜不到相关升级会导致 zsh 卡顿的结果。</p>
<p>甚至我还想到可能是本子用的时间太长,ssd 读写速度下降导致的 zsh 卡顿。。。</p>
<p>我怎么用怎么觉得不爽,再也无心他事,直接扑在了改进 zsh 的速度上面。</p>
<p>我谷歌了很多资料,zsh 太慢的问题被很多人抱怨过,在此过程中我也学会了使用 <code class="language-plaintext highlighter-rouge">zsh -xv</code> 命令调试 zsh 。</p>
<p>我发现启动和运行过慢的原因有四点。</p>
<p>第一,加载过多了插件。</p>
<p>可能当我刚开始尝试用 oh-my-zsh 的时候,我参考了网上许多文章,加载了很多我用不到的插件。比如我同时开启了 z 和 autojump ,这两个插件的作用是一样的。在每次切换目录的时候,它们都会分别将切换的信息记入自己的数据库以进行权重统计,所以同时开启在一定程度上影响着 prompt 的响应速度。</p>
<p>在我关闭了许多自己用不到的插件之后, 明显速度提升了一些,但还不是非常明显。</p>
<p>第二,某些响应卡顿的命令明显影响 zsh 启动速度。</p>
<p>我使用<code class="language-plaintext highlighter-rouge">zsh -xv</code> 命令调试 zsh 的时候发现,每次启动当加载到了某些插件,比如 autojump,执行到<code class="language-plaintext highlighter-rouge">brew --prefix</code>命令的时候会有非常明显的卡顿。 而在加载过程中,不止一次会调用到这个命令。</p>
<p>所以我将所有插件中的<code class="language-plaintext highlighter-rouge">brew --prefix</code>都替换回了它的结果<code class="language-plaintext highlighter-rouge">/usr/local</code>,我觉得我并不会轻易改动 brew 的安装目录。修改之后,zsh 的启动时间从十几秒直接缩减到了 3.5 秒。</p>
<p>可以用下面这条命令测量 zsh 的启动时间。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>usr/bin/time /bin/zsh -i -c exit
</code></pre></div></div>
<p>第三,所用主题的 prompt 功能会非常影响 prompt 的响应速度,尤其是 git prompt</p>
<p>我根据自己的使用习惯,在 <code class="language-plaintext highlighter-rouge">agnoster</code> 主题之上做了一些修改,添加了一些逻辑。在这次事件发生后,我读了一下主题的源码,做了一些优化。</p>
<p>比如,把类似 <code class="language-plaintext highlighter-rouge">echo $var |sed ...</code> 等造成多进程开销的命令都使用 Bash 内部替换代替(详见<a href="http://echohn.github.io/2016/05/21/bash-style-guide-cn/">我翻译的这篇文章</a>)。</p>
<p>而且这次我发现主题中的 git prompt 逻辑会非常影响 prompt 的响应速度。尤其是判断 git 中的版本有没有未提交的文件等状态的相关命令。我在测试的时候,将其替换成一个只显示 git 分支,不显示其他状态的 git prompt,其响应速度直接提升到让我满意的程度。</p>
<p>在这次 zsh 的卡顿事件中,在功能和性能之间,我最终做出了妥协,去掉了一些用不到功能和插件,换来一个我能接受的性能提升。</p>
<p>至于为什么不切换成速度更快的 fish,我考虑到我毕竟是做运维的,还是使用跟服务器上自带的 Bash 更相似一些的 zsh 为好。</p>
<p>这次我顺便还了解了 Antigen 、Antibody 等工具,和几个很实用、有意思的插件。</p>
<p>但是我还是没有使用 Antibody,我感觉它能支持的插件还是太少,当然这也可能是我对其了解的太浅显了。</p>
<p>最后为了缓解自己在 zsh 加载时候的焦虑心情,我做了一个 Loading 的命令行动画。</p>
<p><img src="/img/in-post/ScreenFlow.gif" alt="" /></p>
<p>挺有意思的吧!</p>
</description>
<pubDate>Sat, 01 Oct 2016 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2016/10/01/about-improve-zsh-response-speed/</link>
<guid isPermaLink="true">https://echohn.github.io/2016/10/01/about-improve-zsh-response-speed/</guid>
<category>Mac</category>
<category>ZSH</category>
<category>工具</category>
</item>
<item>
<title>「时间管理」读书笔记</title>
<description><p>今天读了「<a href="https://zhuanlan.zhihu.com/p/22494362">你知道吗?每个时间管理方法都只适合解决某一类问题</a>」这篇文章,觉得很受用。</p>
<p>正好我正想系统化的梳理一下之前学习过的时间管理相关资料,就以此文章为基础,先做一篇读书笔记。</p>
<p>对于这篇文章中所提到的「生命之花」和「晨间日记」我之前并不是很了解,所以在笔记中做了一些拓展。</p>
<p>以后如果有时间,我再把之前学过的其他时间管理的知识总结到这里。</p>
<p><a href="https://github.com/echohn/my-mindmap/blob/master/时间管理.pdf">点击这里查看</a></p>
</description>
<pubDate>Sat, 01 Oct 2016 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2016/10/01/the-reading-note-of-time-management/</link>
<guid isPermaLink="true">https://echohn.github.io/2016/10/01/the-reading-note-of-time-management/</guid>
<category>时间管理</category>
</item>
<item>
<title>使用 cloc 统计你的代码量</title>
<description><p>今天发现一个特别好用的工具 <a href="https://github.com/AlDanial/cloc">cloc</a>,可以用它统计代码的行数。它可以识别多种开发语言,并在计算的时候忽略掉注释和空行。</p>
<p>我记得我上次申请软件著作权的时候,申请表格中要求提交代码量,当时为了计算行数,我写了类似于 <code class="language-plaintext highlighter-rouge">find xxx -prune xxx | xargs grep -vE xxx | wc -l</code> 的超长命令。</p>
<p>每年写年终总结统计工作量的时候,我也常常会用到类似的命令。</p>
<p>所以我今天突然发现这个工具的时候,还是很惊喜的。</p>
<p>在 macOS 上,可以通过 <code class="language-plaintext highlighter-rouge">brew install cloc</code> 来安装它,它支持包括 Windows 在内的多个系统。</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">npm <span class="nb">install</span> <span class="nt">-g</span> cloc <span class="c"># https://www.npmjs.com/package/cloc</span>
<span class="nb">sudo </span>apt-get <span class="nb">install </span>cloc <span class="c"># Debian, Ubuntu</span>
<span class="nb">sudo </span>yum <span class="nb">install </span>cloc <span class="c"># Red Hat, Fedora</span>
<span class="nb">sudo </span>dnf <span class="nb">install </span>cloc <span class="c"># Fedora 22 or later</span>
<span class="nb">sudo </span>pacman <span class="nt">-S</span> cloc <span class="c"># Arch</span>
<span class="nb">sudo </span>pkg <span class="nb">install </span>cloc <span class="c"># FreeBSD</span>
<span class="nb">sudo </span>port <span class="nb">install </span>cloc <span class="c"># Mac OS X with MacPorts</span>
brew <span class="nb">install </span>cloc <span class="c"># Mac OS X with Homebrew</span>
choco <span class="nb">install </span>cloc <span class="c"># Windows with Chocolatey</span></code></pre></figure>
<p>它有诸多优点:</p>
<ol>
<li>下载安装方便。</li>
<li>能识别多种语言。</li>
<li>允许通过项目或语言等多种方式来输出统计结果。</li>
<li>多种输出格式,包括纯文本、SQL、JSON、XML、YAML 等。</li>
<li>能直接从压缩包里统计代码。</li>
<li>多种排错选项。</li>
<li>识别含有非常用字符和空格的文件、目录名。</li>
<li>没有外部依赖。</li>
<li>可在多种系统上运行。</li>
</ol>
<p>由于它出色的灵活性,可以和多种工具结合使用。</p>
<p>比如写一个 <a href="http://stackoverflow.com/questions/26881441/can-you-get-the-number-of-lines-of-code-from-a-github-repository">cloc-git</a> 的脚本,用来统计 git 远程项目的代码量。</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="c">#!/usr/bin/env bash</span>
git clone <span class="nt">--depth</span> 1 <span class="s2">"</span><span class="nv">$1</span><span class="s2">"</span> temp-linecount-repo <span class="o">&amp;&amp;</span>
<span class="nb">printf</span> <span class="s2">"('temp-linecount-repo' will be deleted automatically)</span><span class="se">\n\n\n</span><span class="s2">"</span> <span class="o">&amp;&amp;</span>
cloc temp-linecount-repo <span class="o">&amp;&amp;</span>
<span class="nb">rm</span> <span class="nt">-rf</span> temp-linecount-repo</code></pre></figure>
<p>运行结果如下:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>cloc-git https://github.com/rails/rails.git
Cloning into <span class="s1">'temp-linecount-repo'</span>...
remote: Counting objects: 3615, <span class="k">done</span><span class="nb">.</span>
remote: Compressing objects: 100% <span class="o">(</span>3048/3048<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
remote: Total 3615 <span class="o">(</span>delta 174<span class="o">)</span>, reused 1576 <span class="o">(</span>delta 52<span class="o">)</span>, pack-reused 0
Receiving objects: 100% <span class="o">(</span>3615/3615<span class="o">)</span>, 6.08 MiB | 2.28 MiB/s, <span class="k">done</span><span class="nb">.</span>
Resolving deltas: 100% <span class="o">(</span>174/174<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
Checking connectivity... <span class="k">done</span><span class="nb">.</span>
<span class="o">(</span><span class="s1">'temp-linecount-repo'</span> will be deleted automatically<span class="o">)</span>
3043 text files.
2893 unique files.
309 files ignored.
github.com/AlDanial/cloc v 1.70 <span class="nv">T</span><span class="o">=</span>19.61 s <span class="o">(</span>141.1 files/s, 18560.1 lines/s<span class="o">)</span>
<span class="nt">-------------------------------------------------------------------------------</span>
Language files blank comment code
<span class="nt">-------------------------------------------------------------------------------</span>
Ruby 2152 47525 41996 213275
Markdown 74 13832 0 34880
JavaScript 23 732 747 3385
YAML 144 307 584 2505
ERB 318 248 11 1736
CSS 20 157 120 1105
CoffeeScript 11 87 104 318
HTML 19 15 3 198
yacc 1 4 0 45
SQL 1 6 0 43
JSON 1 0 0 24
builder 2 0 0 6
DTD 1 0 0 1
<span class="nt">-------------------------------------------------------------------------------</span>
SUM: 2767 62913 43565 257521
<span class="nt">-------------------------------------------------------------------------------</span></code></pre></figure>
<p>cloc 也支持使用 <code class="language-plaintext highlighter-rouge">--diff</code> 选项对两个版本的代码量进行比较。</p>
<p>但是在我尝试 cloc 使用 <code class="language-plaintext highlighter-rouge">--diff</code> 选项比较文件并输出结果的时候, 我发现了一个问题,cloc 输出的 yaml 或 json 文件内容是不正确的。如下所示:</p>
<figure class="highlight"><pre><code class="language-yaml" data-lang="yaml"><span class="nn">---</span>
<span class="c1"># github.com/AlDanial/cloc</span>
<span class="na">header </span><span class="pi">:</span>
<span class="nn">...</span>
<span class="na">same </span><span class="pi">:</span>
<span class="na">language </span><span class="pi">:</span> <span class="s">CSS</span>
<span class="na">files_count </span><span class="pi">:</span> <span class="m">3</span>
<span class="na">blank </span><span class="pi">:</span> <span class="m">0</span>
<span class="na">comment </span><span class="pi">:</span> <span class="m">25</span>
<span class="na">code </span><span class="pi">:</span> <span class="m">2</span>
<span class="na">language </span><span class="pi">:</span> <span class="s">JavaScript</span>
<span class="na">files_count </span><span class="pi">:</span> <span class="m">38</span>
<span class="na">blank </span><span class="pi">:</span> <span class="m">0</span>
<span class="na">comment </span><span class="pi">:</span> <span class="m">131</span>
<span class="na">code </span><span class="pi">:</span> <span class="m">2177</span>
<span class="na">language </span><span class="pi">:</span> <span class="s">HTML</span>
<span class="na">files_count </span><span class="pi">:</span> <span class="m">3</span>
<span class="na">blank </span><span class="pi">:</span> <span class="m">0</span>
<span class="na">comment </span><span class="pi">:</span> <span class="m">3</span>
<span class="na">code </span><span class="pi">:</span> <span class="m">182</span>
<span class="nn">...</span></code></pre></figure>
<p>这是 diff 输出的 yaml 文件。注意 same 下面的 key 并不是根据开发语言区分的二级 Hash,而是所有结果都使用了同样的 key 名放在了一起。这样如果有其他工具读取输出文件,势必会导致前面同名 key 的值被后面的值覆盖。造成解析后会丢失绝大部分的报告内容。</p>
<p>这个问题我已经在项目提交了<a href="https://github.com/AlDanial/cloc/issues/127">Issue</a>,作者说过几天就将修复这个问题。</p>
<p>最后统计了一下我最近在做的项目。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cloc .
365 text files.
339 unique files.
225 files ignored.
github.com/AlDanial/cloc v 1.70 T=9.31 s (16.3 files/s, 2338.0 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
YAML 7 13 47 14366
JavaScript 38 1 131 2177
Ruby 72 396 728 1281
CoffeeScript 7 148 29 1192
SASS 4 34 19 347
ERB 16 60 0 250
Markdown 2 143 0 182
HTML 3 15 3 182
CSS 3 2 25 2
-------------------------------------------------------------------------------
SUM: 152 812 982 19979
-------------------------------------------------------------------------------
</code></pre></div></div>
<p>最多的 YAML 代码是从业务库导出的基线数据。由于这是个基于 echarts 的业务数据可视化的项目,前端代码占的比重稍大了一点。</p>
</description>
<pubDate>Sat, 24 Sep 2016 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2016/09/24/use-cloc-to-count-your-code/</link>
<guid isPermaLink="true">https://echohn.github.io/2016/09/24/use-cloc-to-count-your-code/</guid>
<category>工具</category>
</item>
<item>
<title>升级到 macOS Sierra 之后踩到的坑 (持续更新)</title>
<description><p>本来没想这么早升级的,主要是之前看相关的消息,我以为新版本 GateKeeper 无法关闭,怕很多应用无法使用了。</p>
<p>之后看到<a href="https://zhuanlan.zhihu.com/p/22537236">《macOS Sierra 正式版升级须知一览》</a>发现 GateKeeper 仍是可以通过命令行进行关闭的,这才放下心兴致勃勃的点了 Sierra 的下载。</p>
<p>安装过程一切顺利,完成之后直接重置了 NVRAM。</p>
<p>正常启动之后没有发现大的问题,比如 Homebrew 无法使用之类的。</p>
<p>但仍然发现了一些小问题。</p>
<h2 id="坚果云导致-finder-使用右键菜单时崩溃已解决">坚果云导致 Finder 使用右键菜单时崩溃(已解决)</h2>
<p><img src="/img/in-post/sierra-finder-crash.jpg" alt="" /></p>
<p>起初我直觉以为是杀毒软件 ESET Cyber Security 引起的,因为 ESET 启动后明确提示不支持 Sierra ,并且在我删除 ESET 套件后也突然发现 Finder 右键可用了,但是重启后发现问题仍在。</p>
<p>仔细看了看详细信息,发现崩溃信息中提到 NutstorePlugin,才确定是由坚果云导致的崩溃。</p>
<p>在坚果云论坛搜到了这篇<a href="http://bbs.jianguoyun.com/topic.php?id=6553">帖子</a>,其中官方提到可<a href="https://www.jianguoyun.com/p/DTLhAzEQjof1BRjTohU">下载最新的测试版本Mac客户端</a> 。</p>
<p>更新之后问题解决。</p>
<h2 id="xtrafinder-剪切文件时候导致-finder-崩溃待解决">XtraFinder 剪切文件时候导致 Finder 崩溃(待解决)</h2>
<p>在升级 Sierra 之后,发现 Bartender 中的 Spotlight 图标无法隐藏(我还是习惯用 Alfred),并且打开 Finder 后发现 XtraFinder 没有加载。</p>
<p>仍然是 SIP(System Integrity Protection)的问题。</p>
<p>解决方法是开机 Command + R 进入恢复模式。</p>
<p>点击实用工具打开终端,执行命令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csrutil enable --without debug
</code></pre></div></div>
<p>重启后发现 XtraFinder 可以加载了,但是当我尝试剪切文件的时候,发现 Finder 会闪退,看来 XtraFinder 还是与 Sierra 兼容性上存在问题。于是</p>
<p>只能卸载 XtraFinder 等待更新了。</p>
<h2 id="bartender-图标位置错乱待解决">Bartender 图标位置错乱(待解决)</h2>
<p>发现本由 Bartender 掌管的菜单栏图标位置,在每次重启之后,都不大一样。</p>
<p>据说这是由于 Sierra 也支持按住 Command 键拖动图标了引起的问题。</p>
<p>只能等 Bartender 更新了。</p>
<h2 id="sar-命令被移除待解决">sar 命令被移除(待解决)</h2>
<p>这个还是在 <a href="https://www.v2ex.com/t/308007">V2EX</a> 上看到的。</p>
<p>sar(System Activity Reporter) 我在 Linux 上经常用它来分析网络性能。</p>
<p>我试着在 homebrew 搜索 sar ,没找到。我又下了 sysstat 的源码包试着编译了一下,在编译的时候出错了。</p>
<p>用 Google 搜索,发现已有人在项目 Issue 里提出<a href="https://github.com/sysstat/sysstat/issues/74">如何在 mac 上编译 sysstat</a> ,但是开发者说因为他没用 mac ,所以也帮不上忙。</p>
<h2 id="itunes-桌面歌词插件-dynamiclyrics-无法使用已解决">iTunes 桌面歌词插件 DynamicLyrics 无法使用(已解决)</h2>
<p>我看该项目的 Github 中已经有人提了相关的 Issue, 等待作者更新吧。</p>
<p>(2016年09月25日项目已更新,已可正常使用。)</p>
<h2 id="升级之后的感受">升级之后的感受</h2>
<p>这次升级,外观上几乎没有变化。</p>
<p>(后续更新:刚发现通知中心变丑了。。。)</p>
<p>剪切板同步、存储优化、和完全支持了 ES 6 的 Safari 10,都是让我特别惊喜的功能。</p>
<p>部分功能没有想象中的好用,可能因为很多功能已经有很好的解决方案了。</p>
<p>比如 Siri 除了记录提醒事项外,其他功能的效率并不比 Alfred 更高,而且中英文混说的时候识别率不高。</p>
<p>中文输入法仍然不支持自定义双拼方案。</p>
<p>自动解锁我之前一直用 Near Lock ,嗯,可能如果我有 Apple Watch 的话,也会觉得这个很酷吧。</p>
<p>等我发现了其他问题,再继续更新这篇文章吧。</p>
</description>
<pubDate>Thu, 22 Sep 2016 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2016/09/22/hit-the-pit-after-updated-osx-to-sierra/</link>
<guid isPermaLink="true">https://echohn.github.io/2016/09/22/hit-the-pit-after-updated-osx-to-sierra/</guid>
<category>Mac</category>
</item>
<item>
<title>这两个月我在忙什么</title>
<description><p>转眼间有两个多月没有写一篇文章了。</p>
<p>这两个多月,我一直在公司忙于开发一个给客户使用的数据可视化的项目。</p>
<p>说起来我接到做这个项目的因为,是因为研发的同事实在太忙了,研发的 Boss 对业务说实在抽不出人手来做这个项目,所以这个项目落到运维来了。</p>
<p>毕竟之前是一直写东西给自己人用,现在终于能写东西给客户用,我刚接到这个项目的时候还是很兴奋的。</p>
<p>这个项目立项时有三个人,我负责项目进度和开发,还有研发的一位设计师和一位前端工程师。但是,因为他们实在太忙了,所以除了有必要找他们把控界面以外,这个项目其实只有我一个人在做。</p>
<p>所以,我这段时间看上去还挺忙的。</p>
<p>因为是由我自己把控项目进度,我对这个项目进度的焦虑感还挺少的,因为我很清楚自己开发的效率,每个任务都留了足够的时间。</p>
<p>然而,我在这个项目中思考了一些以往自己可能没那么在意的事情。</p>
<h2 id="对于我对项目把控的缺点">对于我对项目把控的缺点</h2>
<p>我对项目把控属于典型的虎头蛇尾型。</p>
<p>我往往在项目开始时,把任务分解的特别周到详细,我的项目计划书多次做为范例被领导分享给其他同事做参考。</p>
<p>但是在项目中后期,项目进度就会渐渐失控,其主要原因就是我没有对他人的任务进度给予即时的监控。</p>
<p>我总以为别人跟我一样,会认真的对待项目计划和 Deadline。开始我问他们,按照这个项目计划有问题吗,他们说放心吧,没问题。然后我就很放心的不管了。等到了共同的项目节点需要沟通的时候,结果往往是他们的任务还没有完成,进度还差很大一截。我猜这样的原因主要就是他们对别人的项目不重视,所以导致没有细读计划,不遵守 Deadline,甚至对自己的任务完不成时,也不提前做沟通。</p>
<p>当然,还有一点,就是我对其他人的任务监控确实有待提高。只能说,多沟通吧。</p>
<p>而且,我身为项目负责人,理应每周向上级汇报进度的,我后来也懒了。</p>
<h2 id="对于与需求方沟通">对于与需求方沟通</h2>
<p>这次,真的体会到了研发同事的苦。</p>
<p>我发现在面对满脑子啥想法都没有的业务同事的时候,想保持一种平常心真的是挺难的。</p>
<p>第一次与业务开项目碰头会的时候,我们大眼瞪小眼。接到任务的我,等着业务跟我详细的说说需求。接到会议通知的业务,以为我们拿到任务已经有一些实现的想法了要汇报给他们。</p>
<p>然后在他们真正明白这次会议目的之后,就开始天南海北的胡扯,跑的都没边了。</p>
<p>幸亏我人精人精的领导也参了会,及时给他们刹住了车,直到这时,我还处于懵逼的状态中。</p>
<p>业务在产品出现之前,他们说的特别客气,时间挺紧的,功能实现了就行哈。待真的产品出来之后,就开始冷着脸各种挑刺了。</p>
<p>对这我倒是表示理解,就像问一些男生你想找个什么样的女朋友?他说,诶呀,啥样的都行,是女的就行。</p>
<p>他说不出来,因为他没有目标。</p>
<p>但是让他说不喜欢什么的,他却恰恰能从各种细节跟你说出个百八十条。</p>
<p>因为不喜欢什么,自己通常是很了解的,我觉得是一样的道理。</p>
<h2 id="对于接受与思考">对于接受与思考</h2>
<p>我是想事情想的很少那种人。</p>
<p>我开始觉得业务的需求是需要尽量满足的,因为他们更贴近客户,他们的意见值得尊重。</p>
<p>嗯,也是我审美水平太次,我对业务的意见挑不出毛病,我觉得他们的想法也行吧,也没啥不好的,改一下试试呗。</p>
<p>但是跟我一块的还有一个非常具有审美水平的暴脾气设计师。</p>
<p>他的原话是,信他们的就麻烦了,东一榔头,西一榔头,拍脑袋改,早晚玩完!</p>
<p>当时我就夹在他们中间,我觉得好难过。</p>
<p>一方面是对项目的责任感,一方面是答应了别人要实现,但是没有去做的惶恐感。</p>
<p>这件事让我在公司和回家的时候都在思考怎么做,我也咨询了身为牛逼闪闪的前某公司首席需求分析师现在专心休假在家带孩子的老婆大人。</p>
<p>老婆大人在鄙视了我公司业务的审美水准之后,教导我,以后定需求的时候,别说的那么死,可以说我回去再考虑一下嘛。</p>
<p>其实后来想想,这事主要确实是我沟通方式不够圆通,另一方面是我对于类似的事情缺乏经验,思考的还是太少了。</p>
<hr />
<p>总之,到节前,项目已经基本完成了。</p>
<p>我因自己「太忙」找借口懒得更新的理由也没法再用了。</p>
<p>还是要让自己忙起来,多看一些书,多学一些感兴趣的东西。毕竟,看到自己进步,还是挺有乐趣的。</p>
</description>
<pubDate>Fri, 16 Sep 2016 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2016/09/16/what-did-i-do-in-these-months/</link>
<guid isPermaLink="true">https://echohn.github.io/2016/09/16/what-did-i-do-in-these-months/</guid>
<category>杂记</category>
</item>
<item>
<title>如何自动备份 Safari 书签</title>
<description><p>今天上午美男子找我,「我 Safari 的书签突然全没啦,怎么办?」</p>
<p>「你上次说买 <a href="http://www.apple.com/cn/shop/product/ME177CH/A/airport-time-capsule-2tb?fnode=5f">Time Capsule</a> 后来买了吗?」</p>
<p>「还没啊。」</p>
<p>「那你试试登 iCloud 看看,我记得好像有恢复书签的功能。」</p>
<p>过了一会,美男子告诉我,确实在 iCloud 里找到了恢复书签的选项,包括通讯录,日历和 iCloud Drive 的文件,iCloud 都有恢复的功能。</p>
<p>这件事就这样结束了,然后我就在想,Safari 的书签是存在 ~/Library/Safari/Bookmarks.plist 里的,而 Safari 导出的书签实际上是一个 HTML 文件,其实写一个脚本就可以把书签自动备份了呀。</p>
<p>(我写这个就是写着玩,我平时用 Time Capsule 做备份也用不着这个。。。)</p>
<p>我尝试研究了一下,发现确实完全可行,但是发现了 Safari 的一个问题,Safari 在导入书签的时候,无法正确地识别<code class="language-plaintext highlighter-rouge">&lt;/dt&gt;</code>标签。而且只能解析与<code class="language-plaintext highlighter-rouge">&lt;dt&gt;</code>标签处在同一行的书签。</p>
<p>这么说可能不易理解,我举例解释一下。</p>
<p>正常 HTML 生成的<code class="language-plaintext highlighter-rouge">&lt;dt&gt;</code>标签应该是闭合的。如果在输出后的 HTML 文件不换行,是下面的样式。</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;DT&gt;&lt;a</span> <span class="na">href=</span><span class="s">"http://www.zhihu.com/"</span><span class="nt">&gt;</span>知乎<span class="nt">&lt;/a&gt;&lt;/DT&gt;</span></code></pre></figure>
<p>这种情况下,Safari 会错误的把<code class="language-plaintext highlighter-rouge">&lt;/dt&gt;</code>前面的<code class="language-plaintext highlighter-rouge">&lt;/a&gt;</code>也解析成书签名,书签名会变成<code class="language-plaintext highlighter-rouge">知乎&lt;/a&gt;</code></p>
<p>如果输出允许 indent,例如下面的样式:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;DT&gt;</span>
<span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"http://www.zhihu.com/"</span><span class="nt">&gt;</span>知乎<span class="nt">&lt;/a&gt;</span>
<span class="nt">&lt;/DT&gt;</span></code></pre></figure>
<p>。。。Safari 根本就认不出来这个书签啦。</p>
<p>我试验出的结果是,Safari 在导入书签的时候,只能识别出非闭合的<code class="language-plaintext highlighter-rouge">&lt;dt&gt;</code>标签,并且需要把书签放置在<code class="language-plaintext highlighter-rouge">&lt;dt&gt;</code>标签的同一行中,例如下面这样才能够正常的解析。</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="nt">&lt;DT&gt;&lt;a</span> <span class="na">href=</span><span class="s">"http://www.zhihu.com/"</span><span class="nt">&gt;</span>知乎<span class="nt">&lt;/a&gt;</span></code></pre></figure>
<p>由于上面的问题,而且 xsltproc 将 xml 转换成 html 的时候,没法转换非闭合的标签,最后我在写脚本的时候,只能在导出 HTML 时,加了一个 sed 删除所有的<code class="language-plaintext highlighter-rouge">&lt;/dt&gt;</code>标签,这真让强迫症痛苦。。。</p>
<p>最后附上脚本。</p>
<p>自动备份脚本的使用方法:</p>
<p>将 「<a href="https://gist.github.com/echohn/eb8f31165aa288a3d0de115ac11ee543">备份脚本</a> 」与「 <a href="https://gist.github.com/echohn/4c5edcd8697b29cec9bafb36889e6953">转换模板</a> 」下载到同一目录,然后在 crontab 里添加执行 <code class="language-plaintext highlighter-rouge">SCRIPT_PATH/backup_safari_bookmarks.sh OUTPUT_PATH</code>即可,其中 OUTPUT_PATH 是书签备份将存放的目录,脚本执行之后,会在这个目录下生成一个文件名为当天日期的 HTML 书签文件。</p>
<p>导入备份书签的方法:</p>
<p>选择 Safari -&gt; 文件 -&gt; 导入自 -&gt; 书签 HTML 文件…,然后选择最新的备份文件恢复即可。</p>
</description>
<pubDate>Fri, 22 Jul 2016 00:00:00 +0800</pubDate>
<link>https://echohn.github.io/2016/07/22/auto-backup-safari-bookmarks/</link>
<guid isPermaLink="true">https://echohn.github.io/2016/07/22/auto-backup-safari-bookmarks/</guid>
<category>Safari</category>
<category>Mac</category>
<category>script</category>
</item>
</channel>
</rss>