2015年3月29日 星期日

大隱隱於市



下午跟家人一起看電視時,剛好看到節目在介紹一位在上海的畫家,主持人很好奇他怎樣在這樣的環境下創作,於是乎畫家就說了這句話: 「大隱隱於市...」

搭火車時,突然想起查了一下典故,看來像是個俗語似的,本意是說厲害的隱者不必到清幽的環境才能修煉,而更完整的句字:
大隱隱於朝;中隱隱於市;小隱隱於林
還滿不錯的意境。

更有一則相關詩句:中隱(白居易 唐詩)

大隱住朝市,小隱入丘樊
丘樊太冷落,朝市太囂喧
不如作中隱,隱在留司官
似出復似處,非忙亦非閑
不勞心與力,又免飢與寒
終歲無公事,隨月有俸錢
君若好登臨,城南有秋山
君若愛游蕩,城東有春園
君若欲一醉,時出赴賓筵
洛中多君子,可以恣歡言
君若欲高臥,但自深掩關
亦無車馬客,造次到門前
人生處一世,其道難兩全
賤即苦凍餒,貴則多憂患
唯此中隱士,致身吉且安
窮通與豐約,正在四者間

2015年3月26日 星期四

搭配 CyanogenMod 銷售的手機 - OnePlus One


前陣子跟友人閒聊起這個牌子,想說 2013 年買了小米2S送人,今年就換另一品牌吧!

OnePlus One 的特色就是搭配 CyanogenMod (CM) 作為預設的操作環境,若真的要說的話,有點像另類的 Nexus 系列,畢竟 CM 在 Android 刷機門派中早有一席之地,在 2013 年底也開始搭配實體機器來銷售了。

至於好不好用?我也不知道,因為要拿來送人 XD 我單純就 OnePlus 的路線來看,至今的確走得挺精彩的,把持著品牌路線、CP 值,以及手機質感,但不是走機海、海撈使用者和瘋狂搶佔市佔率模式。

這走法讓我對軟體服務業也有了一番省思。

2015年3月24日 星期二

AWS 筆記 - 建立自己的 Virtual Private Cloud (VPC)



原先以為 Amazon EC2 的 default vpc 不能綁定多組 public ip 才自己跳下去建立一個 VPC 把玩(事實證明是自己搞錯了),就順便筆記一下 XDD

首先,我先以 10.10.0.0/16 作為 Personal VPC 的範圍,接著希望在這裡頭的機器一樣可以連外,所以需設定 Internet Gateways 以及 Route tables,如此一來就跟 EC2-VPC 沒什麼兩樣了。









AWS 筆記 - Amazon EC2 一台機器綁定多組 Public IP


我原先以為只要增加實體網卡,接著從 Elastic Public IP 綁定即可,但結果一直不通,搞了一陣子終於搞懂流程了 XD 關鍵的地方在於只能用在一張實體網卡上,透過 Secondary IP addresses 機制,給予多個 public ip,這可能跟 AWS routing 本身設計有關。

總之,紀錄一下成功的步驟:
  1. 開機器過程中,在 Configure Instance Details -> Network interfaces 中,記得要使用 Secondary IP addresses ,如果打算讓一台機器綁定多組 public ip,則可以依據你要增加的 Public IP 數量進行,例如預計這台機器有 3 組 Public IP,那就是需增加兩組 Secondary IP addresses。(如果機器已開啟,則可以透過 Amazon EC2 Web UI -> Instances -> 查看 Description -> 挑選 Network interface -> 點擊 Interface ID -> Actions -> Manage Private IP Addresses -> Assign new IP)
  2. 在 OS 層新增虛擬網卡,我在 Amazon 提供的 Ubuntu 14.04 中,採用 static 的用法。
  3. 接著,在 Amazon EC2 Web UI -> Elastic IP -> Allocate New Address 後,再來接著 Associate Address -> 在挑選要綁定的 Private IP address -> Associate


以上就收工了,大不了第二步需要重開機一下。以下是第二步在 Amazon Ubuntu 14.04 64Bit 操作流程:

$ cat /etc/network/interfaces.d/eth0.cfg
# The primary network interface
auto eth0
iface eth0 inet dhcp

$ ifconfig
eth0    
          inet addr:172.##.##.##  Bcast:172.##.##.255  Mask:255.255.240.0
