近期折騰的那些軟件和腳本

renyuneyun 2020年01月29日(週三) 1 mins

忽然發現自己好像好久沒寫什麼技術性的博文了,但想想好像最近除了繼續在維護Easer 從而繼續學一堆Android開發相關的東西(庫和坑)以外,並沒有什麼成果可以說道(倒是有許多翻了資料,但沒時間實現的東西)。但最近倒是折騰/試用了許多軟件,拼拼湊湊來一篇文章倒也沒什麼不好意思的,畢竟許多情況下人們的問題是「不知道還有這個東西的存在」。

除了都是開源項目以及不依賴「雲」以外,折騰了的這些軟件並沒有什麼一致的目標。然而我卻是很意外地有一條線索將這些軟件串了起來。

同步軟件——Syncthing

出於各種原因,我需要在幾個設備間同步一些數據,主要是一些文檔之類的東西。由於設備涉及手機、筆記本以及臺式機,其存儲、電能都不大不相同,所以需要一個較爲靈活的軟件;然而這些設備並不一定會同時全部在線,我又不喜歡「雲」(噫,感覺好像找到了新一篇博文主題?),所以需要該軟件支持分佈式場景。挑來挑去,最後選擇了Syncthing,試用之後感覺的確比較符合我的需求。

其實更早的時候我是在用網/雲盤的,但很顯然,免費的網盤肯定是沒法完美的。用得最好的其實是堅果雲——雖然有每30天1G上傳的流量限制,總體來說還能接受(指早期;後來我因爲流量問題充過會員),而且對開發者以及Linux用戶(相對來說)比較友善。然而,它上傳照片後會將照片重命名,官方說法是爲了方便按時間倒序排列,但在社區(當時還是很簡陋的一個小討論板)中有很多人早就說了照片本身已經是按時間命名的/照片有EXIF所以幹嘛不自動提取EXIF/幹嘛不用文件修改時間直接完全重命名文件,這種所謂的排序根本毫無意義,然而官方始終對此無有回應。當然,除去這個問題,我真心是覺得堅果雲是國內做得最好的網盤——哪怕光是後來嚴格按照法律規定,僅僅在分享文件時纔會要求綁定手機這件事就遠遠甩開國內幾乎所有其他對公衆提供業務的企業/事業單位(不只是網盤公司)。

尋找合適軟件的過程中,我最主要看的是這些需求:

  1. 去中心化
  2. 同步而非上傳
  3. 增量傳輸
  4. 加密傳輸

滿足這些條件的軟件其實不多,尤其是滿足前兩項的。另一個比較知名的軟件/協議是BT Sync(現在改名叫Resilio Sync了),但BT Sync是閉源的,我沒有任何理由去用它。

試用Syncthing一段時間,感覺整體上很符合我的需求,尤其是它還有個簡易的歷史版本功能。但在幾個細節上它還是不夠令我滿意。其中最主要的是沒辦法對「文件夾」(是的,Syncthing是這麼叫的)進行編組,一打開它的控制面板就是一大堆文件夾,看起來很煩,而且不同設備上對哪些文件夾要同步來進行初始挑選時也很麻煩。其次就是沒法移動同步目錄,只能刪除了重新再來;而且文檔中沒有提及能不能將原目錄剪貼過去,所以我也不太敢這麼做。不過好在基本上設置好了就再也不用去管它了,這些也就影響一下增加同步文件夾,其餘時候也沒什麼影響,倒也不是太令人心煩。

文本格式的待辦事項清單——todo.txt

用了一段Syncthing,將許多目錄陸續納入了同步清單,然後我就想弄個可以通過它同步的待辦事項管理軟件。找來找去弄得我啞然失笑:原來根本沒有一個通用數據庫格式,甚至沒有好好描述自己存儲格式的,除了唯一的選擇——todo.txt(HTTP協議,嗯,不是我漏了s,是他們沒配置對)。

