CY's Blog

All work is preparing yourself for the accident waiting to happen.

人生的意義到底是什麼呢?這個問題應該每個人或多或少在成長過程都有想過吧?特別是在青春期的時候,心裡因為不知道未來的方向,而有陷入迷惘中,會覺得人生好像是沒有意義的。在我高中時期就是在這樣的狀態中,為了符合外在的要求(拿到好成績)而努力,但是卻不知道自己心裡真正是為何而努力。這樣的心情雖然隨著年齡的增長而慢慢減緩,但是若是問到自己的人生有什麼意義這回事,我想我還是回答不出來。

但是,人生的意義其實根本就只是個偽命題。我們通常期望很輕鬆地得到一個目標,然後再去努力,但是常常人生的意義是先去努力,然後才會得到。最近看了「心流:最優體驗心理學」 ,裡面提到了「最終目標只要能為一生的精神能量建立秩序,它本身是什麽並不重要。人生的意義就在於“尋求意義”:不論它的本質,不論它來自何處,只要找到一個統一的大方向,人生就會有意義。」,這時才隱隱約約明白,原來我根本不缺乏人生意義,我想要的是內心的平靜、內心的秩序,也就是作者所講的心流狀態。意義本身並不重要,每個人都可能有屬於自己的意義,但是在追求意義本身就會為自己生命賦予價值。

「心流」這個概念其實我很久以前就聽過了,一開始是從強者我朋友那裡得知,我原本以為這是一個用在學習的工具罷了,並不是很在意。最近因為有些我看的書籍有再次提到這個概念,才想說來看看當初提出這個概念的作者米哈里的原書。這本書最早是在1990出版,台灣也有出自己的翻譯本,應該是叫快樂.從心開始 ,但也已經絕版了,而最近中國才重出了這本書。的確,如果 google 心流這個詞,十之八九是講我們在面對有一定挑戰性的事情時,進入了聚精會神的狀態,忘了時間的流動,只專注在當下。進入心流會創造最佳的體驗,會讓自己想要一再體驗,這也是很多學習的書籍鼓吹的學習方式。

如果把進入心流的條件和刻意練習相比,會發現兩著有很高的相似性。兩者都一樣需要有個明確的目標、有即時的反饋、需要全神貫注地投入、需要有適當的挑戰性(跨出舒適圈)。但是在本書的介紹序也有提到,兩者的動機是完全不同的,刻意練習是為了讓自己的能力獲得提升,是一種行為,而心流則是一種體驗,讓人沈醉且上癮。儘管如此,我個人的經驗是有意識進行刻意練習時,有時候也會有種進入心流的狀態,忘記時間,想要繼續做下去。雖然本質不同,但是兩者是可以相輔相成的。

為什麼進入心流會讓我們愉悅呢?書中有提到一個概念叫做精神熵,熵在物理的意義是亂度,越高代表越混亂。如果我們的精神熵越高,就代表我們的意識失去了秩序,受到了威脅,我們必須要去防衛,自然就會感到不快樂。心流的意義我會解釋成心靈的秩序,就像磁鐵要有磁性一定要被磁化,讓內部分子的南北極都同向,對外才會產生出一股磁力。當我們進入心流狀態也就是在內心建立起了秩序,不會被外界可能讓心靈混亂的事物打擾,因此才會有忘記自我,忘記時間的感覺。

以秩序來解釋為什麼會快不快樂似乎有其道理。米哈里提到了享樂和樂趣的差別:享樂是恢復均衡的體驗,主要是維持意識的秩序,但無法創造新秩序,樂趣需要高度注意力,完成意料之外的事情。因為樂趣的高複雜度、有挑戰性,所以不斷提供大腦新鮮感,這也是樂趣可以維持比較長久的快樂。另外值得一提的是,如果我們是為了什麼目的才做某件事情,可能就不有趣,就像我們不是為了得到勝利而玩遊戲,而是享受在玩遊戲的過程。因為如果有目的的話,我們就不是專心在當下遊戲規則所帶來的秩序了。遊戲規則主導了我們的心流,讓我們內心維持了秩序,所以有些人在使用外掛後很快就會對遊戲失去興趣的原因也是在秩序已經被破壞了,規則無法再帶給我們心靈秩序了。

米哈里不只是用心流來解釋我們進入專心的狀態,書中他更是嘗試用心流來解釋人類的社會、文化、甚至是遇到困境時要怎麼克服。這也是讓我眼界大開的一部份,原來心流也是可以用來解釋更高層次的現象。社會與文化說穿了其實也就是一種規則,一種秩序,在過去社會文化上的規範會規定我們的外在行為應該要怎麼做,有很多的限制,但是大多數人在成長過程中接受了這樣的限制,然後久而久之自己也成為要求他人遵守這些規則的人。然而在現在的世界,國際間的文化交流、網際網路的發達,拓展了每個人的視野,追求個人自由的風氣中屏棄掉了傳統文化,因此人們有更多選擇。但是更多選擇不代表會更快樂,因為會陷入了不知道要選什麼才好的狀態。這就跟我們父母一輩不會有用興趣選職業這件事,而是找個穩定收入的工作或繼承家業,沒有什麼其他選擇,而我們這代則會迷惘進大學時到底要選擇什麼樣的科系,未來要找什麼工作,到底自己對什麼有興趣。這個選擇越多越不快樂的現象正呼應了人失去了秩序後會不快樂的概念。

但是我個人覺得,這不代表我們要走回頭路,的確規範可以帶給大多數人秩序,但是並沒有道理要求所有人都遵守這樣的規範,自由與民主已經深入人心,難以逆轉。我們能做的是知道這個現象,然後清楚自己的迷惘是來自心靈的失序,接著透過不斷與外界的互動來重新建立自己的秩序,最後就會形塑出屬於個人的價值觀,也就是個人的生命意義。米哈里也建議,我們可以從宗教、歷史、文學等等過去前人所建立的秩序中吸取經驗,建立起屬於自己內心不被擾亂的模式,用前人的力量賦予自己生命新的意義。

本書帶給我很多新的觀念,特別是讓我重新認識了「心流」。在閱讀時,我得承認作者的敘述、排版方式有點冗長,比較沒有架構性,不過不妨礙本書的價值。另外我會推薦大家要看一下推薦序的部分,雖然我從來沒看過那麼長的推薦序,但是卻是一個很好的總結,書中大多數的精華都有被整理出來了。我們不只是要追求在學習上全神貫注的心流,更是要追求人生的心流,真正內心的秩序必須要上從人生觀下到自己的行為都達成一致,並且能心無旁騖專注在其中。如果要用一句話解釋我從這本書得到的觀念,我會這麼說:快樂與幸福來自我們內心的和諧,建立一個可以應付外界干擾的秩序,讓自己的外在行為與內心秩序一致,那就是在人生的心流之中了

