Hightlight.js-9.15.6

2019年3月23日 星期六

[Web] 利用FileSaver.js使瀏覽器彈出存檔視窗儲存前端資料

在撰寫前端程式(ex:Single Pag Application)時,有時需要使用者儲存使用者端產生的資料,這時候可以使用FileSaver.js,任何轉換成Web API中的Blob物件的資料都能夠使用FileSaver.js存檔,因此在使用FileSaver.js之前至少要了解什麼是Blob物件、以及Blob建構式。



Blob物件

在MDN上關於Blob(Binary Large Object)的描述是"類檔案的不可變原始資料物件"(a file-like object of immutable, raw data),而File介面就是繼承Blob,並增強瀏覽器使用者系統上檔案的操作功能,要實現儲存前端資料這個功能可以先了解Blob建構式。...但值得謹記在心的是目前為止Android上主流瀏覽器對Blob的支援不明朗


Blob建構式

// Blob物件建構式語法:
let Blob = new Blob(array [, options]);

array是建構式必要的參數,是ArrayBuffer、ArrayBufferView、Blob、DOMString組成的Array物件或多種型別混合的陣列。

options作為一個物件傳入建構式,可以有兩種key:type跟endings:

type是對Blob型別描述(例如:text/csv、image/jpeg...),沒有預設值(type: ""),選項可以參考MDN上的MIME type

endings則可以指定對行尾\n的處理方式預設選項是"transparent"會保留\n為換行符號,如果指定為"native"就會將\n轉換為各OS定義的換行符號。

延伸學習

Blob Properties、Blob Methods、File API



FileSaver.js範例:

這裡的範例都是參考官方網站上改成cdn引入的,而測試的時候儲存遠端URL資源似乎無法使用?另外官網也提供用Web API 的 File產生Blob物件再套入saveAs(),這部分可以自行延伸。

儲存文字

<script src="https://fastcdn.org/FileSaver.js/1.1.20151003/FileSaver.min.js"></script>
<script>
  let blob = new Blob(["Hello, FileSaver.js!"], {type: "text/plain;charset=utf-8"});
  saveAs(blob, "hello.txt");
</script>

儲存convas

原理是Canvas元素用HTMLCanvasElement.toBlob()轉換成Blob,再存檔。
<script src="https://fastcdn.org/FileSaver.js/1.1.20151003/FileSaver.min.js"></script>
<script>
  let canvas = document.getElementById("canvasId");
  canvas.toBlob(blob =>
    saveAs(blob, "pretty image.png");
  );
</script>

2019年2月17日 星期日

[Google] 用Linux CLI操作google drive雲端硬碟

最新的流程需重新編譯gdrive,請參考 https://tigernaxo.github.io/blog/post/tools/gdrive/

介紹一個好用的工具:Gdrive CLI Client,可以透過指令列在Linux主機上和google雲端硬碟之間執行上傳、下載、同步,要將資料分享給其他人時特別好用,如果有教育版的帳號那基本上雲端空間是沒有限制的,不用白不用,下面流程的使用的版本是2.1.0:

設定Gdrive CLI Client


下載與設定

需要先從瀏覽器下載gdrive-linux-x64版本之後上傳Linux,假設放在${HOME}/gdrive-linux-x64:
# 建立${HOME}/bin
$ mkdir -p ${HOME}/bin
# 把gdrive-linux-x64放進去重新命名為gdrive
$ mv ${HOME}/gdrive-linux-x64 ${HOME}/bin/gdrive
# 賦予gdrive執行權限
$ chmod u+x ${HOME}/bin/gdrive

# 如果PATH裡面找不到${HOME}/bin就新增並重新讀取環境設定
$ echo ${PATH} | grep -qE ${HOME}/bin[^/] && \
> echo "PATH=\${HOME}/bin:\${PATH}" >> ~/.bashrc && \
> . ~/.bashrc

連結google帳戶