據官網所說,todo.txt源於lifehacker上2006年有人放出來的管理腳本。文件格式很直觀,每行一條記錄,按規定分成幾個部分,有些部分可選。更細節的直接看官方文檔就好,我也不會比它說得更清楚。

除了其命令行的todo.sh腳本外,我還試了試efficient task這個todo.txt的GUI(Rust寫的),以及gnome的time++插件(支持kanban化)。事實上,我是先用了gnome的time++插件的(相比Syncthing),所以其實用todo.txt的時間比Syncthing還長。但我本來仍然希望能有個別的軟件,畢竟todo.txt並沒有好看的前端,而且不支持子任務。

但其實用了一段時候發現,自己對子任務其實並沒有那麼大的依賴(或許是我仍然不是待辦事項軟件的重度用戶吧)。我還額外用它記錄自己的零食果汁等的過期時間,省得自己老是想不起來吃。於是順便寫了個count插件,方便操作那些有「數量」的項目。

備份軟件——Borg

在用了Syncthing一段時間以後,忽然感覺這樣似乎不夠安全。畢竟雖然Syncthing有個「歷史版本」機制,但畢竟它一直在運行,萬一Syncthing軟件本身有什麼bug不就坑了麼。於是又顛顛地去找備份軟件,畢竟我之前的備份方案最初抄自仙子在這篇中提出的方案,後來改爲btrfs send/recv,於是僅僅對HOME整坨整坨地進行複製。

備份軟件還是很多的,alternativeto上就有至少十數個,archlinux的wiki上也有很多。Arch wiki其實對此進行了分類,極大地方便了我的挑選。

其實我的挑選並沒有一個很特定的目標,只是有這些大概的目的:

  1. 必須支持增量備份
  2. 必須支持自動去重
  3. 必須有辦法保留歷史版本
  4. 最好有加密(沒有的話自己套一個cryfs)
  5. 最好能支持主從備份

其中前四個都比較好理解,但第五個我其實是不太確定的。這個想法的出發點其實是擔心我的移動硬盤萬一掛了,這些數據還有第二個備份點。由於之前是用的Synchting,所以思考這個問題的時候其實還是沿用了Syncthing的思路:在任意地方都可以操作備份,然後其他存儲點之間相互同步。但稍微一想覺得不對,因爲這樣的自動同步萬一中間出了問題,造成數據不一致怎麼辦——Syncthing畢竟是同步的文件,就算不一致還或許能挽救,但這些備份可是專門的二進制格式啊。於是就想着應該能手動在各個存儲點之間傳輸,類似於git push和git pull這樣的手動分佈式同步的方式。

然而看來看去,似乎這個第五點沒有任何軟件能滿足,無論是前後哪種想法。所以只好拋棄軟件自帶主從支持,改爲只要存儲爲固定的文件,我之後自己手動用外部工具來同步。於是對着分類比了比,打開一些軟件的官網看了看,最後看上了Borg。

我不會說選它還因爲它的名稱。雖然我並不喜歡《星際迷航》裏Borg的理念(如果那能稱爲理念的話),但其技術性上優點很多,尤其是分佈式的備份。當然我不可避免地會期望這個軟件也有這個功能(也就可以完成第五點),但實際上並沒有。

Borg默認提供的是命令行工具,用法還算比較直觀。它官方似乎是有個(有限功能的)web端的,我也能找到,但沒能成功使用,所以最後還是放棄了。

它的優點很多,比如它完全滿足我的前四點要求,而且還帶自動壓縮。它的去重是按區塊進行的,所以效果非常好。它還有個FUSE可以直接將備份掛載起來查看。另外,Borg真的只是「備份」——一旦創建,歸檔幾乎就是只讀的了(除了可以改名和刪除外)。當然,實際上它還有個(實驗性的)borg recreate命令,但我沒怎麼弄懂這個命令的用法。哦,對了,Borg創建歸檔(一個備份)的時候,可以同時指定多個目錄一起納入備份,避免了爲了備份而重新整理目錄結構的麻煩。