第一次看到這本書的原因是是跟朋友在逛書展時發現的,原本對書名並沒有什麼興趣,但是忽然瞄到作者是孫圈圈,馬上就有興致了。之前都會在她的公眾號發現不錯的文章,內容有條理,而且不會流於口號,都有如何實行的方法論。而這本書看完後的確是不負所望,內容很紮實,有把她做諮詢累積的經驗分享出來,我覺得非常適合初入職場的人閱讀。

本書大致上分為好幾個部分:挖掘天賦、如何學習、思維、溝通、職涯規劃、情緒等等,每個都有寫出作者的見解和方法論,這本書編排很好的地方是在每篇文章最後面都會有總結,以及可以怎麼做讀後練習,就像書中一開始所說,現在「道」和「器」的書太多了,但很多都沒有實作方法,所以她想要寫一篇關於「術」的文章。

簡單分享一下我在書中特別有感觸的觀念。挖掘天賦這塊作者列舉了各種職業定位並做簡單分析,並且合理推出天賦型的定位比較適合我們,然後再給出了挖掘自己天賦的方法。雖然我不認同作者說的每個人天生上就有各自的天賦,因為我覺得只要是硬體沒差很多(人的身體),基本上差異都是後天學習造成的,但是作者在這邊有擴大天賦的定義,她認為意願也是種天賦,有些人可能因為家庭等後天學習因素而喜歡做什麼事、不喜歡做什麼事,這也算天賦的優勢。這個觀念我以前並沒有想過,不過想想也是很合理,理論上人透過一定正確的訓練應該能力不會差太多,但是如果有些人本身就不喜歡該領域,就更不可能去做正確的訓練了,因此能力上就會出現落差。

學習的部分並沒有提到什麼新東西,大概還是離不開刻意練習的概念,然而在思維和溝通的部分就有很多可以參考的點了。畢竟作者是做諮商的,所以這兩個領域都算是她的專業吧!思維的話可以分為結構化思維和創造性的思維,而這其中是有些方法論可以運用來思考的。像是結構化思維可以用常用的架構來輔助思考,或是透過歸納法從資訊找出有意義的內容等等。除了思維,定義問題也是其中一個很重要的因素,我們要清楚自己要解決什麼問題,而且不是所有問題都值得被解決。我以前常常都會想說每個遇到的事情都要全力去做,不這樣做的話就好像是沒有負責任,但是作者反駁這樣的想法,應該是要看CP值,高的才需要全力找最佳解,一般的就只要能處理掉即可。溝通部分則是描述有條理發表言論、與人找話題聊天的方法,這邊是我的弱項,應該可以再好好地吸收消化一下。

職涯規劃的部分有提到可以使用個人商業模式畫布,這個概念我在「程序員跳槽全攻略」看過,不過當初自己做職涯規劃只有幾年後要達到什麼目標,學到什麼能力之類,結果列完後還是沒有去做到,應該說連去回顧都沒有了。作者強調說我們做職涯規劃不該強調目標,而是要強調過程、實現的路徑是什麼,這樣的概念相對來說也比較踏實,不會只是空中畫大餅而已。書中最後情緒的部分有個概念讓我非常受用:面對所謂的性格缺陷,最佳策略不是對抗,而是找應對方式。我很清楚自己的弱點,包括不擅長社交、不喜歡在人多的地方、不喜歡引人注目,但是有時還是會想說要克服自己的缺陷,努力去改變。然而作者的說法是性格是我們的天性,需要花很多資源去改變,因此與其去改變,不如想想如何提高其他的能力來彌補這個缺陷。例如社交要做得好有很多因素,性格只是其中一項,我們可以強化其他因素來達到同樣結果。這個概念在前面的天賦也有提過,不要想著要彌補自己的弱點,而是將彌補劣勢的時間拿來強化自己的天賦,發揮他並且用其他能力彌補弱勢的部分。這個概念就如同巴菲特的雙目標清單系統(Two-List System)一樣,集中資源在自己的目標、強項,不會變成樣樣通樣樣鬆。

本書的內容從我的角度來看,雖然還是有些自己並不是很認同或是覺得有邏輯不清的地方,但是這本書提供給我們一個可以去嘗試的方法,利用這個方法來嘗試改變自己,而我們可以基於這些方法開始思考要怎麼建立屬於自己的方法論,而不會遇到職業、人生的問題時總是滿頭霧水,不斷窮緊張。透過不斷參考、試錯,就可以找到更適合的方法來面對自己的人生。

會知道這本書是因為之前有在追蹤該作者的部落格,該部落格是分享作者看完書後的讀後心得,他看的書品質都算是很高,有時候我也都會參考他的書單、心得來決定是否要看這本書。後來作者把他看的書做一個總結,寫成一本關於學習的書,也就是這本「深度學習的技術」。原本是有點懶得買,因為並不是實體而且感覺轉帳什麼的很麻煩,不過在同事的勸誘下還是買了。從結論來說我覺得這本真的值得這個價錢,畢竟作者的論述很清晰、有條理,而且都有引用其他著名書籍內容,某種程度上也是集大成了,可以從作者的方法再進一步學習、研究出屬於自己的學習方式。

作者把整個學習過程分成五個階段:記、懂、網、拓、活。記是記憶的意思,講了幾個科學上實驗研究很有用的記憶方法,包括「提取練習效應」、「間隔效應」、「交錯效應」、「生產效應」、「變動效應」等等。但我從中學到的是記不是要強調記憶本身,而是要練習「提取記憶」這件事,所以這些方法都是訓練自己在不同情況下都能夠順利提取記憶,確保自己真的有記憶牢靠,所以也難怪背誦時只是不斷重複閱讀是效率極差,而透過各種提取,如講出來、寫出來、測驗等等記憶的效率會再高一點。這點我應該可以拿來在學習單字上試試做些驗證。

懂的部分就是要讓自己記憶力最大化,有幾個方式:相鄰可能(複利效應)、發散模式(利用散步等時間思考事情)、自然頻率(找適合人類的學習方式,如故事、思想實驗)、透徹程度(以教為學)、工作記憶(善用紙筆)。內容就不一一多提,但是我想最重要的是人類在演化上、構造上還是屬於生物,所以學習上還是有一定生理限制,這些就是讓我們可以用比較輕鬆的方式理解知識。

網則是強調知識的排列重要性,作者強調了碎片化學習不是不好,畢竟很多時候都只能利用零散的時間來學習,但是最重要的是我們需要把知識進行排列,因為往往知識的排列本身比起知識點是更為重要的。要構成知識網有兩個支柱,分別為知識排列以及刻意練習,知識排列算是我們對外顯知識(例如物理學、經濟學等理論)的人工佈線,透過佈線構成自己的知識架構,而刻意練習則是用在學習內隱知識(如開車、游泳等等難用文字描述的領域),強化我們網狀架構的廣度、強度和密度。這邊不得不提刻意練習真的自從出版後就被各種提到,而且都是我覺得值得一看的好書,好的方法果然是會被其他好書不斷重複提起,這也驗證了重要知識是很容易在生活中重複出現的。