安裝好Google drive CLI後需要取得雲端硬碟帳戶授權,gdrive預設會在${HOME}/.gdrive底下找授權檔,由於目前我們沒有任何授權,所以需要先下簡單的指令觸發token請求,取得token之後會出現一個檔案叫做${HOME}/.gdrive/token_v2.json,並且在終端機出現雲端硬碟所有檔案及資料夾清單(預設最多出現30筆):
# 以list命令觸發token請求
# 這裡會得到一個網址,貼到瀏覽器的網址列enter,之後選擇你要連結的帳戶,按照步驟授權後貼上授權碼,成功的話就會出現清單。
$ gdrive list
Authentication needed
Go to the following url in your browser:
https://accounts.google.com/o/oauth2/auth?access_type=offline&client_id=...

Enter verification code:7/4wDh2A_4vtaFR9JibaVC-l-lv2sV7SSCj0QsWL-J2-mcTGY9xrTi9rU



查詢檔案


gdrive除了一些特殊資料夾,像是根目錄沒有ID直接叫做root之外,對於檔案跟資料夾的操作都基於id,而獲得檔案與資料夾id常用的方式有三種:
  1. 資料夾網址觀察id:https://drive.google.com/drive/u/1/folders/1D8kkabcEecxxxxxxNSAy8ho97gTRuyNa
  2. 檔案右鍵後選擇"取得檔案共用連結,貼到文字編輯器觀察id:https://drive.google.com/open?id=1QJUxAzep1s4xxxxxxxUWUxf1H3KBrTNO
  3. 透過gdrive list指令配合搜尋參數(重要!可參閱文件)查詢,就是以下要介紹的方法。

查詢雲端檔案清單

# 列出雲端硬碟最上層資料夾(root)的內容
$ ./gdrive-linux-x64 list -q "'root' in parents"
Id                                             Name         Type   Size   Created
1zY5UMnx-xxxxxxfuetg7cyrY5MU-k8w4              tmp          dir           2018-05-29 02:32:33
1D8kkabcEecxxxxxxNSAy8ho97gTRuyNa              Backup       dir           2018-03-27 05:14:21
1gFOCwss-xxxxxxKF5td-g-Ovj_z4JoEcqpVHq1t5u4Y   Google 相簿    dir           2017-07-07 14:02:17

# 列出特定資料夾的內容,1D8kkabcEecxxxxxxNSAy8ho97gTRuyNa是資料夾id
$ ./gdrive-linux-x64 list -q "'1D8kkabcEecxxxxxxNSAy8ho97gTRuyNa' in parents"
Id                                  Name        Type   Size      Created
1sqZTRRd5ucxxxxxx7l4ApnlLs4kVOsyF   note0001    bin    196.0 B   2018-07-18 06:41:12
1V-CvduOE9exxxxxxAflObt2wbGbD49zz   note0002    bin    199.0 B   2018-07-18 06:41:11
1SOq0opXxXQxxxxxxiCy5eY3ivO-KFVLy   back        dir              2018-07-18 06:40:56
1tyJcRaO9Dfxxxxxxo6yvndSkr8zpos_D   test.sh     bin    4.6 KB    2018-07-18 06:38:25



上傳/下載


下載
# 下載某個檔案
$ gdrive download 1tyJcRaO9Dfxxxxxxo6yvndSkr8zpos_D
Downloading myTestFile1 -> myTestFile1
Downloaded 1tyJcRaO9Dfxxxxxxo6yvndSkr8zpos_D at 402.0 B/s, total 402.0 B

# 下載整個資料夾
$ gdrive download -r 1D8kkabcEecxxxxxxNSAy8ho97gTRuyNa
Downloading myTestFile1  -> myTestFolder /myTestFile1
Downloading myTestFile2  -> myTestFolder /myTestFile2
Downloading myTestFile3  -> myTestFolder /myTestFile3
Downloading myTestFile4  -> myTestFolder /myTestFile4

上傳
# 上傳某個檔案到某個資料夾
$ gdrive upload -p 1D8kkabcEecxxxxxxNSAy8ho97gTRuyNa myTestFile4
Uploading myTestFile5
Uploaded 1tyJcRaO9Dfxxxxxxo6yvndSkr8zpos_D at 87.8 KB/s, total 151.3 KB