$ sudo vim /etc/network/interfaces.d/eth0.cfg
auto eth0
iface eth0 inet dhcp

auto eth0:0
iface eth0:0 inet static
address EC2-Private-IP
netmask 255.255.240.0

$ sudo ifup eth0:0
$ ifconfig
eth0    
          inet addr:172.##.##.##  Bcast:172.##.##.255  Mask:255.255.240.0
eth0:0  
          inet addr:172.##.##.##  Bcast:172.##.##.255  Mask:255.255.240.0

2015年3月18日 星期三

[Linux] 透過 sed 將 MySQL Table 資料轉成 csv 格式 @ Ubuntu 14.04

印象中之前找資料時,有發現 MySQL Server 可以輸出 CSV 格式到本地端。但是,對於無法存取到 DB Server 的檔案系統的環境時(AWS RDS),只好手動處理一下 :P

用法:

$ mysql -h rds-server -u root -p -e "SELECT field1, field2 FROM db_name.table_name" | grep "^Keyword" | sed 's/\t/","/g' | sed 's/^/"/g' | sed 's/$/"/g' > db-table-export.csv

其中 grep 那段只是為了mysql 輸出時,略過第一行 XD

[Linux] 透過 dpkg 指令,完整移除軟體 @ Ubuntu 14.04

有時為了製作乾淨的測試環境,多安裝的軟體會透過 apt-get remove package 來移除,並用 apt-get autoremove 清掉相依軟體。例如原本想安裝 php,偷懶用:

$ sudo apt-get install php5

結果系統就幫你裝了一卡車 apache2 相關東西,但你其實是想用 nginx 而已。

這時若只透過 apt-get remove 反安裝 apache2 後,系統還會遺留 /etc/apache2 的設定檔,為了避免後續維護誤導其他人,最佳的方式還是把這些東西都清光,此時就可透過 dpkg -P package 的方式清一清。

$ sudo dpkg -P apache2

如果有一卡車的東西,可以用 dpkg --get-selections 來查詢。連續動作(強烈建議先看過 dpkg --get-selections | grep deinstall 結果再使用):

$ dpkg --get-selections | grep deinstall | xargs sudo dpkg -P

2015年3月16日 星期一

AWS 筆記 - 使用 Amazon Cloudfront (CDN) 服務



切換到 AWS Cloudfront 頁面,可以看到支援 Web 跟 RTMP ,其中後者是 streaming media files。這次只使用 Web 方面。



整體設定上還滿簡單的,以 service.changyy.org 為例,後面是一台 server (node.changyy.org):
  • 先決定使用者最後會連結的服務的 domain name,此例是 service.changyy.org
  • 設定 cloudfront 的資訊,例如 Origin Domain name 填寫實際服務的機器位置 node.changyy.org
如此,cloudfront 會建立一筆 xxxxxxxxx.cloudfront.net 是提供 CDN 服務了。


可以用 nslookup xxxxxxxxx.cloudfront.net 可以看到有一批機器在服務了。如果,想要用自己的 domain name 的話,需要再 cloudfront 多設定 Alternate Domain Names(CNAMEs) 的資訊,未設定則會出現:


這主因是使用 cloudfront 是要計費的,若別人亂設定個 CNAME 導到你的 Amazon Cloudfront 的話,就默默地一直被扣錢 XD 至於費用的部分:
  • HTTP requests 費用: 在美國每 10000 則要價 0.0075 美金
  • 資料傳輸費用:在美國每 1GB 要價 0.02 美金
若一天要服務 10000 個 reqeusts,每則 100kb,那 30 天的費用:
30 天 * [10000 * 0.0075/10000 (HTTP) + 10000 * 100kb * 0.02/GB (DATA) ] = 30 * (0.075 + 0.01907) 美金附近 = 2.82 美金
對於費用部分,建議連上官網觀看,例如各地費用皆不同等:http://aws.amazon.com/tw/cloudfront/pricing/

2015年3月11日 星期三

AWS 筆記 - 使用 Amazon Simple Email Service (Amazon SES) 服務