前面都在講怎麼學習,但是學習什麼也是很重要的。拓的部分在講知識是有品質的差別的,要如何辨別知識對自己的價值有三個方面:正確性(過濾機制)、多樣性(跨領域學習)、創造性(思想孵化器)。我認為正確性講的是人類總是有心理學上的弱點,而透過第二層思考就可以盡可能避免被錯誤的知識誤導。多樣性則提到了蒙格的多元思維模型,透過學習多個學科最重要的模型,破除學問間的壁壘,可以解決更多困難的問題。順帶一提,蒙格的窮查理的普通常識也是被各種推廣的好書,雖然內容並不是很有條理的方法論(比較多是演講形式),但背後的思想可是備受推崇,之後可能也會想收藏一本當傳教用(誤)。最後的創造性則是強調透過寫作讓自己的思維可視化,並且促進更進一步的思考。

最後的「活」先提到了要時時注意一石多鳥,學習要用最有效率的方式學習,不論是閱讀還是做筆記都是,找到好的方法,並且使用它。而更重要的是學了知識就是要用,我很喜歡書中的這句話「知識就像是金錢一樣,不花就等於不曾有過」,作者建議使用知識的方法是開始屬於自己的個人項目,並且給了一些找到與實踐個人項目的方法和原則。我是很認同他的想法,畢竟我也常覺得看完書後好像就只是這樣,沒有真正改變了什麼。也許我也該從一個個人項目開始發揮我所學到的內容。

這本書原則上我非常地推薦,是值得一讀的好書。先不論書中方法對錯,光是作者把各個書的精華統整出自己的知識架構就已經值回票價了。當然,我不是完全認同書中的方法,但是我覺得書中的統整確確實實是改變我一些學習的方法。所以我的建議是不要完全照抄書中的方法,而是要善用作者的統整,建構出屬於自己的學習習慣,這樣才算是最大化利用這本書。

總覽

根據DEVCORE,相關HTTP header可以如下分類

  • 防禦 XSS:
    • Content-Security-Policy
    • Set-Cookie: HttpOnly
    • X-XSS-Protection
    • X-Download-Options
  • 防禦 Clickjacking:
    • X-Frame-Options
  • 強化 HTTPS 機制:
    • Set-Cookie: Secure
    • Strict-Transport-Security
  • 避免瀏覽器誤判文件形態:
    • X-Content-Type-Options
  • 保護網站資源別被任意存取:
    • Access-Control-Allow-Origin
    • X-Permitted-Cross-Domain-Policies

防禦 XSS

Content-Security-Policy

  • 原理:
    • 用來控制不要讀取外部不可信賴資源,可以防止XSS或injection
  • 啟動方式:
    1
    Content-Security-Policy: policy # policy代表描述你的CSP的策略
    • 範例
      1
      2
      3
      4
      5
      6
      # 所有內容都來自同一個地方
      Content-Security-Policy: default-src 'self'
      # 比較複雜的設定,不擋image來源,但是設定media和script的來源,注意後方設定會蓋掉default-src的設定
      Content-SecContent-Security-Policy: default-src 'self'; img-src *; media-src media1.com media2.com; script-src userscripts.example.com
      # 推薦設定:因為預設會擋html裡有js,style,但是大部分都會用到,所以要加上unsafe-inline
      Content-Security-Policy: default-src 'self' 'unsafe-inline'
  • 可參考
  • 原理:
    • http only確保javascript無法直接存取cookie。
  • 啟動方式:
    • 只要在Set-Cookie的header加上HttpOnly就可以生效了。

X-XSS-Protection

  • 原理:
    • 這是IE引進的功能,可以檢查XSS攻擊,不過firefox不支援。基本上CSP已經提供足夠防禦,但是可以讓不支援CSP舊版瀏覽器有比較高的安全性。
  • 啟動方式:
    1
    2
    3
    X-XSS-Protection: 0   # 禁止XSS過濾
    X-XSS-Protection: 1 # 允許XSS過濾,遇到XSS會清除頁面
    X-XSS-Protection: 1; mode=block # 允許XSS過濾,遇到XSS會阻擋頁面加載
  • 可參考:

X-Download-Options

  • 原理:
    • 在IE8加入了這個選項,防止使用者下載檔案的時候點選直接開啟,避免執行執行了程式而且沒有在下載管理員留下紀錄的問題。
  • 啟動方式:
    1
    X-Download-Options: noopen
  • 可參考

防禦 Clickjacking

X-Frame-Options

  • 原理:
    • 控制frame和iframe顯示頁面的規則,不讓別人可以內嵌頁面。
  • 啟動方式:
    • 在header加上X-Frame-Options: XXX,XXX可以是
      • DENY:禁止frame頁面
      • SAMEORIGIN:允許frame顯示同一網站頁面
      • ALLOW-FROM url:允許frame顯示某一網站頁面
        1
        X-Frame-Options: SAMEORIGIN

強化 HTTPS 機制

  • 原理:
    • 強制讓cookie必須要在https的情況下才能傳輸
  • 啟動方式:
    • 只要在Set-Cookie的header加上Secure就可以生效了。

Strict-Transport-Security

  • 原理:
    • 當使用者用http連線,強制轉成https連線,這個選項只有在https連線的情況下才有用,如果是http會被忽略(因為可能有MITM)
  • 啟動方式:
    1
    2
    3
    Strict-Transport-Security: max-age=expireTime [; includeSubdomains]
    # max-age=expireTime: browser要記住這個網站要用https連線的時間
    # includeSubdomains: 哪些subdomain也都要同樣設定
  • 可參考

避免瀏覽器誤判文件形態

X-Content-Type-Options

  • 原理:
    • 告訴client要遵守Content-Type的MIME設定,不要自行偵測,管理者必須要確保自己的設定是沒有錯誤的。
  • 啟動方式:
    1
    X-Content-Type-Options:nosniff
  • 可參考

保護網站資源別被任意存取

Access-Control-Allow-Origin

X-Permitted-Cross-Domain-Policies

參考

文件

開啟docx, pttx, xlsx

  • Office(word, excel, powerpoint, visio):Windows和MAC上還是用就微軟的工具比較方便。
  • LibreOffice:Linux上的話可以用這個,但是其實我是不推薦在Linux上做類似的事。

開啟pdf

  • Foxit:適用於Windows、Linux,可用來取代Adobe Reader來看pdf檔案。
  • MAC的話其實用預設的預覽程式就足夠了。

筆記

