Classic Shell Scripting 讀書筆記(一)

  • Devops

入門

printf

  • 格式聲明 (format specfications) 是一種佔位符號 (placeholder),結構包含 1) 百分比符號 (%) 2) 指示符 (specifier),常用的有字符串 %s 及十進位整數 %d

tr

範例:Translate DOS file to UNIX

  • tr -d: 自 stdin 刪除 source-char-list 的字符
  • \r: ASCII carriage return

/dev/tty

範例:Read password via /dev/tty

  • 當程序打開 /dev/tty 時,UNIX 會將它重定向到一個終端再與程序結合,該終端可以是 1)實體的 console 2) 串行端口 (serial port) 3) 偽終端 (pseudoterminal)
  • stty (set tty) 用來控制終端的設置,echo/-echo 選項用來開關自動打印輸入的功能

i18n and l10n

  • 當 i18n 作為設計軟體的過程時,無須再修改軟體或重新編譯程式代碼,就可以給特定的群體使用
  • 當 l10n 作為設計軟體的過程時,目的是讓特定的使用者可以使用軟體。其中包含翻譯輸出的文字、貨幣、日期、時間、單位等格式
  • 對使用者來說,用來控制讓哪種語言或文化環境生效的功能,叫做 locale
  • 除了 CPOSTFIX 以外,locale 名稱並未標準化
  • BSD 與 Mac OS X 完全不支援 locale
  • locale 的支援仍未成熟:Shell 腳本常受到 locale 影響;在大多數 UNIX 系統下,很難從 locale 文件與工具來判定字元集 (character class)、等價字元集 (equivalence class) 實際上包含了哪些字元,以及有哪些排序符號 (collating symbol) 可用。
  • Shell 腳本開發者應了解 locale 對他們代碼所造成的影響

列出所有 locales

取得特定 locale 的資訊

定義 LC_ALL 來覆寫預設的 locale,可查詢的變量有日期時間格式 LC_TIME、貨幣格式LC_MONETARY

Matching text

  • 1992 POSFIX 整合了 grepegrepfgrep,透過不同選項控制
    • 最早的 grep: 使用 BRE (Basic Regular Expression),只能匹配單一正則
    • egrep: 使用 ERE (Extended Regular Expression),只能匹配單一正則
    • fgrep: 不使用正則,使用特定演算法可以同時匹配多個固定字串

Reqular expression

一些重要的 POSIX BRE/ERE 的 meta 字元

Unix 程序使用何種類型

Bracket expression

UNIX 的範圍表達式在 POSIX 的標準下,現在叫做方括號表達式。其中包含三種字元集構造:

  • 字元集 (character class): [:關鍵字:],關鍵字描述不同的字元集,如 alphadigit,例如 [[:alpha:]!] 匹配任一英文字母或驚嘆號
  • 排序符號 (collating symbol): [.排序元素.],受特定 locale 影響,在非英語系的語言,某些成對的字元必須視為單個字元,例如在捷克或西班牙語系,ch 兩個字元會保持連續狀態,在 locale 支持下,可用於如 [ab[.ch.]de] 的匹配
  • 等價字元集 (equivalence class):[=字元=],列出應視為等值的一組字元,如在法文的 locale 裡,[[=e=]] 可能匹配 e、é、ë

