星期日, 12月 31, 2017

Extract binary data from MS SQL

在微軟範例 AdventureWorks,Production Schema 有個 Document 資料表,其中有一個欄位 Document 型態是 varbinary,儲存著 FileName 欄位所記載的檔案內容。藉由工具程式與適當的對話,可以取出內容復原:
  • bcp "SELECT Document FROM AdventureWorks.Production.Document WHERE FileName = 'Introduction 1.doc'" queryout /tmp/Introduction_1.doc -S localhost -U sa -P ...
  • Enter the file storage type of field Document [varbinary(max)]:
  • Enter prefix-length of field Document [8]: 0
  • Enter length of field Document [0]:
  • Enter field terminator [none]:
  • Do you want to save this format information in a file? [Y/n]
  • Host filename [bcp.fmt]:
雖然大多是預設值,唯一要特別注意的是 prefix-length,這裡有可能自作主張地把檔案前面多加了八位元組,讓 Word 開不起來或形成一堆亂碼的內容,因此必須輸入 0 覆蓋掉預設的 8 才能得到正常的檔案結果。在此之後,我們可以再利用 bcp.fmt:
  • bcp "SELECT Document FROM AdventureWorks.Production.Document WHERE FileName = 'Introduction 1.doc'" queryout /tmp/Introduction_1.doc -f bcp.fmt -S localhost -U sa -P ...
可惜的是除此之外,參數無法讓這段過程無需人工介入又産生正確的結果。另一個變通的做法:
  • bcp "SELECT Document FROM AdventureWorks.Production.Document WHERE FileName = 'Introduction 1.doc'" queryout /tmp/Introduction_1_with_prefix.doc -n -S localhost -U sa -P ...
  • tail --bytes=+9 /tmp/Introduction_1_with_prefix.doc > /tmp/Introduction_1.doc

星期二, 12月 26, 2017

JMeter JSR223 Pre / Post Processor

過去以為在 JMeter 裡會用 RegEx 處理動態 SessionId 就很高段了?這次遇到了些更有挑戰性的需求,不得不研究了一下何謂 JSR223?基本上就是一個在 Java 執行腳本程式語言的環境。結合 Groovy,能解決:
  • 取亂數
    • def uuid = UUID.randomUUID().toString();
    • vars.put("id", uuid);
  • 字串拆解、合併,Base64 編碼
    • char0 = (char)0
    • jid = vars.get("jid")
    • token = vars.get("token")
    • def(name, domain) = jid.split("@")
    • plain = jid + char0 + name + char0 + token
    • encoded = plain.bytes.encodeBase64().toString()
    • vars.put("encoded", encoded)

星期一, 12月 11, 2017

git sparse checkout

有時候我們只想拿 Git 上的一兩個檔案,但整個儲存庫很大,或歷史悠久,實在有點浪費。首先有個下指令 sparse checkout 指定要取的路徑,也可以搭配深度省略不需要的歷史:
  • git init <repository_name>
  • cd <repository_name>
  • git config core.sparseCheckout true
  • echo '/path/to/file1' > .git/info/sparse-checkout
  • echo '/path/to/files/*' >> .git/info/sparse-checkout
  • git remote add origin https://<repository_url>
  • git pull --depth 1 origin master
指令有點多,用 api 看有沒有好一點?以無需認證的 GitHub repository 為例:
  • curl -H 'Accept: application/vnd.github.v3.raw' -O -L https://api.github.com/repos/:owner/:repo/contents/:path
需認證的 GitLab 比較麻煩些:
  • curl -H 'PRIVATE-TOKEN: <token>' https://<git_host>/api/v4/projects/:id/repository/files/<url_encoded_file_path>/raw?ref=master -o output.ext
    • token 要取一個 scope 包含 api,尚在有效期限內的 personal access token
    • project id 可在專案的一般設定找到,通常是個數字
    • 以專案第一層 a 目錄下的 b.txt 為例,url_encoded_file_path 會是 a%2Fb.txt
    • master 是分支名,也可以是 tag 或 commit id
    • output.ext 是輸出檔名

星期一, 12月 04, 2017

GIT_ASKPASS timeout on Jenkins

有些 Jenkins Project 在運作一陣子之後,某天突然出現取不到 Git 原始碼(逾時)的問題,目前只找到兩個共同特徵:
  • using GIT_ASKPASS to set credentials
  • Jenkins node on Windows
在一些文章中提到,若在 Jenkins 使用帳密(非 ssh token)登入 Git,事實上只能由 GIT_ASKPASS 傳遞帳密,但這機制又不是那麼穩,有時會壞的。解法是:
  • Command Prompt (Admin) > git config --system --unset credential.helper

星期二, 11月 28, 2017

Docker shared folder between host and containers

因為很多 Docker Image 都陽春到沒有方便的交換檔案做法,像是要從 Host 複製檔案進 Docker Container,或反方向,或是 Docker Container 之間互相分享檔案,也許連平常視為基本的 SCP SSH 都沒有。幸好 Docker 有專門設計 Volume 給我們用,方法也不只一種,這邊講個最簡單又通用的:
  • docker volume create <your_volume_name> 建立新的共享目錄
  • docker volume ls 查詢目前有哪些共享目錄
  • docker volume inspect <your_volume_name> | grep Mountpoint 查詢共享目錄在主機上的實體路徑
  • docker volume rm <your_volume_name> 刪除共享目錄
當我們要開一個新的 Container,可以掛上這個共享目錄,如:
  • docker run
    • -d
    • --name <your_container_name>
    • -v <your_volume_name>:/tmp
    • <your_image_name>
就能在 Container 的 /tmp 找到我們放在 Mountpoint 的檔案。

星期六, 11月 18, 2017

Intranet jail break

我們常開發了一些網站應用程式,部署在個人開發環境、內網測試環境與客戶測試環境,因為各有各的用途與限制,三者缺一不可,但又瑣碎費時。
  • 個人開發環境:通常與開發工具結合,不太需要擔心如何部署,但配備要夠(資料庫不一定是隨便一部電腦就跑得動吧?)。
  • 內網測試環境:為了整合測試,或給 SA 驗收確認,可以搭配 Jenkins 持續部署。
  • 客戶測試環境:為了給客戶 Prototyping,請工程師帶個人開發環境(筆電)秀給客戶看?或請客戶提供機器讓我們去裝一套?或請公司的 MIS 把內網開給客戶?
現在有個神器 ngrok 能幫忙,原理應該是與分享檔案的 JustBeamIt 類似,只要是內網測試環境,我們自己就能把內網開給客戶。下載解壓之後,只有一個執行檔,請在內網執行環境的主機上開終端機/命令提示字元,執行類似如下的指令:
  • ./ngrok http 80
就會把本機的 http port 80 公開在 Internet 上,網址是隨時産生的。這時再把網址傳給客戶,我們這些廢宅工程師就免出門吹風了。

星期三, 10月 25, 2017

VirtualBox VT-x

對於這個選項放在每個 Guest VM 上,一直以來引人誤解為「只要勾選就能讓 Guest VM 相當於 BIOS 設定啟用 VT-x」,其實只是代表「Host 在啟動 Guest 時能用到 VT-x」,這篇有比較詳細的討論。
如果想讓 Guest VM 支援 VT-x,專業術語叫 nested virtualization,大家已對 VirtualBox 喊話很久了。