下方筆記軟體都是可以跨平台的

  • QOwnNotes:支援Markdown、tags和資料夾的筆記軟體,我會搭配dropbox來進行同步,可參考官網
  • evernote:最常見的筆記軟體,但是不支援完整Markdown,我只用來記雜事用。
  • GitBook:之前有用這個來做筆記,但是反應速度有點慢,不推薦。

特殊文件

  • texmaker: 專門處理Latex的工具
  • Poedit: 專門處理po的工具

網路功能

browser

  • Chrome
  • Firefox

檔案交換

  • Dropbox:支援跨平台

FTP client

  • FileZilla FTP:支援跨平台。

遠端連線

  • TeamViewer:支援跨平台。

ssh client

下面只介紹Windows的部分,因為Linux和MAC都可以用ssh或scp指令連線

  • putty(MTPutty)
  • pietty:支援Big5的putty版本
  • winscp:如果要用ssh來取得檔案用這個很方便。

VPN

  • FortiClient SSL VPN:我只用過這個,而且還是舊版的,我記得是每個OS都可以使用,未來可以再研究看看。

TFTP

只支援Windows,如果是Linux和MAC是可以用command line下載TFTP。

  • Tftpd32:如果要自架TFTP Server的好工具,可參考官網

社交軟體

  • Skype
  • LINE
  • Telegram

程式

文字編輯器

一樣只介紹Windows,其他平台建議直接用vim

  • notepad++:非常輕量級的文字編輯器,非常好用。
  • gvim:Windows上的vim,但是有時候並不是那麼好用。

git

其他平台我是都用command line,但是也許可以再找找有沒有好的圖形化介面

  • Git / Tortoise Git:用來追蹤code必備工具

虛擬化

  • VirtualBox:跟其他虛擬機的差異是他是Open Source,但是穩定度比起來還是有差。
  • Docker:我是比較少用,但是用的對的話,其實是個好工具。
  • qemu:當沒有開發板的時候挺好用的

interpreter

  • Python:可以用來執行我們寫的簡單小程式。

compiler

  • CodeBlock:要測試code可以在上面compile看看,但是不夠輕量,有時候不如開Linux虛擬機測試比較快。
  • gcc:MAC和Linux。

Editor

  • vscode:好用的編輯器,而且跨平台,支援許多套件,但是對C/C++的支援比較低。

debug工具

  • Wireshark:抓封包專用,三個平台都適用。

以下都是Windows上的工具,還沒找到其他平台的版本

  • iReasoning:可以用來做SNMP query。
  • HxD:看檔案的二進位。
  • WinMerge:比對code專用。
  • Colasoft Packet Builder: 修改pcap
  • Colasoft Packet Player: 重放packet

影音

播放音樂

  • iTunes:適用Windows和MAC,播放、整理音樂的工具。

影片

  • SMPlayer:適用於Windows和Linux的播放器
  • IINA:適用於MAC。

剪輯影片

  • 威力導演:剪影片專用,適用於MAC

燒錄

目前找到的都只適合Windows

  • Free Make Vedio Converter:燒DVD專用。
  • burnaware:可以燒iso和音樂CD。
  • DVDFab Virtual Drive:模擬虛擬光碟機。

轉檔

  • 格式工廠:如果要轉檔的話非常好用。

系統

套件管理

  • Linux就隨Distro而有不同
  • MAC的話可用homebrew
    • brew的使用方法如下
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      # 更新list
      brew update
      # 找套件
      brew search [套件名]
      # 檢查哪些套件過時
      brew outdated
      # 更新套件
      brew upgrade
      # 清除cache
      brew cleanup
      # 找官網
      brew home

優化電腦

  • WiseCare 365:適合Windows
  • Magican、AppCleaner:適合MAC

監控系統狀態

  • CrystalDiskInfo:監控硬碟狀態,適合Windows
  • smartd:Linux可用這套軟體看硬碟狀態。
  • menumeter:看系統整體資訊的付費軟體,適用MAC。

解壓縮工具

  • 7-zip:適合Windows
  • The Unarchiver:解壓縮工具,適用MAC
  • CleanArchiver:壓縮工具,適用MAC

連接手機

  • Android File Transfer:在MAC上如果要連android手機必備

CLI tools

MAC可以用iterm取代原來terminal

Editor

  • vim

shell

  • zsh
  • tmux
  • mosh:可以保持連線不要斷掉,當網路一旦恢復就會馬上連回去。

version

  • git
  • tig

program

  • ipython
  • irb
  • silversearcher-ag:找字串
  • cloc:算程式碼數量
  • ctags
  • astyle:coding style工具

system

  • lynis: 檢查系統安全性
    • 使用方式lynis -c
  • smartmontools:讀取硬碟資訊
  • mtr:看網路狀態,ping和traceroute的結合
  • tree:可以列出目錄
  • htop、iotop、iftop:各類的top
  • httpie:command是http
  • ncdu:加強版的du
  • tldr:簡化版的man
  • trash-cli:trash-list, trash-rm, trash-put, trash-empty, restore-trash
  • fd:更簡單的find

hacker

  • nmap:掃描網路上的機器
  • hydra:暴力破解的軟體
  • openssl:加解密工具
  • sqlmap:SQL injection工具

others

  • qpdf:對pdf檔做一些操作
  • gnuplot:畫圖的工具
  • youtube-dl:下載youtube
    • 使用方式youtube-dl -F [URL]:看有哪些格式
    • youtube-dl -f 136/mp4 [URL]:選擇格式下載
  • ffmepg:轉換影片檔
  • GPG:認證工具
  • irssi:IRC工具

我之前一直想要自己寫 blog,可以留下些記錄,但是一方面不想要自己架 server,管理有點麻煩
另一方面又希望可以有 markdown 的功能,而這是 Google 的 blogger 所欠缺的,後來發現可以使用 hexo+Github 架設自己的 blog,對我而言是最佳選擇
Github 讓我不用自己架 server,hexo 讓我可以快速有個漂亮的介面,而且還可以用 markdown 來寫 blog

第一次安裝

這邊一開始要先安裝好 git 和 npm,兩者的使用就不在這邊多提了。

  1. 先在 GitHub 上創立一個新的 repo,像我的話就是 evshary.github.io
  2. clone 下來並且創立 main 和 source 兩個 branch,這兩個 branch 分別有不同用途,main 用來放顯示的網頁,source 用來放產生網頁的原始檔
  3. 首先先切到 source 的 branch,然後開始安裝 hexo (當然要先裝好 npm)
    1
    2
    3
    4
    5
    6
    7
    # 安裝 hexo command line tool
    npm install -g hexo-cli
    # 安裝 deployer
    npm install hexo-deployer-git --save
    # 初始化
    hexo init
    npm install
  4. 修改 _config.yml 的 deploy 參數,branch 改為 main,這個代表的意思是我們會把產生的網頁放到 main 這個 branch 上
  5. 執行 hexo g 來產生顯示的網頁
  6. 當我們修改好 blog,就可以把 source 的 branch commit 並且 push 上 GitHub
  7. 最後執行 hexo d 就可以上傳網頁了,這個動作代表著把 main push 上 GitHub
  8. 未來的使用都是在 source 的 branch 下 commit 並 push,然後才用hexo d 上傳

