2015年2月9日 星期一

[Linux] 透過 echo, od, sed 將字串轉 HEX String @ Ubuntu 14.04

用法:

$ echo -n "0123456789" | od -A n -t x1 | sed 's/ /\\x/g'
\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39

$ echo -n "你好嗎" | od -A n -t x1 | sed 's/ /\\x/g'
\xe4\xbd\xa0\xe5\xa5\xbd\xe5\x97\x8e

2015年2月7日 星期六

當小傑奇犽離開雲古時...

很久沒寫一點內心戲了?不知不覺已在業界打滾五年多了? coding 早已破十來年。最近回顧起身旁的強者我同學、學弟,都開始挑選不一樣的人生道路行走,甚至回憶起過往點滴,都會驚覺當年真的握有一手好牌啊,可惜事過境遷,錯過了,就很難相聚,更別說再一同打拼。

夜深時,泡杯咖啡,不禁意地想起,原來當年的彼此都是很不錯的,套句愛情老台詞:在錯誤的時間點(失敗的案子),遇上對的人(爆強的工程師)?

人總會成長,強者更是跳躍,環境永遠是重要的因素 (孟母也略懂三遷),就像獵人漫畫的情節,小傑奇犽終究離開了雲古。

大家仍舊繼續成長,用著彼此不熟悉的步調或價值觀,世界也因亂度增加而美好!我想,越來越期待偶爾的吃飯相聚了 XD

2015年2月5日 星期四

[VB] 透過 Macro (巨集) 亂數挑選句子 @ Microsoft Powerpoint / OpenOffice Impress

前幾天接到朋友的一個需求,我想了一會覺得應該不難,就下海摸索一下,使用情境如下:

活動中讓賓客可以跟一些世界名句拍照合影(例如七言絕句等),希望每個賓客都可以透過抽籤(亂數)機制跟不同句子拍照。

分析一下技術:
  • 亂數功能
  • 有一個文字區域,每次亂數得到的結果要更新在文字區
原本朋友是說用網頁也行,但我覺得活動場所要連網路好像有點危險(雖然純HTML+JS也能離線),於是乎還是來用用投影片模式 XD 方向:試試看巨集吧!

簡言之,以 Microsoft Office 2007 / OpenOffice Impress 為例,亂數用法:

Public Function chooseWords As String
Dim MyArray As Variant

REM *** Comment ***
MyArray = Array("懶人包", "天龍人", "卡卡獸", "給開司一罐啤酒", "完全沒有××", "數學老ㄙ常請假", "天大地大臺科大","雅量背影出師表")

REM *** Random ***
ArraySize = UBound(MyArray)
index = Int(Rnd * ArraySize ) + 1

REM *** Return
chooseWords = MyArray(index)
REM MSGBox(MyArray(index))
End Function


至於更換掉投影片內的文字框,以 OpenOffice Impress 為例,假定投影片只有第一張,且只有一個文字框:

Sub Main
Dim Doc As Object
Dim SlideList as Object
Dim Slide AS Object
Dim Target As Object

Doc = ThisComponent
SlideList = Doc.getDrawPages()
Slide = SlideList.getByIndex(0)
Target = Slide.getByIndex(0)
REM MSGBox(chooseWords())
Target.setString( chooseWords() )
End Sub


以 Microsoft Office 2007 - Powerpoint 為例:

Sub Main()
    For Each sld In ActivePresentation.Slides
        For Each sh In sld.Shapes
            Rem MsgBox sh.Type
            If sh.Type = msoPlaceholder Or sh.Type = msoTextBox Then
                sh.TextFrame.TextRange.Text = chooseWords()
            End If
        Next
    Next
End Sub


上述 Microsoft 文件比較豐富(至少對沒經驗的我來說比較快找到),發現可以判斷物件的型態( msoPlaceholder 和 msoTextBox )。

最後則是事件綁定,例如在什麼事件下,呼叫巨集(Macro: Main) ,在 Microsoft Office - PowerPoint 方面,發現在插入圖片後,點擊圖片時,可以替他增加"動作",這時就可以輕鬆綁定巨集,至於 OpenOffice Impress 的部分...由於需求解掉,就沒再繼續鑽了。

2015年1月29日 星期四

[SQL] select n rows from each group @ MySQL 5.6

假設有一張 table 名為 log 長這樣:

{
id INTEGER,
level VARCHAR(16),
user VARCHAR(32)
}

mysql> SELECT * FROM log
1, "SA", "admin1"
2, "SA", "admin2"
3, "SA", "admin3"
4, "SA", "admin4"
5, "RD", "programmer1"
6, "RD", "programmer2"
7, "RD", "programmer3"
8, "RD", "programmer4"
9, "RD", "programmer1"
10, "FAE", "programmerA"
11, "FAE", "programmerB"
12, "FAE", "programmerC"


有沒有一招可以撈出,讓每個 Level 只顯示 3 筆資料?假想成果:

mysql> SELECT ... FROM log GROUP BY level
1, "SA", "admin1"
2, "SA", "admin2"
3, "SA", "admin3"
5, "RD", "programmer1"
6, "RD", "programmer2"
7, "RD", "programmer3"
10, "FAE", "programmerA"
11, "FAE", "programmerB"
12, "FAE", "programmerC"


土法煉鋼法,用 UNION ALL 來處理:

mysql> SELECT * FROM (SELECT * FROM log WHERE level = 'SA' LIMIT 3) AS t UNION ALL (SELECT * FROM log WHERE level = 'RD' LIMIT 3) UNION ALL (SELECT * FROM log WHERE level = 'FAE' LIMIT 3);