BRE

  • 在前面放置 \ 用來轉義 meta 符號,常用的有 \\\[
  • 在方括號表達式中,^ 放在字首是取反 (complement) 的意思
  • 方括號表達式可以表達字元的範圍,如 [0-9a-fA-F],但範圍表示法是根據機器中字元集的數值(ASCII vs EBCDIC),有可移植性的問題。建議用 POSIX 字元集表示法取代。
  • 在方括號表達式中,meta 符號不再具備特殊含意
  • 後向引用 (backreference) 的結構 \( \)\digit 於後方調用,例如匹配所有引號括起來的字 \(["']\).\1
  • 錨點 (anchor) meta 字元 ^$,分別用來針對字串的開始/結尾處進行匹配

範例:預先消除空行

BRE 運算元優先級 (precedence)

由高至低排列

  1. [..][::][==]
  2. \metacharacter
  3. []
  4. \(\)\digit
  5. *\{\}
  6. no symbol,表示連續
  7. ^$

ERE

  • 以匹配單個字串來說,與 BRE 一致,不同之處在於匹配多個字串方面
  • 不存在後向引用
  • ?+ 可以更細膩處理匹配控制
  • 方括號表達式用來「匹配此字串,或其他字串」;交替運算符| 用來「匹配這個序列,或其他序列」
  • () 用來分組
  • ^$ 永遠是 meta 符號,與 BRE 不同,若放在字串中間會匹配不到任何東西

範例:匹配多個連續出現的 read 或是 write,且中間可以是空白

ERE 運算元優先級 (precedence)

  1. [..][::][==]
  2. \metacharacter
  3. []
  4. ()
  5. *+?{}
  6. no symbol
  7. ^$
  8. |

文本替換(substitution) sed

  • / 扮演定界符號(delimiter),分隔正則與替代文本
  • 除了 /,任何可顯示的符號都可以當定界符號,在處理文件名稱時,通常用標點符號 ;:, 取代 /,因為轉義完路徑看起來會很醜
  • 在 s 命令最後,若以 g 結尾,代表全域(global)取代,若以數字結尾,則表示「第 n 個匹配才取代」
  • sed 會記住 -f 腳本裡遇到的最後一個正則,透過使用空的正則,可重複利用同一個正則
  • 命令裡的每個文件會依序打開與讀取,如果沒有文件,則用標準輸入,或用單個破折號 - 表示標準輸入
  • 讀取文件時,將讀取的行放到記憶體某個位置,稱為模式空間(pattern space),將一次次修改的結果覆蓋在相同位置,最後輸出模式空間裡的最後內容

範例:擷取第一個字段(將第一個冒號之後的文本取代為空字串)

範例:將 /home/tolstoy 的目錄結構建立一份副本在 /home/lt 底下,並追蹤執行

  • 使用產生命令(generating commands)的手法,使命令內容成為 shell 的輸入

範例:轉換 HTML 為 XHTML

範例:模擬 grep 的功能,只打印含 的行

addressing

默認情況下,每一個編輯命令(editing command)會套用到每個輸入行;要限制應用到哪些行,須在命令前加個地址(address),以下為不同種類的地址;注意 address 限用單引號

  1. 正則表達式

    範例:為部份代碼增加註釋

  2. 最終行(符號 $ 在 sed 裡表示「最終行」)

    範例:打印文件最終行

  3. 絕對的行號

    範例:模擬 head 功能,q 命令要求 sed 馬上離開,不再讀取其他輸入

  4. 範圍(以逗號隔開兩個絕對行號或正則)

    範例:只打印 10~42 行

    範例:只替代範圍內的行

  5. 否定正則

    注意 ! 後面最好不要加上空格,因為會導致某些老舊的 sed 版本無法識別

    範例: 將沒有 used 的每個行裡的 new 取代為 used

改變定界符

範例:以 : 隔開正則,以 ; 扮演 s 命令的定界符

Longest leftmost 從最長最左邊匹配原則

POSIX 標準指出:「完全一致的匹配,指的是自最左邊開始、針對每個子模式、由左至右,必須匹配到最長的可能的字串」

留意 null 字串的匹配

選定字段 cut

因行內的每個字段長度不一,使用字元 -c 剪下資料的風險較大,一般偏好使用字段 -f 配合定界符 -d 為基礎來提取資料

連接字段 join

範例:刪除註解、取代分隔符為 whitespace 並排序後合併文件

重新編排字段 awk

  • 程序架構為 pattern {action},pattern 通常是以 / 定界的 ERE,action 為 awk 語句,意思是「如果 pattern 為真,則執行 action」

  • 記得在參數間用逗號分隔,否則字段會連在一起

  • BEGINEND 模式

範例:以自訂分隔符輸出特定欄位

範例:自訂變數、使用 printf 混和文本

笑忘書

  • Quote

失去的信件

klement-gottwald-vladimír-clementis-vanish

人類對抗權力的鬥爭,就是記憶與遺忘的鬥爭。

憲法保障言論自由,話是沒錯,但是任何有可能被認定是危害國家安全的行為,都會遭到法律的制裁。沒有人知道,我們的國家什麼時候會跳起來厲聲指責說,這句話或哪句話危害到了國家的安全。

知識份子這個詞,在當時慣用的政治語彙裡屬於侮辱性的字眼,意思是說一個人缺乏現實感,跟人民拖了節。在那段時日裡,所有被共產黨員絞死的共產黨員,都曾經被安上這種羞辱。據說,知識份子和腳踏實地的人們不同,他們總是活在半空中,不知自己飄盪在何處。所以就某種意義上來說,跟他們雙腳永遠離開地面也是對的,就讓他們吊在那兒,跟地面保持一點距離也好。

智利總統阿言德的暗殺事件,很快就取代了俄國人入侵波希米亞在我們心中留下的記憶;孟加拉的血腥大屠殺讓人忘記了阿言德;西奈沙漠裡,以色列人和阿拉伯人的殺聲喧天,蓋過了孟加拉傳來的呻吟;柬埔寨大大小小的屠殺事件又讓人忘掉了西奈沙漠;依此類推,類推,再類推,最後每個人會將每件事都徹底遺忘。

在從前的日子裡,歷史還是緩慢前行的,為數不多的事件在人們的記憶裡悠然留下身影,交織成眾人熟悉的佈景。人們的生活就在這幅佈景前,展現著種種令人驚奇的事蹟,演出扣人心弦的戲劇。如今,時間卻踏著大步前進。歷史事件如朝露般一閃即逝,晨光降臨即被遺忘;歷史事件不再是敘事者的背景布幕,它本身就引人注目,它以人們再熟悉不過的庸碌生活為背景,演出一齣齣令人驚奇的事蹟

我再強調一次:牧歌,為所有的人。長久以來,人類總是嚮往著牧歌,嚮往這片夜鷹歌聲繚繞的田園,嚮往這個和諧的國度。在這個國度裡,人類不會遭到陌生世界的侵擾,人與人之間也不會扞格不入;相反地,世界和每一個人都是用同一種材料捏造出來的。在那裡,人人都是巴哈賦格曲裡反覆澎湃歌詠同一崇高主題的一棵音符,不想當音符的,就杵在那兒像個沒用的小黑點似的,毫無意義,只消輕輕拈來,用指甲一掐,小黑點就會像跳蚤一般,被捏得粉身碎骨。

他覺得自己對命運負有責任,但命運卻不覺得它對他有什麼責任。

歷史事件往往前仆後繼,相互模仿而了無心意。但我認為,人類的歷史卻在波希米亞完成了一場史無前例的試驗。這一次,歷史的進程不是依照古老的慣例,由一群人(一個階級,或是一個民族)起來反抗另一群人,而是有人(整個世代的男男女女)奮起造反,對抗自己的青春。

米瑞克的名字也給抹掉了。現在,雖然他踩著一階一階的樓梯走向芝丹娜的家門口,但實際上,他只是一塊污漬抹境之後殘留的白痕,一小片鑲著輪廓的空無,順著迴旋的樓梯向上走去。

他們會逼著他把自己的生命拋擲向遠方,讓自己化為暗影,成為一個沒有過去的人、一個沒有角色的演員,他們甚至會逼他把被人拋向遠方的生命和演員放棄的角色也一併化為暗影。非得如此將他的形體化為暗影,他們才要讓他活下去。

男孩把女孩從他的生命的相本中抹去,那並不是因為他不愛她,而是因為他愛過她。他把她抹掉,她的人以及他對她的愛,他刮落她的身影,直到消失為止,就像黨的宣傳部讓克雷蒙提斯從戈特瓦發表歷史演說的陽台上消失一樣。米瑞克改寫歷史的手法跟共產黨如出一轍,跟所有政黨也毫無二致,跟所有民族,跟全人類,都一樣。人們高聲疾呼,說要打造一個更美好的未來,其實是騙人的,未來不過是一片無足輕重的空白,任誰都不會有興趣,但是,過去卻充滿了活力,它的臉孔激怒我們,反抗我們,傷害我們,其為禍之深,直教人動念將它摧毀,或至少重繪它的面貌。人們想要主宰未來,其實只是為了能夠改變過去。人們相鬥相殘,就是爭著要進入那些神奇的暗房,去修整照片,改寫個人的傳記,甚至人類的歷史。

他們要把幾十萬人的生命從記憶中抹去,好讓無暇的田園牧歌永遠無暇。然而正是在這首牧歌裡,米瑞克要以自己的血肉之軀拋擲其間,橫灑一片污漬。他要一直待在那裡,就像克雷蒙提斯的氈帽一直留在戈特瓦的頭上一樣。

媽媽

這麼說吧:其實所有的愛情都是建立在一些不成文的公約上,那是戀人們還在熱戀的最初幾星期裡,未經深思熟慮就草草擬定的公約。那時戀人們還沈浸在夢裡,但這時候,他們其實已經不知不覺地扮演起難纏的法學家,開始逐條逐字編寫他們的愛情合約。噢!戀人們,開頭這幾個險惡的日子裡要當心哪!如果您幫別人把早餐端到床上,你就得一輩子幫他送早餐過去,否則您就會揹上讓愛情褪色與背叛的罪名。

沒錯,經歷這許多年,夫妻倆已經變成了雙胞胎,兩人用同樣的字彙,有同樣的想法,也擁有相同的命運。夫妻倆彼此都將艾娃當作禮物送給對方,讓對方快樂。夫妻倆都覺得自己在推石頭上山。夫妻倆都覺得倦了。

現在,他眼前浮現那全小城崗巒悠悠的景致,木雕的廊柱、一群群綿羊在山丘上的草原覓食、羊頸上的小鈴叮叮噹噹地晃著。他在腦海裡把娜拉赤裸的身體安插在這片鄉野景致之中(就像拼貼畫的作者在一幅畫裡貼上從另一幅畫剪下來的圖片),他腦中閃現一個想法:美,就是兩個不同的年代跨越了時光之炬,在相遇時迸濺激射的火花。美,就是對編年紀事的棄絕,就是對時間概念的反叛。

天使們

支配世界的權力,誠如我們所知,是由天使和惡魔分享的。然而,世上的善並不能保證天使就比魔鬼佔優勢(像我小時候所相信的那樣),事實上,兩者的權力差不多是平衡的。如果世界上有太多不容爭辯的意義(天使專權),人類就會被這些意義的重量壓垮。而如果世界失去所有的意義(魔鬼統治),人們也一樣活不下去。

笑帶有某種壞的成份(事物的呈現突然跟原本設想的不同),不過也有好的一面,它可以讓人得到紓解(事物變得比其外表來得輕逸,讓我們活得比較自由,事物也不再以其肅穆莊嚴的外表來壓迫我們)。

這世界上有兩種笑,而我們卻沒有詞彙來區辨他們。

最後,她希望至少能和她的學生們處於完全和諧的狀態,也就是說和他們成為一個整體,意思就是說,她要學生們永遠都得跟她有相同的想法、相同的說法,她要學生們跟她形同單一的身體、單一的靈魂,在相同的圈子裡跳著相同的舞步。

如果我們遠離的是一列行伍,或許還有歸隊的機會。但圓圈是封閉的,一旦脫離,斷難回頭。要知道,行星繞著圓周運行絕非偶然,一顆石頭脫離了行星,無可避免地會被離心力拋擲出去。

失去的信件

照我估計,每秒鐘都有兩、三個新的小說人物經歷受洗命名般的過程,來到人間。

這句『對,我也是這樣,我……』看似每種附和的回聲,好像要接續別人的想法,但其中卻有詐:事實上,這句話是一種以暴制暴的粗魯行徑,說話的人粗魯地把自己受奴役的耳朵拯救出來,同時迫使對手的耳朵成為階下囚。人們沉浮在跟自己相似的人群裡,而人生也不過是一場征服他人耳朵的戰爭。

『小說是人類錯覺的結晶,一種自以為可以了解他人的錯覺。』

普遍的疏離引發了寫作狂,而普遍的寫作狂又強化了疏離。過去,印刷術的發明讓人們得以相互瞭解。然而值此寫作狂遍地可見的年代,寫書這回事的意義卻大異其趣:人人都被困在自己的言詞裡,像被大片鑲著鏡子的牆壁所圍繞,任何外界的聲音都無法穿透。

寫書的人,要嘛化身為全部(一個獨特的世界——為他,也為所有人而創的世界),要嘛就是個零。由於沒有人能夠化身為『全部』,所以我們這些寫書的,每個人都是『零』。我們被人看輕,我們善妒又尖刻,我們恨不得別人都去死。

不論政客或是計程車司機、產婦還是情婦,也不論殺手、小偷、妓女、警察局長、醫生還是病人,各行各業裡,寫作狂的激增說明了一件事:人類無一例外,皆有成為作家的潛能,因此大家都可以理直氣壯地跑到街上大喊:我們都是作家!這是因為大家都害怕自己會隱沒在一個無關輕重的世界裡,沒人聽,沒人理,所以要趁著還來得及的時候,把自己轉化成一個世界,一個用話語堆砌而成的世界。

總有一天(這一天也不遠了),每個人都會發現自己是作家,當這一天來臨的時候,人類就會進入一個全面聾聵、全面誤解的年代。

行過死蔭之地

  • Quote

「牢中生活不見得能感化他們,但肯定會加強他們的犯罪技巧。」

人生啊!曾有人說過,對於那些靠思考過日子的人像是一齣喜劇,對於那些憑感覺過日子的來說卻是一場悲劇。對我而言,無論怎麼過日子都是有喜有悲,即使你什麼都不做也逃不掉。

深入理解 Nginx 讀書筆記 (第二章)

進程間的關係

  • Nginx 支持僅單進程(master)提供服務
  • 常態的部署是使用一個 master 進程來管理多個 worker 進程
  • Worker 數量與 CPU 核心數相等,進程切換代價最小

使用多進程的好處

  1. master 進程僅專注於純管理工作,為管理員提供命令行服務(啟動、停止、重配置、升級)
  2. master 進程需要比較大的權限,通常會以 root 使用者啟動
  3. 一個 worker 進程出錯後,其他 worker 仍然可以正常服務
  4. 充分利用 SMP(Symmetric multiprocessing) 多核架構,實現微觀上真正的多核併發處理
  5. Worker 通常不會進入睡眠狀態:可以同時處理多個請求,不像 Apache 每個進程只能同時處理一個請求,以致進程切換代價大

配置語法

每個模組都有自己感興趣的配置項,大部分模組都必須在 nginx.conf 中讀取到某個配置後才會啟用,例如只有當配置 http {…} 時, ngx_http_module 模組才會啟用,其他依賴的模組也才能正常使用

區塊配置項

  • 由名稱及一對大括號組成,如 http, server, location 都屬於區塊配置項
  • 傳入的參數取決於解析這個區塊配置項的模組
  • 大括號表示包含其中的配置同時生效
  • 可以嵌套,內層配置直接繼承外層
  • 當內外層配置發生衝突,以哪層配置為準,取決於解析這個區塊配置項的模組,例如範例的 gzip 開關

配置項語法格式

  • 名稱必須合法的(是某個 Nginx 模組想要處理的)
  • 傳入的參數取決於解析這個區塊配置項的模組
  • 若任一參數包含空格符,須要用單引號或雙引號包住
  • 以分號結尾

Read More »深入理解 Nginx 讀書筆記 (第二章)

深入理解 Nginx 讀書筆記 (第一章)

為什麼選擇 Nginx

  1. 更快: 1)單次請求更快響應 2) 在高峰期比其他服務器更快響應
  2. 高擴展性: 1)由耦合度極低模塊組成 2)模塊皆嵌入到2進制文件中執行
  3. 高可靠性: 1)模塊穩定 2)進程相對獨立 3)worker出錯可快速輪替
  4. 低內存消耗: 1)10,000個非活躍 HTTP Keep-Alive 連接僅消耗 2.5 MB
  5. 高併發: 1)單機支援 100,000 以上連接
  6. 熱部署: 1)基於 master 與 worker 進程分離 2)服務不間斷下,進行升級可執行元件、配置及更換日誌
  7. BSD 許可協議