備註:hexo d的上傳可以用 GitHub Action 取代,只要 source branch 有更新,就會自動在 main branch 產生 blog 結果。相關設定可以參考這邊的範例

重裝

未來要在新電腦重建環境就不用像第一次那麼麻煩了

  1. 首先在新電腦把 blog 的 repo clone 下來並切到 source 的 branch,如下面指令
    1
    git clone -b source git@github.com:[你的github帳號]/[repo名稱].git
  2. 重新安裝相依套件,然後就可以直接開始使用了
    1
    2
    npm install -g hexo-cli
    npm install

使用

  • 建立新文章
    一開始最重要的事怎麼建立新文章

    1
    hexo n "文章主題"

    這時候會在source/_posts/底下新增一個md檔案,打開它就可以開始寫blog了

  • 根據 markdown 產生 html 頁面

    1
    hexo g

    產生結果會在 public 資料夾下

  • local 端預覽
    寫完之後的當然要產生頁面來看自己寫的如何,下面這個指令可以建立測試的 server

    1
    hexo s

    這時候開瀏覽器連線 http://localhost:4000 應該就可以連上

  • push 到 GitHub 上

    1
    hexo d

主題

使用 hexo 當然最重要的是漂亮的主題囉,hexo 的 GitHub 上已經有提供許多主題推薦,可以參考 Themes
不過我個人覺得 theme-next/hexo-theme-next 比較好看,所以就用這個了
官網推薦的安裝方法有兩種 ,一個是用 npm,另一個是直接 clone repo,為了方便未來升級管理,這邊使用 npm 的方式

  1. 用 npm 下載 hexo-theme-next,套件會出現在 node_modules 中
    1
    npm install hexo-theme-next@latest
  2. 設定檔的部份會先找當前目錄下的 _config.next.yml,所以我們先複製一份設定檔出來
    1
    cp node_modules/hexo-theme-next/_config.yml _config.next.yml
  3. 接著在 hexo 的設定檔 _config.yml 修改 theme 關鍵字,也就是剛剛命名的 next,這樣就順利完成了
    1
    theme: next

設定檔

主要會修改到的設定檔有兩個:

套件

當然 hexo 提供很多套件,我目前用到的是下面這兩個

google analytics

可參考 如何讓google analytics追踪你的Hexo Blog
使用方法很簡單,這個功能在 theme 中已經內建,只要開啟即可

  1. 先打開 _config.next.yml
  2. 找到下列字串
    1
    2
    google_analytics:
    tracking_id:
    在 tracking_id 後面填上自己申請的 google analytics ID 就可以了。

Disqus的留言板功能

可參考 [Hexo] 加入 Disqus 讓 Blog多個留言功能
部署在 GitHub 的 hexo 沒有讓訪客留言的功能,所以這時候就需要第三方的整合型留言板 Disqus 了
這個也是跟 theme 綁一起的

  1. 開啟 _config.next.yml
  2. 找到下列字串
    1
    2
    3
    disqus:
    enable: true
    shortname: evshary
  3. 確認 enable 為 true,然後在 shortname 填上自己在Disquz註冊的short name就可以囉!

LocalSearch 的搜尋功能

我們如果要 blog 支援搜尋功能,可參考 Hexo博客添加搜索功能 ,下面列出應該要做的步驟

  1. 首先要安裝 hexo-generator-searchdb 套件
    1
    npm install hexo-generator-searchdb --save
  2. 接著在 _config.yml 新增如下設定
    1
    2
    3
    4
    # Search
    search:
    path: search.xml
    field: post
  3. 開啟_config.next.yml,修改 enable 設定
    1
    2
    3
    # Local search
    local_search:
    enable: true
  4. 最後重新生成啟動即可
    1
    2
    hexo clean
    hexo s -g

如果搜尋功能不斷轉圈圈

通常會有一種情況搜尋功能會有問題,就是產生的search.xml有文字編碼錯誤

  1. 先檢查 search.xml 的語法,可使用 Validate an XML file 這個線上網站
  2. 網站會告訴你哪邊有錯誤的編碼,可以直接進去修改
  3. 如果使用 vscode 的話可以從設定啟動 renderControlCharacters,就會顯示錯誤的字元了
  4. 如果有必要可以直接把該字元複製並且使用全域搜尋並修正(因為我們沒辦法打出該字元)

詳情可參考 HEXO-NexT的Local Search轉圈圈問題

RSS

如果要在 hexo 上加上 RSS 訂閱,需要使用 hexo-generator-feed 套件

  1. 先安裝 hexo-generator-feed
    1
    npm install hexo-generator-feed --save
  2. _config.yml 內加上如下內容
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # RSS
    feed:
    type: atom
    path: atom.xml
    limit: 10
    hub:
    content:
    content_limit:
    content_limit_delim: ' '
  3. 最後重新生成啟動即可
    1
    2
    hexo g
    hexo s

可參考 为hexo博客添加RSS订阅功能

增加 live2d

  1. 先安裝必要的 npm 包
    1
    2
    npm install hexo-helper-live2d --save
    npm install live2d-widget-model-shizuku --save
  2. 設定 _config.yml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # live2d
    # https://github.com/EYHN/hexo-helper-live2d
    live2d:
    enable: true
    scriptFrom: local
    pluginRootPath: live2dw/
    pluginJsPath: lib/
    pluginModelPath: assets/
    tagMode: false
    debug: false
    model:
    use: live2d-widget-model-shizuku
    display:
    position: left
  3. 最後重新生成啟動即可
    1
    2
    hexo g
    hexo s

可參考 用Live2D让看板喵入住你的Hexo博客吧(^o^)/~

不過這邊提一下,EYHN/hexo-helper-live2d 已經沒有再更新了,如果上到 GitHub,可能會有些套件安全疑慮,以後可能需要找些替代套件了。

這邊記錄一下我看clean code的筆記整理
不過我得承認其實書裡很多做法我是不太贊同的,例如function要壓在20行以內這種
在C要這樣實踐很有難度,而且我看很多open source的project也都沒有遵循這樣的規範
但是這本書還是很有參考價值的,至少會讓自己反省寫code時有沒有犯了這些問題。
書中提到一個概念:

程式設計師有大半時間花在看code,因此好閱讀的code對快速寫程式是有幫助的

我想這就是我從書裡得到最大的收穫吧!