# 上傳整個資料夾到某個資料夾底下
$ gdrive upload -r -p 1D8kkabcEecxxxxxxNSAy8ho97gTRuyNa myTestFolder
Creating directory myTestFolder
Uploading myTestFolder/myTestFile1
Uploading myTestFolder/myTestFile2
Uploading myTestFolder/myTestFile3
Uploading myTestFolder/myTestFile4




資料夾同步


資料夾同步到雲端
# 建立一個空資料夾並上傳雲端,作為雲端同步資料夾
$ mkdir syncTest
$ gdrive upload -r syncTest

# 查詢剛剛上傳的空資料夾ID
$ gdrive -q "name = 'syncTest'"
Id                                  Name       Type   Size   Created
1Uv5MxUXcxxxxxxcjM2nT_3hcuz-SMNnV   syncTest   dir           2019-02-18 09:52:26

# 把本地資料夾的內容同步到雲端
$ gdrive sync upload local_folder 1Uv5MxUXcxxxxxxcjM2nT_3hcuz-SMNnV
Starting sync...
Collecting local and remote file information...
Found 7 local files and 0 remote files

1 remote directories are missing
[0001/0001] Creating directory syncTest/ae006468

6 remote files are missing
[0001/0006] Uploading ae006468/0.error -> syncTest/ae006468/0.error
...
Sync finished in 13.435891267s

雲端同步到資料夾
# 建立一個空資料夾準備接收雲端資料
$ mkdir syncTest2

# 把雲端內容同步到本地資料夾
$ gdrive sync download 1Uv5MxUXcxxxxxxcjM2nT_3hcuz-SMNnV syncTest2
Starting sync...
Collecting file information...
Found 0 local files and 7 remote files

1 local directories are missing
[0001/0001] Creating directory syncTest2/ae006468

6 local files are missing
[0001/0006] Downloading ae006468/result.ok -> syncTest2/ae006468/result.ok
Sync finished in 7.269982268s

2019年2月15日 星期五

[台灣杉] 善用module切換python環境

台灣杉有module載入的功能,module可以快速幫我們在台灣杉上面切換執行環境,台灣杉預設載入的${HOME}/.bashrc有一行module load gcc,如果你沒更動過的話那預設就可以找到gcc6.3.0 (以gcc開頭的module只有gcc/6.3.0才可以這樣載入),要注意有些module間並不相容。

module常用功能


  取得module功能的說明:module -H
  列出當下已載入的module:module list
  載入特定module:module add/load modulefile [modulefile ...]
  卸載特定module:module rm/unload modulefile [modulefile ...]
  清空當前環境所有module:module purge

$ module list
Currently Loaded Modulefiles:
  1) gcc/6.3.0



範例


掛載python3


# 台灣杉預設的python版本是2.7.5
$ python -V
Python 2.7.5

# 原本是沒有python3的
$ which python3
/usr/bin/which: no python3 in ...

# 掛載python3/3.5.6模組
$ module load python3/3.5.6
$ module list
Currently Loaded Modulefiles:
  1) gcc/6.3.0       2) python3/3.5.6

# 測試掛載後是否可使用python3及pip
$ which python3 && python3 -V
/pkg/python3/bin/python3
Python 3.6.5
$ which pip3 && pip3 -V
/pkg/python3/bin/pip3
pip 9.0.3 from /pkg/python3/lib/python3.6/site-packages (python 3.6)

掛載anaconda3/5.1.10


我們可以透過掛載anaconda3/5.1.10管理虛擬環境,並且使預設的python指令指向掛載的python3:
# 未掛載anaconda3/5.1.10模組之前台灣杉預設的python是版本2.7.5
$ python -V
Python 2.7.5

# 掛載anaconda3/5.1.10
$ module load anaconda3/5.1.10
$ module list
Currently Loaded Modulefiles:
  1) gcc/6.3.0          2) anaconda3/5.1.10

# 掛載anaconda3/5.1.10模組之後python指向版本3.6.4
$ python -V
Python 3.6.4 :: Anaconda, Inc.

2019年2月12日 星期二

[台灣杉] 利用(Access Control List)權限設定團隊專屬資料夾