但同樣,由於它是「備份」,所以歸檔不可修改這點在某些情況下就是缺點了:我備份HOME的時候會指定歸檔名稱爲home;但當我再次備份的時候,我就必須想辦法解決名稱衝突了。於是我的最後解決方案是指定歸檔名稱爲home.yyyy-mm-dd。但這樣實在有點蠢,因爲Borg本來就會自動添加時間戳,我這樣額外增加一個沒有什麼意義。

在轉移備份的時候,我還注意到官方說Borg其實是會緩存每個歸檔(有UUID)的一些元信息的。所以很不建議將倉庫複製到其他地方,尤其是警告道不要在兩個地方分別修改。官方推薦的做法是對兩個倉庫個執行一次borg create——因爲Borg可以直接通過ssh傳輸過去,尤其是當對面有borg的時候會更快一些(我暫時沒有實際嘗試,但過一段說不定會)。當然,官方也說了,僅僅複製倉庫只是不建議,而沒有實際的危險。所以目前我仍是採取複製的方式。

即時加密文件傳輸——MagicWormhole

發現這個軟件純屬意外,因爲我本來是在找如何直接建立點對點的SSH通道,以便通過Borg直接推到遠程服務器上的。

尋找建立點對點SSH通道的後續其實就是我所謂的「翻了資料沒時間實現」中最主要的那個。我翻了不少資料來查詢如何打洞,但發現好像沒有標準的協議來實現——STUN和ICE似乎是,但又似乎不是。在SU上倒是有人提到一個ssh-p2p,但畢竟僅限於SSH。於是就起了自己寫一個通用軟件的念頭。但除了在crates.io上搜到個打洞的庫,自己跑了一下示例代碼,測試了一下連接維持時間以外,什麼都沒寫。

這個軟件的使用很簡單,指定文件,自動生成密碼句,密碼句交給對方,對方輸入密碼、接收就行。它的特點就是點對點——除了密碼以及協商的時候需要依賴一個公網服務器外,傳輸的時候並不需要。後續使用中發現,其實它還是往往使用relay的,並沒有我之前想的打洞。查詢文檔發現,它只是試圖直接建立TCP連接,不成就進行relay……而打洞是在「未來計劃」中的……

照片集管理軟件——digiKam

再然後,在有了穩定的備份方案之後,我終於想起來仔細整理一下照片了。這時候就需要一個照片整理軟件了。

找了一圈,看下來似乎只有digiKam可用。另一個被人提到的是shotwell,但打開看一眼就發現其功能比digiKam少得很多。

我本來其實只希望找這些功能:

  1. 能夠按EXIF的時間排鋪
  2. 能夠尋找相同照片
  3. 能夠在地圖顯示

想要一是因爲文件名並不統一,我也不想費事去統一文件命名,而且其實也沒法統一(因爲有的照片是別人傳給我的,命名早就亂了)。想要二是因爲以前備份比較混亂,有的照片(目錄)有很多地方都有,但我又不敢輕易說某個目錄的文件一定全過其他目錄。想要三則和一類似,都是爲了方便查看。

而digiKam其實讓我大喜過望,因爲它不光提供了這些功能,還提供了人物識別——不光是檢測出人臉,還能(基於用戶的標記)自動識別人臉(而且有用戶確認步驟,不自作聰明地完全相信模型的結論)。它也不是尋找「相同」圖片,而是可以更寬泛地尋找「相似」圖片。

當然,要說問題也還是有的。比如說我發現它在識別相似照片後,只能一組一組分別手動操作,效率很低,而且都是機械勞動。再比如它讀取EXIF中照片時間的時候,如果有「數字化時間」,它就會使用這個,而不是「原始時間」,哪怕「原始時間」比數字化時間更新(這實際上是我當時那個手機相機的問題,它的數字化時間永遠都是2002年某日)。