有意義的名稱

  • 讓程式碼的隱含性高,名稱和意圖符合

  • 避免誤導
    讓變數不會相似高(autocomplete好找)
    像是l和1,0和O

  • 產生有意義的區別
    例如a1,a2、ProductInfo,ProductData,或是table, variable等等都看不出差別

  • 使用能念出來的名稱
    人類大腦有一大部分都專注在字詞的概念,字詞是可發音的,方便理解
    方便同事間彼此溝通

  • 使用可被搜尋的名字
    使用單一字母變數或是數值常數很難被找到
    例如MAX_CLASSES_PER_STUDENT7還要好找,命名變數e幾乎每段程式碼都會用到
    一般來說,長命名比短命名好,命名長度應該和scope作對應,範圍越大的應該要用比較容易識別的名字

  • 避免編碼
    這邊的編碼是指形態或視野,作者不推薦使用匈牙利標誌法,因為那是早期編譯器不會進形型態檢查,但是現在編譯器已經會做了,所以不需要浪費時間做這件事

    可是有時候在看code,有提示還是比較容易記憶的,見仁見智

  • 成員的字首
    不需要在變數前加上類似m_

  • 類別方法命名
    類別:要用名詞來命名
    方法:用動詞命名,而且accessors要用get開頭、mutators用set、predicates要用is

  • 使用一致性的詞彙
    例如取得方法不要同時有get, fetch, retrieve

  • 將命名放在有意義的上下文
    例如state要配合address看才會知道是州,如果沒辦法配合上下文那就手動加上前綴,例如addrState

  • 不要添加過多無意義資訊
    例如每個變數名稱都加上特定前綴,會讓IDE無法幫你找變數

函式

  • 函式要非常簡短,盡量低於20行
  • 函式內的縮排也不要大過一兩層
  • 做一件的函式是無法被區分成不同段落的,如宣告區、初始區等等
  • 降層準則:程式閱讀應該是由上而下敘事,希望每個函式後面都進接著下一層次的概念。
  • 函式應該做一件事,他們應該把這件事做好,而且他們應該只做這件事。
  • 函式參數最多不要超過三個,越少越好,如果需要超過三個,可以考慮使用物件代替
  • 越多參數要測試會越困難,而且參數有傳達概念的能力,讀者必須去了解它
  • 另外不要用輸出型參數,用回傳值
  • 分離指令和查詢(set和get)
  • 使用例外處理來取代回傳錯誤碼,讓使用者不需要一遇到錯誤碼就必須馬上處理錯誤
  • 結構化程式:雖然Dijkstra提到在一個函式內只能有一個return,不要有break和continue,以及goto,但是作者認為在小函式時可以適當使用,但是不應該用goto,因為只有大函式goto才有用處

註解

  • 適當使用註解是用來彌補我們用程式碼表達意圖的失敗
  • 沒有提供比程式碼更多資訊或是反而誤導的註解就是壞註解,當然過多資訊也是
  • git已經提供修改紀錄,不該寫在註解中,包括程式碼的註解也應該拿掉

適合用註解的時機

  • 法律型註解
  • 資訊型的註解
  • 對意圖的解釋
  • 闡明
  • 對後果的告誡
  • TODO
  • 放大重要性
  • Javadoc

編排

每個檔案應該大部分用200行,最多不超過500行

垂直距離

  • 程式中,應該要用垂直空白區分思緒(兩個函式間),而且如果兩個函式密且相關的話,不要放太多註解在兩者之間
  • 變數宣告:變數的宣告應該盡可能靠近變數被使用的地方
  • 實體變數(instance):盡量集中在最上方或最下方,方便被查詢
  • 相依的函式應該放在同一區塊,相依性越高,彼此的垂直距離就要越短

水平距離

  • 通常程式設計師偏好短的程式碼,不一定要80,但不要超過120

  • 水平空白也可以用來表示優先權,例如乘法之間不要有空白,加減法則要

  • 水平的對齊也沒有必要,因為自動化編排程式會毀掉這樣的對齊,而且這樣會讓人忽略變數型態,只關注上下的對齊

    不過像define我就覺得有必要對齊,這樣方便觀看

    1
    2
    int    abc;
    float def;
  • 不要使用一行文,包括單行while加上分號,很容易搞錯

    這邊注意if如果是一行,也許加上大括號會比較好,常常會在下方加上其他敘述卻忘了加括號,這樣會有不同的行為

物件及資料結構

不要幫每個private都加上get, set,應該要思考怎樣才能隱藏更多資訊
例如

1
2
3
FuelTankCapacityInGallons(){
double getGallonsOfGasoline();
}

會差於

1
2
3
publice interface Vehicle{
double getPercentFuelRemaining();
}

因為使用者知道怎麼計算油量

資料與物件有反對稱性

結構化的程式碼容易添加新函式,而不需變更原有的資料結構
物件導向的程式碼容易添加新類別,而不用變動已有函式

錯誤處理

  • 如前所說,作者建議用例外事件而非錯誤碼
  • 不要使用java中的checked exception,因為如果底層函式被修改,會強制所有被呼叫的函式都要做錯誤檢查,會破壞函式封閉原則
  • 不要回傳null,會讓使用者需要做額外判斷
  • 傳遞null也會讓函式需要做額外判斷

邊界

當使用第三方軟體時,可以考慮製作一個介面來與第三方API銜接,這樣如果有大改動時,我們只需要修改介面即可

單元測試

TDD(Test-Driven Development)有三大準則

  1. 在撰寫一個單元測試前,不可以撰寫任何產品程式
  2. 只撰寫剛好無法通過的單元測試,不能編譯也算無法通過
  3. 只撰寫剛好能通過當前測試失敗的產品程式
    以上準則可以讓程式設計師被限制在30s的循環:測試程式和產品程式是一起被撰寫的。

一個測試一個assert,但作者認為不需要嚴格遵守,盡可能少即可
一個測試一個概念

FIRST

  • Fast:測試要夠快,能夠快速執行,讓人有意願去執行
  • Independent:測試程式不應該互相依賴,會讓人更難尋找錯誤
  • Repeatable:可以在任何環境下執行
  • Self-Validating:要輸出boolean告知程式成功或失敗,而非去看log主觀判斷
  • Timely:單元測試要再寫產品程式之前,這樣才能寫出可被測試的程式

類別

  • Single Responsibility Principle(SRP):單一職責原則
  • 一個類別或模組應該只有一個被修改的理由
  • 保持類別的凝聚性(每個變數被多個method使用):這樣會得到許多小class

系統

軟體系統相較於實體系統來說是獨特的,如果我們持續保持適當的關注點分離,軟體系統的架構就能遞增地成長

羽化

遵守四個原則:

  1. 執行完所有測試:有測試就會消除整理程式碼會破壞程式的恐慌
  2. 沒有重複的部分
  3. 表達程式設計師的本意
  4. 最小化類別和方法的數量:這條守則的優先權是最低的