在大型主機上會發生多團隊並共用某個資料夾,一般來說自己資料夾只有自己可以存取倒是沒什麼問題,但是如果有資料只想要分享給所屬團隊成員,偏偏這些團隊又都隸屬同個Linux群組,單純只是把權限改成750又會被別的團隊看到。這時候就需要額外的ACL (Access Control List)權限設定了:

# 建立分享資料夾並先關閉group、other的權限
$ mkdir share && chmod 700 share

# 逐一設定設定使用者id1 id2 id3
setfacl -m d:u:id1:rx,d:u:id2:rx,d:u:id3:rx share

# 查看ACL資料夾設定
$ getfacl share
# file: share/
# owner: myId
# group: myGroup
user::rwx
user:id1:r-x
user:id2:r-x
user:id3:r-x
group::---
mask::r-x
other::---
default:user::rwx
default:user:id1:r-x
default:user:id2:r-x
default:user:id3:r-x
default:group::---
default:mask::r-x
default:other::---
設定完成!現在只有剛剛設定的使用者可以讀、進入該資料夾,並且新增的資料夾可以繼承權限設定,所以使用者id1~id4也都可以讀取新增的資料夾,現在可以開始把資料放進去了,但是資料本身的權限要打開喔!

2019年1月22日 星期二

[台灣杉] 一鍵登入國網中心台灣杉(Taiwania)

台灣杉(Taiwania)是國網中心2018年啟用的超級電腦,登入時密碼必須附加OTP (One-time Password),國網中心建議取得OTP的方式是從驗證器取得OTP密碼,但這樣的方式每次都需要打開驗證器(手機、chrome插件... etc),並且需要手動輸入OTP,下面分享我從Windows以及Linux環境下登入台灣杉所使用的一鍵登入方式。

OTP的演算法可粗分為HOTP (HMAC-based OTP);以及基於HOTP的TOTP (Time-based OTP),我們不必瞭解演算法細節,只需知道台灣杉採用Base32編碼作為TOTP金鑰(Secret),時間間格為30秒,每30秒可以根據"Secret"與"當前時間區間"以sha1演算法生成一次性密碼(OTP,或稱為Key),由於這是單向加密的過程所以無法用時間區間與Key逆推Secret,並且OTP在成功使用一次之後就會被伺服器廢棄,以確保安全性。

傳送門

  1. 從Windows登入台灣杉
  2. 從Linux(具有管理員權限)登入台灣杉
  3. 從Linux(沒有管理員權限)登入台灣杉
  4. 附錄:在沒有權限的主機上使用oathtool (練習抽取package、滿足相依性)

注意事項

  • 校時。由於TOTP演算法依據當前時間區間產生OTP,如果作業系統的時間不正確則會產生錯誤的OTP,在Windows環境之下可以到國家時間與頻率標準實驗室的網頁下載NTP校時軟體,以管理員身分執行進行校時;Linux環境可以用下述指令更新時間並寫入BIOS:
    # 從NTP時間伺服器進行網路校時
    sudo ntpdate time.stdtime.gov.tw
    # 將更新的時間寫入BIOS
    sudo hwclock -w
  • 所有登入行為之間必須間隔30秒(包含使用winSCP、putty或從Linux直接登入)。每個30秒區間會產生一個OTP,而該OTP一旦經過使用就會被伺服器廢棄而無法再用。我曾經連續登入以為程式壞了,但核對iService上面產生的密碼又是一樣的,後來才發現這件事...中間還因為連登失敗太頻繁還被鎖,因此記得間隔30秒以上再登入。
  • Linux要登入台灣衫需要將台灣衫加入know host,以生醫節點為例:
    ssh-keyscan 140.110.148.14 1>>~/.ssh/known_hosts 2>/dev/null

從Windows登入台灣杉

前置工作
  1. 安裝Go,並設置GOPATH
  2. 安裝putty
  3. 安裝WinSCP
  4. 知道怎麼打開windows的命令提示字元 (WIN+R、鍵入cmd、enter)。
編譯TOTP產生器