原先在開發電子報服務時就有要用,嘗試到一半就被其他事件 Orz 所以還是花點時間筆記一下這塊。首先,使用上需要 Amazon 帳號,打通後則是要用 AWS SES 服務的流程而已,其中 AWS 許多流程仍是依據 IAM 權限管理的,其實也是個挺漂亮的架構,粗略流程:
  1. 透過 AWS 最高權限,在 Amazon SES -> SMTP Settings -> Create My SMTP Credentials,將得到一組 SMTP Username 和 Password 可使用。過程中會建立一個 AWS user,我印象中早期是要自己去處理的
  2. 預設是 sandbox 環境,只能寄給已驗證的收信者,在 Amzaon SES Verified Sender 可以新增幾個試試。
  3. 透過 SMTP protocol 寄信看看
此次使用 PHPMailer 來測試:

$ git clone https://github.com/Synchro/PHPMailer.git
$ vim PHPMailer/AWS-SES-test.php
<?php
require 'PHPMailerAutoload.php';

$mail = new PHPMailer;
$mail->SMTPDebug = 3;
$mail->isSMTP();
$mail->Host = 'email-smtp.us-west-2.amazonaws.com';
$mail->SMTPAuth = true;
$mail->Username = 'YourSMTPUsername';
$mail->Password = 'YourSMTPPassword';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;

$mail->From = 'YourSenderEmail';
$mail->FromName = 'Mailer';

$mail->addAddress('YourTargetEmail');

$mail->isHTML(true);
$mail->Subject = 'Here is the subject';
$mail->Body    = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';

if(!$mail->send()) {
    echo 'Message could not be sent.';
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'Message has been sent';
}

$ php PHPMailer/AWS-SES-test.php


在 sandbox 中,如果 $mail->addAddress 或是 $mail->From 使用的不是驗證過的,會出現 554 Message rejected: Email address is not verified.


最後,測試都差不多了,想要正式使用時,在申請一下  Requesting Production Access to Amazon SES 即可。理由可以很簡單,例如寄信給註冊的使用者們,不到20個英文字就搞定啦,但各個 region 必須分開申請。

Facebook 開發筆記 - Facebook app 無法取得真實的 account id

最近在開發 Facebook app 時,發現 Facebook API 已經有更新不少東西,其中有一項還滿不錯的,第三方 Facebook app 無法取得 Facebook user 的真實 ID 資訊,每個 app 會各別拿到一個,例如在 A app 跟 B app 詢問 graph api: /me 時,拿到的 id 會不一樣。然而,不一樣的 ID 卻仍可以一樣定位到同一個使用者。

這個最大的缺點是各個 Facebook app 沒有互通的資訊,但對於各個 facebook app 取得到的資訊卻還是一樣夠用。此外,可以用 www.facebook.com/id 去測試,可以發現仍可以定位到同一個 user,算是滿貼心的隱私設計。

https://developers.facebook.com/docs/graph-api/reference/v2.2/user
The id of this person's user account. This ID is unique to each app and cannot be used across different apps. Our upgrade guide provides more info about this.

2015年3月10日 星期二

Facebook 開發筆記 - 使用單一 Facebook app 仿 OAuth 架構提供單多平台多 app 登入使用

由於 Facebook app 在任何平台上,只能允許一個 app,例如 iOS platform 就只能綁定一個 iOS app,如果想要多個 iOS app 都用同一款 Facebook app 時,就出現了這奇妙的需求 :P

因此,再次包裝的方式,那就是用 UIWebview/WebView 來解吧!對於任何一款 Mobile app 都是採用 Browser 來完成登入的。而 Backend service 是維持採用同一款 Facebook app。

原理:主體是以 Facebook Javascript SDK 來使用,當完成 Facebook app 登入認證後,將 Javascript 端取得的 Facebook app token 丟給 backend service ,驗證後交換成自家 service token,未來用自己的 service token 來進行服務互動。

以上狀態僅需依照 Facebook SDK Javascript 文件已經可以完成大半了:

FB.getLoginStatus(function(response) {
  if (response.status === 'connected') {
    console.log('get facebook app token');
  }
  else {
    FB.login();
  }
});


在 response.status === 'connected' 就能取得 facebook token,再轉呼叫自家 service 來交換 token 即可收工。

然而?事情不是那麼簡單的 XD 在 mobile platform 環境上,用 chrome browser 或是 safari 都可以正常工作,唯獨 PhoneGap 等類似架構會出錯,主因是 Facebook SDK Javascript 登入時,會彈跳視窗,結束後可以再導回來,但在 PhoneGap 架構上,可能受限於沒有分頁機制而出錯?總之,解法:自行用 direct_url 跟 Facebook 互動吧!這招印象中是在寫 server side 的用法:

