GitHub是全球最大的程式碼託管平台,許多軟體資源都可以在該網站上取得。有些人如筆者就喜歡除了把程式原始碼上傳到GitHub外,也把已經編譯好的二進制檔案也一併上傳到GitHub替每個倉庫(Repository)所提供的「Release」區,這樣一來不想自行編譯原始碼的使用者就可以直接到「Release」區中找到對應平台已經編譯好的二進制檔案來直接下載使用。
以OpenH264這個H.264的開源函式庫為例,其GitHub倉庫網址如下:
我們可以在其「Release」區下,找到各個版本已經官方編譯好的函式庫和重新打包過的原始碼專案。如下圖:
其中,libopenh264-1.8.0-linux64.4.so.bz2
就是Linux x86_64所使用的動態函式庫,我們可以將其下載下來,就能在Linux x86_64上直接使用。
然而每次都要用網頁瀏覽器開啟GitHub來找到這個頁面來載最新版的檔案好像也挺麻煩的,在懶惰蟲的趨使下,就必須要想個方式能夠直接在Linux環境下,以指令的方式下載到GitHub倉庫上最新發佈出來的檔案。
GitHub提供的 /releases/latest
HTTP API
GitHub有提供許多方便的HTTP API,其中的/releases/latest
可以協助我們做到這件事。HTTP請求的網址格式如下:
GET https://api.github.com/repos/<user>/<repo>/releases/latest
以剛才提到的OpenH264為例,就是:
GET https://api.github.com/repos/cisco/openh264/releases/latest
這支API的回傳值大概如以下這樣(已刪減冗長訊息):
{
"url": "https://api.github.com/repos/cisco/openh264/releases/11663903",
"assets_url": "https://api.github.com/repos/cisco/openh264/releases/11663903/assets",
"upload_url": "https://uploads.github.com/repos/cisco/openh264/releases/11663903/assets{?name,label}",
"html_url": "https://github.com/cisco/openh264/releases/tag/v1.8.0",
"id": 11663903,
"node_id": "MDc6UmVsZWFzZTExNjYzOTAz",
"tag_name": "v1.8.0",
"target_commitish": "master",
"name": "Release version 1.8.0",
"draft": false,
"author": {
"login": "GuangweiWang",
"id": 11676737,
"node_id": "MDQ6VXNlcjExNjc2NzM3",
"avatar_url": "https://avatars2.githubusercontent.com/u/11676737?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/GuangweiWang",
"html_url": "https://github.com/GuangweiWang",
"followers_url": "https://api.github.com/users/GuangweiWang/followers",
"following_url": "https://api.github.com/users/GuangweiWang/following{/other_user}",
"gists_url": "https://api.github.com/users/GuangweiWang/gists{/gist_id}",
"starred_url": "https://api.github.com/users/GuangweiWang/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/GuangweiWang/subscriptions",
"organizations_url": "https://api.github.com/users/GuangweiWang/orgs",
"repos_url": "https://api.github.com/users/GuangweiWang/repos",
"events_url": "https://api.github.com/users/GuangweiWang/events{/privacy}",
"received_events_url": "https://api.github.com/users/GuangweiWang/received_events",
"type": "User",
"site_admin": false
},
"prerelease": false,
"created_at": "2018-06-27T01:36:43Z",
"published_at": "2018-06-27T02:03:37Z",
"assets": [
{
"url": "https://api.github.com/repos/cisco/openh264/releases/assets/7676582",
"id": 7676582,
"node_id": "MDEyOlJlbGVhc2VBc3NldDc2NzY1ODI=",
"name": "libopenh264-1.8.0-linux64.4.so.bz2",
"label": null,
"uploader": {
"login": "GuangweiWang",
"id": 11676737,
"node_id": "MDQ6VXNlcjExNjc2NzM3",
"avatar_url": "https://avatars2.githubusercontent.com/u/11676737?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/GuangweiWang",
"html_url": "https://github.com/GuangweiWang",
"followers_url": "https://api.github.com/users/GuangweiWang/followers",
"following_url": "https://api.github.com/users/GuangweiWang/following{/other_user}",
"gists_url": "https://api.github.com/users/GuangweiWang/gists{/gist_id}",
"starred_url": "https://api.github.com/users/GuangweiWang/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/GuangweiWang/subscriptions",
"organizations_url": "https://api.github.com/users/GuangweiWang/orgs",
"repos_url": "https://api.github.com/users/GuangweiWang/repos",
"events_url": "https://api.github.com/users/GuangweiWang/events{/privacy}",
"received_events_url": "https://api.github.com/users/GuangweiWang/received_events",
"type": "User",
"site_admin": false
},
"content_type": "application/x-bzip2",
"state": "uploaded",
"size": 529202,
"download_count": 1122,
"created_at": "2018-06-27T01:45:48Z",
"updated_at": "2018-06-27T01:45:57Z",
"browser_download_url": "https://github.com/cisco/openh264/releases/download/v1.8.0/libopenh264-1.8.0-linux64.4.so.bz2"
},
{
"url": "https://api.github.com/repos/cisco/openh264/releases/assets/7676588",
"id": 7676588,
"node_id": "MDEyOlJlbGVhc2VBc3NldDc2NzY1ODg=",
"name": "libopenh264-1.8.0-linux64.4.so.sig.bz2",
"label": null,
"uploader": {
"login": "GuangweiWang",
"id": 11676737,
"node_id": "MDQ6VXNlcjExNjc2NzM3",
"avatar_url": "https://avatars2.githubusercontent.com/u/11676737?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/GuangweiWang",
"html_url": "https://github.com/GuangweiWang",
"followers_url": "https://api.github.com/users/GuangweiWang/followers",
"following_url": "https://api.github.com/users/GuangweiWang/following{/other_user}",
"gists_url": "https://api.github.com/users/GuangweiWang/gists{/gist_id}",
"starred_url": "https://api.github.com/users/GuangweiWang/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/GuangweiWang/subscriptions",
"organizations_url": "https://api.github.com/users/GuangweiWang/orgs",
"repos_url": "https://api.github.com/users/GuangweiWang/repos",
"events_url": "https://api.github.com/users/GuangweiWang/events{/privacy}",
"received_events_url": "https://api.github.com/users/GuangweiWang/received_events",
"type": "User",
"site_admin": false
},
"content_type": "application/x-bzip2",
"state": "uploaded",
"size": 418,
"download_count": 119,
"created_at": "2018-06-27T01:46:23Z",
"updated_at": "2018-06-27T01:46:25Z",
"browser_download_url": "https://github.com/cisco/openh264/releases/download/v1.8.0/libopenh264-1.8.0-linux64.4.so.sig.bz2"
}
],
"tarball_url": "https://api.github.com/repos/cisco/openh264/tarball/v1.8.0",
"zipball_url": "https://api.github.com/repos/cisco/openh264/zipball/v1.8.0"
}
其中,tarball_url
和zipball_url
欄位是GitHub替每個Release主動提供的快照下載網址,而assets
欄位是GitHub倉庫的擁有者自行在建立Release時所額外加入的檔案。assets
欄位中的每個檔案的browser_download_url
欄位,正是該檔案的下載網址。
curl
指令
我們可以利用Linux發行版中常會內建的curl
指令來調用GitHub提供的這支API。如果環境中沒有安裝curl
的話,基於Debian的Linux發行版可以使用以下指令來安裝:
紅帽系的Linux發行版則可以使用以下指令來安裝curl
:
curl
指令的使用方式如下:
curl -s https://api.github.com/repos/cisco/openh264/releases/latest
curl
指令的-s
參數可以讓curl
指令只輸出URL資源的主體(body)資料。
sed
指令
接著我們可以利用Linux作業系統中內建的sed
指令來處理curl
指令呼叫GitHub的API所回傳的JSON資料。
例如要抓取browser_download_url
欄位中的網址,sed
指令可以這樣寫:
sed -r -n 's/.*"browser_download_url": *"(.*)".*/\1/p'
sed
指令的-r
參數可以讓\1
發揮作用(也就是正規表示式的群組功能);-n
參數可以讓輸出結果只保留/p
要輸出的部份(此處就是\1
)。
結合curl
指令,寫法如下:
curl -s https://api.github.com/repos/cisco/openh264/releases/latest | sed -r -n 's/.*"browser_download_url": *"(.*)".*/\1/p'
如上圖,由於每個Release中可能會有超過一個的額外檔案,因此我們必須要確保這些網址所連結到的檔案資源都是我們需要下載,不然就得繼續再過濾。這部份可以再使用grep
指令來達成,或者我們也可以修改剛才寫好的sed
指令,在(.*)
內加入更嚴苛的條件,例如:
curl -s https://api.github.com/repos/cisco/openh264/releases/latest | sed -r -n 's/.*"browser_download_url": *"(.*-linux64\..*\.so\.bz2)".*/\1/p'
如上圖,只剩下一個網址了!
wget
指令
最後可以利用Linux發行版中常會內建的wget
指令來下載這個網址所連結到的檔案。如果環境中沒有安裝wget
的話,基於Debian的Linux發行版可以使用以下指令來安裝:
紅帽系的Linux發行版則可以使用以下指令來安裝wget
:
有關於wget
更詳細的介紹可以參考這篇文章:
例如要用標準輸入(stdin)中取得的網址來下載檔案,指令可以這樣寫:
wget -q -i -
wget
指令的-q
參數可以讓wget
在下載時不印出一堆資訊;-i
參數可以指定一個檔案路徑或是用-
表示標準輸入,來輸入多筆要進行檔案下載的網址。
最後結合curl
指令和sed
指令,寫法如下:
curl -s https://api.github.com/repos/cisco/openh264/releases/latest | sed -r -n 's/.*"browser_download_url": *"(.*-linux64\..*\.so\.bz2)".*/\1/p' | wget -q -i -
如此一來就能用一行指令把GitHub倉庫上最新發佈的檔案給下載下來了!