所幸,問了一下強者我同學,得到個關鍵字:GROUP_CONCAT , http://dev.mysql.com/doc/refman/5.6/en/group-by-functions.html#function_group-concat

mysql> SELECT level, GROUP_CONCAT(user) FROM log GROUP BY level;
"SA", "admin1,admin2,admin3"
"RD", "programmer1, programmer2, programmer3"
"FAE", "programmerA, programmerB, programmerC"


如果想限制撈出的資料個數,要設定 group_concat_max_len:

mysql> SET group_concat_max_len = 2;
mysql> SELECT level, GROUP_CONCAT(user) FROM log GROUP BY level;
"SA", "admin1,admin2"
"RD", "programmer1, programmer2"
"FAE", "programmerA, programmerB"


雖然上述結果還不太適合再做 JOIN 來處理,但,已經算佛心了... XD

其他 Google 用的關鍵字:"select top n rows from each group",會看到一些 RANK() OVER(PARTITION BY level) ,但對 MySQL 應該不適用 XD 強者我同學說,若在 PostgreSQL 可以用:

postgrel> select level, array_aggr(user)[0:1] from table group by level;

看來該多給 PostgrelSQL 機會 XD (當初案子用到 GIS 相關 plugin 才有用它...)

此外,跟強者我同學閒聊時,發現去年的一些經驗還滿適合使用的,有些查詢很久的指令,可以考慮定期產生並儲存在另一張 tabel,降低一般 client 觸發複雜的 SQL Query,像是 JOIN, GROUP 等,這也是在大型服務中也常用到的方式。算是此次閒聊最大的心得,因為去年也有應用這個架構來處理服務,驗證自已的(偷懶)做法無誤 XDDD

2015年1月24日 星期六

[Linux] 快速安裝 Gitlab 及簡易設定 @ Ubuntu 14.04

感覺近年來幾套出色的管理套件都是 Ruby 派的,例如 Redmine 等,然而有許多安裝瑣事要處理 Orz 所幸 Gitlab 官方有打包一個 debian package 讓初學者可以快速上手:

$ wget https://downloads-packages.s3.amazonaws.com/ubuntu-14.04/gitlab_7.6.2-omnibus.5.3.0.ci.1-1_amd64.deb
$ sudo apt-get install openssh-server
$ sudo apt-get install postfix # Select 'Internet Site'
$ sudo dpkg -i gitlab_7.6.2-omnibus.5.3.0.ci.1-1_amd64.deb
$ sudo gitlab-ctl reconfigure


如此一來,預設 http://localhost/ 就可以登入查看了。然而,預設環境比較適合體驗啦,我又多做了幾個動作,包含也在系統裝上 Ruby2.0 方便未來的相關使用。

更新 Gitlab 環境:
$ sudo vim /etc/gitlab/gitlab.rb

# 對外 Web 資訊
external_url = 'http://YourPublicDomainName'
# 對外 SSH 資訊
gitlab_rails['gitlab_ssh_host'] = 'YourPublicDomainName'
# 時區
gitlab_rails['time_zone'] = 'Asia/Taipei'
# 開啟 https 服務, 以及強制使用 https
nginx['redirect_http_to_https'] = true
nginx['redirect_http_to_https_port'] = 80
nginx['ssl_certificate'] = "/etc/gitlab/ssl/YourPublicDomainName.crt"
nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/YourPublicDomainName.key"

$ sudo gitlab-ctl reconfigure
$ sudo gitlab-ctl restart


更新 Postfix 環境:

$ sudo vim /etc/postfix/main.cf
myhostname = YourPublicDomainName
$ sudo postfix reload


安裝 Ruby 2.0 (非必要):

$ sudo apt-get update
$ sudo apt-get install ruby2.0 ruby2.0-dev
$ ruby -v
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]
$ gem -v
1.8.23
$ sudo ln -sf /usr/bin/ruby2.0 /usr/bin/ruby
$ sudo ln -sf /usr/bin/gem2.0 /usr/bin/gem
$ ruby -v
ruby 2.0.0p384 (2014-01-12) [x86_64-linux-gnu]
$ gem -v
2.0.14


以上則是稍微完整一點的調整。

然而,有時為了確保服務長久性,會有一些變動方式,例如 gitlab 資料儲存在於 /var/opt/gitlab ,可以給予一個獨立空間維護,因此,在安裝 gitlab 軟體前,先自行把 /var/opt/gitlab 擺在額外的 partition (此例是 AWS EC2 管理,給予一個 64GB 空間: http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ebs-using-volumes.html ):

$ lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  20G  0 disk
└─xvda1 202:1    0  20G  0 part /
xvdb    202:16   0   4G  0 disk /mnt
xvdc    202:32   0  64G  0 disk
$ sudo mkfs -t ext4  /dev/xvdc
$ sudo mkdir /64GB
$ sudo mount /dev/xvdc /64GB
$ sudo mkdir -p /64GB/gitlab /var/opt
$ sudo ln -s /64GB/gitlab /var/opt/gitlab


接著再跑安裝 gitlab 流程...如果已經安裝了,那就是配置好 /64GB 後:

$ sudo gitlab-ctl stop
ok: down: logrotate: 1s, normally up
ok: down: nginx: 0s, normally up
ok: down: postgresql: 0s, normally up
ok: down: redis: 1s, normally up
ok: down: sidekiq: 0s, normally up
ok: down: unicorn: 0s, normally up
$ sudo cp -a /var/opt/gitlab /64GB/gitlab
$ sudo mv /var/opt/gitlab /var/opt/gitlab-bak
$ sudo ln -s /64GB/gitlab /var/opt/gitlab
$ sudo gitlab-ctl start