取得TOTP套件
go get github.com/pquerna/otp/totp
撰寫程式碼main.go
package main

import (
        "fmt"
        "github.com/pquerna/otp/totp"
        "os"
        "time"
)

func main() {
        secret := os.Args[1]
        code, _ := totp.GenerateCode(secret, time.Now().UTC())
        fmt.Print(code)
}
編譯
go build -o taiwaniaOTP.exe main.go
設置putty

按照圖片步驟設置putty session,如果不想修改預設字型可跳過步驟4~6,全部設置完成後要回Session標籤按Save(步驟7、8)

撰寫批次檔 (串聯TOTP產生器與putty session)

建立資料夾(例如: D:\BioPkg\taiwania),把剛剛的taiwaniaOTP.exe丟進去,在資料夾內複製下面指令建立taiwania-putty.bat批次檔,按照步驟1~3進行設置:
@echo off
:: 1.設置putty執行檔位置
SET putty=D:\Programs\putty.exe
:: 2.設置固定密碼(取代password)
SET regular_pw=password
:: 3.設置TOTP金鑰(從iservice服務網複製的金鑰取代TOTPsecret)
SET secret=TOTPsecret

:: 取得totp
for /f %%i in ('%cd%/taiwaniaOTP.exe %secret%') do set totp=%%i

:: 5.把taiwania-14取代成你剛剛設置的session name
start D:\Programs\putty.exe -load "taiwania-14" -pw %regular_pw%%totp%
exit
撰寫批次檔 (串聯TOTP產生器與WinSCP)

在資料夾內複製下面指令建立taiwania-sftp.bat,按照步驟1~4設置:
@echo off
:: 1.設置WinSCP執行檔位置
SET winSCP="C:\Program Files (x86)\WinSCP\WinSCP.exe"
:: 2.設置使用者名稱(取代userName)
SET user=userName
:: 3.設置固定密碼(取代password)
SET regular_pw=password
:: 4.設置TOTP金鑰(從iservice服務網複製的金鑰取代TOTPsecret)
SET secret=TOTPsecret

:: 取得totp
for /f %%i in ('%cd%/taiwaniaOTP.exe %secret%') do set totp=%%i

:: 呼叫winSCP登入台灣杉資料傳輸專用節點
start %winSCP% sftp://%user%:%regular_pw%%totp%@140.110.148.21:22
exit
測試

目前為止我們完成了兩件事,接下來我們一分鐘的安全間隔進行測試,你可以在桌面上建立批次檔的捷徑方便登入,甚至是改icon讓它們更像一回事:
  1. 雙擊taiwania-putty.bat呼叫putty session登入台灣杉生醫節點(140.110.148.14)。
  2. 雙擊taiwania-sftp.bat呼叫winSCP登入台灣杉的資料傳輸節點(140.110.148.21)。

從Linux(具有管理員權限)登入台灣杉

使用Linux的設定自動登入需要熟悉基本Linux操作(套件安裝、環境變數、shell script),或是嘗試按照下列步驟設定,當然您也可以自行編譯上述的OTP產生器(從Windows登入小節所提到)取代oathtool:
安裝oathtool、sshpass
# 如果系統為Red Hat/CentOs/Fedora則改用yum
sudo apt-get update
sudo apt-get install oathtool sshpass
設置腳本loginTaiwania.sh
##### loginTaiwania.sh #####
#!/bin/bash
secret="Enter-Your-Otp-Secret-Got-From-Nchc"
taiwaniaIP="140.110.148.14"
userName="Enter-Your-Id-On-Taiwania"
fixedPW="Enter-Your-Fixed-Password"
otp=$(oathtool -b -d6 -s30 --totp="sha1" ${secret})
sshpass -p ${fixedPW}${otp} ssh ${userName}@${taiwaniaIP}
授予登入腳本執行權限
chmod a+x loginTaiwania.sh
測試登入
./loginTaiwania.sh

從Linux(沒有管理員權限)登入台灣杉

有時候會用使用其他機器登入台灣杉,但是卻沒有管理員權限可以安裝sshpass、oathtool,以下是變通方法。

確認sshpass、oathtool