爲了解決這個EXIF時間的問題,我最開始嘗試用digiKam自己提供的批處理功能。但那個功能實在太慢,十分鐘也就處理了沒多少(我一共有數千張要處理)。最後不得已,自己動手用Python擼了一個來處理。這時候發現,原來處理效率真的低下,因爲我擼的這個每秒只能處理十來張。要知道我可是換了好幾個庫,最後選了這個僅處理EXIF的piexif庫來(而不是像PIL/Pillow一樣處理整張圖片的),是嘗試的所有庫裏邊最快的了。

人物識別功能也並不是十全十美,但比沒有要好得多。其中不乏一些有意思的識別結果,比如將不是人的識別成人,將某人識別成另一個人之類的。當然,最有意思的是將溶洞中一個暗處的石壁上一小塊辨識成人臉,而且那塊還真的有點像臉。前面提到它也可以基於你之前的標籤來識別人物,而且在識別完並不自動確定,而是歸類到「未確定」等待用戶自行確定或修改,以便(萬一錯了)再次識別。但比較煩人的是它並沒有一個「忽略」組所以有些明確知道不認識的人(或者不是人)也沒法處理,總是會(在再次掃描時)被再次識別的。

目錄對比

另外,在解決照片重複問題時,我還嘗試了幾種文件對比方案。我的實際需求是很明確的:每次指定兩個目錄,告訴我這兩個目錄中哪些文件是僅在一個目錄中存在的,以及哪些文件是修改過的。有少量的文件名修改識別不出來無所謂,只要不是大量的就行(而且從結果上來看,其實我根本沒改過文件名或移動文件到子目錄中過)。

搜索一番能看到兩個主要的推薦:diff --briefrsync --dry-run,以及還有一些圍繞其上的前端。然而,實際使用下來,我發現這兩個的效率實在都是很低,需要耗費大量時間(和內存,不過主要是時間)。

這個現象的因素大約是我要對比的目錄文件數太多:較大的目錄有6000餘個文件,30G+,另一個並不少太多。不過這次我實在是沒有預期到會用這麼久,總是覺得「快完了吧」,所以並沒有自己去寫對比腳本。而有趣的是,我本來以爲rsync應該會比diff快很多,但實際上並不是,甚至還慢了。

備份和還原文件修改時間

在解決照片的EXIF信息錯誤時,我使用了自製的腳本。但很顯然,在運行腳本之後文件的修改時間便被更新了。雖然不太要緊(因爲EXIF畢竟有時間),但我還是覺得不太舒服,所以就去查找了如何批量備份和回覆文件修改時間。

在SuperUser上有人問了這個問題,也有人給了腳本來做。雖然需要perl,但畢竟perl還是很常見的,我的機器上也是有的,所以就用了這個方案。由於是文件系統的操作,故而理所當然地,其效率非常之高。

當然,其中細節部分還是要調整的,比如那個find /就得換成目標目錄。

沙盒軟件——firejail

我其實早就聽過firejail的名字,而且也裝了它。但直到在整理照片時候,纔真正想起來可以用它來限制軟件對目錄的讀寫權限——主要是防止自己一個手殘rsync忘了寫--dry-run把目標目錄修改了。

實際上firejail的沙盒功能很全面,基於Linux Namespace,所以可以對很多東西進行隔離,而不僅僅是文件系統。當然,它的配置也比較複雜,我其實也直到得不多。但好在可以以自定義profile來啓動shell,所以調試profile還是比較方便的。

我目前對firejail的主要用途也就是測試軟件和控制命令行只讀;日常主要用來限制firefox對大多數目錄的訪問,防止潛在的瀏覽器漏洞。


Related posts:

您可以在Hypothesis上的該群組內進行評論,或使用下面的Disqus評論。