平行化

  • 物件是處理過程的抽象化,執行緒是排程的抽象化
  • 平行化是去耦合的抽象化,讓「做什麼」和「什麼時候做」分開
  • 另外也可以解決response time和throughput的限制

迷思

X 平行化總是能改善效能
X 撰寫平行化程式並不需要修改原有的設計
O 平行化會帶來額外負擔
O 正確的平行化是複雜的
O 平行化的錯誤通常不容易重複出現

平行化防禦方法

  • 單一職責原則(SRP):保持平行化程式碼與其他程式有清楚劃分
  • 限制資料視野:嚴格限制共享資料的存取次數
  • 使用資料的副本:複製唯讀副本,減少共享資料次數
  • 執行緒盡可能獨立運行
  • 另外也要保持同步區塊的簡短,因為cost高
  • 優雅的關閉平行化程式碼,注意能讓子thread可以關閉

測試

  • 不要因為系統後來通過測試就忽略失敗,因為未來會有越來越多錯誤建立在有缺陷的基礎上
  • 先讓非執行緒的程式碼可以運作,不要兩者同時debug
  • 讓執行緒是可以自我調校
  • 執行比處理器還多的執行緒,bug會越容易找到
  • 在不同平台執行
  • 調整程式碼,使其產生失敗

Bad Smell

註解

  • 無效、沒意義、不適當的註解
  • 被註解掉的程式碼

開發環境

  • 需要多個步驟建立專案或系統
  • 需要多個步驟進行測試

函式

  • 過多參數
  • 輸出行參數
  • 旗標參數
  • 被遺棄的函式

一般狀況

  • 同份原始碼有多種語言
  • 明顯該有的行為沒被實現(最小驚奇原則)
  • 在邊界上的不正確行為:不要依賴直覺,為邊界條件寫測試程式
  • 無視安全規範:不要關閉編譯器的警告
  • 重複的程式碼:這是最重要的規範之一
  • 在錯誤抽象層次上的程式碼:高層次概念都要在基底類別
  • 基底類別相依於其衍生類別
  • 過多資訊:應該要把暴露在介面上的資訊減少
  • 被遺棄的程式碼
  • 垂直分隔:如前所示
  • 不一致性:維持命名一致性
  • 雜亂程式:保持原始檔整潔
  • 人為耦合:不要將變數隨意宣告,然後就留在某處
  • 特色留戀:類別的方法應該只對同一類別裡的變數和函式感興趣,不應該操作其他類的變數或函式
  • 選擇型參數:在函式尾端加上true, false
  • 模糊的意圖:盡可能讓程式碼有表達力
  • 錯置的職責:像是要把常數放在讀者認為他應該要在的地方
  • 使用具解釋性的變數:將計算過程拆解成富有意義名稱的暫存變數
  • 函數名稱要說到做到
  • 了解演算法:不是調整函式做到想讓其做到的事,而是確定解決方法是正確,並且讓函式明顯透露出是怎麼運作的
  • 用多型取代if-else和switch-case
  • 遵循標準的慣例:用團隊的慣例
  • 用有名稱的常數取代魔術數字
  • 要精確:不要有模擬兩可的程式碼,精確表達該函式要做什麼
  • 封裝條件判斷:if(shouldBeDeleted(timer))取代if(timer.hasExpired() && !timre.isRecurrent())
  • 避免否定條件判斷
  • 函式只該做一件事
  • 不要隨意:如果程式碼保持一致性,這樣後來修改的人就會按造前面的原則改
  • 封裝邊界條件:如果a+1常被用到,那就用b=a+1取代,這點跟refactoring似乎不太一樣

命名

  • 選擇有描述性的名稱
  • 在適當的抽象層次使用適當的名稱
  • 越大的scope就要用較長的名稱

測試

  • 不足夠的測試程式
  • 不要跳過簡單的測試
  • 對程式錯誤處進行詳細測試
  • 測試要夠快速

前言

其實我一直對code review有點好奇,到底有什麼樣的好處。
所以統整了些資料,研究看看實行的好處以及如何實行code review。

重要:這篇只是我想理解code review方式而整理出來的文章,不一定真的實用,之後會隨著我經驗增加而更新內容

好處

  1. 品質提升:開發者太熟悉流程了,可能會有盲點,其他人可能可以幫忙找到邏輯問題。
  2. 更容易維護:其他人幫忙看code可以確保程式的可讀性,不會只有開發者才看得懂,開發者開發時也因為會有人來看,所以會思考我這樣是否可以讓review的人看懂邏輯。
  3. 同步文化、設計理念:確保程式有符合團隊開發的風格、coding style、API使用習慣等等,也比較不會有開發了功能跟原來架構設計理念有落差的情況。
  4. 經驗傳承和相互學習:資深員工把經驗傳給新進員工,或是大家彼此間可以學到寫程式的小技巧。
  5. 備份功能:確保至少有兩個人知道code的意思。

成本

  • 開發時需要多花費時間在上面code review上,但長遠來說會減少maintain時間
  • 要有正確的心態來review,不然會造成團隊氣氛不佳

心態

  • code和人是分開的:我們是針對code做討論,而不是質疑人的能力。
  • 相互信任:信任團隊沒人會故意寫爛code,有問題是可能只是沒想到而已。
  • 相互尊重:
    • 討論過程中是相互學習的關係,而不是監視和監視的關係。
    • review者討論態度語氣不能太尖銳,被review者也要能接受合理的意見
  • 相互學習:做code review不只是要維護品質,更重要的是大家可以彼此學習,學會更好的技巧。

方法

前置作業

  • 說明code review規則,以及建立正確的心態
  • 事先訂定公司開發的文化,如coding style,命名規則
  • 使用工具在處理機械化作業,如coding style統一,減少人為介入

開發功能前

  • 開發時間需要預估code review的時間
  • 先規劃如何將大功能切成小部分:
    • 控制在reviewer 15min內可以看完的程度,這樣reviewer可以在工作一段落時稍微看一下,不佔用太多時間
    • 如果功能出了大問題,也可以把風險控制在最小

review前

  • review前要先準備好環境,可以demo或讓reviewer測試
  • 如果有使用分析工具,先使用工具產生報表
    • review時可以針對上面的重點討論
    • 減少review的effort

review中

  • 讓reviewer主導review的過程,這樣才能發現盲點
  • code review時間不要超過半小時
  • 利用checklist來檢查
    • 功能需求是什麼?設計方式是否有達到目的?
    • 是否可以做未來擴充?
    • 是否足夠安全?有沒有邏輯漏洞?
    • Error handling和corner case是否都有處理好?
    • 程式是否易讀?複雜地方是否有註解?可以再精簡嗎?
    • 有符合團隊coding style嗎?命名好嗎?有沒有通過工具測試?
    • 效能是否可以再提升?
  • review過程不改code,用todo list先記錄