查詢系統是否提供sshpass、oathtool,如果已有可以省略編譯的步驟,下面在台灣杉上查詢的結果顯示PATH中有sshpass但找不到oathtool,所以在台灣杉上可以跳過編譯sshpass的步驟。
$ which sshpass
/usr/bin/sshpass
$ which oathtool
/usr/bin/which: no oathtool in (/home/ux/xxx/bin:/home/xxx/bin:/cm/local/apps/gcc/6.3.0/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/sbin:/cm/local/apps/environment-modules/3.2.10/bin:/opt/pbs/bin:/usr/bin:/usr/bin:/home/xxx/.local/bin:/home/xxx/bin)
編譯sshpass

最後sshpass的可執行檔預期是/path/to/sshpass-1.06/sshpass。
$ wget http://sourceforge.net/projects/sshpass/files/latest/download -O sshpass.tgz
$ tar zxf sshpass.tgz
$ cd sshpass-1.06
$ ./configure && make
$ /path/to/sshpass-1.06/sshpass
Usage: sshpass [-f|-d|-p|-e] [-hV] command parameters
   -f filename   Take password to use from file
   -d number     Use number as file descriptor for getting password
   -p password   Provide password as argument (security unwise)
   -e            Password is passed as env-var "SSHPASS"
   With no parameters - password will be taken from stdin

   -P prompt     Which string should sshpass search for to detect a password prompt
   -v            Be verbose about what you're doing
   -h            Show help (this screen)
   -V            Print version information
At most one of -f, -d, -p or -e should be used
編譯OTP產生器(oathtool替代方案)

要在像台灣杉類似的主機上編譯oathtool有點複雜,如果一定要用oathtool比較可行的方法是下載binary及so(參考附錄),但最簡單的方法還是直接編譯自己的OTP產生器,這一步需要先安裝Go,並及設置GOPATH
$ go get github.com/pquerna/otp/totp
撰寫TOTP產生器 main.go
package main

import (
        "fmt"
        "github.com/pquerna/otp/totp"
        "os"
        "time"
)

func main() {
        secret := os.Args[1]
        code, _ := totp.GenerateCode(secret, time.Now().UTC())
        fmt.Print(code)
}
編譯TOTP產生器
go build -o taiwaniaOTP main.go
設置腳本loginTaiwania.sh。
#!/bin/bash
secret="Enter-Your-Otp-Secret-Got-From-Nchc"
taiwaniaIP="140.110.148.14"
userName="Enter-Your-Id-On-Taiwania"
fixedPW="Enter-Your-Fixed-Password"
# 如果系統本身有提供oathtool,就把taiwaniaOTP改成oathtool
otp=$(taiwaniaOTP ${secret})
sshpass -p ${fixedPW}${otp} ssh ${userName}@${taiwaniaIP}
測試登入
./loginTaiwania.sh

附錄:在沒有權限的主機上使用oathtool (練習抽取package、滿足相依性)

如果要在沒有權限的主機上使用oathtool,就得要自己下載rpm/deb,從裡面抽取binaries及Requires,下面分成rpm(RedHat/CentOS/Fedora)跟apt(Debian/Ubuntu)系統說明:

rpm(RedHat/CentOS/Fedora)系統

查詢OS版本資訊,得知台灣衫的OS是Red Hat 7.3。
$ lsb_release -d
Description:    Red Hat Enterprise Linux Server release 7.3 (Maipo)
pkgs.org找相應的Binary Package rpm版本,我們點選CentOS 7的EPEL x86_64版本oathtool-2.4.1-9.el7.x86_64.rpm ( CentOS與Red Hat是相容的,EPEL代表Extra Packages for Enterprise Linux,rpm套件管理員當中描述的x86_64是指cpu的x86-64架構,雖然有伺服器已經開始採用較省電的ARM架構,但目前幾乎所有的伺服器架構都是x86-64 ),接著在Download底下取得Binary Package的下載連結,以下面的指令下載、展開、確認相依性:
# 下載Binary Package
$ wget http://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/o/oathtool-2.4.1-9.el7.x86_64.rpm
# 抽取Binary Package
$ rpm2cpio oathtool-2.4.1-9.el7.x86_64.rpm | cpio -ivd
./usr/bin/oathtool
./usr/share/doc/oathtool-2.4.1
./usr/share/doc/oathtool-2.4.1/COPYING
./usr/share/man/man1/oathtool.1.gz
165 blocks
# 查看oathtool相依性,not found標註代表相依性未滿足
$ ldd ./usr/bin/oathtool
        linux-vdso.so.1 =>  (0x00002aaaaaaab000)
        liboath.so.0 => not found
        libc.so.6 => /lib64/libc.so.6 (0x00002aaaaaad4000)
        /lib64/ld-linux-x86-64.so.2 (0x0000555555554000)
