為了下載投影片,但懶得一個個複製貼上、改指令,所以預先把投影片網址跟預定的檔名放在文字檔裡,然後用 awk 一次下載。
文字檔的格式是:url filename ,假定這個文字檔的檔名是 slides.txt
那麼,這樣就能搞定:
awk '{system("wget -O \"" $2 "\" " $1)}' slides.txt
Just thinking more…
為了下載投影片,但懶得一個個複製貼上、改指令,所以預先把投影片網址跟預定的檔名放在文字檔裡,然後用 awk 一次下載。
文字檔的格式是:url filename ,假定這個文字檔的檔名是 slides.txt
那麼,這樣就能搞定:
awk '{system("wget -O \"" $2 "\" " $1)}' slides.txt
花了一些時間簡單的架設 parse-server,把過程紀錄一下。
cd parse-server && docker build --tag parse-server .
docker build --tag parse-dashboard .
{
"apps": [
{
"serverURL": "http://<your-ip>:1337/parse",
"appId": "APPLICATION_ID",
"masterKey": "MASTER_KEY",
"appName": "MyApp",
"production": false
}
],
"users": [
{
"user": "user",
"pass": "pass"
}
]
}
---
version: '3'
services:
mongodb:
image: mongo:3.4
parse:
image: parse-server:latest
environment:
FOO: bar
command: --appId APPLICATION_ID --masterKey MASTER_KEY --databaseURI mongodb://mongodb/test
links:
- mongodb
ports:
- "1337:1337"
parse-board:
image: parse-dashboard:latest
environment:
PARSE_DASHBOARD_ALLOW_INSECURE_HTTP: "yes"
links:
- parse
ports:
- "4040:4040"
volumes:
- ./config.json:/src/Parse-Dashboard/parse-dashboard-config.json
要啟用 push notification ,得調整 docker-compose.yml 裡 parse service 的 command,加入 push notification 的相關選項。從選項可以看出,parse 仍是利用 GCM/APNs 來發送通知。
LiveQuery 在佈署到 AWS 時,要用 ALB,因為 ELB 不支援 WebSocket。
在正式環境裡,要記得把 PARSE_DASHBOARD_ALLOW_INSECURE_HTTP 設為 “no” ,並且加上 SSL 。也可以參考 parse-server github 網頁上對於佈署的說明,有蠻多佈署到平台上的現成範例可參考。
參考資料:
aria2 的 web UI,紀錄一下怎麼使用。
提高安全性:
參考資料:
本來是打算用 snipmate 的,但看到這篇 UltiSnips 让 Vim 飞起来 – 吕小荣 ,馬上轉投 UltiSnips 。XD
安裝與設定上沒什麼困難。
" Install ultisnips using Vundle Plugin 'SirVer/ultisnips' Plugin 'honza/vim-snippets'
裝好以後,輸入特定的關鍵字 (關鍵字要自己去挖 vim-snippets 下的 UltiSnips/snippets 資料夾裡的檔案),再按 tab ,就會自動出現 snippet,如果 snippet 有指定 ${1:pass} 之類的,可以在輸入完畢以後,用 ctrl + j 或 ctrl + k 來切到上一個或下一個位置。
我卡到的問題是自訂的 snippets 沒被載入。找了半天,才發現我把 UltiSnips 資料夾放錯位置。(把我的時間還來!!)
UltiSnips 的 python docstring 可以自訂,看格式是要用 google, sphinx, doxygen, numpy 還是 jedi 的格式。在 .vimrc 裡放下面這行就可以了:
let g:ultisnips_python_style="google"
Jenkins 裡能用的環境變數可以參考:
但是有時候,就是覺得少了那麼一些。我們可以使用 EnvInject plugin 在建置時,插入需要的環境變數,讓後續的建置步驟使用。
使用方法:
參考資料:
dockerd 預設只使用 /var/run/docker.sock,如果需要讓其他的 host 去管理,就需要額外設定。
在 Ubuntu trusty 裡,要編輯 /etc/default/docker,加入
DOCKER_OPTS="-H 0.0.0.0:2375"
然後重新啟動就可以了。
不過這樣設定以後,就等於任何人都可以透過這個 port 去控制你這台機器裡的所有 container ,官方建議加上 TLS 來保障連線的安全,晚點再來研究怎麼加上 TLS 。
參考資料:
簡單的說,depends_on 跟 links 只保證相依的 container 有啟動,但不保證裏面的服務已經啟動完畢,可以接受服務了。
我找到的解決方法,是利用 wait-for-it 這個 bash script 來測試 container 的 port 是否開啟。docker-compose v3 好像有要試圖解決這問題,不過還沒正式釋出。也是有一些其他的解法,不過,我覺得不是很直覺,就先放著了。
參考資料:
最近在 Windows 試 docker-toolbox,想讓外部連線連到 host 時,其實是連接到 在 VM 裡服務的 docker container,所以查了看怎麼做。
結果比想像中還要簡單,就是利用 vboxmanage controlvm 去設定 port forwarding 就可以了。
/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe controlvm vm_name natpf1 "rule1,tcp,,80,,80"
那要刪除掉這條 port forwarding 的規則,用
/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe controlvm vm_name natpf1 delete rule1
即可。
那在 linux 下也可以用同樣的方式來做 port forwarding,唯一的限制是非 root 用戶,沒辦法做 port 1024 以下的 port forwarding。
說明:
參考資料:
主要看這篇:Classes
大致用法跟 C#/Java 差不多,幾個特別的地方:
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
this._fullName = newName;
}
}
後面提到的 constructor functions 是一個進階技巧,不過感覺上用到機會不大。
今天是看這篇:Interfaces
TypeScript 有 anonymous interface ,就像下面的程式一樣:
// 有點 anonymous interface 的味道
function printLabel1(labelledObj: { label: string }) {
console.log(labelledObj.label);
}
// 也可以明確的用 interface 寫
interface LabelledValue {
label: string;
}
function printLabel2(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}
在宣告成員時,如果加入 ? ,表示可有可無,這個寫法應該是參考了 Ruby 的作法
interface SquareConfig {
color?: string;
width?: number;
}
用 readonly 修飾詞則是表示唯讀
interface Point {
readonly x: number;
readonly y: number;
}
如果要需告一個唯讀的陣列,可以用 ReadonlyArray
let ro: ReadonlyArray = a;
我覺得 Function types 比較不是那麼直覺,不容易看懂
interface SearchFunc {
(source: string, subString: string): boolean;
}
let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
let result = source.search(subString);
return result > -1;
}
大抵來說就是 python 的 __call__ 或是 c++ 的 operator()。
Indexable type 也是不太直覺
interface StringArray {
[index: number]: string;
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];
let myStr: string = myArray[0];
大抵來說就是 python 的 __item__ 或是 c++ 的 operator[]。
要讓類別實作介面是用 implements 關鍵字
interface ClockInterface {
currentTime: Date;
}
class Clock implements ClockInterface {
currentTime: Date;
constructor(h: number, m: number) { }
}
下面這例子是想要限定 ClockInterface 裡的 constructor 必須符合 ClockConstructor 規範的作法,第一眼不太容易看懂。
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick();
}
// 傳進來的 ctor 必須符合 ClockConstructor 的規範,要有 hour 跟 minute 這兩個 number 型別的參數。
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("tick tock");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
介面也可以繼承,跟類別一樣,是用 extends,而且允許繼承多個
interface Shape {
color: string;
}
interface PenStroke {
penWidth: number;
}
interface Square extends Shape, PenStroke {
sideLength: number;
}
蠻令我驚訝的是,Interface 可以繼承 class … @_@