開發準備工作

必要

  1. Linux 內核版本 2.6 以上 (須靠 epoll 處理高併發)
  2. GCC 編譯器編譯 C 語言

非必要

  1. G++,用來編譯 C++ 以編寫 HTTP 模塊
  2. PCRE(Perl 兼容正則表達式),用來在配置文件中使用正則表達式,pcre-devel 是使用 PCRE 做二次開發所需
  3. zlib, 用來對 HTTP 內容做 gzip 壓縮,減少網路傳輸量
  4. OpenSSL,支持 SSL 協議,或想使用 MD5 或 SHA 雜湊

目錄結構

  1. 源代碼目錄
  2. 編譯中間文件(置於源碼目錄底下,命名為objs)
  3. 部署目錄(莫認為 /usr/local/nginx)
  4. 日誌目錄

Linux 內核參數優化

  1. 須要修改內核參數,使得 Nginx 可以擁有更高的性能
  2. 通常根據業務特性進行調整,作為內容服務器、反向代理,或是提供縮圖用的服務器,會做不同調整

Read More »深入理解 Nginx 讀書筆記 (第一章)

Rabbitmq Exchange and its Types

Definition

exchange

Message routing agents.

Messages are not published directly to a queue. Instead, the publisher sends messages to an exchange.

Defined by the virtual host within RabbitMQ.

Predefined default exchanges are created at server starts.

Clients can create their own exchanges.

Exchange parameters:

  • type
  • name
  • durability
  • auto-delete (once last bound object is unbound from the exchange)

binding

Link between an exchange and a queue.

Use message attributes: routing key, header to route to the messages to queue(s).

Exchange Types

default exchange

No name. (usually referred by an empty string)

Every queue is automatically bound to the default exchange.

Binding key will be the queue name.

direct exchange

Similar to default exchange, but got a name and the bindings are not created automatically.

A message goes to the queue(s) with the binding key that exactly matches the routing key of the message.

fanout exchange

Routing key doesn’t have any effect.

Route message to all queues.

topic exchange

Similar to direct exchange, but use binding pattern not binding key.

A message goes to the queue(s) with the binding pattern that matches the routing key of the message.

image

header exchange

Similar to direct exchange, but use message header not routing key; use binding header not binding key

If x-match=all, then all header attributes should match

If x-match=any, then any header attributes match counts

image