review後

  • 要留下reviewer是誰,不是要抓戰犯,而是當開發者不在時,可以知道有誰懂這段code
  • review後要留下紀錄提供學習使用
  • 定期開會評估code review流程和效用
    • review的方式要不要調整?
    • 工具是否要調整?
    • checklist是否要更新?

輔助工具

下面工具只是先整理起來,我並沒有每個都用過,等真正用過再來寫心得吧!

如何實際落實

通常要在運作一段時間的團隊加入新機制並不是那麼的容易,特別是怕會影響正常業務。
所以可以試試沙盒的概念,先少部分的人開始測試使用,
而且也不要一下子就把所有機制加上去,以不一下子造成過多改變為主,慢慢調整
最後相信可以找到適合團隊的做法。

可以調整的選項

code review的基本概念是要讓其他人來看開發者的code,以客觀角度檢視,藉此提高品質和增進彼此相互學習
所以只要能達到這個目標的手段其實都是可以接受的,重點是要找到適合團隊的方式
這邊有幾項可以思考的方向:

  • review的方式:網路上找到大部分的方式都是git的Pull Request功能,可以線上直接看code,不過或許直接到對方位置看也是個選項。
  • review的頻率:這個可以隨團隊開發內容的性質作調整
  • review的大小:有些review是多人一起,這個比較適合有很多新進人員,需要一起建立開發文化。不然一般是用peer review即可。

如何評估效用

當然code review一定是好處大於壞處才會讓大家採用,那要怎麼評估好處部分呢?
可以從下面幾個方向來想:

  1. 執行前後,bug減少的數量(這是品質部分)
  2. 執行前後,團隊多花費的時間(這是成本部分)
  3. 大家在執行後的感想?是否有所學習?(畢竟學習這種東西很難用數據衡量)
  4. 在code review中發現哪些問題?(bug減少數量如果不好統計,可以看有哪些潛在問題被發掘)
  5. code品質部分?這部分可以用工具評分或是問問開發者的感受。

參考

Code Review Guidance:這篇微軟的文章非常值得一看,該講的都有講出來。
[如何提升系統品質-Day30]Code Review與總結:這邊有提到許多工具,可以研究看看
你今天 code review 了嗎?:這篇也很推薦,對code review的本質和方法有不錯的論述
參考腾讯Bugly的回答:這邊提到code review如何實現在不同種類團隊上,偏實務方面的文章
Airbnb 資深工程師分享:怎樣才是正確、有效的 code review:提到了code review的正確態度
我們是怎麼做Code Review的:別人實現code review的經驗

簡介

port knocking就像是敲門的暗號一樣,以特定順序碰觸port,server就會執行特定指令
我們可以把這個功能用來開port,就像阿里巴巴要用咒語才可以開門一樣。
詳情可參考port knocking的定義

安裝

我這邊server是用Ubuntu, client是MAC環境。

server

1
sudo apt-get install knockd

client

1
brew insrall knock

設定檔

通常在位置在/etc/knockd.conf
最初的設定檔,可參考manual
這邊是客製化的設定,目的是可以開關port 22,防止有人亂連。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[options]
UseSyslog

[openSSH]
sequence = 3389:udp,80:tcp,21:udp,53:tcp,23:udp
seq_timeout = 5
command = /sbin/iptables -I INPUT 1 -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn

[closeSSH]
sequence = 443:tcp,80:udp
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn

功能大概看名字也可以猜出來

  • sequence: 敲port的順序
  • seq_timeout: 間隔時間
  • command: 如果成功敲完,要執行什麼命令,這邊是用開ssh來當示範
  • tcpflags: 如果是TCP連線,需要有什麼flag

使用

server端

/etc/default/knockd中的START_KNOCKD改成1
然後啟動

1
sudo service knockd start

記得防火牆要先設定不讓外面的人進入

1
/sbin/iptables -A INPUT --dport 8888 -j DROP

client端

須先安裝knock

1
2
3
4
# 開啓
knock -v 192.168.0.1 3389:udp 80:tcp 21:udp 53:tcp 23:udp
# 關閉
knock -v 192.168.0.1 443:tcp 80:udp

注意

knock不一定要完全正確
例如說如果順序是7000,8000,9000
那麼我們用7000-9000依序敲過去仍然是可以打開
但是如果是分兩次knock就沒有用了

問題

通常我們都會用Makefile來看相依性,如果有改動make會自動幫我們判別
但是有些情況,make可能無法判斷
以下面為例,我們有四個檔案:main.c, test.c, test.h, private.h

main.c

1
2
3
4
5
6
#include "test.h"

int main() {
test();
return 0;
}

test.c

1
2
3
4
5
6
7
8
9
#include <stdio.h>
#include "private.h"
#include "test.h"

void test()
{
printf("test=%d\n", PRIV_VALUE);
return;
}

test.h

1
2
3
4
5
6
#ifndef _TEST_H
#define _TEST_H

void test();

#endif

private.h

1
2
3
4
5
6
#ifndef _PRIVATE_H
#define _PRIVATE_H

#define PRIV_VALUE 3

#endif

然後假設我們的Makefile是這樣寫

1
2
3
4
5
6
7
8
9
10
11
12
CC=gcc
OBJ=$(patsubst %.c,%.o,$(wildcard *.c))
BIN=main.out

%.o: %.c
$(CC) -c $^

all: $(OBJ)
$(CC) $^ -o $(BIN)

clean:
rm *.o $(BIN)

我們試著修改private.h的MACRO值,就會發現重新make結果還是不變,需要重新make clean

解法

可以使用gcc的特殊option

  • gcc -M xxx.c: 找出所有相依檔
  • gcc -MM xxx.c: 同-M,但不含系統檔
    1
    main.o: main.c test.h
  • gcc -MP -MM xxx.c: 會加上其他header,避免某些compiler error
    1
    2
    3
    test.o: test.c test.h

    test.h:
  • -MF file: 輸出的dependency檔案名
  • -MD: 同-M -MF
  • -MMD: 同-MM -MF
  • -MT: 可以更改dependency檔案內的目標,可參考关于 gcc MT MF[转]

因此只要把Makefile改成這樣即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CC=gcc
OBJ=$(patsubst %.c,%.o,$(wildcard *.c))
BIN=main.out

all: $(OBJ)
$(CC) $^ -o $(BIN)

-include $(OBJ:.o=.d)

%.o: %.c
$(CC) -c $<
$(CC) -MM $< > $*.d

clean:
rm *.o $(BIN) *.d

-代表如果有錯誤不要停止執行,$(OBJ:.o=.d)代表把.o換成.d,因此會變成類似

1
2
test.o: test.c private.h test.h
main.o: main.c test.h

由於該rule底下沒有statement,所以會直接對應%.o: %.c

參考

0%