下載oathtool未滿足的相依性,可以直接到剛剛取得下載連結的下載頁面,從Requires欄位下直接點選項目liboath.so.0()(64bit)的連結,一樣選擇CentOS 7的EPEL x86_64版本下載
# 下載Binary Package
$ wget http://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/l/liboath-2.4.1-9.el7.x86_64.rpm
# 抽取Binary Package
$ rpm2cpio liboath-2.4.1-9.el7.x86_64.rpm | cpio -ivd
./etc/liboath
./usr/lib64/liboath.so.0
./usr/lib64/liboath.so.0.1.3
./usr/share/doc/liboath-2.4.1
./usr/share/doc/liboath-2.4.1/COPYING
# 查看liboath.so.0相依性,可看到皆滿足
$ ldd ./usr/lib64/liboath.so.0
        linux-vdso.so.1 =>  (0x00002aaaaaaab000)
        libc.so.6 => /lib64/libc.so.6 (0x00002aaaaacdf000)
        /lib64/ld-linux-x86-64.so.2 (0x0000555555554000)
到這一步oathtool仍然找不到liboath.so.0,我們也無法把liboath.so.0所在的資料夾加入/etc/ld.so.conf的定義,所以我們要定義一個oathtool.sh腳本,腳本會自動新增LD_LIBRARY_PATH,告訴oathtool要去哪裡找我們剛剛下載的liboath.so.0:
##### oathtool.sh #####
#!/bin/bash
oathtool="/path/to/oathtool"
ldPath=$(dirname $(readlink -f ${oathtool}))"/../lib64"
export LD_LIBRARY_PATH_OLD=${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH="${ldPath}:${LD_LIBRARY_PATH}"
${oathtool} $@
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH_OLD}
現在oathtool.sh表現得就跟oathtool一樣了,以下測試:
$ ./oathtool.sh
oathtool 2.4.1

Generate and validate OATH one-time passwords.