當使用者點擊 login 時,不要用 Facebook Javascript SDK,而是將網址導向到:

https://www.facebook.com/dialog/oauth?client_id=YourFacebookAppID&redirect_uri=http://localhostOrServiceWebURL/&response_type=token&scope=publish_stream,email

當使用者完成登入後,將導回你指定的位置,而這時在 FB.getLoginStatus 時,又可以正常取得 response.status === 'connected' 等資訊了。

2015年3月3日 星期二

不因善小而不為 –〉 快的打敗慢的

前陣子連續幾天下班後跟一位在 Y! 的學長聊天,聊著到底要選擇藍海還是紅海?讓我想起以前當兵擁抱藍色的經驗:

三年下來,幾乎都朝著藍海走,每年夏天都要提計畫、想創意,然後被顧問打槍... XD 後來,隨著神秘組織解散後,終於不用再想創意(當時為了想創意也開始看漫畫、讀小說,補齊兒時記憶)。那時的職業病:東西看越多,越想不出創意。任何組員提得出來的創意,都可以舉個國內外的例子出來。為了藍海目標、不與民爭利,於是乎...空轉。由於是藍海方向,高失敗率,於是乎...繼續空轉。

離開單位後,反而擁抱老二哲學。只要有想做的,馬上身體力行,因為自己想得到也深信別人也想得到 :P 大概是幾年空轉的職業傷害讓人更珍惜時間,一旦有想做的就是馬上衝,不二話,實在是點子就像錢存在銀行一樣,只會貶值。對於別人找我閒聊的方向,也一樣是建議對方盡快且堅定意志執行,別人有沒有做過沒什麼,就像大象(大公司)踩不死螞蟻(小公司、工作室),差異化就像嘴炮一樣,永遠都可以找到,只是有沒有價值(客戶)是另一回事 XD 隨著工作經驗的增加,方向又稍微修正。做服務不會馬上衝下去弄個 prototype ,而是稍微想一下再進行,沒想好容易砍掉重練,為了不要讓思考過長,設定個 deadline 是很不錯的。

學長的經歷是支持藍海走向的,反而讓我回憶起不少事情:
  • 到處都有聰明的人
    • 隨意逛 FB 還看到一位 28 歲的強者,除了在山景城工作外,兩年前還買了房 Orz 可真是高富帥的代言人
    • 學長在 Y! 碰到純數學派的強者,因為金融界玩膩了跑來玩資料分析 Orz 做事時可是直接設計數學 Model 來分析的
  • 資訊的匯流、個人或團隊成長跟環境有非常大的關係
    • 剛進研究單位時,我曾經很佩服老闆怎會有那些創意構想,過了一兩年後,我開始覺得那只是該位置會收集到的資訊,就像組織請的那一排顧問吧?當了顧問常常打槍別人,開槍完再把對方的點子收起來用 XD
    • 環境是非常重要的 :P 孟母三遷是非常經典的例子。有些環境雖然資源不錯,但沒有發揮環境時,除了自省有沒有哪些沒盡力之外,想進步還是要換換,不然只是另一個慢性毒藥
  • 藍海、紅海,只不過是投資報酬率的問題
    • 就像買樂透一樣,投資 50 元就有參加機會,但不參加,什麼機會都沒有
    • 紅海,屬於民眾已教育過的為重,文化上已轉換成很直觀的項目,屬於穩定的低報酬投資
    • 藍海,有機會還是去嘗試!畢竟有什麼比固定領薪水更差的情況呢?
  • 外商薪情好
    • 人太老實時,都會好奇為何外商肯用 2~3 倍台商的薪水請一個人?特別像是美商公司,然而,結論就只是生態,這就像台灣紡織業或其他高勞力傳統業,需要大量勞力的工作,在台灣有基本薪資19k,但去了大陸、越南、印尼等,基本薪資降到 3~9k 台幣,如此而已。
    • 所以對於外商的薪資,在台灣聘人真的是省到錢,至少省一半以上!
今天跟朋友閒聊一些開發服務郁悶的事情,得到一個結論:快的,打敗慢的

沒有什麼永遠會贏的,與其躊躇著某些服務差異性不大,倒不如回歸底心,有愛就繼續,有時間就繼續,失敗了也沒什麼大不了。