Usage: oathtool [OPTIONS]... [KEY [OTP]]...

  -h, --help                    Print help and exit
  -V, --version                 Print version and exit
      --hotp                    use event-based HOTP mode  (default=on)
      --totp                    use time-variant TOTP mode  (default=off)
  -b, --base32                  use base32 encoding of KEY instead of hex
                                  (default=off)
  -c, --counter=COUNTER         HOTP counter value
  -s, --time-step-size=DURATION TOTP time-step duration  (default=`30s')
  -S, --start-time=TIME         when to start counting time steps for TOTP
                                  (default=`1970-01-01 00:00:00 UTC')
  -N, --now=TIME                use this time as current time for TOTP
                                  (default=`now')
  -d, --digits=DIGITS           number of digits in one-time password
  -w, --window=WIDTH            window of counter values to test when
                                  validating OTPs
  -v, --verbose                 explain what is being done  (default=off)

Report bugs to: oath-toolkit-help@nongnu.org
oathtool home page: 
General help using GNU software: 
apt(Debian/Ubuntu)系統

查詢作業系統版本
$ lsb_release -d
Description:    Ubuntu 18.04.1 LTS
pkgs.org找相應的Binary Package apt版本,我們點選Ubuntu 18.04 LTS (Bionic Beaver)的Ubuntu Universe amd64版本oathtool_2.6.1-1_amd64.deb ( BSD Linux家族把x86-64架構稱為AMD64,目前幾乎所有的伺服器架構都是x86_64 ),接著在Download底下取得Binary Package的下載連結,以下面的指令下載、展開、確認相依性:
# 先下載oathtool
$ wget http://archive.ubuntu.com/ubuntu/pool/universe/o/oath-toolkit/oathtool_2.6.1-1_amd64.deb
# 抽取oathtool到特定資料夾oathtool內
$ dpkg -X oathtool_2.6.1-1_amd64.deb ./oathtool
./
./usr/
./usr/share/
./usr/share/doc/
./usr/share/doc/oathtool/
./usr/share/doc/oathtool/copyright
./usr/share/man/
./usr/share/man/man1/
./usr/share/man/man1/oathtool.1.gz
./usr/bin/
./usr/bin/oathtool
./usr/share/doc/oathtool/AUTHORS
./usr/share/doc/oathtool/README
./usr/share/doc/oathtool/NEWS.gz
./usr/share/doc/oathtool/changelog.Debian.gz
# 查看oathtool相依性
$ ldd ./oath/usr/bin/oathtool
        linux-vdso.so.1 (0x00007fff10bfe000)
        liboath.so.0 => not found
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fda6c3ea000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fda6c7db000)
# 取得、抽取未滿足的相依性libc.so.6
$ wget http://archive.ubuntu.com/ubuntu/pool/universe/o/oath-toolkit/liboath0_2.6.1-1_amd64.deb
$ dpkg -X liboath0_2.6.1-1_amd64.deb ./oathtool
./
./usr/
./usr/share/
./usr/share/doc/
./usr/share/doc/liboath0/
./usr/share/doc/liboath0/AUTHORS
./usr/share/doc/liboath0/README
./usr/share/doc/liboath0/copyright
./usr/share/doc/liboath0/NEWS.gz
./usr/share/doc/liboath0/changelog.Debian.gz
./usr/lib/
./usr/lib/liboath.so.0.1.3
./usr/lib/liboath.so.0
# 檢查libc.so.6是否滿足
$ ldd ./oath/usr/lib/liboath.so.0
        linux-vdso.so.1 (0x00007ffc0f0f5000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8f6da78000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f8f6e07d000)
到這一步oathtool仍然找不到libc.so.6,我們也無法把libc.so.6所在的資料夾加入/etc/ld.so.conf的定義,所以我們要定義一個oathtool.sh腳本,腳本會自動新增LD_LIBRARY_PATH,告訴oathtool要去哪裡找我們剛剛下載的libc.so.6:
##### oathtool.sh #####
#!/bin/bash
oathtool="/path/to/oathtool"
ldPath=$(dirname $(readlink -f ${oathtool}))"/../lib"
export LD_LIBRARY_PATH_OLD=${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH="${ldPath}:${LD_LIBRARY_PATH}"
${oathtool} $@
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH_OLD}
現在oathtool.sh表現得就跟oathtool一樣了,以下測試:
$ ./oathtool/usr/bin/oathtool.sh
oathtool 2.6.1

Generate and validate OATH one-time passwords.

Usage: oathtool [OPTIONS]... [KEY [OTP]]...

  -h, --help                    Print help and exit
  -V, --version                 Print version and exit
      --hotp                    use event-based HOTP mode  (default=on)
      --totp[=STRING]           use time-variant TOTP mode  (possible
                                  values="sha1", "sha256", "sha512"
                                  default=`sha1')
  -b, --base32                  use base32 encoding of KEY instead of hex
                                  (default=off)
  -c, --counter=COUNTER         HOTP counter value
  -s, --time-step-size=DURATION TOTP time-step duration  (default=`30s')
  -S, --start-time=TIME         when to start counting time steps for TOTP
                                  (default=`1970-01-01 00:00:00 UTC')
  -N, --now=TIME                use this time as current time for TOTP
                                  (default=`now')
  -d, --digits=DIGITS           number of digits in one-time password
  -w, --window=WIDTH            window of counter values to test when
                                  validating OTPs
  -v, --verbose                 explain what is being done  (default=off)

Report bugs to: oath-toolkit-help@nongnu.org
oathtool home page: 
General help using GNU software: